1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-01-13 Lyons first version
9 * 2021-06-23 RiceChen refactor
10 */
11
12 #include <rthw.h>
13 #include <rtdevice.h>
14
15 #ifdef BSP_USING_I2C
16
17 #define LOG_TAG "drv.i2c"
18 #include <drv_log.h>
19
20 #if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) && !defined(BSP_USING_I2C4)
21 #error "Please define at least one BSP_USING_I2Cx"
22 #endif
23
24 #include "fsl_iomuxc.h"
25 #include "drv_i2c.h"
26
27 static struct imx6ull_i2c_config i2c_config[] =
28 {
29 #ifdef BSP_USING_I2C1
30 I2C1_BUS_CONFIG,
31 #endif
32 #ifdef BSP_USING_I2C2
33 I2C2_BUS_CONFIG,
34 #endif
35 #ifdef BSP_USING_I2C3
36 I2C3_BUS_CONFIG,
37 #endif
38 #ifdef BSP_USING_I2C4
39 I2C4_BUS_CONFIG,
40 #endif
41 };
42
43 static struct imx6ull_i2c_bus i2c_obj[sizeof(i2c_config) / sizeof(i2c_config[0])];
44 static char i2c_buff_temp[4][1024];
45 extern uint32_t I2C_GetInstance(I2C_Type *base);
46
47 #ifdef IMX_I2C_IRQ_MODE
48 static uint32_t g_MasterCompletionFlag[4] = {0,0,0,0};
i2c_master_callback(I2C_Type * base,i2c_master_handle_t * handle,status_t status,void * userData)49 static void i2c_master_callback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData)
50 {
51 /* Signal transfer success when received success status. */
52 struct imx6ull_i2c_config *config;
53
54 config = (struct imx6ull_i2c_config*)userData;
55
56 uint32_t instance = I2C_GetInstance(config->hw_base);
57 if (status == kStatus_Success)
58 {
59 g_MasterCompletionFlag[instance-1] = 1;
60 }
61 }
62 #endif
63
imx6ull_i2c_mst_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)64 static rt_ssize_t imx6ull_i2c_mst_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
65 {
66 rt_ssize_t i = 0;
67 struct imx6ull_i2c_bus *i2c_bus = RT_NULL;
68 static i2c_master_transfer_t xfer = {0};
69 RT_ASSERT(bus != RT_NULL);
70 #ifdef IMX_I2C_IRQ_MODE
71 uint32_t timeout_cnt = 100;
72 #endif
73 uint32_t instance = 0;
74
75 i2c_bus = (struct imx6ull_i2c_bus *)bus;
76 instance = I2C_GetInstance(i2c_bus->config->hw_base);
77 for(i = 0 ;i < num; i++)
78 {
79 if(msgs[i].flags & RT_I2C_RD)
80 {
81 xfer.flags = kI2C_TransferNoStartFlag;
82 xfer.slaveAddress = msgs[i].addr;
83 xfer.direction = kI2C_Read;
84 xfer.subaddress = 0;
85 xfer.subaddressSize = 0;
86 xfer.data = (uint8_t *volatile)i2c_buff_temp[instance - 1];
87 xfer.dataSize = msgs[i].len ;
88
89 #ifdef IMX_I2C_IRQ_MODE
90 I2C_MasterTransferNonBlocking(i2c_bus->config->I2C, &i2c_bus->config->master_handle,&xfer);
91 while(!g_MasterCompletionFlag[instance - 1])
92 {
93 rt_thread_delay(1);
94 timeout_cnt--;
95 if(timeout_cnt == 0)
96 {
97 break;
98 }
99 }
100 timeout_cnt = 100;
101 g_MasterCompletionFlag[instance - 1] = 0;
102 #else
103 I2C_MasterTransferBlocking(i2c_bus->config->I2C, &xfer);
104 #endif
105 rt_memcpy(msgs[i].buf,i2c_buff_temp[instance - 1],msgs[i].len);
106 }
107 else
108 {
109 xfer.flags = kI2C_TransferNoStartFlag;
110 xfer.slaveAddress = msgs[i].addr;
111 xfer.direction = kI2C_Write;
112 xfer.subaddress = 0;
113 xfer.subaddressSize = 0;
114 xfer.data = (uint8_t *volatile)i2c_buff_temp[instance - 1];
115 xfer.dataSize = msgs[i].len;
116 rt_memcpy(i2c_buff_temp[instance - 1],msgs[i].buf,msgs[i].len);
117
118 #ifdef IMX_I2C_IRQ_MODE
119 I2C_MasterTransferNonBlocking(i2c_bus->config->I2C, &i2c_bus->config->master_handle,&xfer);
120 while(!g_MasterCompletionFlag[instance - 1])
121 {
122 timeout_cnt--;
123 rt_thread_delay(1);
124 if(timeout_cnt == 0)
125 {
126 break;
127 }
128 }
129 timeout_cnt = 100;
130 g_MasterCompletionFlag[instance - 1] = 0;
131 #else
132 I2C_MasterTransferBlocking(i2c_bus->config->I2C, &xfer);
133 #endif
134 }
135 }
136
137 return i;
138 }
139
imx6ull_i2c_bus_control(struct rt_i2c_bus_device * bus,rt_uint32_t cmd,rt_uint32_t arg)140 static rt_err_t imx6ull_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t cmd, rt_uint32_t arg)
141 {
142 return RT_EOK;
143 }
144
imx6ull_i2c_gpio_init(struct imx6ull_i2c_bus * bus)145 static rt_err_t imx6ull_i2c_gpio_init(struct imx6ull_i2c_bus *bus)
146 {
147 struct imx6ull_i2c_bus *i2c_bus = RT_NULL;
148
149 i2c_bus = (struct imx6ull_i2c_bus *)bus;
150
151 imx6ull_gpio_init(&i2c_bus->config->scl_gpio);
152 imx6ull_gpio_init(&i2c_bus->config->sda_gpio);
153 return RT_EOK;
154
155 }
156
157 #ifdef RT_USING_DEVICE_OPS
158 static const struct rt_i2c_bus_device_ops imx6ull_i2c_ops =
159 {
160 .master_xfer = imx6ull_i2c_mst_xfer,
161 .slave_xfer = RT_NULL,
162 .i2c_bus_control = imx6ull_i2c_bus_control,
163 };
164 #endif
165
166 extern void I2C_DriverIRQHandler(int irq, void *base);
rt_hw_i2c_init(void)167 int rt_hw_i2c_init(void)
168 {
169 rt_uint16_t obj_num = 0;
170 rt_uint32_t src_clock;
171 i2c_master_config_t masterConfig = {0};
172
173 obj_num = sizeof(i2c_config) / sizeof(i2c_config[0]);
174
175 src_clock = (CLOCK_GetFreq(kCLOCK_IpgClk) / (CLOCK_GetDiv(kCLOCK_PerclkDiv) + 1U));
176
177 for(int i = 0; i < obj_num; i++)
178 {
179 i2c_obj[i].config = &i2c_config[i];
180 i2c_obj[i].config->hw_base = i2c_obj[i].config->I2C;
181 i2c_obj[i].config->I2C = (I2C_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)i2c_obj[i].config->hw_base);
182 i2c_obj[i].parent.ops = &imx6ull_i2c_ops;
183 imx6ull_i2c_gpio_init(&i2c_obj[i]);
184
185 I2C_MasterGetDefaultConfig(&masterConfig);
186 masterConfig.baudRate_Bps = i2c_config[i].baud_rate;
187
188 CLOCK_EnableClock(i2c_obj[i].config->clk_ip_name);
189
190 I2C_MasterInit(i2c_obj[i].config->I2C, &masterConfig, src_clock);
191
192 rt_i2c_bus_device_register(&i2c_obj[i].parent, i2c_obj[i].config->name);
193
194 #ifdef IMX_I2C_IRQ_MODE
195 I2C_MasterTransferCreateHandle(i2c_obj[i].config->hw_base, &i2c_obj[i].config->master_handle, i2c_master_callback, i2c_obj[i].config);
196 rt_hw_interrupt_install(i2c_obj[i].config->irq_num, (rt_isr_handler_t)I2C_DriverIRQHandler, i2c_obj[i].config, i2c_obj[i].config->name);
197 #endif
198 }
199
200 return RT_EOK;
201 }
202 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
203
204 #endif
205