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