674561b4ad7ebcdd97538f94b8c6a5e20b51006f
[oweals/u-boot.git] / drivers / i2c / ihs_i2c.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2013
4  * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
5  */
6
7 #include <common.h>
8 #include <i2c.h>
9 #ifdef CONFIG_DM_I2C
10 #include <dm.h>
11 #include <regmap.h>
12 #else
13 #include <gdsys_fpga.h>
14 #endif
15 #include <log.h>
16 #include <asm/unaligned.h>
17
18 #ifdef CONFIG_DM_I2C
19 struct ihs_i2c_priv {
20         uint speed;
21         struct regmap *map;
22 };
23
24 struct ihs_i2c_regs {
25         u16 interrupt_status;
26         u16 interrupt_enable_control;
27         u16 write_mailbox_ext;
28         u16 write_mailbox;
29         u16 read_mailbox_ext;
30         u16 read_mailbox;
31 };
32
33 #define ihs_i2c_set(map, member, val) \
34         regmap_set(map, struct ihs_i2c_regs, member, val)
35
36 #define ihs_i2c_get(map, member, valp) \
37         regmap_get(map, struct ihs_i2c_regs, member, valp)
38
39 #else /* !CONFIG_DM_I2C */
40 DECLARE_GLOBAL_DATA_PTR;
41
42 #ifdef CONFIG_SYS_I2C_IHS_DUAL
43
44 #define I2C_SET_REG(fld, val) \
45         do { \
46                 if (I2C_ADAP_HWNR & 0x10) \
47                         FPGA_SET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
48                 else \
49                         FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
50         } while (0)
51 #else
52 #define I2C_SET_REG(fld, val) \
53                 FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
54 #endif
55
56 #ifdef CONFIG_SYS_I2C_IHS_DUAL
57 #define I2C_GET_REG(fld, val) \
58         do {                                    \
59                 if (I2C_ADAP_HWNR & 0x10) \
60                         FPGA_GET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
61                 else \
62                         FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
63         } while (0)
64 #else
65 #define I2C_GET_REG(fld, val) \
66                 FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
67 #endif
68 #endif /* CONFIG_DM_I2C */
69
70 enum {
71         I2CINT_ERROR_EV = BIT(13),
72         I2CINT_TRANSMIT_EV = BIT(14),
73         I2CINT_RECEIVE_EV = BIT(15),
74 };
75
76 enum {
77         I2CMB_READ = 0 << 10,
78         I2CMB_WRITE = 1 << 10,
79         I2CMB_1BYTE = 0 << 11,
80         I2CMB_2BYTE = 1 << 11,
81         I2CMB_DONT_HOLD_BUS = 0 << 13,
82         I2CMB_HOLD_BUS = 1 << 13,
83         I2CMB_NATIVE = 2 << 14,
84 };
85
86 enum {
87         I2COP_WRITE = 0,
88         I2COP_READ = 1,
89 };
90
91 #ifdef CONFIG_DM_I2C
92 static int wait_for_int(struct udevice *dev, int read)
93 #else
94 static int wait_for_int(bool read)
95 #endif
96 {
97         u16 val;
98         uint ctr = 0;
99 #ifdef CONFIG_DM_I2C
100         struct ihs_i2c_priv *priv = dev_get_priv(dev);
101 #endif
102
103 #ifdef CONFIG_DM_I2C
104         ihs_i2c_get(priv->map, interrupt_status, &val);
105 #else
106         I2C_GET_REG(interrupt_status, &val);
107 #endif
108         /* Wait until error or receive/transmit interrupt was raised */
109         while (!(val & (I2CINT_ERROR_EV
110                | (read ? I2CINT_RECEIVE_EV : I2CINT_TRANSMIT_EV)))) {
111                 udelay(10);
112                 if (ctr++ > 5000) {
113                         debug("%s: timed out\n", __func__);
114                         return -ETIMEDOUT;
115                 }
116 #ifdef CONFIG_DM_I2C
117                 ihs_i2c_get(priv->map, interrupt_status, &val);
118 #else
119                 I2C_GET_REG(interrupt_status, &val);
120 #endif
121         }
122
123         return (val & I2CINT_ERROR_EV) ? -EIO : 0;
124 }
125
126 #ifdef CONFIG_DM_I2C
127 static int ihs_i2c_transfer(struct udevice *dev, uchar chip,
128                             uchar *buffer, int len, int read, bool is_last)
129 #else
130 static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
131                             bool is_last)
132 #endif
133 {
134         u16 val;
135         u16 data;
136         int res;
137 #ifdef CONFIG_DM_I2C
138         struct ihs_i2c_priv *priv = dev_get_priv(dev);
139 #endif
140
141         /* Clear interrupt status */
142         data = I2CINT_ERROR_EV | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV;
143 #ifdef CONFIG_DM_I2C
144         ihs_i2c_set(priv->map, interrupt_status, data);
145         ihs_i2c_get(priv->map, interrupt_status, &val);
146 #else
147         I2C_SET_REG(interrupt_status, data);
148         I2C_GET_REG(interrupt_status, &val);
149 #endif
150
151         /* If we want to write and have data, write the bytes to the mailbox */
152         if (!read && len) {
153                 val = buffer[0];
154
155                 if (len > 1)
156                         val |= buffer[1] << 8;
157 #ifdef CONFIG_DM_I2C
158                 ihs_i2c_set(priv->map, write_mailbox_ext, val);
159 #else
160                 I2C_SET_REG(write_mailbox_ext, val);
161 #endif
162         }
163
164         data = I2CMB_NATIVE
165                | (read ? 0 : I2CMB_WRITE)
166                | (chip << 1)
167                | ((len > 1) ? I2CMB_2BYTE : 0)
168                | (is_last ? 0 : I2CMB_HOLD_BUS);
169
170 #ifdef CONFIG_DM_I2C
171         ihs_i2c_set(priv->map, write_mailbox, data);
172 #else
173         I2C_SET_REG(write_mailbox, data);
174 #endif
175
176 #ifdef CONFIG_DM_I2C
177         res = wait_for_int(dev, read);
178 #else
179         res = wait_for_int(read);
180 #endif
181         if (res) {
182                 if (res == -ETIMEDOUT)
183                         debug("%s: time out while waiting for event\n", __func__);
184
185                 return res;
186         }
187
188         /* If we want to read, get the bytes from the mailbox */
189         if (read) {
190 #ifdef CONFIG_DM_I2C
191                 ihs_i2c_get(priv->map, read_mailbox_ext, &val);
192 #else
193                 I2C_GET_REG(read_mailbox_ext, &val);
194 #endif
195                 buffer[0] = val & 0xff;
196                 if (len > 1)
197                         buffer[1] = val >> 8;
198         }
199
200         return 0;
201 }
202
203 #ifdef CONFIG_DM_I2C
204 static int ihs_i2c_send_buffer(struct udevice *dev, uchar chip, u8 *data, int len, bool hold_bus, int read)
205 #else
206 static int ihs_i2c_send_buffer(uchar chip, u8 *data, int len, bool hold_bus,
207                                int read)
208 #endif
209 {
210         int res;
211
212         while (len) {
213                 int transfer = min(len, 2);
214                 bool is_last = len <= transfer;
215
216 #ifdef CONFIG_DM_I2C
217                 res = ihs_i2c_transfer(dev, chip, data, transfer, read,
218                                        hold_bus ? false : is_last);
219 #else
220                 res = ihs_i2c_transfer(chip, data, transfer, read,
221                                        hold_bus ? false : is_last);
222 #endif
223                 if (res)
224                         return res;
225
226                 data += transfer;
227                 len -= transfer;
228         }
229
230         return 0;
231 }
232
233 #ifdef CONFIG_DM_I2C
234 static int ihs_i2c_address(struct udevice *dev, uchar chip, u8 *addr, int alen,
235                            bool hold_bus)
236 #else
237 static int ihs_i2c_address(uchar chip, u8 *addr, int alen, bool hold_bus)
238 #endif
239 {
240 #ifdef CONFIG_DM_I2C
241         return ihs_i2c_send_buffer(dev, chip, addr, alen, hold_bus, I2COP_WRITE);
242 #else
243         return ihs_i2c_send_buffer(chip, addr, alen, hold_bus, I2COP_WRITE);
244 #endif
245 }
246
247 #ifdef CONFIG_DM_I2C
248 static int ihs_i2c_access(struct udevice *dev, uchar chip, u8 *addr,
249                           int alen, uchar *buffer, int len, int read)
250 #else
251 static int ihs_i2c_access(struct i2c_adapter *adap, uchar chip, u8 *addr,
252                           int alen, uchar *buffer, int len, int read)
253 #endif
254 {
255         int res;
256
257         /* Don't hold the bus if length of data to send/receive is zero */
258         if (len <= 0)
259                 return -EINVAL;
260
261 #ifdef CONFIG_DM_I2C
262         res = ihs_i2c_address(dev, chip, addr, alen, len);
263 #else
264         res = ihs_i2c_address(chip, addr, alen, len);
265 #endif
266         if (res)
267                 return res;
268
269 #ifdef CONFIG_DM_I2C
270         return ihs_i2c_send_buffer(dev, chip, buffer, len, false, read);
271 #else
272         return ihs_i2c_send_buffer(chip, buffer, len, false, read);
273 #endif
274 }
275
276 #ifdef CONFIG_DM_I2C
277
278 int ihs_i2c_probe(struct udevice *bus)
279 {
280         struct ihs_i2c_priv *priv = dev_get_priv(bus);
281
282         regmap_init_mem(dev_ofnode(bus), &priv->map);
283
284         return 0;
285 }
286
287 static int ihs_i2c_set_bus_speed(struct udevice *bus, uint speed)
288 {
289         struct ihs_i2c_priv *priv = dev_get_priv(bus);
290
291         if (speed != priv->speed && priv->speed != 0)
292                 return -EINVAL;
293
294         priv->speed = speed;
295
296         return 0;
297 }
298
299 static int ihs_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
300 {
301         struct i2c_msg *dmsg, *omsg, dummy;
302
303         memset(&dummy, 0, sizeof(struct i2c_msg));
304
305         /* We expect either two messages (one with an offset and one with the
306          * actucal data) or one message (just data)
307          */
308         if (nmsgs > 2 || nmsgs == 0) {
309                 debug("%s: Only one or two messages are supported\n", __func__);
310                 return -ENOTSUPP;
311         }
312
313         omsg = nmsgs == 1 ? &dummy : msg;
314         dmsg = nmsgs == 1 ? msg : msg + 1;
315
316         if (dmsg->flags & I2C_M_RD)
317                 return ihs_i2c_access(bus, dmsg->addr, omsg->buf,
318                                       omsg->len, dmsg->buf, dmsg->len,
319                                       I2COP_READ);
320         else
321                 return ihs_i2c_access(bus, dmsg->addr, omsg->buf,
322                                       omsg->len, dmsg->buf, dmsg->len,
323                                       I2COP_WRITE);
324 }
325
326 static int ihs_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
327                               u32 chip_flags)
328 {
329         uchar buffer[2];
330         int res;
331
332         res = ihs_i2c_transfer(bus, chip_addr, buffer, 0, I2COP_READ, true);
333         if (res)
334                 return res;
335
336         return 0;
337 }
338
339 static const struct dm_i2c_ops ihs_i2c_ops = {
340         .xfer           = ihs_i2c_xfer,
341         .probe_chip     = ihs_i2c_probe_chip,
342         .set_bus_speed  = ihs_i2c_set_bus_speed,
343 };
344
345 static const struct udevice_id ihs_i2c_ids[] = {
346         { .compatible = "gdsys,ihs_i2cmaster", },
347         { /* sentinel */ }
348 };
349
350 U_BOOT_DRIVER(i2c_ihs) = {
351         .name = "i2c_ihs",
352         .id = UCLASS_I2C,
353         .of_match = ihs_i2c_ids,
354         .probe = ihs_i2c_probe,
355         .priv_auto_alloc_size = sizeof(struct ihs_i2c_priv),
356         .ops = &ihs_i2c_ops,
357 };
358
359 #else /* CONFIG_DM_I2C */
360
361 static void ihs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
362 {
363 #ifdef CONFIG_SYS_I2C_INIT_BOARD
364         /*
365          * Call board specific i2c bus reset routine before accessing the
366          * environment, which might be in a chip on that bus. For details
367          * about this problem see doc/I2C_Edge_Conditions.
368          */
369         i2c_init_board();
370 #endif
371 }
372
373 static int ihs_i2c_probe(struct i2c_adapter *adap, uchar chip)
374 {
375         uchar buffer[2];
376         int res;
377
378         res = ihs_i2c_transfer(chip, buffer, 0, I2COP_READ, true);
379         if (res)
380                 return res;
381
382         return 0;
383 }
384
385 static int ihs_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
386                         int alen, uchar *buffer, int len)
387 {
388         u8 addr_bytes[4];
389
390         put_unaligned_le32(addr, addr_bytes);
391
392         return ihs_i2c_access(adap, chip, addr_bytes, alen, buffer, len,
393                               I2COP_READ);
394 }
395
396 static int ihs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
397                          int alen, uchar *buffer, int len)
398 {
399         u8 addr_bytes[4];
400
401         put_unaligned_le32(addr, addr_bytes);
402
403         return ihs_i2c_access(adap, chip, addr_bytes, alen, buffer, len,
404                               I2COP_WRITE);
405 }
406
407 static unsigned int ihs_i2c_set_bus_speed(struct i2c_adapter *adap,
408                                           unsigned int speed)
409 {
410         if (speed != adap->speed)
411                 return -EINVAL;
412         return speed;
413 }
414
415 /*
416  * Register IHS i2c adapters
417  */
418 #ifdef CONFIG_SYS_I2C_IHS_CH0
419 U_BOOT_I2C_ADAP_COMPLETE(ihs0, ihs_i2c_init, ihs_i2c_probe,
420                          ihs_i2c_read, ihs_i2c_write,
421                          ihs_i2c_set_bus_speed,
422                          CONFIG_SYS_I2C_IHS_SPEED_0,
423                          CONFIG_SYS_I2C_IHS_SLAVE_0, 0)
424 #ifdef CONFIG_SYS_I2C_IHS_DUAL
425 U_BOOT_I2C_ADAP_COMPLETE(ihs0_1, ihs_i2c_init, ihs_i2c_probe,
426                          ihs_i2c_read, ihs_i2c_write,
427                          ihs_i2c_set_bus_speed,
428                          CONFIG_SYS_I2C_IHS_SPEED_0_1,
429                          CONFIG_SYS_I2C_IHS_SLAVE_0_1, 16)
430 #endif
431 #endif
432 #ifdef CONFIG_SYS_I2C_IHS_CH1
433 U_BOOT_I2C_ADAP_COMPLETE(ihs1, ihs_i2c_init, ihs_i2c_probe,
434                          ihs_i2c_read, ihs_i2c_write,
435                          ihs_i2c_set_bus_speed,
436                          CONFIG_SYS_I2C_IHS_SPEED_1,
437                          CONFIG_SYS_I2C_IHS_SLAVE_1, 1)
438 #ifdef CONFIG_SYS_I2C_IHS_DUAL
439 U_BOOT_I2C_ADAP_COMPLETE(ihs1_1, ihs_i2c_init, ihs_i2c_probe,
440                          ihs_i2c_read, ihs_i2c_write,
441                          ihs_i2c_set_bus_speed,
442                          CONFIG_SYS_I2C_IHS_SPEED_1_1,
443                          CONFIG_SYS_I2C_IHS_SLAVE_1_1, 17)
444 #endif
445 #endif
446 #ifdef CONFIG_SYS_I2C_IHS_CH2
447 U_BOOT_I2C_ADAP_COMPLETE(ihs2, ihs_i2c_init, ihs_i2c_probe,
448                          ihs_i2c_read, ihs_i2c_write,
449                          ihs_i2c_set_bus_speed,
450                          CONFIG_SYS_I2C_IHS_SPEED_2,
451                          CONFIG_SYS_I2C_IHS_SLAVE_2, 2)
452 #ifdef CONFIG_SYS_I2C_IHS_DUAL
453 U_BOOT_I2C_ADAP_COMPLETE(ihs2_1, ihs_i2c_init, ihs_i2c_probe,
454                          ihs_i2c_read, ihs_i2c_write,
455                          ihs_i2c_set_bus_speed,
456                          CONFIG_SYS_I2C_IHS_SPEED_2_1,
457                          CONFIG_SYS_I2C_IHS_SLAVE_2_1, 18)
458 #endif
459 #endif
460 #ifdef CONFIG_SYS_I2C_IHS_CH3
461 U_BOOT_I2C_ADAP_COMPLETE(ihs3, ihs_i2c_init, ihs_i2c_probe,
462                          ihs_i2c_read, ihs_i2c_write,
463                          ihs_i2c_set_bus_speed,
464                          CONFIG_SYS_I2C_IHS_SPEED_3,
465                          CONFIG_SYS_I2C_IHS_SLAVE_3, 3)
466 #ifdef CONFIG_SYS_I2C_IHS_DUAL
467 U_BOOT_I2C_ADAP_COMPLETE(ihs3_1, ihs_i2c_init, ihs_i2c_probe,
468                          ihs_i2c_read, ihs_i2c_write,
469                          ihs_i2c_set_bus_speed,
470                          CONFIG_SYS_I2C_IHS_SPEED_3_1,
471                          CONFIG_SYS_I2C_IHS_SLAVE_3_1, 19)
472 #endif
473 #endif
474 #endif /* CONFIG_DM_I2C */