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