common: Drop linux/bitops.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/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
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
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
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
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 */
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 */
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) */
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 */
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 */
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 */
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
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
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
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
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
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
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
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          * U-Boot still doesn't assign automatically
257          * sequence numbers to devices
258          */
259         dev->req_seq = 1;
260
261         return 0;
262 }
263
264 static const struct dm_i2c_ops versatile_i2c_ops = {
265         .xfer = versatile_i2c_xfer,
266         .probe_chip = versatile_i2c_chip_probe,
267         .set_bus_speed = versatile_i2c_set_bus_speed,
268 };
269
270 static const struct udevice_id versatile_i2c_of_match[] = {
271         { .compatible = "arm,versatile-i2c" },
272         { }
273 };
274
275 U_BOOT_DRIVER(versatile_i2c) = {
276         .name = "i2c-bus-versatile",
277         .id = UCLASS_I2C,
278         .of_match = versatile_i2c_of_match,
279         .probe = versatile_i2c_probe,
280         .priv_auto_alloc_size = sizeof(struct versatile_i2c_priv),
281         .ops = &versatile_i2c_ops,
282 };