1 /*
2  * Copyright (c) 2020, Seagate Technology LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_lpc11u6x_i2c
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/irq.h>
13 #include "i2c_lpc11u6x.h"
14 
15 #define DEV_BASE(dev) (((struct lpc11u6x_i2c_config *)(dev->config))->base)
16 
lpc11u6x_i2c_set_bus_speed(const struct lpc11u6x_i2c_config * cfg,const struct device * clk_dev,uint32_t speed)17 static void lpc11u6x_i2c_set_bus_speed(const struct lpc11u6x_i2c_config *cfg,
18 				       const struct device *clk_dev,
19 				       uint32_t speed)
20 {
21 	uint32_t clk, div;
22 
23 	clock_control_get_rate(clk_dev, (clock_control_subsys_t) cfg->clkid,
24 			       &clk);
25 	div = clk / speed;
26 
27 	cfg->base->sclh = div / 2;
28 	cfg->base->scll = div - (div / 2);
29 }
30 
lpc11u6x_i2c_configure(const struct device * dev,uint32_t dev_config)31 static int lpc11u6x_i2c_configure(const struct device *dev,
32 				  uint32_t dev_config)
33 {
34 	const struct lpc11u6x_i2c_config *cfg = dev->config;
35 	struct lpc11u6x_i2c_data *data = dev->data;
36 	uint32_t speed;
37 	int ret;
38 	uint8_t mux_selection = PINCTRL_STATE_DEFAULT;
39 
40 	switch (I2C_SPEED_GET(dev_config)) {
41 	case I2C_SPEED_STANDARD:
42 		speed = 100000;
43 		break;
44 	case I2C_SPEED_FAST:
45 		speed = 400000;
46 		break;
47 	case I2C_SPEED_FAST_PLUS:
48 		mux_selection = PINCTRL_STATE_FAST_PLUS;
49 		speed = 1000000;
50 		break;
51 	case I2C_SPEED_HIGH:
52 	case I2C_SPEED_ULTRA:
53 		return -ENOTSUP;
54 	default:
55 		return -EINVAL;
56 	}
57 
58 	if (dev_config & I2C_ADDR_10_BITS) {
59 		return -ENOTSUP;
60 	}
61 
62 	k_mutex_lock(&data->mutex, K_FOREVER);
63 	lpc11u6x_i2c_set_bus_speed(cfg, cfg->clock_dev, speed);
64 
65 	ret = pinctrl_apply_state(cfg->pincfg, mux_selection);
66 	if (ret) {
67 		k_mutex_unlock(&data->mutex);
68 		return ret;
69 	}
70 	k_mutex_unlock(&data->mutex);
71 	return 0;
72 }
73 
lpc11u6x_i2c_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)74 static int lpc11u6x_i2c_transfer(const struct device *dev,
75 				 struct i2c_msg *msgs,
76 				 uint8_t num_msgs, uint16_t addr)
77 {
78 	const struct lpc11u6x_i2c_config *cfg = dev->config;
79 	struct lpc11u6x_i2c_data *data = dev->data;
80 	int ret = 0;
81 
82 	if (!num_msgs) {
83 		return 0;
84 	}
85 
86 	k_mutex_lock(&data->mutex, K_FOREVER);
87 
88 	data->transfer.msgs = msgs;
89 	data->transfer.curr_buf = msgs->buf;
90 	data->transfer.curr_len = msgs->len;
91 	data->transfer.nr_msgs = num_msgs;
92 	data->transfer.addr = addr;
93 
94 	/* Reset all control bits */
95 	cfg->base->con_clr = LPC11U6X_I2C_CONTROL_SI |
96 		LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_START;
97 
98 	/* Send start and wait for completion */
99 	data->transfer.status = LPC11U6X_I2C_STATUS_BUSY;
100 	cfg->base->con_set = LPC11U6X_I2C_CONTROL_START;
101 
102 	k_sem_take(&data->completion, K_FOREVER);
103 
104 	if (data->transfer.status != LPC11U6X_I2C_STATUS_OK) {
105 		ret = -EIO;
106 	}
107 	data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
108 
109 	/* If a slave is registered, put the controller in slave mode */
110 	if (data->slave) {
111 		cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
112 	}
113 
114 	k_mutex_unlock(&data->mutex);
115 	return ret;
116 }
117 
lpc11u6x_i2c_slave_register(const struct device * dev,struct i2c_target_config * cfg)118 static int lpc11u6x_i2c_slave_register(const struct device *dev,
119 				       struct i2c_target_config *cfg)
120 {
121 	const struct lpc11u6x_i2c_config *dev_cfg = dev->config;
122 	struct lpc11u6x_i2c_data *data = dev->data;
123 	int ret = 0;
124 
125 	if (!cfg) {
126 		return -EINVAL;
127 	}
128 
129 	if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
130 		return -ENOTSUP;
131 	}
132 
133 	k_mutex_lock(&data->mutex, K_FOREVER);
134 	if (data->slave) {
135 		ret = -EBUSY;
136 		goto exit;
137 	}
138 
139 	data->slave = cfg;
140 	/* Configure controller to act as slave */
141 	dev_cfg->base->addr0 = (cfg->address << 1);
142 	dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_START |
143 		LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_SI;
144 	dev_cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
145 
146 exit:
147 	k_mutex_unlock(&data->mutex);
148 	return ret;
149 }
150 
151 
lpc11u6x_i2c_slave_unregister(const struct device * dev,struct i2c_target_config * cfg)152 static int lpc11u6x_i2c_slave_unregister(const struct device *dev,
153 					 struct i2c_target_config *cfg)
154 {
155 	const struct lpc11u6x_i2c_config *dev_cfg = dev->config;
156 	struct lpc11u6x_i2c_data *data = dev->data;
157 
158 	if (!cfg) {
159 		return -EINVAL;
160 	}
161 	if (data->slave != cfg) {
162 		return -EINVAL;
163 	}
164 
165 	k_mutex_lock(&data->mutex, K_FOREVER);
166 	data->slave = NULL;
167 	dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA;
168 	k_mutex_unlock(&data->mutex);
169 
170 	return 0;
171 }
172 
lpc11u6x_i2c_isr(const struct device * dev)173 static void lpc11u6x_i2c_isr(const struct device *dev)
174 {
175 	struct lpc11u6x_i2c_data *data = dev->data;
176 	struct lpc11u6x_i2c_regs *i2c = DEV_BASE(dev);
177 	struct lpc11u6x_i2c_current_transfer *transfer = &data->transfer;
178 	uint32_t clear = LPC11U6X_I2C_CONTROL_SI;
179 	uint32_t set = 0;
180 	uint8_t val;
181 
182 	switch (i2c->stat) {
183 		/* Master TX states */
184 	case LPC11U6X_I2C_MASTER_TX_START:
185 	case LPC11U6X_I2C_MASTER_TX_RESTART:
186 		i2c->dat = (transfer->addr << 1) |
187 			(transfer->msgs->flags & I2C_MSG_READ);
188 		clear |= LPC11U6X_I2C_CONTROL_START;
189 		transfer->curr_buf = transfer->msgs->buf;
190 		transfer->curr_len = transfer->msgs->len;
191 		break;
192 
193 	case LPC11U6X_I2C_MASTER_TX_ADR_ACK:
194 	case LPC11U6X_I2C_MASTER_TX_DAT_ACK:
195 		if (!transfer->curr_len) {
196 			transfer->msgs++;
197 			transfer->nr_msgs--;
198 			if (!transfer->nr_msgs) {
199 				transfer->status = LPC11U6X_I2C_STATUS_OK;
200 				set |= LPC11U6X_I2C_CONTROL_STOP;
201 			} else {
202 				set |= LPC11U6X_I2C_CONTROL_START;
203 			}
204 		} else {
205 			i2c->dat = transfer->curr_buf[0];
206 			transfer->curr_buf++;
207 			transfer->curr_len--;
208 		}
209 		break;
210 
211 		/* Master RX states */
212 	case LPC11U6X_I2C_MASTER_RX_DAT_NACK:
213 		transfer->msgs++;
214 		transfer->nr_msgs--;
215 		set |= (transfer->nr_msgs ? LPC11U6X_I2C_CONTROL_START :
216 				LPC11U6X_I2C_CONTROL_STOP);
217 		if (!transfer->nr_msgs) {
218 			transfer->status = LPC11U6X_I2C_STATUS_OK;
219 		}
220 		__fallthrough;
221 	case LPC11U6X_I2C_MASTER_RX_DAT_ACK:
222 		transfer->curr_buf[0] = i2c->dat;
223 		transfer->curr_buf++;
224 		transfer->curr_len--;
225 		__fallthrough;
226 	case LPC11U6X_I2C_MASTER_RX_ADR_ACK:
227 		if (transfer->curr_len <= 1) {
228 			clear |= LPC11U6X_I2C_CONTROL_AA;
229 		} else {
230 			set |= LPC11U6X_I2C_CONTROL_AA;
231 		}
232 		break;
233 
234 		/* Slave States */
235 	case LPC11U6X_I2C_SLAVE_RX_ADR_ACK:
236 	case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_ADR_ACK:
237 	case LPC11U6X_I2C_SLAVE_RX_GC_ACK:
238 	case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_GC_ACK:
239 		if (data->slave->callbacks->write_requested(data->slave)) {
240 			clear |= LPC11U6X_I2C_CONTROL_AA;
241 		}
242 		break;
243 
244 	case LPC11U6X_I2C_SLAVE_RX_DAT_ACK:
245 	case LPC11U6X_I2C_SLAVE_RX_GC_DAT_ACK:
246 		val = i2c->dat;
247 		if (data->slave->callbacks->write_received(data->slave, val)) {
248 			clear |= LPC11U6X_I2C_CONTROL_AA;
249 		}
250 		break;
251 
252 	case LPC11U6X_I2C_SLAVE_RX_DAT_NACK:
253 	case LPC11U6X_I2C_SLAVE_RX_GC_DAT_NACK:
254 		val = i2c->dat;
255 		data->slave->callbacks->write_received(data->slave, val);
256 		data->slave->callbacks->stop(data->slave);
257 		set |= LPC11U6X_I2C_CONTROL_AA;
258 		break;
259 
260 	case LPC11U6X_I2C_SLAVE_RX_STOP:
261 		data->slave->callbacks->stop(data->slave);
262 		set |= LPC11U6X_I2C_CONTROL_AA;
263 		break;
264 
265 	case LPC11U6X_I2C_SLAVE_TX_ADR_ACK:
266 	case LPC11U6X_I2C_SLAVE_TX_ARB_LOST_ADR_ACK:
267 		if (data->slave->callbacks->read_requested(data->slave, &val)) {
268 			clear |= LPC11U6X_I2C_CONTROL_AA;
269 		}
270 		i2c->dat = val;
271 		break;
272 	case LPC11U6X_I2C_SLAVE_TX_DAT_ACK:
273 		if (data->slave->callbacks->read_processed(data->slave, &val)) {
274 			clear |= LPC11U6X_I2C_CONTROL_AA;
275 		}
276 		i2c->dat = val;
277 		break;
278 	case LPC11U6X_I2C_SLAVE_TX_DAT_NACK:
279 	case LPC11U6X_I2C_SLAVE_TX_LAST_BYTE:
280 		data->slave->callbacks->stop(data->slave);
281 		set |= LPC11U6X_I2C_CONTROL_AA;
282 		break;
283 
284 		/* Error cases */
285 	case LPC11U6X_I2C_MASTER_TX_ADR_NACK:
286 	case LPC11U6X_I2C_MASTER_RX_ADR_NACK:
287 	case LPC11U6X_I2C_MASTER_TX_DAT_NACK:
288 	case LPC11U6X_I2C_MASTER_TX_ARB_LOST:
289 		transfer->status = LPC11U6X_I2C_STATUS_FAIL;
290 		set = LPC11U6X_I2C_CONTROL_STOP;
291 		break;
292 
293 	default:
294 		set = LPC11U6X_I2C_CONTROL_STOP;
295 		break;
296 	}
297 
298 	i2c->con_clr = clear;
299 	i2c->con_set = set;
300 	if ((transfer->status != LPC11U6X_I2C_STATUS_BUSY) &&
301 	    (transfer->status != LPC11U6X_I2C_STATUS_INACTIVE)) {
302 		k_sem_give(&data->completion);
303 	}
304 }
305 
306 
lpc11u6x_i2c_init(const struct device * dev)307 static int lpc11u6x_i2c_init(const struct device *dev)
308 {
309 	const struct lpc11u6x_i2c_config *cfg = dev->config;
310 	struct lpc11u6x_i2c_data *data = dev->data;
311 	int err;
312 
313 	err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
314 	if (err) {
315 		return err;
316 	}
317 
318 	if (!device_is_ready(cfg->clock_dev)) {
319 		return -ENODEV;
320 	}
321 
322 	/* Configure clock and de-assert reset for I2Cx */
323 	clock_control_on(cfg->clock_dev, (clock_control_subsys_t) cfg->clkid);
324 
325 	/* Configure bus speed. Default is 100KHz */
326 	lpc11u6x_i2c_set_bus_speed(cfg, cfg->clock_dev, 100000);
327 
328 	/* Clear all control bytes and enable I2C interface */
329 	cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA | LPC11U6X_I2C_CONTROL_SI |
330 		LPC11U6X_I2C_CONTROL_START | LPC11U6X_I2C_CONTROL_I2C_EN;
331 	cfg->base->con_set = LPC11U6X_I2C_CONTROL_I2C_EN;
332 
333 	/* Initialize mutex and semaphore */
334 	k_mutex_init(&data->mutex);
335 	k_sem_init(&data->completion, 0, 1);
336 
337 	data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
338 	/* Configure IRQ */
339 	cfg->irq_config_func(dev);
340 	return 0;
341 }
342 
343 static DEVICE_API(i2c, i2c_api) = {
344 	.configure = lpc11u6x_i2c_configure,
345 	.transfer = lpc11u6x_i2c_transfer,
346 	.target_register = lpc11u6x_i2c_slave_register,
347 	.target_unregister = lpc11u6x_i2c_slave_unregister,
348 #ifdef CONFIG_I2C_RTIO
349 	.iodev_submit = i2c_iodev_submit_fallback,
350 #endif
351 };
352 
353 #define LPC11U6X_I2C_INIT(idx)						      \
354 									      \
355 static void lpc11u6x_i2c_isr_config_##idx(const struct device *dev);	      \
356 									      \
357 PINCTRL_DT_INST_DEFINE(idx);                                                  \
358 									      \
359 static const struct lpc11u6x_i2c_config i2c_cfg_##idx = {		      \
360 	.base =								      \
361 	(struct lpc11u6x_i2c_regs *) DT_INST_REG_ADDR(idx),		      \
362 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)),		      \
363 	.irq_config_func = lpc11u6x_i2c_isr_config_##idx,		      \
364 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),                        \
365 	.clkid = DT_INST_PHA_BY_IDX(idx, clocks, 0, clkid),		      \
366 };									      \
367 									      \
368 static struct lpc11u6x_i2c_data i2c_data_##idx;			              \
369 									      \
370 I2C_DEVICE_DT_INST_DEFINE(idx,						      \
371 		    lpc11u6x_i2c_init,					      \
372 		    NULL,						      \
373 		    &i2c_data_##idx, &i2c_cfg_##idx,			      \
374 		    PRE_KERNEL_1, CONFIG_I2C_INIT_PRIORITY,		      \
375 		    &i2c_api);						      \
376 									      \
377 static void lpc11u6x_i2c_isr_config_##idx(const struct device *dev)		      \
378 {									      \
379 	IRQ_CONNECT(DT_INST_IRQN(idx),					      \
380 		    DT_INST_IRQ(idx, priority),				      \
381 		    lpc11u6x_i2c_isr, DEVICE_DT_INST_GET(idx), 0);	      \
382 									      \
383 	irq_enable(DT_INST_IRQN(idx));					      \
384 }
385 
386 DT_INST_FOREACH_STATUS_OKAY(LPC11U6X_I2C_INIT);
387