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