1 /*
2  * Copyright (c) 2018, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #include <drivers/i2c.h>
9 #include <dt-bindings/i2c/i2c.h>
10 #include <nrfx_twi.h>
11 
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL);
14 
15 #define I2C_TRANSFER_TIMEOUT_MSEC		K_MSEC(500)
16 
17 struct i2c_nrfx_twi_data {
18 	struct k_sem transfer_sync;
19 	struct k_sem completion_sync;
20 	volatile nrfx_err_t res;
21 	uint32_t dev_config;
22 };
23 
24 struct i2c_nrfx_twi_config {
25 	nrfx_twi_t twi;
26 	nrfx_twi_config_t config;
27 };
28 
get_dev_data(const struct device * dev)29 static inline struct i2c_nrfx_twi_data *get_dev_data(const struct device *dev)
30 {
31 	return dev->data;
32 }
33 
34 static inline
get_dev_config(const struct device * dev)35 const struct i2c_nrfx_twi_config *get_dev_config(const struct device *dev)
36 {
37 	return dev->config;
38 }
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 	int ret = 0;
45 
46 	k_sem_take(&(get_dev_data(dev)->transfer_sync), K_FOREVER);
47 
48 	/* Dummy take on completion_sync sem to be sure that it is empty */
49 	k_sem_take(&(get_dev_data(dev)->completion_sync), K_NO_WAIT);
50 
51 	nrfx_twi_enable(&get_dev_config(dev)->twi);
52 
53 	for (size_t i = 0; i < num_msgs; i++) {
54 		if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) {
55 			ret = -ENOTSUP;
56 			break;
57 		}
58 
59 		nrfx_twi_xfer_desc_t cur_xfer = {
60 			.p_primary_buf  = msgs[i].buf,
61 			.primary_length = msgs[i].len,
62 			.address	= addr,
63 			.type		= (msgs[i].flags & I2C_MSG_READ) ?
64 					  NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX
65 		};
66 		uint32_t xfer_flags = 0;
67 		nrfx_err_t res;
68 
69 		/* In case the STOP condition is not supposed to appear after
70 		 * the current message, check what is requested further:
71 		 */
72 		if (!(msgs[i].flags & I2C_MSG_STOP)) {
73 			/* - if the transfer consists of more messages
74 			 *   and the I2C repeated START is not requested
75 			 *   to appear before the next message, suspend
76 			 *   the transfer after the current message,
77 			 *   so that it can be resumed with the next one,
78 			 *   resulting in the two messages merged into
79 			 *   a continuous transfer on the bus
80 			 */
81 			if ((i < (num_msgs - 1)) &&
82 			    !(msgs[i + 1].flags & I2C_MSG_RESTART)) {
83 				xfer_flags |= NRFX_TWI_FLAG_SUSPEND;
84 			/* - otherwise, just finish the transfer without
85 			 *   generating the STOP condition, unless the current
86 			 *   message is an RX request, for which such feature
87 			 *   is not supported
88 			 */
89 			} else if (msgs[i].flags & I2C_MSG_READ) {
90 				ret = -ENOTSUP;
91 				break;
92 			} else {
93 				xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP;
94 			}
95 		}
96 
97 		res = nrfx_twi_xfer(&get_dev_config(dev)->twi,
98 				    &cur_xfer,
99 				    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(&(get_dev_data(dev)->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 nrfx_twi_bus_recover() to
126 			 * 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(&get_dev_config(dev)->twi);
131 			nrfx_twi_bus_recover(get_dev_config(dev)->config.scl,
132 					     get_dev_config(dev)->config.sda);
133 			ret = -EIO;
134 			break;
135 		}
136 
137 		res = get_dev_data(dev)->res;
138 		if (res != NRFX_SUCCESS) {
139 			LOG_ERR("Error 0x%08X occurred for message %d", res, i);
140 			ret = -EIO;
141 			break;
142 		}
143 	}
144 
145 	nrfx_twi_disable(&get_dev_config(dev)->twi);
146 	k_sem_give(&(get_dev_data(dev)->transfer_sync));
147 
148 	return ret;
149 }
150 
event_handler(nrfx_twi_evt_t const * p_event,void * p_context)151 static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context)
152 {
153 	struct i2c_nrfx_twi_data *dev_data = p_context;
154 
155 	switch (p_event->type) {
156 	case NRFX_TWI_EVT_DONE:
157 		dev_data->res = NRFX_SUCCESS;
158 		break;
159 	case NRFX_TWI_EVT_ADDRESS_NACK:
160 		dev_data->res = NRFX_ERROR_DRV_TWI_ERR_ANACK;
161 		break;
162 	case NRFX_TWI_EVT_DATA_NACK:
163 		dev_data->res = NRFX_ERROR_DRV_TWI_ERR_DNACK;
164 		break;
165 	default:
166 		dev_data->res = NRFX_ERROR_INTERNAL;
167 		break;
168 	}
169 
170 	k_sem_give(&dev_data->completion_sync);
171 }
172 
i2c_nrfx_twi_configure(const struct device * dev,uint32_t dev_config)173 static int i2c_nrfx_twi_configure(const struct device *dev,
174 				  uint32_t dev_config)
175 {
176 	nrfx_twi_t const *inst = &(get_dev_config(dev)->twi);
177 
178 	if (I2C_ADDR_10_BITS & dev_config) {
179 		return -EINVAL;
180 	}
181 
182 	switch (I2C_SPEED_GET(dev_config)) {
183 	case I2C_SPEED_STANDARD:
184 		nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K);
185 		break;
186 	case I2C_SPEED_FAST:
187 		nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K);
188 		break;
189 	default:
190 		LOG_ERR("unsupported speed");
191 		return -EINVAL;
192 	}
193 	get_dev_data(dev)->dev_config = dev_config;
194 
195 	return 0;
196 }
197 
198 static const struct i2c_driver_api i2c_nrfx_twi_driver_api = {
199 	.configure = i2c_nrfx_twi_configure,
200 	.transfer  = i2c_nrfx_twi_transfer,
201 };
202 
init_twi(const struct device * dev)203 static int init_twi(const struct device *dev)
204 {
205 	struct i2c_nrfx_twi_data *dev_data = get_dev_data(dev);
206 	nrfx_err_t result = nrfx_twi_init(&get_dev_config(dev)->twi,
207 					  &get_dev_config(dev)->config,
208 					  event_handler, dev_data);
209 	if (result != NRFX_SUCCESS) {
210 		LOG_ERR("Failed to initialize device: %s",
211 			    dev->name);
212 		return -EBUSY;
213 	}
214 
215 	return 0;
216 }
217 
218 #ifdef CONFIG_PM_DEVICE
twi_nrfx_pm_control(const struct device * dev,enum pm_device_action action)219 static int twi_nrfx_pm_control(const struct device *dev,
220 			       enum pm_device_action action)
221 {
222 	int ret = 0;
223 
224 	switch (action) {
225 	case PM_DEVICE_ACTION_RESUME:
226 		init_twi(dev);
227 		if (get_dev_data(dev)->dev_config) {
228 			i2c_nrfx_twi_configure(dev,
229 					       get_dev_data(dev)->dev_config);
230 		}
231 		break;
232 
233 	case PM_DEVICE_ACTION_SUSPEND:
234 		nrfx_twi_uninit(&get_dev_config(dev)->twi);
235 		break;
236 
237 	default:
238 		ret = -ENOTSUP;
239 	}
240 
241 	return ret;
242 }
243 #endif /* CONFIG_PM_DEVICE */
244 
245 #define I2C_NRFX_TWI_INVALID_FREQUENCY  ((nrf_twi_frequency_t)-1)
246 #define I2C_NRFX_TWI_FREQUENCY(bitrate)					       \
247 	 (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K		       \
248 	: bitrate == 250000               ? NRF_TWI_FREQ_250K		       \
249 	: bitrate == I2C_BITRATE_FAST     ? NRF_TWI_FREQ_400K		       \
250 					  : I2C_NRFX_TWI_INVALID_FREQUENCY)
251 #define I2C(idx) DT_NODELABEL(i2c##idx)
252 #define I2C_FREQUENCY(idx)						       \
253 	I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency))
254 
255 #define I2C_NRFX_TWI_DEVICE(idx)					       \
256 	BUILD_ASSERT(I2C_FREQUENCY(idx)	!=				       \
257 		     I2C_NRFX_TWI_INVALID_FREQUENCY,			       \
258 		     "Wrong I2C " #idx " frequency setting in dts");	       \
259 	static int twi_##idx##_init(const struct device *dev)		\
260 	{								       \
261 		IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority),     \
262 			    nrfx_isr, nrfx_twi_##idx##_irq_handler, 0);	       \
263 		return init_twi(dev);					       \
264 	}								       \
265 	static struct i2c_nrfx_twi_data twi_##idx##_data = {		       \
266 		.transfer_sync = Z_SEM_INITIALIZER(                            \
267 			twi_##idx##_data.transfer_sync, 1, 1),                 \
268 		.completion_sync = Z_SEM_INITIALIZER(                          \
269 			twi_##idx##_data.completion_sync, 0, 1)		       \
270 	};								       \
271 	static const struct i2c_nrfx_twi_config twi_##idx##z_config = {	       \
272 		.twi = NRFX_TWI_INSTANCE(idx),				       \
273 		.config = {						       \
274 			.scl       = DT_PROP(I2C(idx), scl_pin),	       \
275 			.sda       = DT_PROP(I2C(idx), sda_pin),	       \
276 			.frequency = I2C_FREQUENCY(idx),		       \
277 		}							       \
278 	};								       \
279 	DEVICE_DT_DEFINE(I2C(idx),					       \
280 		      twi_##idx##_init,					       \
281 		      twi_nrfx_pm_control,				       \
282 		      &twi_##idx##_data,				       \
283 		      &twi_##idx##z_config,				       \
284 		      POST_KERNEL,					       \
285 		      CONFIG_I2C_INIT_PRIORITY,				       \
286 		      &i2c_nrfx_twi_driver_api)
287 
288 #ifdef CONFIG_I2C_0_NRF_TWI
289 I2C_NRFX_TWI_DEVICE(0);
290 #endif
291 
292 #ifdef CONFIG_I2C_1_NRF_TWI
293 I2C_NRFX_TWI_DEVICE(1);
294 #endif
295