1 /*
2  * Copyright (c) 2019 Brett Witherspoon
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_cc13xx_cc26xx_i2c
8 
9 #include <kernel.h>
10 #include <drivers/i2c.h>
11 #include <pm/device.h>
12 #include <pm/pm.h>
13 
14 #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
15 #include <logging/log.h>
16 LOG_MODULE_REGISTER(i2c_cc13xx_cc26xx);
17 
18 #include <driverlib/i2c.h>
19 #include <driverlib/ioc.h>
20 #include <driverlib/prcm.h>
21 
22 #include <ti/drivers/Power.h>
23 #include <ti/drivers/power/PowerCC26X2.h>
24 
25 #include "i2c-priv.h"
26 
27 struct i2c_cc13xx_cc26xx_data {
28 	struct k_sem lock;
29 	struct k_sem complete;
30 	volatile uint32_t error;
31 #ifdef CONFIG_PM
32 	Power_NotifyObj postNotify;
33 	uint32_t dev_config;
34 #endif
35 };
36 
37 struct i2c_cc13xx_cc26xx_config {
38 	uint32_t base;
39 	uint32_t scl_pin;
40 	uint32_t sda_pin;
41 };
42 
get_dev_data(const struct device * dev)43 static inline struct i2c_cc13xx_cc26xx_data *get_dev_data(const struct device *dev)
44 {
45 	return dev->data;
46 }
47 
48 static inline const struct i2c_cc13xx_cc26xx_config *
get_dev_config(const struct device * dev)49 get_dev_config(const struct device *dev)
50 {
51 	return dev->config;
52 }
53 
i2c_cc13xx_cc26xx_transmit(const struct device * dev,const uint8_t * buf,uint32_t len,uint16_t addr)54 static int i2c_cc13xx_cc26xx_transmit(const struct device *dev,
55 				      const uint8_t *buf,
56 				      uint32_t len, uint16_t addr)
57 {
58 	const uint32_t base = get_dev_config(dev)->base;
59 	struct i2c_cc13xx_cc26xx_data *data = get_dev_data(dev);
60 
61 	/* Sending address without data is not supported */
62 	if (len == 0) {
63 		return -EIO;
64 	}
65 
66 	I2CMasterSlaveAddrSet(base, addr, false);
67 
68 	/* The following assumes a single master. Use I2CMasterBusBusy() if
69 	 * wanting to implement multiple master support.
70 	 */
71 
72 	/* Single transmission */
73 	if (len == 1) {
74 		I2CMasterDataPut(base, *buf);
75 
76 		I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
77 
78 		k_sem_take(&data->complete, K_FOREVER);
79 
80 		return data->error == I2C_MASTER_ERR_NONE ? 0 : -EIO;
81 	}
82 
83 	/* Burst transmission */
84 	I2CMasterDataPut(base, buf[0]);
85 
86 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
87 
88 	k_sem_take(&data->complete, K_FOREVER);
89 
90 	if (data->error != I2C_MASTER_ERR_NONE) {
91 		goto send_error_stop;
92 	}
93 
94 	for (int i = 1; i < len - 1; i++) {
95 		I2CMasterDataPut(base, buf[i]);
96 
97 		I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
98 
99 		k_sem_take(&data->complete, K_FOREVER);
100 
101 		if (data->error != I2C_MASTER_ERR_NONE) {
102 			goto send_error_stop;
103 		}
104 	}
105 
106 	I2CMasterDataPut(base, buf[len - 1]);
107 
108 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_FINISH);
109 
110 	k_sem_take(&data->complete, K_FOREVER);
111 
112 	if (data->error != I2C_MASTER_ERR_NONE) {
113 		return -EIO;
114 	}
115 
116 	return 0;
117 
118 send_error_stop:
119 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
120 	return -EIO;
121 }
122 
i2c_cc13xx_cc26xx_receive(const struct device * dev,uint8_t * buf,uint32_t len,uint16_t addr)123 static int i2c_cc13xx_cc26xx_receive(const struct device *dev, uint8_t *buf,
124 				     uint32_t len,
125 				     uint16_t addr)
126 {
127 	const uint32_t base = get_dev_config(dev)->base;
128 	struct i2c_cc13xx_cc26xx_data *data = get_dev_data(dev);
129 
130 	/* Sending address without data is not supported */
131 	if (len == 0) {
132 		return -EIO;
133 	}
134 
135 	I2CMasterSlaveAddrSet(base, addr, true);
136 
137 	/* The following assumes a single master. Use I2CMasterBusBusy() if
138 	 * wanting to implement multiple master support.
139 	 */
140 
141 	/* Single receive */
142 	if (len == 1) {
143 		I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_RECEIVE);
144 
145 		k_sem_take(&data->complete, K_FOREVER);
146 
147 		if (data->error != I2C_MASTER_ERR_NONE) {
148 			return -EIO;
149 		}
150 
151 		*buf = I2CMasterDataGet(base);
152 
153 		return 0;
154 	}
155 
156 	/* Burst receive */
157 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
158 
159 	k_sem_take(&data->complete, K_FOREVER);
160 
161 	if (data->error != I2C_MASTER_ERR_NONE) {
162 		goto recv_error_stop;
163 	}
164 
165 	buf[0] = I2CMasterDataGet(base);
166 
167 	for (int i = 1; i < len - 1; i++) {
168 		I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
169 
170 		k_sem_take(&data->complete, K_FOREVER);
171 
172 		if (data->error != I2C_MASTER_ERR_NONE) {
173 			goto recv_error_stop;
174 		}
175 
176 		buf[i] = I2CMasterDataGet(base);
177 	}
178 
179 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
180 
181 	k_sem_take(&data->complete, K_FOREVER);
182 
183 	if (data->error != I2C_MASTER_ERR_NONE) {
184 		return -EIO;
185 	}
186 
187 	buf[len - 1] = I2CMasterDataGet(base);
188 
189 	return 0;
190 
191 recv_error_stop:
192 	I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
193 	return -EIO;
194 }
195 
i2c_cc13xx_cc26xx_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)196 static int i2c_cc13xx_cc26xx_transfer(const struct device *dev,
197 				      struct i2c_msg *msgs,
198 				      uint8_t num_msgs, uint16_t addr)
199 {
200 	int ret = 0;
201 
202 	if (num_msgs == 0) {
203 		return 0;
204 	}
205 
206 	k_sem_take(&get_dev_data(dev)->lock, K_FOREVER);
207 
208 #ifdef CONFIG_PM
209 	pm_constraint_set(PM_STATE_STANDBY);
210 #endif
211 
212 	for (int i = 0; i < num_msgs; i++) {
213 		/* Not supported by hardware */
214 		if (msgs[i].flags & I2C_MSG_ADDR_10_BITS) {
215 			ret = -EIO;
216 			break;
217 		}
218 
219 		if ((msgs[i].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
220 			ret = i2c_cc13xx_cc26xx_transmit(dev, msgs[i].buf,
221 							 msgs[i].len, addr);
222 		} else {
223 			ret = i2c_cc13xx_cc26xx_receive(dev, msgs[i].buf,
224 							msgs[i].len, addr);
225 		}
226 
227 		if (ret) {
228 			break;
229 		}
230 	}
231 
232 #ifdef CONFIG_PM
233 	pm_constraint_release(PM_STATE_STANDBY);
234 #endif
235 
236 	k_sem_give(&get_dev_data(dev)->lock);
237 
238 	return ret;
239 }
240 
241 #define CPU_FREQ DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency)
i2c_cc13xx_cc26xx_configure(const struct device * dev,uint32_t dev_config)242 static int i2c_cc13xx_cc26xx_configure(const struct device *dev,
243 				       uint32_t dev_config)
244 {
245 	bool fast;
246 
247 	switch (I2C_SPEED_GET(dev_config)) {
248 	case I2C_SPEED_STANDARD:
249 		fast = false;
250 		break;
251 	case I2C_SPEED_FAST:
252 		fast = true;
253 		break;
254 	default:
255 		LOG_ERR("Unsupported speed");
256 		return -EIO;
257 	}
258 
259 	/* Support for slave mode has not been implemented */
260 	if (!(dev_config & I2C_MODE_MASTER)) {
261 		LOG_ERR("Slave mode is not supported");
262 		return -EIO;
263 	}
264 
265 	/* This is deprecated and could be ignored in the future */
266 	if (dev_config & I2C_ADDR_10_BITS) {
267 		LOG_ERR("10-bit addressing mode is not supported");
268 		return -EIO;
269 	}
270 
271 	/* Enables and configures I2C master */
272 	I2CMasterInitExpClk(get_dev_config(dev)->base, CPU_FREQ, fast);
273 
274 #ifdef CONFIG_PM
275 	get_dev_data(dev)->dev_config = dev_config;
276 #endif
277 
278 	return 0;
279 }
280 
i2c_cc13xx_cc26xx_isr(const void * arg)281 static void i2c_cc13xx_cc26xx_isr(const void *arg)
282 {
283 	const uint32_t base = get_dev_config(arg)->base;
284 	struct i2c_cc13xx_cc26xx_data *data = get_dev_data(arg);
285 
286 	if (I2CMasterIntStatus(base, true)) {
287 		I2CMasterIntClear(base);
288 
289 		data->error = I2CMasterErr(base);
290 
291 		k_sem_give(&data->complete);
292 	}
293 }
294 
295 #ifdef CONFIG_PM
296 /*
297  *  ======== postNotifyFxn ========
298  *  Called by Power module when waking up the CPU from Standby. The i2c needs
299  *  to be reconfigured afterwards, unless Zephyr's device PM turned it off, in
300  *  which case it'd be responsible for turning it back on and reconfigure it.
301  */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)302 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
303 	uintptr_t clientArg)
304 {
305 	const struct device *dev = (const struct device *)clientArg;
306 	int ret = Power_NOTIFYDONE;
307 	int16_t res_id;
308 
309 	/* Reconfigure the hardware if returning from sleep */
310 	if (eventType == PowerCC26XX_AWAKE_STANDBY) {
311 		res_id = PowerCC26XX_PERIPH_I2C0;
312 
313 		if (Power_getDependencyCount(res_id) != 0) {
314 			/* Reconfigure and enable I2C only if powered */
315 			if (i2c_cc13xx_cc26xx_configure(dev,
316 				get_dev_data(dev)->dev_config) != 0) {
317 				ret = Power_NOTIFYERROR;
318 			}
319 
320 			I2CMasterIntEnable(get_dev_config(dev)->base);
321 		}
322 	}
323 
324 	return (ret);
325 }
326 #endif
327 
328 #ifdef CONFIG_PM_DEVICE
i2c_cc13xx_cc26xx_pm_control(const struct device * dev,enum pm_device_action action)329 static int i2c_cc13xx_cc26xx_pm_control(const struct device *dev,
330 					enum pm_device_action action)
331 {
332 	int ret = 0;
333 
334 	switch (action) {
335 	case PM_DEVICE_ACTION_RESUME:
336 		Power_setDependency(PowerCC26XX_PERIPH_I2C0);
337 		IOCPinTypeI2c(get_dev_config(dev)->base,
338 			get_dev_config(dev)->sda_pin,
339 			get_dev_config(dev)->scl_pin);
340 		ret = i2c_cc13xx_cc26xx_configure(dev,
341 			get_dev_data(dev)->dev_config);
342 		if (ret == 0) {
343 			I2CMasterIntEnable(get_dev_config(dev)->base);
344 		}
345 		break;
346 	case PM_DEVICE_ACTION_SUSPEND:
347 		I2CMasterIntDisable(get_dev_config(dev)->base);
348 		I2CMasterDisable(get_dev_config(dev)->base);
349 		/* Reset pin type to default GPIO configuration */
350 		IOCPortConfigureSet(get_dev_config(dev)->scl_pin,
351 			IOC_PORT_GPIO, IOC_STD_OUTPUT);
352 		IOCPortConfigureSet(get_dev_config(dev)->sda_pin,
353 			IOC_PORT_GPIO, IOC_STD_OUTPUT);
354 		Power_releaseDependency(PowerCC26XX_PERIPH_I2C0);
355 		break;
356 	default:
357 		return -ENOTSUP;
358 	}
359 
360 	return ret;
361 }
362 #endif /* CONFIG_PM_DEVICE */
363 
i2c_cc13xx_cc26xx_init(const struct device * dev)364 static int i2c_cc13xx_cc26xx_init(const struct device *dev)
365 {
366 	uint32_t cfg;
367 	int err;
368 
369 #ifdef CONFIG_PM
370 	/* Set Power dependencies & constraints */
371 	Power_setDependency(PowerCC26XX_PERIPH_I2C0);
372 
373 	/* Register notification function */
374 	Power_registerNotify(&get_dev_data(dev)->postNotify,
375 		PowerCC26XX_AWAKE_STANDBY,
376 		postNotifyFxn, (uintptr_t)dev);
377 #else
378 	/* Enable I2C power domain */
379 	PRCMPowerDomainOn(PRCM_DOMAIN_SERIAL);
380 
381 	/* Enable I2C peripheral clock */
382 	PRCMPeripheralRunEnable(PRCM_PERIPH_I2C0);
383 	/* Enable in sleep mode until proper power management is added */
384 	PRCMPeripheralSleepEnable(PRCM_PERIPH_I2C0);
385 	PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_I2C0);
386 
387 	/* Load PRCM settings */
388 	PRCMLoadSet();
389 	while (!PRCMLoadGet()) {
390 		continue;
391 	}
392 
393 	/* I2C should not be accessed until power domain is on. */
394 	while (PRCMPowerDomainStatus(PRCM_DOMAIN_SERIAL) !=
395 	       PRCM_DOMAIN_POWER_ON) {
396 		continue;
397 	}
398 #endif
399 
400 	IRQ_CONNECT(DT_INST_IRQN(0),
401 		    DT_INST_IRQ(0, priority),
402 		    i2c_cc13xx_cc26xx_isr, DEVICE_DT_INST_GET(0), 0);
403 	irq_enable(DT_INST_IRQN(0));
404 
405 	/* Configure IOC module to route SDA and SCL signals */
406 	IOCPinTypeI2c(get_dev_config(dev)->base, get_dev_config(dev)->sda_pin,
407 		      get_dev_config(dev)->scl_pin);
408 
409 	cfg = i2c_map_dt_bitrate(DT_INST_PROP(0, clock_frequency));
410 	err = i2c_cc13xx_cc26xx_configure(dev, cfg | I2C_MODE_MASTER);
411 	if (err) {
412 		LOG_ERR("Failed to configure");
413 		return err;
414 	}
415 
416 	I2CMasterIntEnable(get_dev_config(dev)->base);
417 
418 	return 0;
419 }
420 
421 static const struct i2c_driver_api i2c_cc13xx_cc26xx_driver_api = {
422 	.configure = i2c_cc13xx_cc26xx_configure,
423 	.transfer = i2c_cc13xx_cc26xx_transfer
424 };
425 
426 static const struct i2c_cc13xx_cc26xx_config i2c_cc13xx_cc26xx_config = {
427 	.base = DT_INST_REG_ADDR(0),
428 	.sda_pin = DT_INST_PROP(0, sda_pin),
429 	.scl_pin = DT_INST_PROP(0, scl_pin)
430 };
431 
432 static struct i2c_cc13xx_cc26xx_data i2c_cc13xx_cc26xx_data = {
433 	.lock = Z_SEM_INITIALIZER(i2c_cc13xx_cc26xx_data.lock, 1, 1),
434 	.complete = Z_SEM_INITIALIZER(i2c_cc13xx_cc26xx_data.complete, 0, 1),
435 	.error = I2C_MASTER_ERR_NONE
436 };
437 
438 DEVICE_DT_INST_DEFINE(0,
439 		i2c_cc13xx_cc26xx_init,
440 		i2c_cc13xx_cc26xx_pm_control,
441 		&i2c_cc13xx_cc26xx_data, &i2c_cc13xx_cc26xx_config,
442 		POST_KERNEL, CONFIG_I2C_INIT_PRIORITY,
443 		&i2c_cc13xx_cc26xx_driver_api);
444