1 /*
2 * Copyright (c) 2022-2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <rtthread.h>
9 #include <rtdevice.h>
10 #include <rtdbg.h>
11 #ifdef BSP_USING_I2C
12 #include "drv_i2c.h"
13 #include "hpm_i2c_drv.h"
14 #include "hpm_dma_mgr.h"
15 #include "hpm_dmamux_drv.h"
16 #include "hpm_l1c_drv.h"
17 #include "board.h"
18
19
20 #ifdef RT_USING_I2C
21
22 #define HPM_RTT_DRV_RETRY_TIMEOUT (1000000)
23
24 #ifndef HPM_I2C_DRV_DEFAULT_RETRY_COUNT
25 #define HPM_I2C_DRV_DEFAULT_RETRY_COUNT (5000U)
26 #endif
27
28 struct hpm_i2c
29 {
30 struct rt_i2c_bus_device bus;
31 I2C_Type *base;
32 clock_name_t clk_name;
33 char *bus_name;
34 rt_sem_t xfer_sem;
35 rt_bool_t enable_dma;
36 rt_uint8_t dmamux;
37 dma_resource_t dma;
38 rt_uint8_t i2c_irq;
39 rt_uint8_t is_read;
40 };
41
42 static struct hpm_i2c hpm_i2cs[] =
43 {
44 #if defined(BSP_USING_I2C0)
45 {
46 .base = HPM_I2C0,
47 .bus_name = "i2c0",
48 .clk_name = clock_i2c0,
49 #if defined(BSP_I2C0_USING_DMA)
50 .enable_dma = RT_TRUE,
51 #endif
52 .dmamux = HPM_DMA_SRC_I2C0,
53 .i2c_irq = IRQn_I2C0,
54 },
55 #endif
56 #if defined(BSP_USING_I2C1)
57 {
58 .base = HPM_I2C1,
59 .bus_name = "i2c1",
60 .clk_name = clock_i2c1,
61 #if defined(BSP_I2C1_USING_DMA)
62 .enable_dma = RT_TRUE,
63 #endif
64 .dmamux = HPM_DMA_SRC_I2C1,
65 .i2c_irq = IRQn_I2C1,
66 },
67 #endif
68 #if defined(BSP_USING_I2C2)
69 {
70 .base = HPM_I2C2,
71 .bus_name = "i2c2",
72 .clk_name = clock_i2c2,
73 #if defined(BSP_I2C2_USING_DMA)
74 .enable_dma = RT_TRUE,
75 #endif
76 .dmamux = HPM_DMA_SRC_I2C2,
77 .i2c_irq = IRQn_I2C2,
78 },
79 #endif
80 #if defined(BSP_USING_I2C3)
81 {
82 .base = HPM_I2C3,
83 .bus_name = "i2c3",
84 .clk_name = clock_i2c3,
85 #if defined(BSP_I2C3_USING_DMA)
86 .enable_dma = RT_TRUE,
87 #endif
88 .dmamux = HPM_DMA_SRC_I2C3,
89 .i2c_irq = IRQn_I2C3,
90 },
91 #endif
92 };
93 static hpm_stat_t i2c_transfer(I2C_Type *ptr, const uint16_t device_address,
94 uint8_t *buf, const uint32_t size, uint16_t flags);
95 static rt_ssize_t hpm_i2c_master_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
96 static hpm_stat_t i2c_tx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t src, uint32_t size);
97 static hpm_stat_t i2c_rx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t dst, uint32_t size);
98
99 struct rt_i2c_bus_device_ops hpm_i2c_ops =
100 {
101 hpm_i2c_master_transfer,
102 RT_NULL,
103 RT_NULL
104 };
105
handle_i2c_isr(I2C_Type * ptr)106 static inline void handle_i2c_isr(I2C_Type *ptr)
107 {
108 volatile uint32_t irq_status;
109 RT_ASSERT(ptr != RT_NULL);
110 rt_base_t level;
111 level = rt_hw_interrupt_disable();
112 irq_status = i2c_get_status(ptr);
113 if (irq_status & I2C_EVENT_TRANSACTION_COMPLETE)
114 {
115 for (uint32_t i = 0; i < sizeof(hpm_i2cs) / sizeof(hpm_i2cs[0]); i++)
116 {
117 if (hpm_i2cs[i].base == ptr)
118 {
119 rt_sem_release(hpm_i2cs[i].xfer_sem);
120 }
121 }
122 i2c_disable_irq(ptr, I2C_EVENT_TRANSACTION_COMPLETE);
123 i2c_clear_status(ptr, I2C_EVENT_TRANSACTION_COMPLETE);
124 }
125 rt_hw_interrupt_enable(level);
126 }
127
128 #if defined(BSP_USING_I2C0)
i2c0_isr(void)129 void i2c0_isr(void)
130 {
131 handle_i2c_isr(HPM_I2C0);
132 }
133 SDK_DECLARE_EXT_ISR_M(IRQn_I2C0, i2c0_isr);
134 #endif
135
136 #if defined(BSP_USING_I2C1)
i2c1_isr(void)137 void i2c1_isr(void)
138 {
139 handle_i2c_isr(HPM_I2C1);
140 }
141 SDK_DECLARE_EXT_ISR_M(IRQn_I2C1, i2c1_isr);
142 #endif
143
144 #if defined(BSP_USING_I2C2)
i2c2_isr(void)145 void i2c2_isr(void)
146 {
147 handle_i2c_isr(HPM_I2C2);
148 }
149 SDK_DECLARE_EXT_ISR_M(IRQn_I2C2, i2c2_isr);
150 #endif
151
152 #if defined(BSP_USING_I2C3)
i2c3_isr(void)153 void i2c3_isr(void)
154 {
155 handle_i2c_isr(HPM_I2C3);
156 }
157 SDK_DECLARE_EXT_ISR_M(IRQn_I2C3, i2c3_isr);
158 #endif
159
i2c_tx_trigger_dma(DMA_Type * dma_ptr,uint8_t ch_num,I2C_Type * i2c_ptr,uint32_t src,uint32_t size)160 static hpm_stat_t i2c_tx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t src, uint32_t size)
161 {
162 dma_handshake_config_t config;
163
164 dma_default_handshake_config(dma_ptr, &config);
165 config.ch_index = ch_num;
166 config.dst = (uint32_t)&i2c_ptr->DATA;
167 config.dst_fixed = true;
168 config.src = src;
169 config.src_fixed = false;
170 config.data_width = DMA_TRANSFER_WIDTH_BYTE;
171 config.size_in_byte = size;
172
173 return dma_setup_handshake(dma_ptr, &config, true);
174 }
175
i2c_rx_trigger_dma(DMA_Type * dma_ptr,uint8_t ch_num,I2C_Type * i2c_ptr,uint32_t dst,uint32_t size)176 static hpm_stat_t i2c_rx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t dst, uint32_t size)
177 {
178 dma_handshake_config_t config;
179
180 dma_default_handshake_config(dma_ptr, &config);
181 config.ch_index = ch_num;
182 config.dst = dst;
183 config.dst_fixed = false;
184 config.src = (uint32_t)&i2c_ptr->DATA;
185 config.src_fixed = true;
186 config.data_width = DMA_TRANSFER_WIDTH_BYTE;
187 config.size_in_byte = size;
188
189 return dma_setup_handshake(dma_ptr, &config, true);
190 }
191
i2c_dma_channel_tc_callback(DMA_Type * ptr,uint32_t channel,void * user_data)192 void i2c_dma_channel_tc_callback(DMA_Type *ptr, uint32_t channel, void *user_data)
193 {
194 struct hpm_i2c *i2c = (struct hpm_i2c *)user_data;
195 RT_ASSERT(i2c != RT_NULL);
196 RT_ASSERT(ptr != RT_NULL);
197 rt_base_t level;
198 level = rt_hw_interrupt_disable();
199 if ((i2c->dma.base == ptr) && i2c->dma.channel == channel)
200 {
201 dma_mgr_disable_chn_irq(&i2c->dma, DMA_MGR_INTERRUPT_MASK_TC);
202 if (i2c->is_read == true)
203 {
204 rt_sem_release(i2c->xfer_sem);
205 }
206 }
207 rt_hw_interrupt_enable(level);
208 }
209
hpm_i2c_master_transfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)210 static rt_ssize_t hpm_i2c_master_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
211 {
212 RT_ASSERT(bus != RT_NULL);
213 RT_ASSERT(msgs != RT_NULL);
214
215 struct rt_i2c_msg *msg;
216 struct hpm_i2c *i2c_info = (struct hpm_i2c *)bus;
217
218 hpm_stat_t i2c_stat = status_success;
219 rt_size_t ret = 0;
220 rt_uint32_t i;
221 rt_uint8_t *raw_alloc_buf = RT_NULL;
222 rt_uint8_t *aligned_buf = RT_NULL;
223 rt_uint8_t *dummy_buf = RT_NULL;
224 rt_uint32_t aligned_len = 0;
225 rt_uint32_t remaining_size = 0;
226 rt_uint32_t transfer_len;
227 for (i = 0; i < num; i++)
228 {
229 msg = &msgs[i];
230 remaining_size = msg->len;
231 if ((msg->len > 0) && (i2c_info->enable_dma))
232 {
233 aligned_len = (msg->len + HPM_L1C_CACHELINE_SIZE - 1U) & ~(HPM_L1C_CACHELINE_SIZE - 1U);
234 if (l1c_dc_is_enabled())
235 {
236 if (msg->flags & RT_I2C_RD)
237 {
238 /* The allocated pointer is always RT_ALIGN_SIZE aligned */
239 raw_alloc_buf = (uint8_t*)rt_malloc(aligned_len + HPM_L1C_CACHELINE_SIZE - RT_ALIGN_SIZE);
240 RT_ASSERT(raw_alloc_buf != RT_NULL);
241 }
242 else
243 {
244 aligned_buf = (uint8_t*)HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)raw_alloc_buf);
245 /* The allocated pointer is always RT_ALIGN_SIZE aligned */
246 raw_alloc_buf = (uint8_t*)rt_malloc(aligned_len + HPM_L1C_CACHELINE_SIZE - RT_ALIGN_SIZE);
247 RT_ASSERT(raw_alloc_buf != RT_NULL);
248 aligned_buf = (uint8_t*)HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)raw_alloc_buf);
249 rt_memcpy(aligned_buf, msg->buf, msg->len);
250 l1c_dc_flush((uint32_t)aligned_buf, aligned_len);
251 }
252 }
253 }
254 else
255 {
256 aligned_buf = (uint8_t*) msg->buf;
257 }
258
259 if (msg->flags & RT_I2C_ADDR_10BIT)
260 {
261 i2c_enable_10bit_address_mode(i2c_info->base, true);
262 }
263 else
264 {
265 i2c_enable_10bit_address_mode(i2c_info->base, false);
266 }
267 dummy_buf = aligned_buf;
268 if (msg->flags & RT_I2C_RD)
269 {
270 /* maybe probe i2c device */
271 if (msg->len == 0)
272 {
273 i2c_stat = i2c_master_read(i2c_info->base, msg->addr, dummy_buf, remaining_size);
274 }
275 else
276 {
277 while (remaining_size)
278 {
279 transfer_len = MIN(I2C_SOC_TRANSFER_COUNT_MAX, remaining_size);
280 if ((i2c_info->enable_dma))
281 {
282 /* sequential transfer now is not support dma */
283 if ((msg->flags & RT_I2C_NO_START) || (msg->flags & RT_I2C_NO_STOP) ||
284 (msg->flags & RT_I2C_NO_READ_ACK) || (msg->flags & RT_I2C_NO_READ_ACK) ) {
285 i2c_stat = status_invalid_argument;
286 break;
287 }
288 i2c_info->is_read = true;
289 i2c_enable_irq(i2c_info->base, I2C_EVENT_TRANSACTION_COMPLETE);
290 dmamux_config(HPM_DMAMUX, i2c_info->dma.channel, i2c_info->dmamux, true);
291 i2c_stat = i2c_rx_trigger_dma(i2c_info->dma.base, i2c_info->dma.channel, i2c_info->base,
292 core_local_mem_to_sys_address(0, (uint32_t) dummy_buf), transfer_len);
293 if (i2c_stat != status_success)
294 {
295 break;
296 }
297 i2c_stat = i2c_master_start_dma_read(i2c_info->base, msg->addr, msg->len);
298 if (i2c_stat != status_success)
299 {
300 break;
301 }
302 rt_sem_take(i2c_info->xfer_sem, RT_WAITING_FOREVER);
303 }
304 else
305 {
306 i2c_master_transfer(i2c_info->base, msg->addr, dummy_buf, transfer_len, msg->flags);
307 }
308 dummy_buf += transfer_len;
309 remaining_size -= transfer_len;
310 }
311 if (raw_alloc_buf != RT_NULL)
312 {
313 l1c_dc_invalidate((uint32_t) aligned_buf, aligned_len);
314 rt_memcpy(msg->buf, aligned_buf, msg->len);
315 rt_free(raw_alloc_buf);
316 raw_alloc_buf = RT_NULL;
317 aligned_buf = RT_NULL;
318 }
319 }
320 }
321 else
322 {
323 /* maybe probe i2c device */
324 if (msg->len == 0)
325 {
326 i2c_stat = i2c_master_write(i2c_info->base, msg->addr, dummy_buf, remaining_size);
327 }
328 else
329 {
330 while (remaining_size)
331 {
332 transfer_len = MIN(I2C_SOC_TRANSFER_COUNT_MAX, remaining_size);
333 if (i2c_info->enable_dma)
334 {
335 /* sequential transfer now is not support dma */
336 if ((msg->flags & RT_I2C_NO_START) || (msg->flags & RT_I2C_NO_STOP) ||
337 (msg->flags & RT_I2C_NO_READ_ACK) || (msg->flags & RT_I2C_NO_READ_ACK) ) {
338 i2c_stat = status_invalid_argument;
339 break;
340 }
341 i2c_info->is_read = false;
342 i2c_enable_irq(i2c_info->base, I2C_EVENT_TRANSACTION_COMPLETE);
343 dmamux_config(HPM_DMAMUX, i2c_info->dma.channel, i2c_info->dmamux, true);
344 i2c_stat = i2c_tx_trigger_dma(i2c_info->dma.base, i2c_info->dma.channel, i2c_info->base,
345 core_local_mem_to_sys_address(0, (uint32_t) dummy_buf), transfer_len);
346 if (i2c_stat != status_success)
347 {
348 break;
349 }
350 i2c_stat = i2c_master_start_dma_write(i2c_info->base, msg->addr, msg->len);
351 if (i2c_stat != status_success)
352 {
353 break;
354 }
355 rt_sem_take(i2c_info->xfer_sem, RT_WAITING_FOREVER);
356 }
357 else
358 {
359 i2c_master_transfer(i2c_info->base, msg->addr, dummy_buf, transfer_len, msg->flags);
360 }
361 dummy_buf += transfer_len;
362 remaining_size -= transfer_len;
363 }
364 if (raw_alloc_buf != RT_NULL)
365 {
366 rt_free(raw_alloc_buf);
367 raw_alloc_buf = RT_NULL;
368 aligned_buf = RT_NULL;
369 }
370 }
371 }
372 if (i2c_stat != status_success)
373 {
374 break;
375 }
376 }
377
378 if (i2c_stat != status_success)
379 {
380 return ret;
381 }
382
383 ret = i;
384 return ret;
385 }
386
387
rt_hw_i2c_init(void)388 int rt_hw_i2c_init(void)
389 {
390 rt_err_t ret = RT_EOK;
391 hpm_stat_t stat;
392 i2c_config_t config;
393 rt_uint32_t freq;
394 char sem_name[RT_NAME_MAX];
395
396 for (uint32_t i = 0; i < sizeof(hpm_i2cs) / sizeof(hpm_i2cs[0]); i++) {
397 init_i2c_pins(hpm_i2cs[i].base);
398 clock_add_to_group(hpm_i2cs[i].clk_name, 0);
399 clock_set_source_divider(hpm_i2cs[i].clk_name, clk_src_osc24m, 1U);
400
401 config.i2c_mode = i2c_mode_normal;
402 config.is_10bit_addressing = false;
403 freq = clock_get_frequency(hpm_i2cs[i].clk_name);
404 stat = i2c_init_master(hpm_i2cs[i].base, freq, &config);
405 if (stat != status_success) {
406 LOG_E("rt i2c device %s init failed", hpm_i2cs[i].bus_name);
407 }
408
409 hpm_i2cs[i].bus.ops = &hpm_i2c_ops;
410 if (hpm_i2cs[i].enable_dma)
411 {
412 stat = dma_mgr_request_resource(&hpm_i2cs[i].dma);
413 if (stat != status_success)
414 {
415 return -RT_ERROR;
416 }
417 dma_mgr_install_chn_tc_callback(&hpm_i2cs[i].dma, i2c_dma_channel_tc_callback, (void *)&hpm_i2cs[i]);
418 dma_mgr_enable_dma_irq_with_priority(&hpm_i2cs[i].dma, 1);
419 intc_m_enable_irq_with_priority(hpm_i2cs[i].i2c_irq, 2);
420 i2c_disable_irq(hpm_i2cs[i].base, I2C_EVENT_TRANSACTION_COMPLETE);
421 rt_sprintf(sem_name, "%s_s", hpm_i2cs[i].bus_name);
422 hpm_i2cs[i].xfer_sem = rt_sem_create(sem_name, 0, RT_IPC_FLAG_PRIO);
423 if (hpm_i2cs[i].xfer_sem == RT_NULL)
424 {
425 ret = RT_ENOMEM;
426 break;
427 }
428 }
429 ret = rt_i2c_bus_device_register(&hpm_i2cs[i].bus, hpm_i2cs[i].bus_name);
430 if (ret != RT_EOK) {
431 LOG_E("rt i2c device %s register failed, status=%d\n", hpm_i2cs[i].bus_name, ret);
432 }
433 }
434
435 return ret;
436 }
437 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
438
439 #endif /* RT_USING_I2C */
440
441 #endif /*BSP_USING_I2C*/
442
443