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 * 2023-08-21 hywing The first version
9 */
10
11 #include <rtdevice.h>
12 #include "fsl_lpi2c.h"
13 #include "fsl_lpi2c_edma.h"
14 #include "fsl_edma.h"
15
16
17 #ifdef RT_USING_I2C
18
19 #define DBG_TAG "drv.i2c"
20 #define DBG_LVL DBG_INFO
21 #include <rtdbg.h>
22
23 enum
24 {
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
40 struct lpc_i2c_bus
41 {
42 struct rt_i2c_bus_device parent;
43 LPI2C_Type *I2C;
44 clock_attach_id_t clock_attach_id;
45 clock_div_name_t clock_div_name;
46 clock_name_t clock_src;
47 uint32_t baud;
48 char *name;
49 };
50
51
52 struct lpc_i2c_bus lpc_obj[] =
53 {
54 #ifdef BSP_USING_I2C0
55 {
56 .I2C = LPI2C0,
57 .baud = 100000U,
58 #if (defined(CPU_MCXA346VLH) || defined(CPU_MCXA346VLL) || defined(CPU_MCXA346VLQ) || defined(CPU_MCXA346VPN))
59 .clock_attach_id = kFRO_LF_DIV_to_LPI2C0,
60 #else
61 .clock_attach_id = kFRO12M_to_LPI2C0,
62 #endif
63 .clock_div_name = kCLOCK_DivLPI2C0,
64 .clock_src = kCLOCK_Fro12M,
65 .name = "i2c0",
66 },
67 #endif
68 #ifdef BSP_USING_I2C1
69 {
70 .I2C = LPI2C1,
71 .baud = 100000U,
72 #if (defined(CPU_MCXA346VLH) || defined(CPU_MCXA346VLL) || defined(CPU_MCXA346VLQ) || defined(CPU_MCXA346VPN))
73 .clock_attach_id = kFRO_LF_DIV_to_LPI2C1,
74 #else
75 .clock_attach_id = kFRO12M_to_LPI2C1,
76 #endif
77 .clock_div_name = kCLOCK_DivLPI2C1,
78 .clock_src = kCLOCK_Fro12M,
79 .name = "i2c1",
80 },
81 #endif
82 #ifdef BSP_USING_I2C2
83 {
84 .I2C = LPI2C2,
85 .baud = 100000U,
86 #if (defined(CPU_MCXA346VLH) || defined(CPU_MCXA346VLL) || defined(CPU_MCXA346VLQ) || defined(CPU_MCXA346VPN))
87 .clock_attach_id = kFRO_LF_DIV_to_LPI2C2,
88 #else
89 .clock_attach_id = kFRO12M_to_LPI2C2,
90 #endif
91 .clock_div_name = kCLOCK_DivLPI2C2,
92 .clock_src = kCLOCK_Fro12M,
93 .name = "i2c2",
94 },
95 #endif
96 #ifdef BSP_USING_I2C3
97 {
98 .I2C = LPI2C3,
99 .baud = 100000U,
100 #if (defined(CPU_MCXA346VLH) || defined(CPU_MCXA346VLL) || defined(CPU_MCXA346VLQ) || defined(CPU_MCXA346VPN))
101 .clock_attach_id = kFRO_LF_DIV_to_LPI2C3,
102 #else
103 .clock_attach_id = kFRO12M_to_LPI2C3,
104 #endif
105 .clock_div_name = kCLOCK_DivLPI2C3,
106 .clock_src = kCLOCK_Fro12M,
107 .name = "i2c3",
108 },
109 #endif
110 };
111
lpc_i2c_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)112 static rt_ssize_t lpc_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
113 {
114 struct rt_i2c_msg *msg;
115 lpi2c_master_transfer_t xfer = {0};
116 rt_uint32_t i;
117 rt_ssize_t ret = 0;
118
119 struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus *)bus;
120
121 for (i = 0; i < num; i++)
122 {
123 msg = &msgs[i];
124
125 if (msg->flags & RT_I2C_RD)
126 {
127 xfer.slaveAddress = msg->addr;
128 xfer.direction = kLPI2C_Read;
129 xfer.subaddress = 0;
130 xfer.subaddressSize = 0;
131 xfer.data = msg->buf;
132 xfer.dataSize = msg->len;
133 if(i != 0)
134 xfer.flags = kLPI2C_TransferRepeatedStartFlag;
135 else
136 xfer.flags = kLPI2C_TransferDefaultFlag;
137
138 if (LPI2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
139 {
140 LOG_D("i2c bus read failed!\n");
141 return i;
142 }
143 }
144 else
145 {
146 xfer.slaveAddress = msg->addr;
147 xfer.direction = kLPI2C_Write;
148 xfer.subaddress = 0;
149 xfer.subaddressSize = 0;
150 xfer.data = msg->buf;
151 xfer.dataSize = msg->len;
152 if(i == 0)
153 xfer.flags = kLPI2C_TransferNoStopFlag;
154 else
155 xfer.flags = kLPI2C_TransferDefaultFlag;
156
157 if (LPI2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
158 {
159 LOG_D("i2c bus write failed!\n");
160 return i;
161 }
162 }
163 }
164 ret = i;
165
166 return ret;
167 }
168
169 static const struct rt_i2c_bus_device_ops i2c_ops =
170 {
171 lpc_i2c_xfer,
172 RT_NULL,
173 RT_NULL
174 };
175
rt_hw_i2c_init(void)176 int rt_hw_i2c_init(void)
177 {
178 int i;
179 lpi2c_master_config_t masterConfig;
180
181 for(i=0; i<ARRAY_SIZE(lpc_obj); i++)
182 {
183 CLOCK_SetClockDiv(lpc_obj[i].clock_div_name, 1u);
184 CLOCK_AttachClk(lpc_obj[i].clock_attach_id);
185
186 LPI2C_MasterGetDefaultConfig(&masterConfig);
187 masterConfig.baudRate_Hz = lpc_obj[i].baud;
188
189 LPI2C_MasterInit(lpc_obj[i].I2C, &masterConfig, CLOCK_GetFreq(lpc_obj[i].clock_src));
190
191 lpc_obj[i].parent.ops = &i2c_ops;
192
193 rt_i2c_bus_device_register(&lpc_obj[i].parent, lpc_obj[i].name);
194 }
195
196 return RT_EOK;
197 }
198 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
199
200 #endif /* RT_USING_I2C */
201
202
203
204