1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <i2c_api.h>
9
10 #include <internal/i2c_depend.h>
11 #include <internal/i2c_driver.h>
12
13 #include <stdbool.h>
14 #include <stdio.h>
15
16 #define FILE_GRP_ID DBG_DRV_I2C
17 #define CONTROLLER_CODE_VAL 0x04
18
19 static I2C_ERR_t i2c_api_recv_data_i(
20 I2C_EN_CH_t ch,
21 uint32_t target_address,
22 uint32_t address,
23 uint8_t *data,
24 int length,
25 int flgid);
26
27 static I2C_ERR_t i2c_api_send_data_i(
28 I2C_EN_CH_t ch,
29 uint32_t target_address,
30 uint32_t address,
31 const uint8_t *data,
32 int length,
33 int flgid);
34
f_i2c_api_initialize(I2C_ST_PACKET_INFO_t * packet_info,uint32_t reg_base,I2C_TYPE type,const I2C_PARAM_t * param)35 I2C_ERR_t f_i2c_api_initialize(
36 I2C_ST_PACKET_INFO_t *packet_info,
37 uint32_t reg_base,
38 I2C_TYPE type,
39 const I2C_PARAM_t *param)
40 {
41 I2C_ERR_t ercd = I2C_ERR_OK;
42 ercd = i2c_initialize(packet_info, reg_base, type, param);
43 return ercd;
44 }
45
i2c_api_use_hs_mode(I2C_EN_CH_t ch,bool use_hsmode_flag)46 I2C_ERR_t i2c_api_use_hs_mode(I2C_EN_CH_t ch, bool use_hsmode_flag)
47 {
48 I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch);
49
50 if (packet_info == NULL)
51 return I2C_ERR_PARAM;
52
53 if (packet_info->TYPE != I2C_TYPE_F_I2C_SP1)
54 return I2C_ERR_UNAVAILABLE;
55
56 packet_info->USE_HS_MODE = use_hsmode_flag;
57 return I2C_ERR_OK;
58 }
59
i2c_api_recv_data_i(I2C_EN_CH_t ch,uint32_t target_address,uint32_t address,uint8_t * data,int length,int flgid)60 static I2C_ERR_t i2c_api_recv_data_i(
61 I2C_EN_CH_t ch,
62 uint32_t target_address,
63 uint32_t address,
64 uint8_t *data,
65 int length,
66 int flgid)
67 {
68 I2C_ERR_t ercd = I2C_ERR_OK;
69 I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch);
70
71 if (packet_info == NULL)
72 return I2C_ERR_PARAM;
73
74 i2c_enable(packet_info);
75
76 i2c_packet_initialize(&packet_info->PACKET);
77
78 /* Send controller code, only for F_I2C_SP1 */
79 if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) {
80 if (packet_info->USE_HS_MODE) {
81 packet_info->CONTROLLER_CODE_FLAG = true;
82 i2c_packet_set_control(
83 &packet_info->PACKET, CONTROLLER_CODE_VAL, false);
84 }
85 }
86
87 i2c_packet_set_control(&packet_info->PACKET, target_address, false);
88 i2c_packet_set_address(&packet_info->PACKET, address, 1);
89 i2c_packet_set_control(&packet_info->PACKET, target_address, true);
90 i2c_packet_set_payload(&packet_info->PACKET, (char *)data, length);
91
92 ercd = i2c_exec_transfer(packet_info);
93 if ((flgid == 0) && (ercd == I2C_ERR_OK))
94 ercd = i2c_handler_polling(packet_info);
95
96 i2c_disable(packet_info);
97
98 return ercd;
99 }
100
f_i2c_api_recv_data(I2C_EN_CH_t ch,uint32_t target_address,uint32_t address,uint8_t * data,int length)101 I2C_ERR_t f_i2c_api_recv_data(
102 I2C_EN_CH_t ch,
103 uint32_t target_address,
104 uint32_t address,
105 uint8_t *data,
106 int length)
107 {
108 I2C_ERR_t ercd = I2C_ERR_OK;
109
110 if ((target_address <= 0x03) || (target_address >= 0x78))
111 return I2C_ERR_PARAM;
112
113 if (data == NULL)
114 return I2C_ERR_PARAM;
115
116 if (length <= 0)
117 return I2C_ERR_PARAM;
118
119 ercd = i2c_api_recv_data_i(
120 ch, target_address, address, data, length, 0x00000000);
121
122 return ercd;
123 }
124
i2c_api_send_data_i(I2C_EN_CH_t ch,uint32_t target_address,uint32_t address,const uint8_t * data,int length,int flgid)125 static I2C_ERR_t i2c_api_send_data_i(
126 I2C_EN_CH_t ch,
127 uint32_t target_address,
128 uint32_t address,
129 const uint8_t *data,
130 int length,
131 int flgid)
132 {
133 I2C_ERR_t ercd = I2C_ERR_OK;
134 I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch);
135
136 if (packet_info == NULL)
137 return I2C_ERR_PARAM;
138
139 i2c_enable(packet_info);
140
141 i2c_packet_initialize(&packet_info->PACKET);
142
143 /* Send controller code, only for F_I2C_SP1 */
144 if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) {
145 if (packet_info->USE_HS_MODE) {
146 packet_info->CONTROLLER_CODE_FLAG = true;
147 i2c_packet_set_control(
148 &packet_info->PACKET, CONTROLLER_CODE_VAL, false);
149 }
150 }
151
152 i2c_packet_set_control(&packet_info->PACKET, target_address, false);
153 i2c_packet_set_address(&packet_info->PACKET, address, 1);
154 i2c_packet_set_payload(&packet_info->PACKET, (char *)data, length);
155
156 ercd = i2c_exec_transfer(packet_info);
157 if ((flgid == 0) && (ercd == I2C_ERR_OK))
158 ercd = i2c_handler_polling(packet_info);
159
160 i2c_disable(packet_info);
161
162 return ercd;
163 }
164
f_i2c_api_send_data(I2C_EN_CH_t ch,uint32_t target_address,uint32_t address,const uint8_t * data,int length)165 I2C_ERR_t f_i2c_api_send_data(
166 I2C_EN_CH_t ch,
167 uint32_t target_address,
168 uint32_t address,
169 const uint8_t *data,
170 int length)
171 {
172 I2C_ERR_t ercd = I2C_ERR_OK;
173
174 if ((target_address == 0x01) || (target_address == 0x02) ||
175 (target_address == 0x03) || (target_address >= 0x78)) {
176 return I2C_ERR_PARAM;
177 }
178
179 if (length < 0)
180 return I2C_ERR_PARAM;
181
182 ercd = i2c_api_send_data_i(
183 ch, target_address, address, data, length, 0x00000000);
184
185 return ercd;
186 }
187