1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-01-20     wirano       first version
9  */
10 
11 
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include <rtdbg.h>
15 
16 #ifdef BSP_USING_I2C
17 
18 #if defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3)
19 
20 #include "drv_i2c.h"
21 #include "inc/hw_memmap.h"
22 #include "i2c_config.h"
23 
24 enum {
25 #ifdef BSP_USING_I2C0
26     I2C0_INDEX,
27 #endif
28 #ifdef BSP_USING_I2C1
29     I2C1_INDEX,
30 #endif
31 #ifdef BSP_USING_I2C2
32     I2C2_INDEX,
33 #endif
34 #ifdef BSP_USING_I2C3
35     I2C3_INDEX,
36 #endif
37 };
38 
39 static struct tm4c123_i2c tm4c123_i2cs[] =
40         {
41 #ifdef BSP_USING_I2C0
42                 I2C0_BUS_CONFIG,
43 #endif
44 
45 #ifdef BSP_USING_I2C1
46                 I2C1_BUS_CONFIG,
47 #endif
48 
49 #ifdef BSP_USING_I2C2
50                 I2C2_BUS_CONFIG,
51 #endif
52 
53 #ifdef BSP_USING_I2C3
54                 I2C3_BUS_CONFIG,
55 #endif
56         };
57 
58 
59 static rt_ssize_t tm4c123_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
60 
61 
62 struct rt_i2c_bus_device_ops tm4c123_i2c_ops =
63         {
64                 tm4c123_i2c_xfer,
65                 RT_NULL,
66                 RT_NULL
67         };
68 
69 
tm4c123_i2c_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)70 static rt_ssize_t tm4c123_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) {
71     RT_ASSERT(bus != RT_NULL);
72     RT_ASSERT(msgs != RT_NULL);
73 
74     struct rt_i2c_msg *msg;
75     struct tm4c123_i2c *i2c_info = (struct tm4c123_i2c *) bus;
76 
77     rt_err_t ret = -RT_ERROR;
78     rt_uint32_t i;
79 
80     for (i = 0; i < num; i++) {
81         msg = &msgs[i];
82 
83         if (msg->flags & RT_I2C_ADDR_10BIT) {
84             LOG_E("does not support 10bits address!\n");
85         }
86 
87         if (msg->flags & RT_I2C_RD) {
88             rt_uint8_t *data = msg->buf;
89 
90             ROM_I2CMasterSlaveAddrSet(i2c_info->base, msg->addr, true);
91 
92             if (msg->flags & RT_I2C_NO_START) {
93                 ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
94                 while (ROM_I2CMasterBusy(i2c_info->base));
95                 *data = ROM_I2CMasterDataGet(i2c_info->base);
96             } else {
97                 ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_START);
98                 while (ROM_I2CMasterBusy(i2c_info->base));
99                 *data = ROM_I2CMasterDataGet(i2c_info->base);
100             }
101 
102             if (msg->len > 1) {
103                 data++;
104 
105                 for (int j = 1; j < msg->len - 1; ++j) {
106 
107                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
108                     while (ROM_I2CMasterBusy(i2c_info->base));
109                     *data = ROM_I2CMasterDataGet(i2c_info->base);
110                     data++;
111                 }
112 
113                 if (msg->flags & RT_I2C_NO_STOP) {
114                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
115                     while (ROM_I2CMasterBusy(i2c_info->base));
116                     *data = ROM_I2CMasterDataGet(i2c_info->base);
117                 } else {
118                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
119                     while (ROM_I2CMasterBusy(i2c_info->base));
120                     *data = ROM_I2CMasterDataGet(i2c_info->base);
121                 }
122             }
123         } else {
124             rt_uint8_t *data = msg->buf;
125 
126             ROM_I2CMasterSlaveAddrSet(i2c_info->base, msg->addr, false);
127 
128             // use single send when data len = 1
129             if (msg->len == 1) {
130                 if (msg->flags & RT_I2C_NO_START) {
131                     ROM_I2CMasterDataPut(i2c_info->base, *data);
132                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT);
133                 } else if (msg->flags & RT_I2C_NO_STOP) {
134                     ROM_I2CMasterDataPut(i2c_info->base, *data);
135                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT);
136                 } else {
137                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_SINGLE_SEND);
138                     ROM_I2CMasterDataPut(i2c_info->base, *data);
139                 }
140                 while (ROM_I2CMasterBusy(i2c_info->base));
141             // otherwise use burst send
142             } else {
143                 if (msg->flags & RT_I2C_NO_START) {
144                     ROM_I2CMasterDataPut(i2c_info->base, *data);
145                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT);
146                     while (ROM_I2CMasterBusy(i2c_info->base));
147                 } else {
148                     ROM_I2CMasterDataPut(i2c_info->base, *data);
149                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_START);
150                     while (ROM_I2CMasterBusy(i2c_info->base));
151                 }
152 
153                 data++;
154 
155                 for (int j = 1; j < msg->len - 1; ++j) {
156                     ROM_I2CMasterDataPut(i2c_info->base, *data);
157                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT);
158                     while (ROM_I2CMasterBusy(i2c_info->base));
159                     data++;
160                 }
161 
162                 if (msg->flags & RT_I2C_NO_STOP) {
163                     ROM_I2CMasterDataPut(i2c_info->base, *data);
164                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT);
165                 } else {
166                     ROM_I2CMasterDataPut(i2c_info->base, *data);
167                     ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_FINISH);
168                 }
169                 while (ROM_I2CMasterBusy(i2c_info->base));
170             }
171 
172         }
173     }
174     ret = i;
175     return ret;
176 }
177 
rt_hw_i2c_init(void)178 int rt_hw_i2c_init(void) {
179     rt_err_t ret = RT_EOK;
180 
181     i2c_hw_config();
182 
183     for (uint32_t i = 0; i < sizeof(tm4c123_i2cs) / sizeof(tm4c123_i2cs[0]); i++) {
184         if (tm4c123_i2cs[i].clk_freq == 400000) {
185             ROM_I2CMasterInitExpClk(tm4c123_i2cs[i].base, ROM_SysCtlClockGet(), RT_TRUE);
186         } else {
187             ROM_I2CMasterInitExpClk(tm4c123_i2cs[i].base, ROM_SysCtlClockGet(), RT_FALSE);
188         }
189         ROM_I2CMasterEnable(tm4c123_i2cs[i].base);
190 
191         tm4c123_i2cs[i].bus.ops = &tm4c123_i2c_ops;
192         ret = rt_i2c_bus_device_register(&tm4c123_i2cs[i].bus, tm4c123_i2cs[i].bus_name);
193         if (ret != RT_EOK) {
194             LOG_E("rt i2c device %s register failed, status=%d\n", tm4c123_i2cs[i].bus_name, ret);
195         }
196     }
197 
198     return ret;
199 }
200 
201 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
202 
203 #endif /* BSP_USING_I2C1 || BSP_USING_I2C2 || BSP_USING_I2C3 || BSP_USING_I2C4 */
204 
205 #endif /* BSP_USING_I2C */
206 
207