1 /*
2  * Copyright (c) 2018 SiFive Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT sifive_i2c0
8 
9 #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(i2c_sifive);
12 
13 #include <zephyr/device.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <soc.h>
16 #include <zephyr/sys/sys_io.h>
17 
18 #include "i2c-priv.h"
19 
20 /* Macros */
21 
22 #define I2C_REG(config, reg)	((mem_addr_t) ((config)->base + reg))
23 #define IS_SET(config, reg, value) (sys_read8(I2C_REG(config, reg)) & (value))
24 
25 /* Register Offsets */
26 
27 #define REG_PRESCALE_LOW	0x00
28 #define REG_PRESCALE_HIGH	0x04
29 
30 #define REG_CONTROL		0x08
31 
32 /* Transmit on write, receive on read */
33 #define REG_TRANSMIT		0x0c
34 #define REG_RECEIVE		0x0c
35 
36 /* Command on write, status on read */
37 #define REG_COMMAND		0x10
38 #define REG_STATUS		0x10
39 
40 /* Values */
41 
42 #define SF_CONTROL_EN	(1 << 7)
43 #define SF_CONTROL_IE	(1 << 6)
44 
45 #define SF_TX_WRITE	(0 << 0)
46 #define SF_TX_READ	(1 << 0)
47 
48 #define SF_CMD_START	(1 << 7)
49 #define SF_CMD_STOP	(1 << 6)
50 #define SF_CMD_READ	(1 << 5)
51 #define SF_CMD_WRITE	(1 << 4)
52 #define SF_CMD_ACK	(1 << 3)
53 #define SF_CMD_IACK	(1 << 0)
54 
55 #define SF_STATUS_RXACK	(1 << 7)
56 #define SF_STATUS_BUSY	(1 << 6)
57 #define SF_STATUS_AL	(1 << 5)
58 #define SF_STATUS_TIP	(1 << 1)
59 #define SF_STATUS_IP	(1 << 0)
60 
61 /* Structure declarations */
62 
63 struct i2c_sifive_cfg {
64 	uint32_t base;
65 	uint32_t f_sys;
66 	uint32_t f_bus;
67 };
68 
69 /* Helper functions */
70 
i2c_sifive_busy(const struct device * dev)71 static inline bool i2c_sifive_busy(const struct device *dev)
72 {
73 	const struct i2c_sifive_cfg *config = dev->config;
74 
75 	return IS_SET(config, REG_STATUS, SF_STATUS_TIP);
76 }
77 
i2c_sifive_send_addr(const struct device * dev,uint16_t addr,uint16_t rw_flag)78 static int i2c_sifive_send_addr(const struct device *dev,
79 				uint16_t addr,
80 				uint16_t rw_flag)
81 {
82 	const struct i2c_sifive_cfg *config = dev->config;
83 	uint8_t command = 0U;
84 
85 	/* Wait for a previous transfer to complete */
86 	while (i2c_sifive_busy(dev)) {
87 	}
88 
89 	/* Set transmit register to address with read/write flag */
90 	sys_write8((addr | rw_flag), I2C_REG(config, REG_TRANSMIT));
91 
92 	/* Addresses are always written */
93 	command = SF_CMD_WRITE | SF_CMD_START;
94 
95 	/* Write the command register to start the transfer */
96 	sys_write8(command, I2C_REG(config, REG_COMMAND));
97 
98 	while (i2c_sifive_busy(dev)) {
99 	}
100 
101 	if (IS_SET(config, REG_STATUS, SF_STATUS_RXACK)) {
102 		LOG_ERR("I2C Rx failed to acknowledge\n");
103 		return -EIO;
104 	}
105 
106 	return 0;
107 }
108 
i2c_sifive_write_msg(const struct device * dev,struct i2c_msg * msg,uint16_t addr)109 static int i2c_sifive_write_msg(const struct device *dev,
110 				struct i2c_msg *msg,
111 				uint16_t addr)
112 {
113 	const struct i2c_sifive_cfg *config = dev->config;
114 	int rc = 0;
115 	uint8_t command = 0U;
116 
117 	rc = i2c_sifive_send_addr(dev, addr, SF_TX_WRITE);
118 	if (rc != 0) {
119 		LOG_ERR("I2C failed to write message\n");
120 		return rc;
121 	}
122 
123 	for (uint32_t i = 0; i < msg->len; i++) {
124 		/* Wait for a previous transfer */
125 		while (i2c_sifive_busy(dev)) {
126 		}
127 
128 		/* Put data in transmit reg */
129 		sys_write8((msg->buf)[i], I2C_REG(config, REG_TRANSMIT));
130 
131 		/* Generate command byte */
132 		command = SF_CMD_WRITE;
133 
134 		/* On the last byte of the message */
135 		if (i == (msg->len - 1)) {
136 			/* If the stop bit is requested, set it */
137 			if (msg->flags & I2C_MSG_STOP) {
138 				command |= SF_CMD_STOP;
139 			}
140 		}
141 
142 		/* Write command reg */
143 		sys_write8(command, I2C_REG(config, REG_COMMAND));
144 
145 		/* Wait for a previous transfer */
146 		while (i2c_sifive_busy(dev)) {
147 		}
148 
149 		if (IS_SET(config, REG_STATUS, SF_STATUS_RXACK)) {
150 			LOG_ERR("I2C Rx failed to acknowledge\n");
151 			return -EIO;
152 		}
153 	}
154 
155 	return 0;
156 }
157 
i2c_sifive_read_msg(const struct device * dev,struct i2c_msg * msg,uint16_t addr)158 static int i2c_sifive_read_msg(const struct device *dev,
159 			       struct i2c_msg *msg,
160 			       uint16_t addr)
161 {
162 	const struct i2c_sifive_cfg *config = dev->config;
163 	uint8_t command = 0U;
164 
165 	i2c_sifive_send_addr(dev, addr, SF_TX_READ);
166 
167 	while (i2c_sifive_busy(dev)) {
168 	}
169 
170 	for (int i = 0; i < msg->len; i++) {
171 		/* Generate command byte */
172 		command = SF_CMD_READ;
173 
174 		/* On the last byte of the message */
175 		if (i == (msg->len - 1)) {
176 			/* Set NACK to end read */
177 			command |= SF_CMD_ACK;
178 
179 			/* If the stop bit is requested, set it */
180 			if (msg->flags & I2C_MSG_STOP) {
181 				command |= SF_CMD_STOP;
182 			}
183 		}
184 
185 		/* Write command reg */
186 		sys_write8(command, I2C_REG(config, REG_COMMAND));
187 
188 		/* Wait for the read to complete */
189 		while (i2c_sifive_busy(dev)) {
190 		}
191 
192 		/* Store the received byte */
193 		(msg->buf)[i] = sys_read8(I2C_REG(config, REG_RECEIVE));
194 	}
195 
196 	return 0;
197 }
198 
199 /* API Functions */
200 
i2c_sifive_configure(const struct device * dev,uint32_t dev_config)201 static int i2c_sifive_configure(const struct device *dev, uint32_t dev_config)
202 {
203 	const struct i2c_sifive_cfg *config = NULL;
204 	uint32_t i2c_speed = 0U;
205 	uint16_t prescale = 0U;
206 
207 	/* Check for NULL pointers */
208 	if (dev == NULL) {
209 		LOG_ERR("Device handle is NULL");
210 		return -EINVAL;
211 	}
212 	config = dev->config;
213 	if (config == NULL) {
214 		LOG_ERR("Device config is NULL");
215 		return -EINVAL;
216 	}
217 
218 	/* Disable the I2C peripheral */
219 	sys_write8(0, I2C_REG(config, REG_CONTROL));
220 
221 	/* Configure bus frequency */
222 	switch (I2C_SPEED_GET(dev_config)) {
223 	case I2C_SPEED_STANDARD:
224 		i2c_speed = 100000U; /* 100 KHz */
225 		break;
226 	case I2C_SPEED_FAST:
227 		i2c_speed = 400000U; /* 400 KHz */
228 		break;
229 	case I2C_SPEED_FAST_PLUS:
230 	case I2C_SPEED_HIGH:
231 	case I2C_SPEED_ULTRA:
232 	default:
233 		LOG_ERR("Unsupported I2C speed requested");
234 		return -ENOTSUP;
235 	}
236 
237 	/* Calculate prescale value */
238 	prescale = (config->f_sys / (i2c_speed * 5U)) - 1;
239 
240 	/* Configure peripheral with calculated prescale */
241 	sys_write8((uint8_t) (0xFF & prescale), I2C_REG(config, REG_PRESCALE_LOW));
242 	sys_write8((uint8_t) (0xFF & (prescale >> 8)),
243 		   I2C_REG(config, REG_PRESCALE_HIGH));
244 
245 	/* Support I2C Master mode only */
246 	if (!(dev_config & I2C_MODE_CONTROLLER)) {
247 		LOG_ERR("I2C only supports operation as master");
248 		return -ENOTSUP;
249 	}
250 
251 	/*
252 	 * Driver does not support 10-bit addressing. This can be added
253 	 * in the future when needed.
254 	 */
255 	if (dev_config & I2C_ADDR_10_BITS) {
256 		LOG_ERR("I2C driver does not support 10-bit addresses");
257 		return -ENOTSUP;
258 	}
259 
260 	/* Enable the I2C peripheral */
261 	sys_write8(SF_CONTROL_EN, I2C_REG(config, REG_CONTROL));
262 
263 	return 0;
264 }
265 
i2c_sifive_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)266 static int i2c_sifive_transfer(const struct device *dev,
267 			       struct i2c_msg *msgs,
268 			       uint8_t num_msgs,
269 			       uint16_t addr)
270 {
271 	int rc = 0;
272 
273 	/* Check for NULL pointers */
274 	if (dev == NULL) {
275 		LOG_ERR("Device handle is NULL");
276 		return -EINVAL;
277 	}
278 	if (dev->config == NULL) {
279 		LOG_ERR("Device config is NULL");
280 		return -EINVAL;
281 	}
282 	if (msgs == NULL) {
283 		return -EINVAL;
284 	}
285 
286 	for (int i = 0; i < num_msgs; i++) {
287 		if (msgs[i].flags & I2C_MSG_READ) {
288 			rc = i2c_sifive_read_msg(dev, &(msgs[i]), addr);
289 		} else {
290 			rc = i2c_sifive_write_msg(dev, &(msgs[i]), addr);
291 		}
292 
293 		if (rc != 0) {
294 			LOG_ERR("I2C failed to transfer messages\n");
295 			return rc;
296 		}
297 	}
298 
299 	return 0;
300 };
301 
i2c_sifive_init(const struct device * dev)302 static int i2c_sifive_init(const struct device *dev)
303 {
304 	const struct i2c_sifive_cfg *config = dev->config;
305 	uint32_t dev_config = 0U;
306 	int rc = 0;
307 
308 	dev_config = (I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->f_bus));
309 
310 	rc = i2c_sifive_configure(dev, dev_config);
311 	if (rc != 0) {
312 		LOG_ERR("Failed to configure I2C on init");
313 		return rc;
314 	}
315 
316 	return 0;
317 }
318 
319 
320 static const struct i2c_driver_api i2c_sifive_api = {
321 	.configure = i2c_sifive_configure,
322 	.transfer = i2c_sifive_transfer,
323 };
324 
325 /* Device instantiation */
326 
327 #define I2C_SIFIVE_INIT(n) \
328 	static struct i2c_sifive_cfg i2c_sifive_cfg_##n = { \
329 		.base = DT_INST_REG_ADDR(n), \
330 		.f_sys = SIFIVE_PERIPHERAL_CLOCK_FREQUENCY, \
331 		.f_bus = DT_INST_PROP(n, clock_frequency), \
332 	}; \
333 	I2C_DEVICE_DT_INST_DEFINE(n, \
334 			    i2c_sifive_init, \
335 			    NULL, \
336 			    NULL, \
337 			    &i2c_sifive_cfg_##n, \
338 			    POST_KERNEL, \
339 			    CONFIG_I2C_INIT_PRIORITY, \
340 			    &i2c_sifive_api);
341 
342 DT_INST_FOREACH_STATUS_OKAY(I2C_SIFIVE_INIT)
343