1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2018 Arm Ltd.
4  * Author: Liviu Dudau <liviu.dudau@foss.arm.com>
5  *
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <i2c.h>
12 #include <asm/io.h>
13 #include <clk.h>
14 #include <linux/bitops.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 
18 #define I2C_CONTROL_REG		0x00
19 #define I2C_SET_REG		0x00
20 #define I2C_CLEAR_REG		0x04
21 
22 #define SCL	BIT(0)
23 #define SDA	BIT(1)
24 
25 struct versatile_i2c_priv {
26 	phys_addr_t base;
27 	u32 delay;
28 };
29 
versatile_sda_set(struct versatile_i2c_priv * priv,u8 state)30 static inline void versatile_sda_set(struct versatile_i2c_priv *priv, u8 state)
31 {
32 	writel(SDA, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG));
33 	udelay(priv->delay);
34 }
35 
versatile_sda_get(struct versatile_i2c_priv * priv)36 static inline int versatile_sda_get(struct versatile_i2c_priv *priv)
37 {
38 	int v = !!(readl(priv->base + I2C_CONTROL_REG) & SDA);
39 
40 	udelay(priv->delay);
41 	return v;
42 }
43 
versatile_scl_set(struct versatile_i2c_priv * priv,u8 state)44 static inline void versatile_scl_set(struct versatile_i2c_priv *priv, u8 state)
45 {
46 	writel(SCL, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG));
47 	udelay(priv->delay);
48 }
49 
versatile_scl_get(struct versatile_i2c_priv * priv)50 static inline int versatile_scl_get(struct versatile_i2c_priv *priv)
51 {
52 	int v = !!(readl(priv->base + I2C_CONTROL_REG) & SCL);
53 
54 	udelay(priv->delay);
55 	return v;
56 }
57 
58 /* start: SDA goes from high to low while SCL is high */
versatile_i2c_start(struct versatile_i2c_priv * priv)59 static void versatile_i2c_start(struct versatile_i2c_priv *priv)
60 {
61 	udelay(priv->delay);
62 	versatile_sda_set(priv, 1);
63 	versatile_scl_set(priv, 1);
64 	versatile_sda_set(priv, 0);
65 }
66 
67 /* stop: SDA goes from low to high while SCL is high */
versatile_i2c_stop(struct versatile_i2c_priv * priv)68 static void versatile_i2c_stop(struct versatile_i2c_priv *priv)
69 {
70 	versatile_scl_set(priv, 0);
71 	versatile_sda_set(priv, 0);
72 	versatile_scl_set(priv, 1);
73 	versatile_sda_set(priv, 1);
74 }
75 
76 /* read a bit from the SDA line (data or ACK/NACK) */
versatile_i2c_read_bit(struct versatile_i2c_priv * priv)77 static u8 versatile_i2c_read_bit(struct versatile_i2c_priv *priv)
78 {
79 	versatile_scl_set(priv, 0);
80 	versatile_sda_set(priv, 1);
81 	versatile_scl_set(priv, 1);
82 	udelay(priv->delay);
83 	return (u8)versatile_sda_get(priv);
84 }
85 
86 /* write a bit on the SDA line */
versatile_i2c_write_bit(struct versatile_i2c_priv * priv,u8 bit)87 static void versatile_i2c_write_bit(struct versatile_i2c_priv *priv, u8 bit)
88 {
89 	versatile_scl_set(priv, 0);
90 	versatile_sda_set(priv, bit);
91 	versatile_scl_set(priv, 1);
92 	udelay(priv->delay);
93 }
94 
95 /* send a reset sequence of 9 clocks with SDA high */
versatile_i2c_reset_bus(struct versatile_i2c_priv * priv)96 static void versatile_i2c_reset_bus(struct versatile_i2c_priv *priv)
97 {
98 	int i;
99 
100 	for (i = 0; i < 9; i++)
101 		versatile_i2c_write_bit(priv, 1);
102 
103 	versatile_i2c_stop(priv);
104 }
105 
106 /* write byte without start/stop sequence */
versatile_i2c_write_byte(struct versatile_i2c_priv * priv,u8 byte)107 static int versatile_i2c_write_byte(struct versatile_i2c_priv *priv, u8 byte)
108 {
109 	u8 nak, i;
110 
111 	for (i = 0; i < 8; i++) {
112 		versatile_i2c_write_bit(priv, byte & 0x80);
113 		byte <<= 1;
114 	}
115 
116 	/* read ACK */
117 	nak = versatile_i2c_read_bit(priv);
118 	versatile_scl_set(priv, 0);
119 
120 	return nak;	/* not a nack is an ack */
121 }
122 
versatile_i2c_read_byte(struct versatile_i2c_priv * priv,u8 * byte,u8 ack)123 static int versatile_i2c_read_byte(struct versatile_i2c_priv *priv,
124 				   u8 *byte, u8 ack)
125 {
126 	u8 i;
127 
128 	*byte = 0;
129 	for (i = 0; i < 8; i++) {
130 		*byte <<= 1;
131 		*byte |= versatile_i2c_read_bit(priv);
132 	}
133 	/* write the nack */
134 	versatile_i2c_write_bit(priv, ack);
135 
136 	return 0;
137 }
138 
versatile_i2c_send_slave_addr(struct versatile_i2c_priv * priv,struct i2c_msg * msg)139 static int versatile_i2c_send_slave_addr(struct versatile_i2c_priv *priv,
140 					 struct i2c_msg *msg)
141 {
142 	u8 addr;
143 	int ret;
144 
145 	if (msg->flags & I2C_M_TEN) {
146 		/* 10-bit address, send extended address code first */
147 		addr = 0xf0 | ((msg->addr >> 7) & 0x06);
148 		ret = versatile_i2c_write_byte(priv, addr);
149 		if (ret) {
150 			versatile_i2c_stop(priv);
151 			return -EIO;
152 		}
153 
154 		/* remaining bits */
155 		ret = versatile_i2c_write_byte(priv, msg->addr & 0xff);
156 		if (ret) {
157 			versatile_i2c_stop(priv);
158 			return -EIO;
159 		}
160 		/* reads need to resend the addr */
161 		if (msg->flags & I2C_M_RD) {
162 			versatile_i2c_start(priv);
163 			addr |= 1;
164 			ret = versatile_i2c_write_byte(priv, addr);
165 			if (ret) {
166 				versatile_i2c_stop(priv);
167 				return -EIO;
168 			}
169 		}
170 	} else {
171 		/* normal 7-bit address */
172 		addr = msg->addr << 1;
173 		if (msg->flags & I2C_M_RD)
174 			addr |= 1;
175 		ret = versatile_i2c_write_byte(priv, addr);
176 		if (ret) {
177 			versatile_i2c_stop(priv);
178 			return -EIO;
179 		}
180 	}
181 
182 	return 0;
183 }
184 
versatile_i2c_message_xfer(struct versatile_i2c_priv * priv,struct i2c_msg * msg)185 static int versatile_i2c_message_xfer(struct versatile_i2c_priv *priv,
186 				      struct i2c_msg *msg)
187 {
188 	int i, ret;
189 	u8 ack;
190 
191 	versatile_i2c_start(priv);
192 	if (versatile_i2c_send_slave_addr(priv, msg))
193 		return -EIO;
194 
195 	for (i = 0; i < msg->len; i++) {
196 		if (msg->flags & I2C_M_RD) {
197 			ack = (msg->len - i - 1) == 0 ? 1 : 0;
198 			ret = versatile_i2c_read_byte(priv, &msg->buf[i], ack);
199 		} else {
200 			ret = versatile_i2c_write_byte(priv, msg->buf[i]);
201 		}
202 
203 		if (ret)
204 			break;
205 	}
206 
207 	versatile_i2c_stop(priv);
208 
209 	return ret;
210 }
211 
versatile_i2c_xfer(struct udevice * bus,struct i2c_msg * msg,int nmsgs)212 static int versatile_i2c_xfer(struct udevice *bus,
213 			      struct i2c_msg *msg, int nmsgs)
214 {
215 	struct versatile_i2c_priv *priv = dev_get_priv(bus);
216 	int ret;
217 
218 	for ( ; nmsgs > 0; nmsgs--, msg++) {
219 		ret = versatile_i2c_message_xfer(priv, msg);
220 		if (ret)
221 			return -EREMOTEIO;
222 	}
223 
224 	return 0;
225 }
226 
versatile_i2c_chip_probe(struct udevice * bus,uint chip,uint chip_flags)227 static int versatile_i2c_chip_probe(struct udevice *bus,
228 				    uint chip, uint chip_flags)
229 {
230 	/* probe the presence of a slave by writing a 0-size message */
231 	struct i2c_msg msg = { .addr = chip, .flags = chip_flags,
232 			       .len = 0, .buf = NULL };
233 	struct versatile_i2c_priv *priv = dev_get_priv(bus);
234 
235 	return versatile_i2c_message_xfer(priv, &msg);
236 }
237 
versatile_i2c_set_bus_speed(struct udevice * bus,unsigned int speed)238 static int versatile_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
239 {
240 	struct versatile_i2c_priv *priv = dev_get_priv(bus);
241 
242 	priv->delay = 1000000 / (speed << 2);
243 
244 	versatile_i2c_reset_bus(priv);
245 
246 	return 0;
247 }
248 
versatile_i2c_probe(struct udevice * dev)249 static int versatile_i2c_probe(struct udevice *dev)
250 {
251 	struct versatile_i2c_priv *priv = dev_get_priv(dev);
252 
253 	priv->base = (phys_addr_t)dev_read_addr(dev);
254 	priv->delay = 25;	/* 25us * 4 = 100kHz */
255 
256 	return 0;
257 }
258 
259 static const struct dm_i2c_ops versatile_i2c_ops = {
260 	.xfer = versatile_i2c_xfer,
261 	.probe_chip = versatile_i2c_chip_probe,
262 	.set_bus_speed = versatile_i2c_set_bus_speed,
263 };
264 
265 static const struct udevice_id versatile_i2c_of_match[] = {
266 	{ .compatible = "arm,versatile-i2c" },
267 	{ }
268 };
269 
270 U_BOOT_DRIVER(versatile_i2c) = {
271 	.name = "i2c-bus-versatile",
272 	.id = UCLASS_I2C,
273 	.of_match = versatile_i2c_of_match,
274 	.probe = versatile_i2c_probe,
275 	.priv_auto	= sizeof(struct versatile_i2c_priv),
276 	.ops = &versatile_i2c_ops,
277 };
278