1 /*
2 * Copyright (c) 2018, Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7
8 #include <zephyr/drivers/i2c.h>
9 #include <zephyr/dt-bindings/i2c/i2c.h>
10 #include <zephyr/pm/device.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <soc.h>
13 #include <nrfx_twi.h>
14
15 #include <zephyr/logging/log.h>
16 #include <zephyr/irq.h>
17 LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL);
18
19 #if CONFIG_I2C_NRFX_TRANSFER_TIMEOUT
20 #define I2C_TRANSFER_TIMEOUT_MSEC K_MSEC(CONFIG_I2C_NRFX_TRANSFER_TIMEOUT)
21 #else
22 #define I2C_TRANSFER_TIMEOUT_MSEC K_FOREVER
23 #endif
24
25 struct i2c_nrfx_twi_data {
26 struct k_sem transfer_sync;
27 struct k_sem completion_sync;
28 volatile nrfx_err_t res;
29 uint32_t dev_config;
30 };
31
32 struct i2c_nrfx_twi_config {
33 nrfx_twi_t twi;
34 nrfx_twi_config_t config;
35 const struct pinctrl_dev_config *pcfg;
36 };
37
38 static int i2c_nrfx_twi_recover_bus(const struct device *dev);
39
i2c_nrfx_twi_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)40 static int i2c_nrfx_twi_transfer(const struct device *dev,
41 struct i2c_msg *msgs,
42 uint8_t num_msgs, uint16_t addr)
43 {
44 const struct i2c_nrfx_twi_config *config = dev->config;
45 struct i2c_nrfx_twi_data *data = dev->data;
46 int ret = 0;
47
48 k_sem_take(&data->transfer_sync, K_FOREVER);
49
50 /* Dummy take on completion_sync sem to be sure that it is empty */
51 k_sem_take(&data->completion_sync, K_NO_WAIT);
52
53 nrfx_twi_enable(&config->twi);
54
55 for (size_t i = 0; i < num_msgs; i++) {
56 if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) {
57 ret = -ENOTSUP;
58 break;
59 }
60
61 nrfx_twi_xfer_desc_t cur_xfer = {
62 .p_primary_buf = msgs[i].buf,
63 .primary_length = msgs[i].len,
64 .address = addr,
65 .type = (msgs[i].flags & I2C_MSG_READ) ?
66 NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX
67 };
68 uint32_t xfer_flags = 0;
69 nrfx_err_t res;
70
71 /* In case the STOP condition is not supposed to appear after
72 * the current message, check what is requested further:
73 */
74 if (!(msgs[i].flags & I2C_MSG_STOP)) {
75 /* - if the transfer consists of more messages
76 * and the I2C repeated START is not requested
77 * to appear before the next message, suspend
78 * the transfer after the current message,
79 * so that it can be resumed with the next one,
80 * resulting in the two messages merged into
81 * a continuous transfer on the bus
82 */
83 if ((i < (num_msgs - 1)) &&
84 !(msgs[i + 1].flags & I2C_MSG_RESTART)) {
85 xfer_flags |= NRFX_TWI_FLAG_SUSPEND;
86 /* - otherwise, just finish the transfer without
87 * generating the STOP condition, unless the current
88 * message is an RX request, for which such feature
89 * is not supported
90 */
91 } else if (msgs[i].flags & I2C_MSG_READ) {
92 ret = -ENOTSUP;
93 break;
94 } else {
95 xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP;
96 }
97 }
98
99 res = nrfx_twi_xfer(&config->twi, &cur_xfer, xfer_flags);
100 if (res != NRFX_SUCCESS) {
101 if (res == NRFX_ERROR_BUSY) {
102 ret = -EBUSY;
103 break;
104 } else {
105 ret = -EIO;
106 break;
107 }
108 }
109
110 ret = k_sem_take(&data->completion_sync,
111 I2C_TRANSFER_TIMEOUT_MSEC);
112 if (ret != 0) {
113 /* Whatever the frequency, completion_sync should have
114 * been given by the event handler.
115 *
116 * If it hasn't, it's probably due to an hardware issue
117 * on the I2C line, for example a short between SDA and
118 * GND.
119 * This is issue has also been when trying to use the
120 * I2C bus during MCU internal flash erase.
121 *
122 * In many situation, a retry is sufficient.
123 * However, some time the I2C device get stuck and need
124 * help to recover.
125 * Therefore we always call i2c_nrfx_twi_recover_bus()
126 * to make sure everything has been done to restore the
127 * bus from this error.
128 */
129 LOG_ERR("Error on I2C line occurred for message %d", i);
130 nrfx_twi_disable(&config->twi);
131 (void)i2c_nrfx_twi_recover_bus(dev);
132 ret = -EIO;
133 break;
134 }
135
136 res = data->res;
137 if (res != NRFX_SUCCESS) {
138 LOG_ERR("Error 0x%08X occurred for message %d", res, i);
139 ret = -EIO;
140 break;
141 }
142 }
143
144 nrfx_twi_disable(&config->twi);
145 k_sem_give(&data->transfer_sync);
146
147 return ret;
148 }
149
event_handler(nrfx_twi_evt_t const * p_event,void * p_context)150 static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context)
151 {
152 struct i2c_nrfx_twi_data *dev_data = p_context;
153
154 switch (p_event->type) {
155 case NRFX_TWI_EVT_DONE:
156 dev_data->res = NRFX_SUCCESS;
157 break;
158 case NRFX_TWI_EVT_ADDRESS_NACK:
159 dev_data->res = NRFX_ERROR_DRV_TWI_ERR_ANACK;
160 break;
161 case NRFX_TWI_EVT_DATA_NACK:
162 dev_data->res = NRFX_ERROR_DRV_TWI_ERR_DNACK;
163 break;
164 default:
165 dev_data->res = NRFX_ERROR_INTERNAL;
166 break;
167 }
168
169 k_sem_give(&dev_data->completion_sync);
170 }
171
i2c_nrfx_twi_configure(const struct device * dev,uint32_t dev_config)172 static int i2c_nrfx_twi_configure(const struct device *dev,
173 uint32_t dev_config)
174 {
175 const struct i2c_nrfx_twi_config *config = dev->config;
176 struct i2c_nrfx_twi_data *data = dev->data;
177 nrfx_twi_t const *inst = &config->twi;
178
179 if (I2C_ADDR_10_BITS & dev_config) {
180 return -EINVAL;
181 }
182
183 switch (I2C_SPEED_GET(dev_config)) {
184 case I2C_SPEED_STANDARD:
185 nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K);
186 break;
187 case I2C_SPEED_FAST:
188 nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K);
189 break;
190 default:
191 LOG_ERR("unsupported speed");
192 return -EINVAL;
193 }
194 data->dev_config = dev_config;
195
196 return 0;
197 }
198
i2c_nrfx_twi_recover_bus(const struct device * dev)199 static int i2c_nrfx_twi_recover_bus(const struct device *dev)
200 {
201 const struct i2c_nrfx_twi_config *config = dev->config;
202 uint32_t scl_pin;
203 uint32_t sda_pin;
204 nrfx_err_t err;
205
206 scl_pin = nrf_twi_scl_pin_get(config->twi.p_twi);
207 sda_pin = nrf_twi_sda_pin_get(config->twi.p_twi);
208
209 err = nrfx_twi_bus_recover(scl_pin, sda_pin);
210 return (err == NRFX_SUCCESS ? 0 : -EBUSY);
211 }
212
213 static const struct i2c_driver_api i2c_nrfx_twi_driver_api = {
214 .configure = i2c_nrfx_twi_configure,
215 .transfer = i2c_nrfx_twi_transfer,
216 .recover_bus = i2c_nrfx_twi_recover_bus,
217 };
218
init_twi(const struct device * dev)219 static int init_twi(const struct device *dev)
220 {
221 const struct i2c_nrfx_twi_config *config = dev->config;
222 struct i2c_nrfx_twi_data *dev_data = dev->data;
223 nrfx_err_t result = nrfx_twi_init(&config->twi, &config->config,
224 event_handler, dev_data);
225 if (result != NRFX_SUCCESS) {
226 LOG_ERR("Failed to initialize device: %s",
227 dev->name);
228 return -EBUSY;
229 }
230
231 return 0;
232 }
233
234 #ifdef CONFIG_PM_DEVICE
twi_nrfx_pm_action(const struct device * dev,enum pm_device_action action)235 static int twi_nrfx_pm_action(const struct device *dev,
236 enum pm_device_action action)
237 {
238 const struct i2c_nrfx_twi_config *config = dev->config;
239 struct i2c_nrfx_twi_data *data = dev->data;
240 int ret = 0;
241
242 switch (action) {
243 case PM_DEVICE_ACTION_RESUME:
244 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
245 if (ret < 0) {
246 return ret;
247 }
248 init_twi(dev);
249 if (data->dev_config) {
250 i2c_nrfx_twi_configure(dev, data->dev_config);
251 }
252 break;
253
254 case PM_DEVICE_ACTION_SUSPEND:
255 nrfx_twi_uninit(&config->twi);
256
257 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
258 if (ret < 0) {
259 return ret;
260 }
261 break;
262
263 default:
264 ret = -ENOTSUP;
265 }
266
267 return ret;
268 }
269 #endif /* CONFIG_PM_DEVICE */
270
271 #define I2C_NRFX_TWI_INVALID_FREQUENCY ((nrf_twi_frequency_t)-1)
272 #define I2C_NRFX_TWI_FREQUENCY(bitrate) \
273 (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K \
274 : bitrate == 250000 ? NRF_TWI_FREQ_250K \
275 : bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \
276 : I2C_NRFX_TWI_INVALID_FREQUENCY)
277 #define I2C(idx) DT_NODELABEL(i2c##idx)
278 #define I2C_FREQUENCY(idx) \
279 I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency))
280
281 #define I2C_NRFX_TWI_DEVICE(idx) \
282 NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \
283 BUILD_ASSERT(I2C_FREQUENCY(idx) != \
284 I2C_NRFX_TWI_INVALID_FREQUENCY, \
285 "Wrong I2C " #idx " frequency setting in dts"); \
286 static int twi_##idx##_init(const struct device *dev) \
287 { \
288 IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority), \
289 nrfx_isr, nrfx_twi_##idx##_irq_handler, 0); \
290 const struct i2c_nrfx_twi_config *config = dev->config; \
291 int err = pinctrl_apply_state(config->pcfg, \
292 PINCTRL_STATE_DEFAULT); \
293 if (err < 0) { \
294 return err; \
295 } \
296 return init_twi(dev); \
297 } \
298 static struct i2c_nrfx_twi_data twi_##idx##_data = { \
299 .transfer_sync = Z_SEM_INITIALIZER( \
300 twi_##idx##_data.transfer_sync, 1, 1), \
301 .completion_sync = Z_SEM_INITIALIZER( \
302 twi_##idx##_data.completion_sync, 0, 1) \
303 }; \
304 PINCTRL_DT_DEFINE(I2C(idx)); \
305 static const struct i2c_nrfx_twi_config twi_##idx##z_config = { \
306 .twi = NRFX_TWI_INSTANCE(idx), \
307 .config = { \
308 .skip_gpio_cfg = true, \
309 .skip_psel_cfg = true, \
310 .frequency = I2C_FREQUENCY(idx), \
311 }, \
312 .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \
313 }; \
314 PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \
315 I2C_DEVICE_DT_DEFINE(I2C(idx), \
316 twi_##idx##_init, \
317 PM_DEVICE_DT_GET(I2C(idx)), \
318 &twi_##idx##_data, \
319 &twi_##idx##z_config, \
320 POST_KERNEL, \
321 CONFIG_I2C_INIT_PRIORITY, \
322 &i2c_nrfx_twi_driver_api)
323
324 #ifdef CONFIG_HAS_HW_NRF_TWI0
325 I2C_NRFX_TWI_DEVICE(0);
326 #endif
327
328 #ifdef CONFIG_HAS_HW_NRF_TWI1
329 I2C_NRFX_TWI_DEVICE(1);
330 #endif
331