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