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