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