1 /**************************************************************************//**
2 *
3 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2020-1-14 klcheng First version
10 *
11 ******************************************************************************/
12
13 #include <rtconfig.h>
14
15 #if (defined(BSP_USING_UI2C) && defined(RT_USING_I2C))
16
17 #include <rtdevice.h>
18 #include "NuMicro.h"
19
20 /* Private define ---------------------------------------------------------------*/
21 #define LOG_TAG "drv.ui2c"
22 #define DBG_ENABLE
23 #define DBG_SECTION_NAME LOG_TAG
24 #define DBG_LEVEL DBG_INFO
25 #define DBG_COLOR
26 #include <rtdbg.h>
27
28 #define SLV_10BIT_ADDR (0x1E<<2) //1111+0xx+r/w
29
30 /* Private typedef --------------------------------------------------------------*/
31 typedef struct nu_ui2c_bus
32 {
33 struct rt_i2c_bus_device ui2c_dev;
34 struct rt_i2c_msg *msg;
35 UI2C_T *ui2c_base;
36 char *dev_name;
37 } nu_ui2c_bus_t;
38
39 /* Private functions ------------------------------------------------------------*/
40 static rt_ssize_t nu_ui2c_mst_xfer(struct rt_i2c_bus_device *ui2c_dev,
41 struct rt_i2c_msg msgs[],
42 rt_uint32_t num);
43
44 static const struct rt_i2c_bus_device_ops nu_ui2c_ops =
45 {
46 .master_xfer = nu_ui2c_mst_xfer,
47 .slave_xfer = NULL,
48 .i2c_bus_control = NULL,
49 };
50
51 /* Private variables ------------------------------------------------------------*/
52 #ifdef BSP_USING_UI2C0
53 #define UI2C0BUS_NAME "ui2c0"
54 static nu_ui2c_bus_t nu_ui2c0 =
55 {
56 .ui2c_base = UI2C0,
57 .dev_name = UI2C0BUS_NAME,
58 };
59 #endif /* BSP_USING_UI2C0 */
60
61 #ifdef BSP_USING_UI2C1
62 #define UI2C1BUS_NAME "ui2c1"
63 static nu_ui2c_bus_t nu_ui2c1 =
64 {
65 .ui2c_base = UI2C1,
66 .dev_name = UI2C1BUS_NAME,
67 };
68 #endif /* BSP_USING_UI2C1 */
69
70 /* Functions define ------------------------------------------------------------*/
71 #if (defined(BSP_USING_UI2C0) || defined(BSP_USING_UI2C1))
72
nu_ui2c_wait_ready_with_timeout(nu_ui2c_bus_t * nu_ui2c)73 static inline rt_err_t nu_ui2c_wait_ready_with_timeout(nu_ui2c_bus_t *nu_ui2c)
74 {
75 rt_tick_t start = rt_tick_get();
76 while (!(UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & (UI2C_PROTSTS_STARIF_Msk | UI2C_PROTSTS_ACKIF_Msk | UI2C_PROTSTS_NACKIF_Msk | UI2C_PROTSTS_STORIF_Msk)))
77 {
78 if ((rt_tick_get() - start) > nu_ui2c->ui2c_dev.timeout)
79 {
80 LOG_E("\nui2c: timeout!\n");
81 return -RT_ETIMEOUT;
82 }
83 }
84
85 return RT_EOK;
86 }
87
nu_ui2c_send_data(nu_ui2c_bus_t * nu_ui2c,rt_uint8_t data)88 static inline rt_err_t nu_ui2c_send_data(nu_ui2c_bus_t *nu_ui2c, rt_uint8_t data)
89 {
90 UI2C_SET_DATA(nu_ui2c->ui2c_base, data);
91 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG);
92 return nu_ui2c_wait_ready_with_timeout(nu_ui2c);
93 }
94
nu_ui2c_send_address(nu_ui2c_bus_t * nu_ui2c,struct rt_i2c_msg * msg)95 static rt_err_t nu_ui2c_send_address(nu_ui2c_bus_t *nu_ui2c,
96 struct rt_i2c_msg *msg)
97 {
98 rt_uint16_t flags = msg->flags;
99 rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
100 rt_uint8_t addr1, addr2;
101 rt_err_t ret;
102
103 if (flags & RT_I2C_ADDR_10BIT)
104 {
105 UI2C_ENABLE_10BIT_ADDR_MODE(nu_ui2c->ui2c_base);
106 /* Init Send 10-bit Addr */
107 addr1 = ((msg->addr >> 8) | SLV_10BIT_ADDR) << 1;
108 addr2 = msg->addr & 0xff;
109
110 LOG_D("addr1: %d, addr2: %d\n", addr1, addr2);
111
112 ret = nu_ui2c_send_data(nu_ui2c, addr1);
113 if (ret != RT_EOK) //for timeout condition
114 return -RT_EIO;
115
116 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack)
117 {
118 LOG_E("NACK: sending first addr\n");
119
120 return -RT_EIO;
121 }
122 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
123
124 ret = nu_ui2c_send_data(nu_ui2c, addr2);
125 if (ret != RT_EOK) //for timeout condition
126 return -RT_EIO;
127
128 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack)
129 {
130 LOG_E("NACK: sending second addr\n");
131
132 return -RT_EIO;
133 }
134 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
135
136 if (flags & RT_I2C_RD)
137 {
138 LOG_D("send repeated start condition\n");
139
140 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STA));
141 ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c);
142 if (ret != RT_EOK) //for timeout condition
143 return -RT_EIO;
144
145 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk) && !ignore_nack)
146 {
147 LOG_E("sending repeated START fail\n");
148
149 return -RT_EIO;
150 }
151 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk);
152
153 addr1 |= RT_I2C_RD;
154
155 ret = nu_ui2c_send_data(nu_ui2c, addr1);
156 if (ret != RT_EOK) //for timeout condition
157 return -RT_EIO;
158
159 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack)
160 {
161 LOG_E("NACK: sending repeated addr\n");
162 return -RT_EIO;
163 }
164 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
165 }
166 }
167 else
168 {
169 /* 7-bit addr */
170 addr1 = msg->addr << 1;
171 if (flags & RT_I2C_RD)
172 addr1 |= RT_I2C_RD;
173
174 /* Send device address */
175 ret = nu_ui2c_send_data(nu_ui2c, addr1); /* Send Address */
176 if (ret != RT_EOK) //for timeout condition
177 return -RT_EIO;
178
179 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk)
180 && !ignore_nack)
181 {
182 LOG_E("sending addr fail\n");
183 return -RT_EIO;
184 }
185 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
186 }
187
188 return RT_EOK;
189 }
190
nu_ui2c_mst_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)191 static rt_ssize_t nu_ui2c_mst_xfer(struct rt_i2c_bus_device *bus,
192 struct rt_i2c_msg msgs[],
193 rt_uint32_t num)
194 {
195 struct rt_i2c_msg *msg;
196 nu_ui2c_bus_t *nu_ui2c;
197 rt_size_t i;
198 rt_uint32_t cnt_data;
199 rt_uint16_t ignore_nack;
200 rt_err_t ret;
201
202 RT_ASSERT(bus != RT_NULL);
203 nu_ui2c = (nu_ui2c_bus_t *) bus;
204
205 nu_ui2c->msg = msgs;
206
207 (nu_ui2c->ui2c_base)->PROTSTS = (nu_ui2c->ui2c_base)->PROTSTS;//Clear status
208
209 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_STA);
210 ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c);
211
212 if (ret != RT_EOK) //for timeout condition
213 {
214 rt_set_errno(-RT_ETIMEOUT);
215 return 0;
216 }
217
218 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk)) /* Check Send START */
219 {
220 i = 0;
221 LOG_E("Send START Fail");
222 return i;
223 }
224 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk);
225
226 for (i = 0; i < num; i++)
227 {
228 msg = &msgs[i];
229 ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
230
231 if (!(msg->flags & RT_I2C_NO_START))
232 {
233 if (i)
234 {
235 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STA));/* Send repeat START */
236 ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c);
237 if (ret != RT_EOK) //for timeout condition
238 break;
239
240 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk)) /* Check Send repeat START */
241 {
242 i = 0;
243 LOG_E("Send repeat START Fail");
244 break;
245 }
246 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk);
247 }
248
249 if ((RT_EOK != nu_ui2c_send_address(nu_ui2c, msg))
250 && !ignore_nack)
251 {
252 i = 0;
253 LOG_E("Send Address Fail");
254 break;
255 }
256 }
257
258 if (nu_ui2c->msg[i].flags & RT_I2C_RD) /* Receive Bytes */
259 {
260 rt_uint32_t do_rd_nack = (i == (num - 1));
261 for (cnt_data = 0 ; cnt_data < (nu_ui2c->msg[i].len) ; cnt_data++)
262 {
263 do_rd_nack += (cnt_data == (nu_ui2c->msg[i].len - 1)); /* NACK after last byte for hardware setting */
264 if (do_rd_nack == 2)
265 {
266 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG);
267 }
268 else
269 {
270 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_AA));
271 }
272
273 ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c);
274 if (ret != RT_EOK) //for timeout condition
275 break;
276
277 if (nu_ui2c->ui2c_base->PROTCTL & UI2C_CTL_AA)
278 {
279 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk)) /*Master Receive Data ACK*/
280 {
281 i = 0;
282 break;
283 }
284 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
285 }
286 else
287 {
288 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_NACKIF_Msk) != UI2C_PROTSTS_NACKIF_Msk)) /*Master Receive Data NACK*/
289 {
290 i = 0;
291 break;
292 }
293 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_NACKIF_Msk);
294 }
295
296 nu_ui2c->msg[i].buf[cnt_data] = nu_ui2c->ui2c_base->RXDAT;
297 }
298 }
299 else /* Send Bytes */
300 {
301 for (cnt_data = 0 ; cnt_data < (nu_ui2c->msg[i].len) ; cnt_data++)
302 {
303 /* Send register number and MSB of data */
304 ret = nu_ui2c_send_data(nu_ui2c, (uint8_t)(nu_ui2c->msg[i].buf[cnt_data]));
305 if (ret != RT_EOK) //for timeout condition
306 break;
307
308 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk)
309 && !ignore_nack
310 ) /* Send data and get Ack */
311 {
312 i = 0;
313 break;
314 }
315 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk);
316 }
317 }
318 }
319
320 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STO)); /* Send STOP signal */
321 ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c);
322 if (ret != RT_EOK) //for timeout condition
323 {
324 rt_set_errno(-RT_ETIMEOUT);
325 return 0;
326 }
327
328 RT_ASSERT(((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STORIF_Msk) == UI2C_PROTSTS_STORIF_Msk));
329 if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STORIF_Msk) != UI2C_PROTSTS_STORIF_Msk)) /* Bus Free*/
330 {
331 i = 0;
332 LOG_E("Send STOP Fail");
333 }
334
335 UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STORIF_Msk);
336 UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG);
337 UI2C_DISABLE_10BIT_ADDR_MODE(nu_ui2c->ui2c_base); /*clear all sub modes like 10 bit mode*/
338 nu_ui2c->msg = RT_NULL;
339
340 return i;
341 }
342
343 #endif //(defined(BSP_USING_UI2C0) || defined(BSP_USING_UI2C1))
344
345 /* Public functions -------------------------------------------------------------*/
rt_hw_ui2c_init(void)346 int rt_hw_ui2c_init(void)
347 {
348 rt_err_t ret = -RT_ERROR;
349
350 #if defined(BSP_USING_UI2C0)
351 SYS_UnlockReg();
352 SYS_ResetModule(USCI0_RST);
353 SYS_LockReg();
354
355 nu_ui2c0.ui2c_dev.ops = &nu_ui2c_ops;
356 UI2C_Open(nu_ui2c0.ui2c_base, 100000);
357 ret = rt_i2c_bus_device_register(&nu_ui2c0.ui2c_dev, nu_ui2c0.dev_name);
358 RT_ASSERT(RT_EOK == ret);
359 #endif /* BSP_USING_UI2C0 */
360
361 #if defined(BSP_USING_UI2C1)
362 SYS_UnlockReg();
363 SYS_ResetModule(USCI1_RST);
364 SYS_LockReg();
365
366 nu_ui2c1.ui2c_dev.ops = &nu_ui2c_ops;
367 UI2C_Open(nu_ui2c1.ui2c_base, 100000);
368 ret = rt_i2c_bus_device_register(&nu_ui2c1.ui2c_dev, nu_ui2c1.dev_name);
369 RT_ASSERT(RT_EOK == ret);
370 #endif /* BSP_USING_UI2C1 */
371
372 return ret;
373 }
374
375 INIT_DEVICE_EXPORT(rt_hw_ui2c_init);
376
377 #endif //#if defined(BSP_USING_UI2C)
378