/* * TI DaVinci (TMS320DM644x) I2C driver. * * (C) Copyright 2012-2014 * Texas Instruments Incorporated, * (C) Copyright 2007 Sergey Kubushyn * -------------------------------------------------------- * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include "davinci_i2c.h" #define CHECK_NACK() \ do {\ if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ REG(&(i2c_base->i2c_con)) = 0;\ return 1;\ } \ } while (0) static struct i2c_regs *davinci_get_base(struct i2c_adapter *adap); static int wait_for_bus(struct i2c_adapter *adap) { struct i2c_regs *i2c_base = davinci_get_base(adap); int stat, timeout; REG(&(i2c_base->i2c_stat)) = 0xffff; for (timeout = 0; timeout < 10; timeout++) { stat = REG(&(i2c_base->i2c_stat)); if (!((stat) & I2C_STAT_BB)) { REG(&(i2c_base->i2c_stat)) = 0xffff; return 0; } REG(&(i2c_base->i2c_stat)) = stat; udelay(50000); } REG(&(i2c_base->i2c_stat)) = 0xffff; return 1; } static int poll_i2c_irq(struct i2c_adapter *adap, int mask) { struct i2c_regs *i2c_base = davinci_get_base(adap); int stat, timeout; for (timeout = 0; timeout < 10; timeout++) { udelay(1000); stat = REG(&(i2c_base->i2c_stat)); if (stat & mask) return stat; } REG(&(i2c_base->i2c_stat)) = 0xffff; return stat | I2C_TIMEOUT; } static void flush_rx(struct i2c_adapter *adap) { struct i2c_regs *i2c_base = davinci_get_base(adap); while (1) { if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_RRDY)) break; REG(&(i2c_base->i2c_drr)); REG(&(i2c_base->i2c_stat)) = I2C_STAT_RRDY; udelay(1000); } } static uint davinci_i2c_setspeed(struct i2c_adapter *adap, uint speed) { struct i2c_regs *i2c_base = davinci_get_base(adap); uint32_t div, psc; psc = 2; /* SCLL + SCLH */ div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; REG(&(i2c_base->i2c_psc)) = psc; /* 27MHz / (2 + 1) = 9MHz */ REG(&(i2c_base->i2c_scll)) = (div * 50) / 100; /* 50% Duty */ REG(&(i2c_base->i2c_sclh)) = div - REG(&(i2c_base->i2c_scll)); adap->speed = speed; return 0; } static void davinci_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { struct i2c_regs *i2c_base = davinci_get_base(adap); if (REG(&(i2c_base->i2c_con)) & I2C_CON_EN) { REG(&(i2c_base->i2c_con)) = 0; udelay(50000); } davinci_i2c_setspeed(adap, speed); REG(&(i2c_base->i2c_oa)) = slaveadd; REG(&(i2c_base->i2c_cnt)) = 0; /* Interrupts must be enabled or I2C module won't work */ REG(&(i2c_base->i2c_ie)) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; /* Now enable I2C controller (get it out of reset) */ REG(&(i2c_base->i2c_con)) = I2C_CON_EN; udelay(1000); } static int davinci_i2c_probe(struct i2c_adapter *adap, uint8_t chip) { struct i2c_regs *i2c_base = davinci_get_base(adap); int rc = 1; if (chip == REG(&(i2c_base->i2c_oa))) return rc; REG(&(i2c_base->i2c_con)) = 0; if (wait_for_bus(adap)) return 1; /* try to read one byte from current (or only) address */ REG(&(i2c_base->i2c_cnt)) = 1; REG(&(i2c_base->i2c_sa)) = chip; REG(&(i2c_base->i2c_con)) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); udelay(50000); if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_NACK)) { rc = 0; flush_rx(adap); REG(&(i2c_base->i2c_stat)) = 0xffff; } else { REG(&(i2c_base->i2c_stat)) = 0xffff; REG(&(i2c_base->i2c_con)) |= I2C_CON_STP; udelay(20000); if (wait_for_bus(adap)) return 1; } flush_rx(adap); REG(&(i2c_base->i2c_stat)) = 0xffff; REG(&(i2c_base->i2c_cnt)) = 0; return rc; } static int davinci_i2c_read(struct i2c_adapter *adap, uint8_t chip, uint32_t addr, int alen, uint8_t *buf, int len) { struct i2c_regs *i2c_base = davinci_get_base(adap); uint32_t tmp; int i; if ((alen < 0) || (alen > 2)) { printf("%s(): bogus address length %x\n", __func__, alen); return 1; } if (wait_for_bus(adap)) return 1; if (alen != 0) { /* Start address phase */ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; REG(&(i2c_base->i2c_cnt)) = alen; REG(&(i2c_base->i2c_sa)) = chip; REG(&(i2c_base->i2c_con)) = tmp; tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); CHECK_NACK(); switch (alen) { case 2: /* Send address MSByte */ if (tmp & I2C_STAT_XRDY) { REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; } else { REG(&(i2c_base->i2c_con)) = 0; return 1; } tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); CHECK_NACK(); /* No break, fall through */ case 1: /* Send address LSByte */ if (tmp & I2C_STAT_XRDY) { REG(&(i2c_base->i2c_dxr)) = addr & 0xff; } else { REG(&(i2c_base->i2c_con)) = 0; return 1; } tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); CHECK_NACK(); if (!(tmp & I2C_STAT_ARDY)) { REG(&(i2c_base->i2c_con)) = 0; return 1; } } } /* Address phase is over, now read 'len' bytes and stop */ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; REG(&(i2c_base->i2c_cnt)) = len & 0xffff; REG(&(i2c_base->i2c_sa)) = chip; REG(&(i2c_base->i2c_con)) = tmp; for (i = 0; i < len; i++) { tmp = poll_i2c_irq(adap, I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); CHECK_NACK(); if (tmp & I2C_STAT_RRDY) { buf[i] = REG(&(i2c_base->i2c_drr)); } else { REG(&(i2c_base->i2c_con)) = 0; return 1; } } tmp = poll_i2c_irq(adap, I2C_STAT_SCD | I2C_STAT_NACK); CHECK_NACK(); if (!(tmp & I2C_STAT_SCD)) { REG(&(i2c_base->i2c_con)) = 0; return 1; } flush_rx(adap); REG(&(i2c_base->i2c_stat)) = 0xffff; REG(&(i2c_base->i2c_cnt)) = 0; REG(&(i2c_base->i2c_con)) = 0; return 0; } static int davinci_i2c_write(struct i2c_adapter *adap, uint8_t chip, uint32_t addr, int alen, uint8_t *buf, int len) { struct i2c_regs *i2c_base = davinci_get_base(adap); uint32_t tmp; int i; if ((alen < 0) || (alen > 2)) { printf("%s(): bogus address length %x\n", __func__, alen); return 1; } if (len < 0) { printf("%s(): bogus length %x\n", __func__, len); return 1; } if (wait_for_bus(adap)) return 1; /* Start address phase */ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; REG(&(i2c_base->i2c_cnt)) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; REG(&(i2c_base->i2c_sa)) = chip; REG(&(i2c_base->i2c_con)) = tmp; switch (alen) { case 2: /* Send address MSByte */ tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); CHECK_NACK(); if (tmp & I2C_STAT_XRDY) { REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; } else { REG(&(i2c_base->i2c_con)) = 0; return 1; } /* No break, fall through */ case 1: /* Send address LSByte */ tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); CHECK_NACK(); if (tmp & I2C_STAT_XRDY) { REG(&(i2c_base->i2c_dxr)) = addr & 0xff; } else { REG(&(i2c_base->i2c_con)) = 0; return 1; } } for (i = 0; i < len; i++) { tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); CHECK_NACK(); if (tmp & I2C_STAT_XRDY) REG(&(i2c_base->i2c_dxr)) = buf[i]; else return 1; } tmp = poll_i2c_irq(adap, I2C_STAT_SCD | I2C_STAT_NACK); CHECK_NACK(); if (!(tmp & I2C_STAT_SCD)) { REG(&(i2c_base->i2c_con)) = 0; return 1; } flush_rx(adap); REG(&(i2c_base->i2c_stat)) = 0xffff; REG(&(i2c_base->i2c_cnt)) = 0; REG(&(i2c_base->i2c_con)) = 0; return 0; } static struct i2c_regs *davinci_get_base(struct i2c_adapter *adap) { switch (adap->hwadapnr) { #if I2C_BUS_MAX >= 3 case 2: return (struct i2c_regs *)I2C2_BASE; #endif #if I2C_BUS_MAX >= 2 case 1: return (struct i2c_regs *)I2C1_BASE; #endif case 0: return (struct i2c_regs *)I2C_BASE; default: printf("wrong hwadapnr: %d\n", adap->hwadapnr); } return NULL; } U_BOOT_I2C_ADAP_COMPLETE(davinci_0, davinci_i2c_init, davinci_i2c_probe, davinci_i2c_read, davinci_i2c_write, davinci_i2c_setspeed, CONFIG_SYS_DAVINCI_I2C_SPEED, CONFIG_SYS_DAVINCI_I2C_SLAVE, 0) #if I2C_BUS_MAX >= 2 U_BOOT_I2C_ADAP_COMPLETE(davinci_1, davinci_i2c_init, davinci_i2c_probe, davinci_i2c_read, davinci_i2c_write, davinci_i2c_setspeed, CONFIG_SYS_DAVINCI_I2C_SPEED1, CONFIG_SYS_DAVINCI_I2C_SLAVE1, 1) #endif #if I2C_BUS_MAX >= 3 U_BOOT_I2C_ADAP_COMPLETE(davinci_2, davinci_i2c_init, davinci_i2c_probe, davinci_i2c_read, davinci_i2c_write, davinci_i2c_setspeed, CONFIG_SYS_DAVINCI_I2C_SPEED2, CONFIG_SYS_DAVINCI_I2C_SLAVE2, 2) #endif