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