1 /*
2 * Copyright (c) 2019, Henrik Brix Andersen <henrik@brixandersen.dk>
3 *
4 * Based on the i2c_mcux_lpi2c.c driver, which is:
5 * Copyright (c) 2016 Freescale Semiconductor, Inc.
6 * Copyright (c) 2019, NXP
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #define DT_DRV_COMPAT openisa_rv32m1_lpi2c
12
13 #include <drivers/i2c.h>
14 #include <drivers/clock_control.h>
15 #include <fsl_lpi2c.h>
16 #include <logging/log.h>
17 LOG_MODULE_REGISTER(rv32m1_lpi2c);
18
19 #include "i2c-priv.h"
20
21 struct rv32m1_lpi2c_config {
22 LPI2C_Type *base;
23 const struct device *clock_dev;
24 clock_control_subsys_t clock_subsys;
25 clock_ip_name_t clock_ip_name;
26 uint32_t clock_ip_src;
27 uint32_t bitrate;
28 void (*irq_config_func)(const struct device *dev);
29 };
30
31 struct rv32m1_lpi2c_data {
32 lpi2c_master_handle_t handle;
33 struct k_sem transfer_sync;
34 struct k_sem completion_sync;
35 status_t completion_status;
36 };
37
rv32m1_lpi2c_configure(const struct device * dev,uint32_t dev_config)38 static int rv32m1_lpi2c_configure(const struct device *dev,
39 uint32_t dev_config)
40 {
41 const struct rv32m1_lpi2c_config *config = dev->config;
42 uint32_t baudrate;
43 uint32_t clk_freq;
44 int err;
45
46 if (!(I2C_MODE_MASTER & dev_config)) {
47 /* Slave mode not supported - yet */
48 LOG_ERR("Slave mode not supported");
49 return -ENOTSUP;
50 }
51
52 if (I2C_ADDR_10_BITS & dev_config) {
53 /* FSL LPI2C driver only supports 7-bit addressing */
54 LOG_ERR("10 bit addressing not supported");
55 return -ENOTSUP;
56 }
57
58 switch (I2C_SPEED_GET(dev_config)) {
59 case I2C_SPEED_STANDARD:
60 baudrate = KHZ(100);
61 break;
62 case I2C_SPEED_FAST:
63 baudrate = KHZ(400);
64 break;
65 case I2C_SPEED_FAST_PLUS:
66 baudrate = MHZ(1);
67 break;
68 /* TODO: only if SCL pin implements current source pull-up */
69 /* case I2C_SPEED_HIGH: */
70 /* baudrate = KHZ(3400); */
71 /* break; */
72 /* TODO: ultra-fast requires pin_config setting */
73 /* case I2C_SPEED_ULTRA: */
74 /* baudrate = MHZ(5); */
75 /* break; */
76 default:
77 LOG_ERR("Unsupported speed");
78 return -ENOTSUP;
79 }
80
81 err = clock_control_get_rate(config->clock_dev, config->clock_subsys, &clk_freq);
82 if (err) {
83 LOG_ERR("Could not get clock frequency (err %d)", err);
84 return -EINVAL;
85 }
86
87 LPI2C_MasterSetBaudRate(config->base, clk_freq, baudrate);
88
89 return 0;
90 }
91
rv32m1_lpi2c_master_transfer_callback(LPI2C_Type * base,lpi2c_master_handle_t * handle,status_t completionStatus,void * userData)92 static void rv32m1_lpi2c_master_transfer_callback(LPI2C_Type *base,
93 lpi2c_master_handle_t *handle,
94 status_t completionStatus,
95 void *userData)
96 {
97 struct rv32m1_lpi2c_data *data = userData;
98
99 ARG_UNUSED(base);
100 ARG_UNUSED(handle);
101
102 data->completion_status = completionStatus;
103 k_sem_give(&data->completion_sync);
104 }
105
rv32m1_lpi2c_convert_flags(int msg_flags)106 static uint32_t rv32m1_lpi2c_convert_flags(int msg_flags)
107 {
108 uint32_t flags = 0U;
109
110 if (!(msg_flags & I2C_MSG_STOP)) {
111 flags |= kLPI2C_TransferNoStopFlag;
112 }
113
114 if (msg_flags & I2C_MSG_RESTART) {
115 flags |= kLPI2C_TransferRepeatedStartFlag;
116 }
117
118 return flags;
119 }
120
rv32m1_lpi2c_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)121 static int rv32m1_lpi2c_transfer(const struct device *dev,
122 struct i2c_msg *msgs,
123 uint8_t num_msgs, uint16_t addr)
124 {
125 const struct rv32m1_lpi2c_config *config = dev->config;
126 struct rv32m1_lpi2c_data *data = dev->data;
127 lpi2c_master_transfer_t transfer;
128 status_t status;
129 int ret = 0;
130
131 k_sem_take(&data->transfer_sync, K_FOREVER);
132
133 /* Iterate over all the messages */
134 for (int i = 0; i < num_msgs; i++) {
135 if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
136 ret = -ENOTSUP;
137 goto out;
138 }
139
140 /* Initialize the transfer descriptor */
141 transfer.flags = rv32m1_lpi2c_convert_flags(msgs->flags);
142
143 /* Prevent the controller to send a start condition between
144 * messages, except if explicitly requested.
145 */
146 if (i != 0 && !(msgs->flags & I2C_MSG_RESTART)) {
147 transfer.flags |= kLPI2C_TransferNoStartFlag;
148 }
149
150 transfer.slaveAddress = addr;
151 transfer.direction = (msgs->flags & I2C_MSG_READ)
152 ? kLPI2C_Read : kLPI2C_Write;
153 transfer.subaddress = 0;
154 transfer.subaddressSize = 0;
155 transfer.data = msgs->buf;
156 transfer.dataSize = msgs->len;
157
158 /* Start the transfer */
159 status = LPI2C_MasterTransferNonBlocking(config->base,
160 &data->handle,
161 &transfer);
162
163 /* Return an error if the transfer didn't start successfully
164 * e.g., if the bus was busy
165 */
166 if (status != kStatus_Success) {
167 LOG_DBG("Could not start transfer (status %d)", status);
168 ret = -EIO;
169 goto out;
170 }
171
172 /* Wait for the transfer to complete */
173 k_sem_take(&data->completion_sync, K_FOREVER);
174
175 /* Return an error if the transfer didn't complete
176 * successfully. e.g., nak, timeout, lost arbitration
177 */
178 if (data->completion_status != kStatus_Success) {
179 LOG_DBG("Transfer failed (status %d)",
180 data->completion_status);
181 LPI2C_MasterTransferAbort(config->base, &data->handle);
182 ret = -EIO;
183 goto out;
184 }
185
186 /* Move to the next message */
187 msgs++;
188 }
189
190 out:
191 k_sem_give(&data->transfer_sync);
192 return ret;
193 }
194
rv32m1_lpi2c_isr(const struct device * dev)195 static void rv32m1_lpi2c_isr(const struct device *dev)
196 {
197 const struct rv32m1_lpi2c_config *config = dev->config;
198 struct rv32m1_lpi2c_data *data = dev->data;
199
200 LPI2C_MasterTransferHandleIRQ(config->base, &data->handle);
201 }
202
rv32m1_lpi2c_init(const struct device * dev)203 static int rv32m1_lpi2c_init(const struct device *dev)
204 {
205 const struct rv32m1_lpi2c_config *config = dev->config;
206 struct rv32m1_lpi2c_data *data = dev->data;
207 lpi2c_master_config_t master_config;
208 uint32_t clk_freq, dev_cfg;
209 int err;
210
211 CLOCK_SetIpSrc(config->clock_ip_name, config->clock_ip_src);
212
213 err = clock_control_on(config->clock_dev, config->clock_subsys);
214 if (err) {
215 LOG_ERR("Could not turn on clock (err %d)", err);
216 return -EINVAL;
217 }
218
219 err = clock_control_get_rate(config->clock_dev, config->clock_subsys, &clk_freq);
220 if (err) {
221 LOG_ERR("Could not get clock frequency (err %d)", err);
222 return -EINVAL;
223 }
224
225 LPI2C_MasterGetDefaultConfig(&master_config);
226 LPI2C_MasterInit(config->base, &master_config, clk_freq);
227 LPI2C_MasterTransferCreateHandle(config->base, &data->handle,
228 rv32m1_lpi2c_master_transfer_callback,
229 data);
230
231 dev_cfg = i2c_map_dt_bitrate(config->bitrate);
232 err = rv32m1_lpi2c_configure(dev, dev_cfg | I2C_MODE_MASTER);
233 if (err) {
234 LOG_ERR("Could not configure controller (err %d)", err);
235 return err;
236 }
237
238 config->irq_config_func(dev);
239
240 return 0;
241 }
242
243 static const struct i2c_driver_api rv32m1_lpi2c_driver_api = {
244 .configure = rv32m1_lpi2c_configure,
245 .transfer = rv32m1_lpi2c_transfer,
246 };
247
248 #define RV32M1_LPI2C_DEVICE(id) \
249 static void rv32m1_lpi2c_irq_config_func_##id(const struct device *dev); \
250 static const struct rv32m1_lpi2c_config rv32m1_lpi2c_##id##_config = { \
251 .base = \
252 (LPI2C_Type *)DT_INST_REG_ADDR(id), \
253 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
254 .clock_subsys = \
255 (clock_control_subsys_t) DT_INST_CLOCKS_CELL(id, name),\
256 .clock_ip_name = INST_DT_CLOCK_IP_NAME(id), \
257 .clock_ip_src = kCLOCK_IpSrcFircAsync, \
258 .bitrate = DT_INST_PROP(id, clock_frequency), \
259 .irq_config_func = rv32m1_lpi2c_irq_config_func_##id, \
260 }; \
261 static struct rv32m1_lpi2c_data rv32m1_lpi2c_##id##_data = { \
262 .transfer_sync = Z_SEM_INITIALIZER( \
263 rv32m1_lpi2c_##id##_data.transfer_sync, 1, 1), \
264 .completion_sync = Z_SEM_INITIALIZER( \
265 rv32m1_lpi2c_##id##_data.completion_sync, 0, 1), \
266 }; \
267 DEVICE_DT_INST_DEFINE(id, \
268 &rv32m1_lpi2c_init, \
269 NULL, \
270 &rv32m1_lpi2c_##id##_data, \
271 &rv32m1_lpi2c_##id##_config, \
272 POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \
273 &rv32m1_lpi2c_driver_api); \
274 static void rv32m1_lpi2c_irq_config_func_##id(const struct device *dev) \
275 { \
276 IRQ_CONNECT(DT_INST_IRQN(id), \
277 0, \
278 rv32m1_lpi2c_isr, DEVICE_DT_INST_GET(id), \
279 0); \
280 irq_enable(DT_INST_IRQN(id)); \
281 } \
282
283 DT_INST_FOREACH_STATUS_OKAY(RV32M1_LPI2C_DEVICE)
284