blob: f91a96a3aa316f282e3dce8cb9bf2324fbbfeb53 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dirk Eibachb9577432014-07-03 09:28:18 +02002/*
3 * (C) Copyright 2013
Mario Sixb4893582018-03-06 08:04:58 +01004 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
Dirk Eibachb9577432014-07-03 09:28:18 +02005 */
6
7#include <common.h>
8#include <i2c.h>
Mario Six3bb409c2018-01-15 11:08:11 +01009#ifdef CONFIG_DM_I2C
10#include <dm.h>
Mario Six67b845b2019-01-28 09:45:57 +010011#include <regmap.h>
Mario Six3bb409c2018-01-15 11:08:11 +010012#else
Dirk Eibachb9577432014-07-03 09:28:18 +020013#include <gdsys_fpga.h>
Mario Six3bb409c2018-01-15 11:08:11 +010014#endif
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Mario Six48689b42018-01-15 11:08:10 +010016#include <asm/unaligned.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Dirk Eibachb9577432014-07-03 09:28:18 +020019
Mario Six3bb409c2018-01-15 11:08:11 +010020#ifdef CONFIG_DM_I2C
21struct ihs_i2c_priv {
22 uint speed;
Mario Six67b845b2019-01-28 09:45:57 +010023 struct regmap *map;
Mario Six3bb409c2018-01-15 11:08:11 +010024};
25
Mario Six67b845b2019-01-28 09:45:57 +010026struct ihs_i2c_regs {
27 u16 interrupt_status;
28 u16 interrupt_enable_control;
29 u16 write_mailbox_ext;
30 u16 write_mailbox;
31 u16 read_mailbox_ext;
32 u16 read_mailbox;
Mario Six3bb409c2018-01-15 11:08:11 +010033};
34
Mario Six67b845b2019-01-28 09:45:57 +010035#define ihs_i2c_set(map, member, val) \
36 regmap_set(map, struct ihs_i2c_regs, member, val)
37
38#define ihs_i2c_get(map, member, valp) \
39 regmap_get(map, struct ihs_i2c_regs, member, valp)
40
Mario Six3bb409c2018-01-15 11:08:11 +010041#else /* !CONFIG_DM_I2C */
Dirk Eibachb9577432014-07-03 09:28:18 +020042DECLARE_GLOBAL_DATA_PTR;
43
Dirk Eibach9ac33852015-10-28 11:46:22 +010044#ifdef CONFIG_SYS_I2C_IHS_DUAL
Mario Six3bb409c2018-01-15 11:08:11 +010045
Dirk Eibach9ac33852015-10-28 11:46:22 +010046#define I2C_SET_REG(fld, val) \
Dirk Eibach2c7212b2015-10-28 11:46:23 +010047 do { \
48 if (I2C_ADAP_HWNR & 0x10) \
49 FPGA_SET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
50 else \
51 FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
52 } while (0)
Dirk Eibach9ac33852015-10-28 11:46:22 +010053#else
54#define I2C_SET_REG(fld, val) \
Dirk Eibach2c7212b2015-10-28 11:46:23 +010055 FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
Dirk Eibach9ac33852015-10-28 11:46:22 +010056#endif
57
58#ifdef CONFIG_SYS_I2C_IHS_DUAL
59#define I2C_GET_REG(fld, val) \
Dirk Eibach2c7212b2015-10-28 11:46:23 +010060 do { \
61 if (I2C_ADAP_HWNR & 0x10) \
62 FPGA_GET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
63 else \
64 FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
65 } while (0)
Dirk Eibach9ac33852015-10-28 11:46:22 +010066#else
67#define I2C_GET_REG(fld, val) \
Dirk Eibach2c7212b2015-10-28 11:46:23 +010068 FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
Dirk Eibach9ac33852015-10-28 11:46:22 +010069#endif
Mario Six3bb409c2018-01-15 11:08:11 +010070#endif /* CONFIG_DM_I2C */
Dirk Eibach9ac33852015-10-28 11:46:22 +010071
Dirk Eibachb9577432014-07-03 09:28:18 +020072enum {
Mario Six48689b42018-01-15 11:08:10 +010073 I2CINT_ERROR_EV = BIT(13),
74 I2CINT_TRANSMIT_EV = BIT(14),
75 I2CINT_RECEIVE_EV = BIT(15),
Dirk Eibachb9577432014-07-03 09:28:18 +020076};
77
78enum {
Mario Six48689b42018-01-15 11:08:10 +010079 I2CMB_READ = 0 << 10,
Dirk Eibachb9577432014-07-03 09:28:18 +020080 I2CMB_WRITE = 1 << 10,
Mario Six48689b42018-01-15 11:08:10 +010081 I2CMB_1BYTE = 0 << 11,
Dirk Eibachb9577432014-07-03 09:28:18 +020082 I2CMB_2BYTE = 1 << 11,
Mario Six48689b42018-01-15 11:08:10 +010083 I2CMB_DONT_HOLD_BUS = 0 << 13,
Dirk Eibachb9577432014-07-03 09:28:18 +020084 I2CMB_HOLD_BUS = 1 << 13,
85 I2CMB_NATIVE = 2 << 14,
86};
87
Mario Six48689b42018-01-15 11:08:10 +010088enum {
89 I2COP_WRITE = 0,
90 I2COP_READ = 1,
91};
92
Mario Six3bb409c2018-01-15 11:08:11 +010093#ifdef CONFIG_DM_I2C
94static int wait_for_int(struct udevice *dev, int read)
95#else
Dirk Eibachb9577432014-07-03 09:28:18 +020096static int wait_for_int(bool read)
Mario Six3bb409c2018-01-15 11:08:11 +010097#endif
Dirk Eibachb9577432014-07-03 09:28:18 +020098{
99 u16 val;
Mario Six48689b42018-01-15 11:08:10 +0100100 uint ctr = 0;
Mario Six3bb409c2018-01-15 11:08:11 +0100101#ifdef CONFIG_DM_I2C
102 struct ihs_i2c_priv *priv = dev_get_priv(dev);
Mario Six3bb409c2018-01-15 11:08:11 +0100103#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200104
Mario Six3bb409c2018-01-15 11:08:11 +0100105#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100106 ihs_i2c_get(priv->map, interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100107#else
Dirk Eibach9ac33852015-10-28 11:46:22 +0100108 I2C_GET_REG(interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100109#endif
Mario Six48689b42018-01-15 11:08:10 +0100110 /* Wait until error or receive/transmit interrupt was raised */
Dirk Eibachb9577432014-07-03 09:28:18 +0200111 while (!(val & (I2CINT_ERROR_EV
112 | (read ? I2CINT_RECEIVE_EV : I2CINT_TRANSMIT_EV)))) {
113 udelay(10);
Mario Six5525d072019-01-28 09:45:58 +0100114 if (ctr++ > 5000) {
115 debug("%s: timed out\n", __func__);
116 return -ETIMEDOUT;
117 }
Mario Six3bb409c2018-01-15 11:08:11 +0100118#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100119 ihs_i2c_get(priv->map, interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100120#else
Dirk Eibach9ac33852015-10-28 11:46:22 +0100121 I2C_GET_REG(interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100122#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200123 }
124
Mario Six5525d072019-01-28 09:45:58 +0100125 return (val & I2CINT_ERROR_EV) ? -EIO : 0;
Dirk Eibachb9577432014-07-03 09:28:18 +0200126}
127
Mario Six3bb409c2018-01-15 11:08:11 +0100128#ifdef CONFIG_DM_I2C
129static int ihs_i2c_transfer(struct udevice *dev, uchar chip,
130 uchar *buffer, int len, int read, bool is_last)
131#else
Dirk Eibachb9577432014-07-03 09:28:18 +0200132static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
133 bool is_last)
Mario Six3bb409c2018-01-15 11:08:11 +0100134#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200135{
136 u16 val;
Mario Six4d90d9d2018-03-28 14:37:42 +0200137 u16 data;
Mario Six5525d072019-01-28 09:45:58 +0100138 int res;
Mario Six3bb409c2018-01-15 11:08:11 +0100139#ifdef CONFIG_DM_I2C
140 struct ihs_i2c_priv *priv = dev_get_priv(dev);
Mario Six3bb409c2018-01-15 11:08:11 +0100141#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200142
Mario Six48689b42018-01-15 11:08:10 +0100143 /* Clear interrupt status */
Mario Six4d90d9d2018-03-28 14:37:42 +0200144 data = I2CINT_ERROR_EV | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV;
Mario Six3bb409c2018-01-15 11:08:11 +0100145#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100146 ihs_i2c_set(priv->map, interrupt_status, data);
147 ihs_i2c_get(priv->map, interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100148#else
Mario Six4d90d9d2018-03-28 14:37:42 +0200149 I2C_SET_REG(interrupt_status, data);
Dirk Eibach9ac33852015-10-28 11:46:22 +0100150 I2C_GET_REG(interrupt_status, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100151#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200152
Mario Six48689b42018-01-15 11:08:10 +0100153 /* If we want to write and have data, write the bytes to the mailbox */
Dirk Eibachb9577432014-07-03 09:28:18 +0200154 if (!read && len) {
155 val = buffer[0];
156
157 if (len > 1)
158 val |= buffer[1] << 8;
Mario Six3bb409c2018-01-15 11:08:11 +0100159#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100160 ihs_i2c_set(priv->map, write_mailbox_ext, val);
Mario Six3bb409c2018-01-15 11:08:11 +0100161#else
Dirk Eibach9ac33852015-10-28 11:46:22 +0100162 I2C_SET_REG(write_mailbox_ext, val);
Mario Six3bb409c2018-01-15 11:08:11 +0100163#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200164 }
165
Mario Six4d90d9d2018-03-28 14:37:42 +0200166 data = I2CMB_NATIVE
167 | (read ? 0 : I2CMB_WRITE)
168 | (chip << 1)
169 | ((len > 1) ? I2CMB_2BYTE : 0)
170 | (is_last ? 0 : I2CMB_HOLD_BUS);
171
Mario Six3bb409c2018-01-15 11:08:11 +0100172#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100173 ihs_i2c_set(priv->map, write_mailbox, data);
Mario Six3bb409c2018-01-15 11:08:11 +0100174#else
Mario Six4d90d9d2018-03-28 14:37:42 +0200175 I2C_SET_REG(write_mailbox, data);
Mario Six3bb409c2018-01-15 11:08:11 +0100176#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200177
Mario Six3bb409c2018-01-15 11:08:11 +0100178#ifdef CONFIG_DM_I2C
Mario Six5525d072019-01-28 09:45:58 +0100179 res = wait_for_int(dev, read);
Mario Six3bb409c2018-01-15 11:08:11 +0100180#else
Mario Six5525d072019-01-28 09:45:58 +0100181 res = wait_for_int(read);
Mario Six3bb409c2018-01-15 11:08:11 +0100182#endif
Mario Six5525d072019-01-28 09:45:58 +0100183 if (res) {
184 if (res == -ETIMEDOUT)
185 debug("%s: time out while waiting for event\n", __func__);
186
187 return res;
188 }
Dirk Eibachb9577432014-07-03 09:28:18 +0200189
Mario Six48689b42018-01-15 11:08:10 +0100190 /* If we want to read, get the bytes from the mailbox */
Dirk Eibachb9577432014-07-03 09:28:18 +0200191 if (read) {
Mario Six3bb409c2018-01-15 11:08:11 +0100192#ifdef CONFIG_DM_I2C
Mario Six67b845b2019-01-28 09:45:57 +0100193 ihs_i2c_get(priv->map, read_mailbox_ext, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100194#else
Dirk Eibach9ac33852015-10-28 11:46:22 +0100195 I2C_GET_REG(read_mailbox_ext, &val);
Mario Six3bb409c2018-01-15 11:08:11 +0100196#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200197 buffer[0] = val & 0xff;
198 if (len > 1)
199 buffer[1] = val >> 8;
200 }
201
202 return 0;
203}
204
Mario Six3bb409c2018-01-15 11:08:11 +0100205#ifdef CONFIG_DM_I2C
Mario Six96961e82018-01-15 11:08:12 +0100206static int ihs_i2c_send_buffer(struct udevice *dev, uchar chip, u8 *data, int len, bool hold_bus, int read)
Mario Six3bb409c2018-01-15 11:08:11 +0100207#else
Mario Six96961e82018-01-15 11:08:12 +0100208static int ihs_i2c_send_buffer(uchar chip, u8 *data, int len, bool hold_bus,
209 int read)
Mario Six3bb409c2018-01-15 11:08:11 +0100210#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200211{
Mario Six5525d072019-01-28 09:45:58 +0100212 int res;
213
Mario Six96961e82018-01-15 11:08:12 +0100214 while (len) {
215 int transfer = min(len, 2);
216 bool is_last = len <= transfer;
Dirk Eibachb9577432014-07-03 09:28:18 +0200217
Mario Six3bb409c2018-01-15 11:08:11 +0100218#ifdef CONFIG_DM_I2C
Mario Six5525d072019-01-28 09:45:58 +0100219 res = ihs_i2c_transfer(dev, chip, data, transfer, read,
220 hold_bus ? false : is_last);
Mario Six3bb409c2018-01-15 11:08:11 +0100221#else
Mario Six5525d072019-01-28 09:45:58 +0100222 res = ihs_i2c_transfer(chip, data, transfer, read,
223 hold_bus ? false : is_last);
Mario Six3bb409c2018-01-15 11:08:11 +0100224#endif
Mario Six5525d072019-01-28 09:45:58 +0100225 if (res)
226 return res;
Dirk Eibachb9577432014-07-03 09:28:18 +0200227
Mario Six96961e82018-01-15 11:08:12 +0100228 data += transfer;
229 len -= transfer;
Dirk Eibachb9577432014-07-03 09:28:18 +0200230 }
231
232 return 0;
233}
234
Mario Six3bb409c2018-01-15 11:08:11 +0100235#ifdef CONFIG_DM_I2C
Mario Six96961e82018-01-15 11:08:12 +0100236static int ihs_i2c_address(struct udevice *dev, uchar chip, u8 *addr, int alen,
237 bool hold_bus)
238#else
239static int ihs_i2c_address(uchar chip, u8 *addr, int alen, bool hold_bus)
240#endif
241{
242#ifdef CONFIG_DM_I2C
243 return ihs_i2c_send_buffer(dev, chip, addr, alen, hold_bus, I2COP_WRITE);
244#else
245 return ihs_i2c_send_buffer(chip, addr, alen, hold_bus, I2COP_WRITE);
246#endif
247}
248
249#ifdef CONFIG_DM_I2C
Mario Six3bb409c2018-01-15 11:08:11 +0100250static int ihs_i2c_access(struct udevice *dev, uchar chip, u8 *addr,
251 int alen, uchar *buffer, int len, int read)
252#else
Mario Six48689b42018-01-15 11:08:10 +0100253static int ihs_i2c_access(struct i2c_adapter *adap, uchar chip, u8 *addr,
254 int alen, uchar *buffer, int len, int read)
Mario Six3bb409c2018-01-15 11:08:11 +0100255#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200256{
Mario Six5525d072019-01-28 09:45:58 +0100257 int res;
258
Mario Six48689b42018-01-15 11:08:10 +0100259 /* Don't hold the bus if length of data to send/receive is zero */
Mario Six5525d072019-01-28 09:45:58 +0100260 if (len <= 0)
261 return -EINVAL;
262
Mario Six3bb409c2018-01-15 11:08:11 +0100263#ifdef CONFIG_DM_I2C
Mario Six5525d072019-01-28 09:45:58 +0100264 res = ihs_i2c_address(dev, chip, addr, alen, len);
Mario Six3bb409c2018-01-15 11:08:11 +0100265#else
Mario Six5525d072019-01-28 09:45:58 +0100266 res = ihs_i2c_address(chip, addr, alen, len);
Mario Six3bb409c2018-01-15 11:08:11 +0100267#endif
Mario Six5525d072019-01-28 09:45:58 +0100268 if (res)
269 return res;
Dirk Eibachb9577432014-07-03 09:28:18 +0200270
Mario Six3bb409c2018-01-15 11:08:11 +0100271#ifdef CONFIG_DM_I2C
Mario Six96961e82018-01-15 11:08:12 +0100272 return ihs_i2c_send_buffer(dev, chip, buffer, len, false, read);
Mario Six3bb409c2018-01-15 11:08:11 +0100273#else
Mario Six96961e82018-01-15 11:08:12 +0100274 return ihs_i2c_send_buffer(chip, buffer, len, false, read);
Mario Six3bb409c2018-01-15 11:08:11 +0100275#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200276}
277
Mario Six3bb409c2018-01-15 11:08:11 +0100278#ifdef CONFIG_DM_I2C
279
280int ihs_i2c_probe(struct udevice *bus)
281{
282 struct ihs_i2c_priv *priv = dev_get_priv(bus);
Mario Six3bb409c2018-01-15 11:08:11 +0100283
Mario Six67b845b2019-01-28 09:45:57 +0100284 regmap_init_mem(dev_ofnode(bus), &priv->map);
Mario Six3bb409c2018-01-15 11:08:11 +0100285
286 return 0;
287}
288
289static int ihs_i2c_set_bus_speed(struct udevice *bus, uint speed)
290{
291 struct ihs_i2c_priv *priv = dev_get_priv(bus);
292
293 if (speed != priv->speed && priv->speed != 0)
Mario Six5525d072019-01-28 09:45:58 +0100294 return -EINVAL;
Mario Six3bb409c2018-01-15 11:08:11 +0100295
296 priv->speed = speed;
297
298 return 0;
299}
300
301static int ihs_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
302{
303 struct i2c_msg *dmsg, *omsg, dummy;
304
305 memset(&dummy, 0, sizeof(struct i2c_msg));
306
307 /* We expect either two messages (one with an offset and one with the
308 * actucal data) or one message (just data)
309 */
310 if (nmsgs > 2 || nmsgs == 0) {
Mario Six5525d072019-01-28 09:45:58 +0100311 debug("%s: Only one or two messages are supported\n", __func__);
312 return -ENOTSUPP;
Mario Six3bb409c2018-01-15 11:08:11 +0100313 }
314
315 omsg = nmsgs == 1 ? &dummy : msg;
316 dmsg = nmsgs == 1 ? msg : msg + 1;
317
318 if (dmsg->flags & I2C_M_RD)
319 return ihs_i2c_access(bus, dmsg->addr, omsg->buf,
320 omsg->len, dmsg->buf, dmsg->len,
321 I2COP_READ);
322 else
323 return ihs_i2c_access(bus, dmsg->addr, omsg->buf,
324 omsg->len, dmsg->buf, dmsg->len,
325 I2COP_WRITE);
326}
327
328static int ihs_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
329 u32 chip_flags)
330{
331 uchar buffer[2];
Mario Six5525d072019-01-28 09:45:58 +0100332 int res;
Mario Six3bb409c2018-01-15 11:08:11 +0100333
Mario Six5525d072019-01-28 09:45:58 +0100334 res = ihs_i2c_transfer(bus, chip_addr, buffer, 0, I2COP_READ, true);
335 if (res)
336 return res;
Mario Six3bb409c2018-01-15 11:08:11 +0100337
338 return 0;
339}
340
341static const struct dm_i2c_ops ihs_i2c_ops = {
342 .xfer = ihs_i2c_xfer,
343 .probe_chip = ihs_i2c_probe_chip,
344 .set_bus_speed = ihs_i2c_set_bus_speed,
345};
346
347static const struct udevice_id ihs_i2c_ids[] = {
348 { .compatible = "gdsys,ihs_i2cmaster", },
349 { /* sentinel */ }
350};
351
352U_BOOT_DRIVER(i2c_ihs) = {
353 .name = "i2c_ihs",
354 .id = UCLASS_I2C,
355 .of_match = ihs_i2c_ids,
356 .probe = ihs_i2c_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700357 .priv_auto = sizeof(struct ihs_i2c_priv),
Mario Six3bb409c2018-01-15 11:08:11 +0100358 .ops = &ihs_i2c_ops,
359};
360
361#else /* CONFIG_DM_I2C */
362
Dirk Eibachb9577432014-07-03 09:28:18 +0200363static void ihs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
364{
365#ifdef CONFIG_SYS_I2C_INIT_BOARD
366 /*
367 * Call board specific i2c bus reset routine before accessing the
368 * environment, which might be in a chip on that bus. For details
369 * about this problem see doc/I2C_Edge_Conditions.
370 */
371 i2c_init_board();
372#endif
373}
374
375static int ihs_i2c_probe(struct i2c_adapter *adap, uchar chip)
376{
377 uchar buffer[2];
Mario Six5525d072019-01-28 09:45:58 +0100378 int res;
Dirk Eibachb9577432014-07-03 09:28:18 +0200379
Mario Six5525d072019-01-28 09:45:58 +0100380 res = ihs_i2c_transfer(chip, buffer, 0, I2COP_READ, true);
381 if (res)
382 return res;
Dirk Eibachb9577432014-07-03 09:28:18 +0200383
384 return 0;
385}
386
387static int ihs_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
388 int alen, uchar *buffer, int len)
389{
Mario Six48689b42018-01-15 11:08:10 +0100390 u8 addr_bytes[4];
391
392 put_unaligned_le32(addr, addr_bytes);
393
394 return ihs_i2c_access(adap, chip, addr_bytes, alen, buffer, len,
395 I2COP_READ);
Dirk Eibachb9577432014-07-03 09:28:18 +0200396}
397
398static int ihs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
399 int alen, uchar *buffer, int len)
400{
Mario Six48689b42018-01-15 11:08:10 +0100401 u8 addr_bytes[4];
402
403 put_unaligned_le32(addr, addr_bytes);
404
405 return ihs_i2c_access(adap, chip, addr_bytes, alen, buffer, len,
406 I2COP_WRITE);
Dirk Eibachb9577432014-07-03 09:28:18 +0200407}
408
409static unsigned int ihs_i2c_set_bus_speed(struct i2c_adapter *adap,
Dirk Eibach9ac33852015-10-28 11:46:22 +0100410 unsigned int speed)
Dirk Eibachb9577432014-07-03 09:28:18 +0200411{
412 if (speed != adap->speed)
Mario Six5525d072019-01-28 09:45:58 +0100413 return -EINVAL;
Dirk Eibachb9577432014-07-03 09:28:18 +0200414 return speed;
415}
416
417/*
418 * Register IHS i2c adapters
419 */
420#ifdef CONFIG_SYS_I2C_IHS_CH0
421U_BOOT_I2C_ADAP_COMPLETE(ihs0, ihs_i2c_init, ihs_i2c_probe,
422 ihs_i2c_read, ihs_i2c_write,
423 ihs_i2c_set_bus_speed,
424 CONFIG_SYS_I2C_IHS_SPEED_0,
425 CONFIG_SYS_I2C_IHS_SLAVE_0, 0)
Dirk Eibach9ac33852015-10-28 11:46:22 +0100426#ifdef CONFIG_SYS_I2C_IHS_DUAL
427U_BOOT_I2C_ADAP_COMPLETE(ihs0_1, ihs_i2c_init, ihs_i2c_probe,
428 ihs_i2c_read, ihs_i2c_write,
429 ihs_i2c_set_bus_speed,
430 CONFIG_SYS_I2C_IHS_SPEED_0_1,
431 CONFIG_SYS_I2C_IHS_SLAVE_0_1, 16)
432#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200433#endif
434#ifdef CONFIG_SYS_I2C_IHS_CH1
435U_BOOT_I2C_ADAP_COMPLETE(ihs1, ihs_i2c_init, ihs_i2c_probe,
436 ihs_i2c_read, ihs_i2c_write,
437 ihs_i2c_set_bus_speed,
438 CONFIG_SYS_I2C_IHS_SPEED_1,
439 CONFIG_SYS_I2C_IHS_SLAVE_1, 1)
Dirk Eibach9ac33852015-10-28 11:46:22 +0100440#ifdef CONFIG_SYS_I2C_IHS_DUAL
441U_BOOT_I2C_ADAP_COMPLETE(ihs1_1, ihs_i2c_init, ihs_i2c_probe,
442 ihs_i2c_read, ihs_i2c_write,
443 ihs_i2c_set_bus_speed,
444 CONFIG_SYS_I2C_IHS_SPEED_1_1,
445 CONFIG_SYS_I2C_IHS_SLAVE_1_1, 17)
446#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200447#endif
448#ifdef CONFIG_SYS_I2C_IHS_CH2
449U_BOOT_I2C_ADAP_COMPLETE(ihs2, ihs_i2c_init, ihs_i2c_probe,
450 ihs_i2c_read, ihs_i2c_write,
451 ihs_i2c_set_bus_speed,
452 CONFIG_SYS_I2C_IHS_SPEED_2,
453 CONFIG_SYS_I2C_IHS_SLAVE_2, 2)
Dirk Eibach9ac33852015-10-28 11:46:22 +0100454#ifdef CONFIG_SYS_I2C_IHS_DUAL
455U_BOOT_I2C_ADAP_COMPLETE(ihs2_1, ihs_i2c_init, ihs_i2c_probe,
456 ihs_i2c_read, ihs_i2c_write,
457 ihs_i2c_set_bus_speed,
458 CONFIG_SYS_I2C_IHS_SPEED_2_1,
459 CONFIG_SYS_I2C_IHS_SLAVE_2_1, 18)
460#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200461#endif
462#ifdef CONFIG_SYS_I2C_IHS_CH3
463U_BOOT_I2C_ADAP_COMPLETE(ihs3, ihs_i2c_init, ihs_i2c_probe,
464 ihs_i2c_read, ihs_i2c_write,
465 ihs_i2c_set_bus_speed,
466 CONFIG_SYS_I2C_IHS_SPEED_3,
467 CONFIG_SYS_I2C_IHS_SLAVE_3, 3)
Dirk Eibach9ac33852015-10-28 11:46:22 +0100468#ifdef CONFIG_SYS_I2C_IHS_DUAL
469U_BOOT_I2C_ADAP_COMPLETE(ihs3_1, ihs_i2c_init, ihs_i2c_probe,
470 ihs_i2c_read, ihs_i2c_write,
471 ihs_i2c_set_bus_speed,
472 CONFIG_SYS_I2C_IHS_SPEED_3_1,
473 CONFIG_SYS_I2C_IHS_SLAVE_3_1, 19)
474#endif
Dirk Eibachb9577432014-07-03 09:28:18 +0200475#endif
Mario Six3bb409c2018-01-15 11:08:11 +0100476#endif /* CONFIG_DM_I2C */