13cff842bSKuo-Jung Su /* 23cff842bSKuo-Jung Su * Faraday I2C Controller 33cff842bSKuo-Jung Su * 43cff842bSKuo-Jung Su * (C) Copyright 2010 Faraday Technology 53cff842bSKuo-Jung Su * Dante Su <dantesu@faraday-tech.com> 63cff842bSKuo-Jung Su * 7*8dde4ca9STom Rini * SPDX-License-Identifier: GPL-2.0+ 83cff842bSKuo-Jung Su */ 93cff842bSKuo-Jung Su 103cff842bSKuo-Jung Su #include <common.h> 113cff842bSKuo-Jung Su #include <asm/io.h> 123cff842bSKuo-Jung Su #include <i2c.h> 133cff842bSKuo-Jung Su 143cff842bSKuo-Jung Su #include "fti2c010.h" 153cff842bSKuo-Jung Su 163cff842bSKuo-Jung Su #ifndef CONFIG_HARD_I2C 173cff842bSKuo-Jung Su #error "fti2c010: CONFIG_HARD_I2C is not defined" 183cff842bSKuo-Jung Su #endif 193cff842bSKuo-Jung Su 203cff842bSKuo-Jung Su #ifndef CONFIG_SYS_I2C_SPEED 213cff842bSKuo-Jung Su #define CONFIG_SYS_I2C_SPEED 50000 223cff842bSKuo-Jung Su #endif 233cff842bSKuo-Jung Su 243cff842bSKuo-Jung Su #ifndef CONFIG_FTI2C010_FREQ 253cff842bSKuo-Jung Su #define CONFIG_FTI2C010_FREQ clk_get_rate("I2C") 263cff842bSKuo-Jung Su #endif 273cff842bSKuo-Jung Su 283cff842bSKuo-Jung Su /* command timeout */ 293cff842bSKuo-Jung Su #define CFG_CMD_TIMEOUT 10 /* ms */ 303cff842bSKuo-Jung Su 313cff842bSKuo-Jung Su /* 7-bit chip address + 1-bit read/write */ 323cff842bSKuo-Jung Su #define I2C_RD(chip) ((((chip) << 1) & 0xff) | 1) 333cff842bSKuo-Jung Su #define I2C_WR(chip) (((chip) << 1) & 0xff) 343cff842bSKuo-Jung Su 353cff842bSKuo-Jung Su struct fti2c010_chip { 363cff842bSKuo-Jung Su void __iomem *regs; 373cff842bSKuo-Jung Su uint bus; 383cff842bSKuo-Jung Su uint speed; 393cff842bSKuo-Jung Su }; 403cff842bSKuo-Jung Su 413cff842bSKuo-Jung Su static struct fti2c010_chip chip_list[] = { 423cff842bSKuo-Jung Su { 433cff842bSKuo-Jung Su .bus = 0, 443cff842bSKuo-Jung Su .regs = (void __iomem *)CONFIG_FTI2C010_BASE, 453cff842bSKuo-Jung Su }, 463cff842bSKuo-Jung Su #ifdef CONFIG_I2C_MULTI_BUS 473cff842bSKuo-Jung Su # ifdef CONFIG_FTI2C010_BASE1 483cff842bSKuo-Jung Su { 493cff842bSKuo-Jung Su .bus = 1, 503cff842bSKuo-Jung Su .regs = (void __iomem *)CONFIG_FTI2C010_BASE1, 513cff842bSKuo-Jung Su }, 523cff842bSKuo-Jung Su # endif 533cff842bSKuo-Jung Su # ifdef CONFIG_FTI2C010_BASE2 543cff842bSKuo-Jung Su { 553cff842bSKuo-Jung Su .bus = 2, 563cff842bSKuo-Jung Su .regs = (void __iomem *)CONFIG_FTI2C010_BASE2, 573cff842bSKuo-Jung Su }, 583cff842bSKuo-Jung Su # endif 593cff842bSKuo-Jung Su # ifdef CONFIG_FTI2C010_BASE3 603cff842bSKuo-Jung Su { 613cff842bSKuo-Jung Su .bus = 3, 623cff842bSKuo-Jung Su .regs = (void __iomem *)CONFIG_FTI2C010_BASE3, 633cff842bSKuo-Jung Su }, 643cff842bSKuo-Jung Su # endif 653cff842bSKuo-Jung Su #endif /* #ifdef CONFIG_I2C_MULTI_BUS */ 663cff842bSKuo-Jung Su }; 673cff842bSKuo-Jung Su 683cff842bSKuo-Jung Su static struct fti2c010_chip *curr = chip_list; 693cff842bSKuo-Jung Su 703cff842bSKuo-Jung Su static int fti2c010_wait(uint32_t mask) 713cff842bSKuo-Jung Su { 723cff842bSKuo-Jung Su int ret = -1; 733cff842bSKuo-Jung Su uint32_t stat, ts; 743cff842bSKuo-Jung Su struct fti2c010_regs *regs = curr->regs; 753cff842bSKuo-Jung Su 763cff842bSKuo-Jung Su for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { 773cff842bSKuo-Jung Su stat = readl(®s->sr); 783cff842bSKuo-Jung Su if ((stat & mask) == mask) { 793cff842bSKuo-Jung Su ret = 0; 803cff842bSKuo-Jung Su break; 813cff842bSKuo-Jung Su } 823cff842bSKuo-Jung Su } 833cff842bSKuo-Jung Su 843cff842bSKuo-Jung Su return ret; 853cff842bSKuo-Jung Su } 863cff842bSKuo-Jung Su 873cff842bSKuo-Jung Su /* 883cff842bSKuo-Jung Su * u-boot I2C API 893cff842bSKuo-Jung Su */ 903cff842bSKuo-Jung Su 913cff842bSKuo-Jung Su /* 923cff842bSKuo-Jung Su * Initialization, must be called once on start up, may be called 933cff842bSKuo-Jung Su * repeatedly to change the speed and slave addresses. 943cff842bSKuo-Jung Su */ 953cff842bSKuo-Jung Su void i2c_init(int speed, int slaveaddr) 963cff842bSKuo-Jung Su { 973cff842bSKuo-Jung Su if (speed || !curr->speed) 983cff842bSKuo-Jung Su i2c_set_bus_speed(speed); 993cff842bSKuo-Jung Su 1003cff842bSKuo-Jung Su /* if slave mode disabled */ 1013cff842bSKuo-Jung Su if (!slaveaddr) 1023cff842bSKuo-Jung Su return; 1033cff842bSKuo-Jung Su 1043cff842bSKuo-Jung Su /* 1053cff842bSKuo-Jung Su * TODO: 1063cff842bSKuo-Jung Su * Implement slave mode, but is it really necessary? 1073cff842bSKuo-Jung Su */ 1083cff842bSKuo-Jung Su } 1093cff842bSKuo-Jung Su 1103cff842bSKuo-Jung Su /* 1113cff842bSKuo-Jung Su * Probe the given I2C chip address. Returns 0 if a chip responded, 1123cff842bSKuo-Jung Su * not 0 on failure. 1133cff842bSKuo-Jung Su */ 1143cff842bSKuo-Jung Su int i2c_probe(uchar chip) 1153cff842bSKuo-Jung Su { 1163cff842bSKuo-Jung Su int ret; 1173cff842bSKuo-Jung Su struct fti2c010_regs *regs = curr->regs; 1183cff842bSKuo-Jung Su 1193cff842bSKuo-Jung Su i2c_init(0, 0); 1203cff842bSKuo-Jung Su 1213cff842bSKuo-Jung Su /* 1. Select slave device (7bits Address + 1bit R/W) */ 1223cff842bSKuo-Jung Su writel(I2C_WR(chip), ®s->dr); 1233cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 1243cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 1253cff842bSKuo-Jung Su if (ret) 1263cff842bSKuo-Jung Su return ret; 1273cff842bSKuo-Jung Su 1283cff842bSKuo-Jung Su /* 2. Select device register */ 1293cff842bSKuo-Jung Su writel(0, ®s->dr); 1303cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN, ®s->cr); 1313cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 1323cff842bSKuo-Jung Su 1333cff842bSKuo-Jung Su return ret; 1343cff842bSKuo-Jung Su } 1353cff842bSKuo-Jung Su 1363cff842bSKuo-Jung Su /* 1373cff842bSKuo-Jung Su * Read/Write interface: 1383cff842bSKuo-Jung Su * chip: I2C chip address, range 0..127 1393cff842bSKuo-Jung Su * addr: Memory (register) address within the chip 1403cff842bSKuo-Jung Su * alen: Number of bytes to use for addr (typically 1, 2 for larger 1413cff842bSKuo-Jung Su * memories, 0 for register type devices with only one 1423cff842bSKuo-Jung Su * register) 1433cff842bSKuo-Jung Su * buffer: Where to read/write the data 1443cff842bSKuo-Jung Su * len: How many bytes to read/write 1453cff842bSKuo-Jung Su * 1463cff842bSKuo-Jung Su * Returns: 0 on success, not 0 on failure 1473cff842bSKuo-Jung Su */ 1483cff842bSKuo-Jung Su int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) 1493cff842bSKuo-Jung Su { 1503cff842bSKuo-Jung Su int ret, pos; 1513cff842bSKuo-Jung Su uchar paddr[4]; 1523cff842bSKuo-Jung Su struct fti2c010_regs *regs = curr->regs; 1533cff842bSKuo-Jung Su 1543cff842bSKuo-Jung Su i2c_init(0, 0); 1553cff842bSKuo-Jung Su 1563cff842bSKuo-Jung Su paddr[0] = (addr >> 0) & 0xFF; 1573cff842bSKuo-Jung Su paddr[1] = (addr >> 8) & 0xFF; 1583cff842bSKuo-Jung Su paddr[2] = (addr >> 16) & 0xFF; 1593cff842bSKuo-Jung Su paddr[3] = (addr >> 24) & 0xFF; 1603cff842bSKuo-Jung Su 1613cff842bSKuo-Jung Su /* 1623cff842bSKuo-Jung Su * Phase A. Set register address 1633cff842bSKuo-Jung Su */ 1643cff842bSKuo-Jung Su 1653cff842bSKuo-Jung Su /* A.1 Select slave device (7bits Address + 1bit R/W) */ 1663cff842bSKuo-Jung Su writel(I2C_WR(chip), ®s->dr); 1673cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 1683cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 1693cff842bSKuo-Jung Su if (ret) 1703cff842bSKuo-Jung Su return ret; 1713cff842bSKuo-Jung Su 1723cff842bSKuo-Jung Su /* A.2 Select device register */ 1733cff842bSKuo-Jung Su for (pos = 0; pos < alen; ++pos) { 1743cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 1753cff842bSKuo-Jung Su 1763cff842bSKuo-Jung Su writel(paddr[pos], ®s->dr); 1773cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 1783cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 1793cff842bSKuo-Jung Su if (ret) 1803cff842bSKuo-Jung Su return ret; 1813cff842bSKuo-Jung Su } 1823cff842bSKuo-Jung Su 1833cff842bSKuo-Jung Su /* 1843cff842bSKuo-Jung Su * Phase B. Get register data 1853cff842bSKuo-Jung Su */ 1863cff842bSKuo-Jung Su 1873cff842bSKuo-Jung Su /* B.1 Select slave device (7bits Address + 1bit R/W) */ 1883cff842bSKuo-Jung Su writel(I2C_RD(chip), ®s->dr); 1893cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 1903cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 1913cff842bSKuo-Jung Su if (ret) 1923cff842bSKuo-Jung Su return ret; 1933cff842bSKuo-Jung Su 1943cff842bSKuo-Jung Su /* B.2 Get register data */ 1953cff842bSKuo-Jung Su for (pos = 0; pos < len; ++pos) { 1963cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 1973cff842bSKuo-Jung Su uint32_t stat = SR_DR; 1983cff842bSKuo-Jung Su 1993cff842bSKuo-Jung Su if (pos == len - 1) { 2003cff842bSKuo-Jung Su ctrl |= CR_NAK | CR_STOP; 2013cff842bSKuo-Jung Su stat |= SR_ACK; 2023cff842bSKuo-Jung Su } 2033cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 2043cff842bSKuo-Jung Su ret = fti2c010_wait(stat); 2053cff842bSKuo-Jung Su if (ret) 2063cff842bSKuo-Jung Su break; 2073cff842bSKuo-Jung Su buf[pos] = (uchar)(readl(®s->dr) & 0xFF); 2083cff842bSKuo-Jung Su } 2093cff842bSKuo-Jung Su 2103cff842bSKuo-Jung Su return ret; 2113cff842bSKuo-Jung Su } 2123cff842bSKuo-Jung Su 2133cff842bSKuo-Jung Su /* 2143cff842bSKuo-Jung Su * Read/Write interface: 2153cff842bSKuo-Jung Su * chip: I2C chip address, range 0..127 2163cff842bSKuo-Jung Su * addr: Memory (register) address within the chip 2173cff842bSKuo-Jung Su * alen: Number of bytes to use for addr (typically 1, 2 for larger 2183cff842bSKuo-Jung Su * memories, 0 for register type devices with only one 2193cff842bSKuo-Jung Su * register) 2203cff842bSKuo-Jung Su * buffer: Where to read/write the data 2213cff842bSKuo-Jung Su * len: How many bytes to read/write 2223cff842bSKuo-Jung Su * 2233cff842bSKuo-Jung Su * Returns: 0 on success, not 0 on failure 2243cff842bSKuo-Jung Su */ 2253cff842bSKuo-Jung Su int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) 2263cff842bSKuo-Jung Su { 2273cff842bSKuo-Jung Su int ret, pos; 2283cff842bSKuo-Jung Su uchar paddr[4]; 2293cff842bSKuo-Jung Su struct fti2c010_regs *regs = curr->regs; 2303cff842bSKuo-Jung Su 2313cff842bSKuo-Jung Su i2c_init(0, 0); 2323cff842bSKuo-Jung Su 2333cff842bSKuo-Jung Su paddr[0] = (addr >> 0) & 0xFF; 2343cff842bSKuo-Jung Su paddr[1] = (addr >> 8) & 0xFF; 2353cff842bSKuo-Jung Su paddr[2] = (addr >> 16) & 0xFF; 2363cff842bSKuo-Jung Su paddr[3] = (addr >> 24) & 0xFF; 2373cff842bSKuo-Jung Su 2383cff842bSKuo-Jung Su /* 2393cff842bSKuo-Jung Su * Phase A. Set register address 2403cff842bSKuo-Jung Su * 2413cff842bSKuo-Jung Su * A.1 Select slave device (7bits Address + 1bit R/W) 2423cff842bSKuo-Jung Su */ 2433cff842bSKuo-Jung Su writel(I2C_WR(chip), ®s->dr); 2443cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 2453cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 2463cff842bSKuo-Jung Su if (ret) 2473cff842bSKuo-Jung Su return ret; 2483cff842bSKuo-Jung Su 2493cff842bSKuo-Jung Su /* A.2 Select device register */ 2503cff842bSKuo-Jung Su for (pos = 0; pos < alen; ++pos) { 2513cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2523cff842bSKuo-Jung Su 2533cff842bSKuo-Jung Su writel(paddr[pos], ®s->dr); 2543cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 2553cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 2563cff842bSKuo-Jung Su if (ret) 2573cff842bSKuo-Jung Su return ret; 2583cff842bSKuo-Jung Su } 2593cff842bSKuo-Jung Su 2603cff842bSKuo-Jung Su /* 2613cff842bSKuo-Jung Su * Phase B. Set register data 2623cff842bSKuo-Jung Su */ 2633cff842bSKuo-Jung Su for (pos = 0; pos < len; ++pos) { 2643cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2653cff842bSKuo-Jung Su 2663cff842bSKuo-Jung Su if (pos == len - 1) 2673cff842bSKuo-Jung Su ctrl |= CR_STOP; 2683cff842bSKuo-Jung Su writel(buf[pos], ®s->dr); 2693cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 2703cff842bSKuo-Jung Su ret = fti2c010_wait(SR_DT); 2713cff842bSKuo-Jung Su if (ret) 2723cff842bSKuo-Jung Su break; 2733cff842bSKuo-Jung Su } 2743cff842bSKuo-Jung Su 2753cff842bSKuo-Jung Su return ret; 2763cff842bSKuo-Jung Su } 2773cff842bSKuo-Jung Su 2783cff842bSKuo-Jung Su /* 2793cff842bSKuo-Jung Su * Functions for setting the current I2C bus and its speed 2803cff842bSKuo-Jung Su */ 2813cff842bSKuo-Jung Su #ifdef CONFIG_I2C_MULTI_BUS 2823cff842bSKuo-Jung Su 2833cff842bSKuo-Jung Su /* 2843cff842bSKuo-Jung Su * i2c_set_bus_num: 2853cff842bSKuo-Jung Su * 2863cff842bSKuo-Jung Su * Change the active I2C bus. Subsequent read/write calls will 2873cff842bSKuo-Jung Su * go to this one. 2883cff842bSKuo-Jung Su * 2893cff842bSKuo-Jung Su * bus - bus index, zero based 2903cff842bSKuo-Jung Su * 2913cff842bSKuo-Jung Su * Returns: 0 on success, not 0 on failure 2923cff842bSKuo-Jung Su */ 2933cff842bSKuo-Jung Su int i2c_set_bus_num(uint bus) 2943cff842bSKuo-Jung Su { 2953cff842bSKuo-Jung Su if (bus >= ARRAY_SIZE(chip_list)) 2963cff842bSKuo-Jung Su return -1; 2973cff842bSKuo-Jung Su curr = chip_list + bus; 2983cff842bSKuo-Jung Su i2c_init(0, 0); 2993cff842bSKuo-Jung Su return 0; 3003cff842bSKuo-Jung Su } 3013cff842bSKuo-Jung Su 3023cff842bSKuo-Jung Su /* 3033cff842bSKuo-Jung Su * i2c_get_bus_num: 3043cff842bSKuo-Jung Su * 3053cff842bSKuo-Jung Su * Returns index of currently active I2C bus. Zero-based. 3063cff842bSKuo-Jung Su */ 3073cff842bSKuo-Jung Su 3083cff842bSKuo-Jung Su uint i2c_get_bus_num(void) 3093cff842bSKuo-Jung Su { 3103cff842bSKuo-Jung Su return curr->bus; 3113cff842bSKuo-Jung Su } 3123cff842bSKuo-Jung Su 3133cff842bSKuo-Jung Su #endif /* #ifdef CONFIG_I2C_MULTI_BUS */ 3143cff842bSKuo-Jung Su 3153cff842bSKuo-Jung Su /* 3163cff842bSKuo-Jung Su * i2c_set_bus_speed: 3173cff842bSKuo-Jung Su * 3183cff842bSKuo-Jung Su * Change the speed of the active I2C bus 3193cff842bSKuo-Jung Su * 3203cff842bSKuo-Jung Su * speed - bus speed in Hz 3213cff842bSKuo-Jung Su * 3223cff842bSKuo-Jung Su * Returns: 0 on success, not 0 on failure 3233cff842bSKuo-Jung Su */ 3243cff842bSKuo-Jung Su int i2c_set_bus_speed(uint speed) 3253cff842bSKuo-Jung Su { 3263cff842bSKuo-Jung Su struct fti2c010_regs *regs = curr->regs; 3273cff842bSKuo-Jung Su uint clk = CONFIG_FTI2C010_FREQ; 3283cff842bSKuo-Jung Su uint gsr = 0, tsr = 32; 3293cff842bSKuo-Jung Su uint spd, div; 3303cff842bSKuo-Jung Su 3313cff842bSKuo-Jung Su if (!speed) 3323cff842bSKuo-Jung Su speed = CONFIG_SYS_I2C_SPEED; 3333cff842bSKuo-Jung Su 3343cff842bSKuo-Jung Su for (div = 0; div < 0x3ffff; ++div) { 3353cff842bSKuo-Jung Su /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */ 3363cff842bSKuo-Jung Su spd = clk / (2 * (div + 2) + gsr); 3373cff842bSKuo-Jung Su if (spd <= speed) 3383cff842bSKuo-Jung Su break; 3393cff842bSKuo-Jung Su } 3403cff842bSKuo-Jung Su 3413cff842bSKuo-Jung Su if (curr->speed == spd) 3423cff842bSKuo-Jung Su return 0; 3433cff842bSKuo-Jung Su 3443cff842bSKuo-Jung Su writel(CR_I2CRST, ®s->cr); 3453cff842bSKuo-Jung Su mdelay(100); 3463cff842bSKuo-Jung Su if (readl(®s->cr) & CR_I2CRST) { 3473cff842bSKuo-Jung Su printf("fti2c010: reset timeout\n"); 3483cff842bSKuo-Jung Su return -1; 3493cff842bSKuo-Jung Su } 3503cff842bSKuo-Jung Su 3513cff842bSKuo-Jung Su curr->speed = spd; 3523cff842bSKuo-Jung Su 3533cff842bSKuo-Jung Su writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), ®s->tgsr); 3543cff842bSKuo-Jung Su writel(CDR_DIV(div), ®s->cdr); 3553cff842bSKuo-Jung Su 3563cff842bSKuo-Jung Su return 0; 3573cff842bSKuo-Jung Su } 3583cff842bSKuo-Jung Su 3593cff842bSKuo-Jung Su /* 3603cff842bSKuo-Jung Su * i2c_get_bus_speed: 3613cff842bSKuo-Jung Su * 3623cff842bSKuo-Jung Su * Returns speed of currently active I2C bus in Hz 3633cff842bSKuo-Jung Su */ 3643cff842bSKuo-Jung Su 3653cff842bSKuo-Jung Su uint i2c_get_bus_speed(void) 3663cff842bSKuo-Jung Su { 3673cff842bSKuo-Jung Su return curr->speed; 3683cff842bSKuo-Jung Su } 369