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