1 /*
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ambiq_i2c
8 
9 #include <errno.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/pm/device.h>
13 #include <zephyr/pm/policy.h>
14 #include <zephyr/pm/device_runtime.h>
15 
16 #include <am_mcu_apollo.h>
17 
18 #ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
19 #include <zephyr/drivers/gpio.h>
20 #include "i2c_bitbang.h"
21 #endif /* CONFIG_I2C_AMBIQ_BUS_RECOVERY */
22 
23 #include <zephyr/logging/log.h>
24 #include <zephyr/drivers/pinctrl.h>
25 
26 LOG_MODULE_REGISTER(ambiq_i2c, CONFIG_I2C_LOG_LEVEL);
27 
28 typedef int (*ambiq_i2c_pwr_func_t)(void);
29 
30 #define PWRCTRL_MAX_WAIT_US       5
31 #define I2C_TRANSFER_TIMEOUT_MSEC 500 /* Transfer timeout period */
32 
33 #include "i2c-priv.h"
34 
35 struct i2c_ambiq_config {
36 #ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
37 	struct gpio_dt_spec scl;
38 	struct gpio_dt_spec sda;
39 #endif /* CONFIG_I2C_AMBIQ_BUS_RECOVERY */
40 	uint32_t base;
41 	int size;
42 	uint32_t bitrate;
43 	const struct pinctrl_dev_config *pcfg;
44 	ambiq_i2c_pwr_func_t pwr_func;
45 	void (*irq_config_func)(void);
46 };
47 
48 typedef void (*i2c_ambiq_callback_t)(const struct device *dev, int result, void *data);
49 
50 struct i2c_ambiq_data {
51 	am_hal_iom_config_t iom_cfg;
52 	void *iom_handler;
53 	struct k_sem bus_sem;
54 	struct k_sem transfer_sem;
55 	i2c_ambiq_callback_t callback;
56 	void *callback_data;
57 	int inst_idx;
58 	uint32_t transfer_status;
59 	bool pm_policy_state_on;
60 };
61 
i2c_ambiq_pm_policy_state_lock_get(const struct device * dev)62 static void i2c_ambiq_pm_policy_state_lock_get(const struct device *dev)
63 {
64 	if (IS_ENABLED(CONFIG_PM)) {
65 		struct i2c_ambiq_data *data = dev->data;
66 
67 		if (!data->pm_policy_state_on) {
68 			data->pm_policy_state_on = true;
69 			pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES);
70 			pm_device_runtime_get(dev);
71 		}
72 	}
73 }
74 
i2c_ambiq_pm_policy_state_lock_put(const struct device * dev)75 static void i2c_ambiq_pm_policy_state_lock_put(const struct device *dev)
76 {
77 	if (IS_ENABLED(CONFIG_PM)) {
78 		struct i2c_ambiq_data *data = dev->data;
79 
80 		if (data->pm_policy_state_on) {
81 			data->pm_policy_state_on = false;
82 			pm_device_runtime_put(dev);
83 			pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES);
84 		}
85 	}
86 }
87 
88 #ifdef CONFIG_I2C_AMBIQ_DMA
89 static __aligned(32) struct {
90 	__aligned(32) uint32_t buf[CONFIG_I2C_DMA_TCB_BUFFER_SIZE];
91 } i2c_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __attribute__((__section__(".nocache")));
92 
i2c_ambiq_callback(void * callback_ctxt,uint32_t status)93 static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status)
94 {
95 	const struct device *dev = callback_ctxt;
96 	struct i2c_ambiq_data *data = dev->data;
97 
98 	if (data->callback) {
99 		data->callback(dev, status, data->callback_data);
100 	}
101 	data->transfer_status = status;
102 }
103 #endif
104 
i2c_ambiq_isr(const struct device * dev)105 static void i2c_ambiq_isr(const struct device *dev)
106 {
107 	uint32_t ui32Status;
108 	struct i2c_ambiq_data *data = dev->data;
109 
110 	am_hal_iom_interrupt_status_get(data->iom_handler, false, &ui32Status);
111 	am_hal_iom_interrupt_clear(data->iom_handler, ui32Status);
112 	am_hal_iom_interrupt_service(data->iom_handler, ui32Status);
113 	k_sem_give(&data->transfer_sem);
114 }
115 
i2c_ambiq_read(const struct device * dev,struct i2c_msg * msg,uint16_t addr)116 static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *msg, uint16_t addr)
117 {
118 	struct i2c_ambiq_data *data = dev->data;
119 
120 	int ret = 0;
121 
122 	am_hal_iom_transfer_t trans = {0};
123 
124 	trans.ui8Priority = 1;
125 	trans.eDirection = AM_HAL_IOM_RX;
126 	trans.uPeerInfo.ui32I2CDevAddr = addr;
127 	trans.ui32NumBytes = msg->len;
128 	trans.pui32RxBuffer = (uint32_t *)msg->buf;
129 
130 #ifdef CONFIG_I2C_AMBIQ_DMA
131 	data->transfer_status = -EFAULT;
132 	ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback,
133 					      (void *)dev);
134 	if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) {
135 		LOG_ERR("Timeout waiting for transfer complete");
136 		/* cancel timed out transaction */
137 		am_hal_iom_disable(data->iom_handler);
138 		/* clean up for next xfer */
139 		k_sem_reset(&data->transfer_sem);
140 		am_hal_iom_enable(data->iom_handler);
141 		return -ETIMEDOUT;
142 	}
143 	ret = data->transfer_status;
144 #else
145 	ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans);
146 #endif
147 	return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0;
148 }
149 
i2c_ambiq_write(const struct device * dev,struct i2c_msg * msg,uint16_t addr)150 static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *msg, uint16_t addr)
151 {
152 	struct i2c_ambiq_data *data = dev->data;
153 
154 	int ret = 0;
155 
156 	am_hal_iom_transfer_t trans = {0};
157 
158 	trans.ui8Priority = 1;
159 	trans.eDirection = AM_HAL_IOM_TX;
160 	trans.uPeerInfo.ui32I2CDevAddr = addr;
161 	trans.ui32NumBytes = msg->len;
162 	trans.pui32TxBuffer = (uint32_t *)msg->buf;
163 
164 #ifdef CONFIG_I2C_AMBIQ_DMA
165 	data->transfer_status = -EFAULT;
166 	ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback,
167 					      (void *)dev);
168 
169 	if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) {
170 		LOG_ERR("Timeout waiting for transfer complete");
171 		/* cancel timed out transaction */
172 		am_hal_iom_disable(data->iom_handler);
173 		/* clean up for next xfer */
174 		k_sem_reset(&data->transfer_sem);
175 		am_hal_iom_enable(data->iom_handler);
176 		return -ETIMEDOUT;
177 	}
178 	ret = data->transfer_status;
179 #else
180 	ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans);
181 #endif
182 
183 	return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0;
184 }
185 
i2c_ambiq_configure(const struct device * dev,uint32_t dev_config)186 static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config)
187 {
188 	struct i2c_ambiq_data *data = dev->data;
189 
190 	if (!(I2C_MODE_CONTROLLER & dev_config)) {
191 		return -EINVAL;
192 	}
193 
194 	switch (I2C_SPEED_GET(dev_config)) {
195 	case I2C_SPEED_STANDARD:
196 		data->iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
197 		break;
198 	case I2C_SPEED_FAST:
199 		data->iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
200 		break;
201 	case I2C_SPEED_FAST_PLUS:
202 		data->iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
203 		break;
204 	default:
205 		return -EINVAL;
206 	}
207 
208 #ifdef CONFIG_I2C_AMBIQ_DMA
209 	data->iom_cfg.pNBTxnBuf = i2c_dma_tcb_buf[data->inst_idx].buf;
210 	data->iom_cfg.ui32NBTxnBufLength = CONFIG_I2C_DMA_TCB_BUFFER_SIZE;
211 #endif
212 
213 	am_hal_iom_configure(data->iom_handler, &data->iom_cfg);
214 
215 	return 0;
216 }
217 
i2c_ambiq_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)218 static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs,
219 			      uint16_t addr)
220 {
221 	struct i2c_ambiq_data *data = dev->data;
222 	int ret = 0;
223 
224 	if (!num_msgs) {
225 		return 0;
226 	}
227 
228 	i2c_ambiq_pm_policy_state_lock_get(dev);
229 
230 	/* Send out messages */
231 	k_sem_take(&data->bus_sem, K_FOREVER);
232 
233 	for (int i = 0; i < num_msgs; i++) {
234 		if (msgs[i].flags & I2C_MSG_READ) {
235 			ret = i2c_ambiq_read(dev, &(msgs[i]), addr);
236 		} else {
237 			ret = i2c_ambiq_write(dev, &(msgs[i]), addr);
238 		}
239 
240 		if (ret != 0) {
241 			LOG_ERR("i2c transfer failed: %d", ret);
242 			break;
243 		}
244 	}
245 
246 	k_sem_give(&data->bus_sem);
247 
248 	i2c_ambiq_pm_policy_state_lock_put(dev);
249 
250 	return ret;
251 }
252 
253 #if CONFIG_I2C_AMBIQ_BUS_RECOVERY
i2c_ambiq_bitbang_set_scl(void * io_context,int state)254 static void i2c_ambiq_bitbang_set_scl(void *io_context, int state)
255 {
256 	const struct i2c_ambiq_config *config = io_context;
257 
258 	gpio_pin_set_dt(&config->scl, state);
259 }
260 
i2c_ambiq_bitbang_set_sda(void * io_context,int state)261 static void i2c_ambiq_bitbang_set_sda(void *io_context, int state)
262 {
263 	const struct i2c_ambiq_config *config = io_context;
264 
265 	gpio_pin_set_dt(&config->sda, state);
266 }
267 
i2c_ambiq_bitbang_get_sda(void * io_context)268 static int i2c_ambiq_bitbang_get_sda(void *io_context)
269 {
270 	const struct i2c_ambiq_config *config = io_context;
271 
272 	return gpio_pin_get_dt(&config->sda) == 0 ? 0 : 1;
273 }
274 
i2c_ambiq_recover_bus(const struct device * dev)275 static int i2c_ambiq_recover_bus(const struct device *dev)
276 {
277 	const struct i2c_ambiq_config *config = dev->config;
278 	struct i2c_ambiq_data *data = dev->data;
279 	struct i2c_bitbang bitbang_ctx;
280 	struct i2c_bitbang_io bitbang_io = {
281 		.set_scl = i2c_ambiq_bitbang_set_scl,
282 		.set_sda = i2c_ambiq_bitbang_set_sda,
283 		.get_sda = i2c_ambiq_bitbang_get_sda,
284 	};
285 	uint32_t bitrate_cfg;
286 	int error = 0;
287 
288 	LOG_ERR("attempting to recover bus");
289 
290 	if (!gpio_is_ready_dt(&config->scl)) {
291 		LOG_ERR("SCL GPIO device not ready");
292 		return -EIO;
293 	}
294 
295 	if (!gpio_is_ready_dt(&config->sda)) {
296 		LOG_ERR("SDA GPIO device not ready");
297 		return -EIO;
298 	}
299 
300 	k_sem_take(&data->bus_sem, K_FOREVER);
301 
302 	error = gpio_pin_configure_dt(&config->scl, GPIO_OUTPUT_HIGH);
303 	if (error != 0) {
304 		LOG_ERR("failed to configure SCL GPIO (err %d)", error);
305 		goto restore;
306 	}
307 
308 	error = gpio_pin_configure_dt(&config->sda, GPIO_OUTPUT_HIGH);
309 	if (error != 0) {
310 		LOG_ERR("failed to configure SDA GPIO (err %d)", error);
311 		goto restore;
312 	}
313 
314 	i2c_bitbang_init(&bitbang_ctx, &bitbang_io, (void *)config);
315 
316 	bitrate_cfg = i2c_map_dt_bitrate(config->bitrate) | I2C_MODE_CONTROLLER;
317 	error = i2c_bitbang_configure(&bitbang_ctx, bitrate_cfg);
318 	if (error != 0) {
319 		LOG_ERR("failed to configure I2C bitbang (err %d)", error);
320 		goto restore;
321 	}
322 
323 	error = i2c_bitbang_recover_bus(&bitbang_ctx);
324 	if (error != 0) {
325 		LOG_ERR("failed to recover bus (err %d)", error);
326 	}
327 
328 restore:
329 	(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
330 
331 	k_sem_give(&data->bus_sem);
332 
333 	return error;
334 }
335 #endif /* CONFIG_I2C_AMBIQ_BUS_RECOVERY */
336 
i2c_ambiq_init(const struct device * dev)337 static int i2c_ambiq_init(const struct device *dev)
338 {
339 	struct i2c_ambiq_data *data = dev->data;
340 	const struct i2c_ambiq_config *config = dev->config;
341 	uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
342 	int ret = 0;
343 
344 	data->iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
345 
346 	if (AM_HAL_STATUS_SUCCESS !=
347 	    am_hal_iom_initialize((config->base - IOM0_BASE) / config->size,
348 				  &data->iom_handler)) {
349 		LOG_ERR("Fail to initialize I2C\n");
350 		return -ENXIO;
351 	}
352 
353 	ret = config->pwr_func();
354 
355 	ret |= i2c_ambiq_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
356 	if (ret < 0) {
357 		LOG_ERR("Fail to config I2C\n");
358 		goto end;
359 	}
360 
361 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
362 	if (ret < 0) {
363 		LOG_ERR("Fail to config I2C pins\n");
364 		goto end;
365 	}
366 
367 #ifdef CONFIG_I2C_AMBIQ_DMA
368 	am_hal_iom_interrupt_clear(data->iom_handler, AM_HAL_IOM_INT_DCMP | AM_HAL_IOM_INT_CMDCMP);
369 	am_hal_iom_interrupt_enable(data->iom_handler, AM_HAL_IOM_INT_DCMP | AM_HAL_IOM_INT_CMDCMP);
370 	config->irq_config_func();
371 #endif
372 
373 	if (AM_HAL_STATUS_SUCCESS != am_hal_iom_enable(data->iom_handler)) {
374 		LOG_ERR("Fail to enable I2C\n");
375 		ret = -EIO;
376 	}
377 end:
378 	if (ret < 0) {
379 		am_hal_iom_uninitialize(data->iom_handler);
380 	}
381 	return ret;
382 }
383 
384 static DEVICE_API(i2c, i2c_ambiq_driver_api) = {
385 	.configure = i2c_ambiq_configure,
386 	.transfer = i2c_ambiq_transfer,
387 #if CONFIG_I2C_AMBIQ_BUS_RECOVERY
388 	.recover_bus = i2c_ambiq_recover_bus,
389 #endif /* CONFIG_I2C_AMBIQ_BUS_RECOVERY */
390 #ifdef CONFIG_I2C_RTIO
391 	.iodev_submit = i2c_iodev_submit_fallback,
392 #endif
393 };
394 
395 #ifdef CONFIG_PM_DEVICE
i2c_ambiq_pm_action(const struct device * dev,enum pm_device_action action)396 static int i2c_ambiq_pm_action(const struct device *dev, enum pm_device_action action)
397 {
398 	struct i2c_ambiq_data *data = dev->data;
399 	uint32_t ret;
400 	am_hal_sysctrl_power_state_e status;
401 
402 	switch (action) {
403 	case PM_DEVICE_ACTION_RESUME:
404 		status = AM_HAL_SYSCTRL_WAKE;
405 		break;
406 	case PM_DEVICE_ACTION_SUSPEND:
407 		status = AM_HAL_SYSCTRL_DEEPSLEEP;
408 		break;
409 	default:
410 		return -ENOTSUP;
411 	}
412 
413 	ret = am_hal_iom_power_ctrl(data->iom_handler, status, true);
414 
415 	if (ret != AM_HAL_STATUS_SUCCESS) {
416 		return -EPERM;
417 	} else {
418 		return 0;
419 	}
420 }
421 #endif /* CONFIG_PM_DEVICE */
422 
423 #define AMBIQ_I2C_DEFINE(n)                                                                        \
424 	PINCTRL_DT_INST_DEFINE(n);                                                                 \
425 	static int pwr_on_ambiq_i2c_##n(void)                                                      \
426 	{                                                                                          \
427 		uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) +                    \
428 				DT_INST_PHA(n, ambiq_pwrcfg, offset);                              \
429 		sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr);        \
430 		k_busy_wait(PWRCTRL_MAX_WAIT_US);                                                  \
431 		return 0;                                                                          \
432 	}                                                                                          \
433 	static void i2c_irq_config_func_##n(void)                                                  \
434 	{                                                                                          \
435 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_ambiq_isr,              \
436 			    DEVICE_DT_INST_GET(n), 0);                                             \
437 		irq_enable(DT_INST_IRQN(n));                                                       \
438 	};                                                                                         \
439 	static struct i2c_ambiq_data i2c_ambiq_data##n = {                                         \
440 		.bus_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.bus_sem, 1, 1),                     \
441 		.transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1),           \
442 		.inst_idx = n,                                                                     \
443 	};                                                                                         \
444 	static const struct i2c_ambiq_config i2c_ambiq_config##n = {                               \
445 		.base = DT_INST_REG_ADDR(n),                                                       \
446 		.size = DT_INST_REG_SIZE(n),                                                       \
447 		.bitrate = DT_INST_PROP(n, clock_frequency),                                       \
448 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),                                         \
449 		.irq_config_func = i2c_irq_config_func_##n,                                        \
450 		.pwr_func = pwr_on_ambiq_i2c_##n,                                                  \
451 		IF_ENABLED(CONFIG_I2C_AMBIQ_BUS_RECOVERY,			\
452 		(.scl = GPIO_DT_SPEC_INST_GET_OR(n, scl_gpios, {0}),\
453 		 .sda = GPIO_DT_SPEC_INST_GET_OR(n, sda_gpios, {0}),)) };      \
454 	PM_DEVICE_DT_INST_DEFINE(n, i2c_ambiq_pm_action);                                          \
455 	I2C_DEVICE_DT_INST_DEFINE(n, i2c_ambiq_init, PM_DEVICE_DT_INST_GET(n), &i2c_ambiq_data##n, \
456 				  &i2c_ambiq_config##n, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY,     \
457 				  &i2c_ambiq_driver_api);
458 
459 DT_INST_FOREACH_STATUS_OKAY(AMBIQ_I2C_DEFINE)
460