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 * 78dde4ca9STom 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_SYS_I2C_SPEED 17e6d3ab89SKuo-Jung Su #define CONFIG_SYS_I2C_SPEED 5000 183cff842bSKuo-Jung Su #endif 193cff842bSKuo-Jung Su 20*49f4c762SKuo-Jung Su #ifndef CONFIG_SYS_I2C_SLAVE 21*49f4c762SKuo-Jung Su #define CONFIG_SYS_I2C_SLAVE 0 22*49f4c762SKuo-Jung Su #endif 23*49f4c762SKuo-Jung Su 24e6d3ab89SKuo-Jung Su #ifndef CONFIG_FTI2C010_CLOCK 25e6d3ab89SKuo-Jung Su #define CONFIG_FTI2C010_CLOCK clk_get_rate("I2C") 263cff842bSKuo-Jung Su #endif 273cff842bSKuo-Jung Su 28e6d3ab89SKuo-Jung Su #ifndef CONFIG_FTI2C010_TIMEOUT 29e6d3ab89SKuo-Jung Su #define CONFIG_FTI2C010_TIMEOUT 10 /* ms */ 30e6d3ab89SKuo-Jung Su #endif 313cff842bSKuo-Jung Su 32e6d3ab89SKuo-Jung Su /* 7-bit dev address + 1-bit read/write */ 33e6d3ab89SKuo-Jung Su #define I2C_RD(dev) ((((dev) << 1) & 0xfe) | 1) 34e6d3ab89SKuo-Jung Su #define I2C_WR(dev) (((dev) << 1) & 0xfe) 353cff842bSKuo-Jung Su 363cff842bSKuo-Jung Su struct fti2c010_chip { 37e6d3ab89SKuo-Jung Su struct fti2c010_regs *regs; 383cff842bSKuo-Jung Su }; 393cff842bSKuo-Jung Su 403cff842bSKuo-Jung Su static struct fti2c010_chip chip_list[] = { 413cff842bSKuo-Jung Su { 42e6d3ab89SKuo-Jung Su .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE, 433cff842bSKuo-Jung Su }, 443cff842bSKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE1 453cff842bSKuo-Jung Su { 46e6d3ab89SKuo-Jung Su .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE1, 473cff842bSKuo-Jung Su }, 483cff842bSKuo-Jung Su #endif 493cff842bSKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE2 503cff842bSKuo-Jung Su { 51e6d3ab89SKuo-Jung Su .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE2, 523cff842bSKuo-Jung Su }, 533cff842bSKuo-Jung Su #endif 543cff842bSKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE3 553cff842bSKuo-Jung Su { 56e6d3ab89SKuo-Jung Su .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE3, 573cff842bSKuo-Jung Su }, 583cff842bSKuo-Jung Su #endif 593cff842bSKuo-Jung Su }; 603cff842bSKuo-Jung Su 61*49f4c762SKuo-Jung Su static int fti2c010_reset(struct fti2c010_chip *chip) 62*49f4c762SKuo-Jung Su { 63*49f4c762SKuo-Jung Su ulong ts; 64*49f4c762SKuo-Jung Su int ret = -1; 65*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 663cff842bSKuo-Jung Su 67*49f4c762SKuo-Jung Su writel(CR_I2CRST, ®s->cr); 68*49f4c762SKuo-Jung Su for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) { 69*49f4c762SKuo-Jung Su if (!(readl(®s->cr) & CR_I2CRST)) { 70*49f4c762SKuo-Jung Su ret = 0; 71*49f4c762SKuo-Jung Su break; 72*49f4c762SKuo-Jung Su } 73*49f4c762SKuo-Jung Su } 74*49f4c762SKuo-Jung Su 75*49f4c762SKuo-Jung Su if (ret) 76*49f4c762SKuo-Jung Su printf("fti2c010: reset timeout\n"); 77*49f4c762SKuo-Jung Su 78*49f4c762SKuo-Jung Su return ret; 79*49f4c762SKuo-Jung Su } 80*49f4c762SKuo-Jung Su 81*49f4c762SKuo-Jung Su static int fti2c010_wait(struct fti2c010_chip *chip, uint32_t mask) 823cff842bSKuo-Jung Su { 833cff842bSKuo-Jung Su int ret = -1; 843cff842bSKuo-Jung Su uint32_t stat, ts; 85*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 863cff842bSKuo-Jung Su 87e6d3ab89SKuo-Jung Su for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) { 883cff842bSKuo-Jung Su stat = readl(®s->sr); 893cff842bSKuo-Jung Su if ((stat & mask) == mask) { 903cff842bSKuo-Jung Su ret = 0; 913cff842bSKuo-Jung Su break; 923cff842bSKuo-Jung Su } 933cff842bSKuo-Jung Su } 943cff842bSKuo-Jung Su 953cff842bSKuo-Jung Su return ret; 963cff842bSKuo-Jung Su } 973cff842bSKuo-Jung Su 98*49f4c762SKuo-Jung Su static unsigned int set_i2c_bus_speed(struct fti2c010_chip *chip, 99*49f4c762SKuo-Jung Su unsigned int speed) 100*49f4c762SKuo-Jung Su { 101*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 102*49f4c762SKuo-Jung Su unsigned int clk = CONFIG_FTI2C010_CLOCK; 103*49f4c762SKuo-Jung Su unsigned int gsr = 0; 104*49f4c762SKuo-Jung Su unsigned int tsr = 32; 105*49f4c762SKuo-Jung Su unsigned int div, rate; 106*49f4c762SKuo-Jung Su 107*49f4c762SKuo-Jung Su for (div = 0; div < 0x3ffff; ++div) { 108*49f4c762SKuo-Jung Su /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */ 109*49f4c762SKuo-Jung Su rate = clk / (2 * (div + 2) + gsr); 110*49f4c762SKuo-Jung Su if (rate <= speed) 111*49f4c762SKuo-Jung Su break; 112*49f4c762SKuo-Jung Su } 113*49f4c762SKuo-Jung Su 114*49f4c762SKuo-Jung Su writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), ®s->tgsr); 115*49f4c762SKuo-Jung Su writel(CDR_DIV(div), ®s->cdr); 116*49f4c762SKuo-Jung Su 117*49f4c762SKuo-Jung Su return rate; 118*49f4c762SKuo-Jung Su } 1193cff842bSKuo-Jung Su 1203cff842bSKuo-Jung Su /* 1213cff842bSKuo-Jung Su * Initialization, must be called once on start up, may be called 1223cff842bSKuo-Jung Su * repeatedly to change the speed and slave addresses. 1233cff842bSKuo-Jung Su */ 124*49f4c762SKuo-Jung Su static void fti2c010_init(struct i2c_adapter *adap, int speed, int slaveaddr) 1253cff842bSKuo-Jung Su { 126*49f4c762SKuo-Jung Su struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 1273cff842bSKuo-Jung Su 128*49f4c762SKuo-Jung Su if (adap->init_done) 1293cff842bSKuo-Jung Su return; 1303cff842bSKuo-Jung Su 131*49f4c762SKuo-Jung Su #ifdef CONFIG_SYS_I2C_INIT_BOARD 132*49f4c762SKuo-Jung Su /* Call board specific i2c bus reset routine before accessing the 133*49f4c762SKuo-Jung Su * environment, which might be in a chip on that bus. For details 134*49f4c762SKuo-Jung Su * about this problem see doc/I2C_Edge_Conditions. 1353cff842bSKuo-Jung Su */ 136*49f4c762SKuo-Jung Su i2c_init_board(); 137*49f4c762SKuo-Jung Su #endif 138*49f4c762SKuo-Jung Su 139*49f4c762SKuo-Jung Su /* master init */ 140*49f4c762SKuo-Jung Su 141*49f4c762SKuo-Jung Su fti2c010_reset(chip); 142*49f4c762SKuo-Jung Su 143*49f4c762SKuo-Jung Su set_i2c_bus_speed(chip, speed); 144*49f4c762SKuo-Jung Su 145*49f4c762SKuo-Jung Su /* slave init, don't care */ 146*49f4c762SKuo-Jung Su 147*49f4c762SKuo-Jung Su #ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT 148*49f4c762SKuo-Jung Su /* Call board specific i2c bus reset routine AFTER the bus has been 149*49f4c762SKuo-Jung Su * initialized. Use either this callpoint or i2c_init_board; 150*49f4c762SKuo-Jung Su * which is called before fti2c010_init operations. 151*49f4c762SKuo-Jung Su * For details about this problem see doc/I2C_Edge_Conditions. 152*49f4c762SKuo-Jung Su */ 153*49f4c762SKuo-Jung Su i2c_board_late_init(); 154*49f4c762SKuo-Jung Su #endif 1553cff842bSKuo-Jung Su } 1563cff842bSKuo-Jung Su 1573cff842bSKuo-Jung Su /* 1583cff842bSKuo-Jung Su * Probe the given I2C chip address. Returns 0 if a chip responded, 1593cff842bSKuo-Jung Su * not 0 on failure. 1603cff842bSKuo-Jung Su */ 161*49f4c762SKuo-Jung Su static int fti2c010_probe(struct i2c_adapter *adap, u8 dev) 1623cff842bSKuo-Jung Su { 163*49f4c762SKuo-Jung Su struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 164*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 1653cff842bSKuo-Jung Su int ret; 1663cff842bSKuo-Jung Su 1673cff842bSKuo-Jung Su /* 1. Select slave device (7bits Address + 1bit R/W) */ 168*49f4c762SKuo-Jung Su writel(I2C_WR(dev), ®s->dr); 1693cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 170*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 1713cff842bSKuo-Jung Su if (ret) 1723cff842bSKuo-Jung Su return ret; 1733cff842bSKuo-Jung Su 1743cff842bSKuo-Jung Su /* 2. Select device register */ 1753cff842bSKuo-Jung Su writel(0, ®s->dr); 1763cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN, ®s->cr); 177*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 1783cff842bSKuo-Jung Su 1793cff842bSKuo-Jung Su return ret; 1803cff842bSKuo-Jung Su } 1813cff842bSKuo-Jung Su 182*49f4c762SKuo-Jung Su static int fti2c010_read(struct i2c_adapter *adap, 183*49f4c762SKuo-Jung Su u8 dev, uint addr, int alen, uchar *buf, int len) 1843cff842bSKuo-Jung Su { 185*49f4c762SKuo-Jung Su struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 186*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 1873cff842bSKuo-Jung Su int ret, pos; 1883cff842bSKuo-Jung Su uchar paddr[4]; 1893cff842bSKuo-Jung Su 1903cff842bSKuo-Jung Su paddr[0] = (addr >> 0) & 0xFF; 1913cff842bSKuo-Jung Su paddr[1] = (addr >> 8) & 0xFF; 1923cff842bSKuo-Jung Su paddr[2] = (addr >> 16) & 0xFF; 1933cff842bSKuo-Jung Su paddr[3] = (addr >> 24) & 0xFF; 1943cff842bSKuo-Jung Su 1953cff842bSKuo-Jung Su /* 1963cff842bSKuo-Jung Su * Phase A. Set register address 1973cff842bSKuo-Jung Su */ 1983cff842bSKuo-Jung Su 1993cff842bSKuo-Jung Su /* A.1 Select slave device (7bits Address + 1bit R/W) */ 200*49f4c762SKuo-Jung Su writel(I2C_WR(dev), ®s->dr); 2013cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 202*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2033cff842bSKuo-Jung Su if (ret) 2043cff842bSKuo-Jung Su return ret; 2053cff842bSKuo-Jung Su 2063cff842bSKuo-Jung Su /* A.2 Select device register */ 2073cff842bSKuo-Jung Su for (pos = 0; pos < alen; ++pos) { 2083cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2093cff842bSKuo-Jung Su 2103cff842bSKuo-Jung Su writel(paddr[pos], ®s->dr); 2113cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 212*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2133cff842bSKuo-Jung Su if (ret) 2143cff842bSKuo-Jung Su return ret; 2153cff842bSKuo-Jung Su } 2163cff842bSKuo-Jung Su 2173cff842bSKuo-Jung Su /* 2183cff842bSKuo-Jung Su * Phase B. Get register data 2193cff842bSKuo-Jung Su */ 2203cff842bSKuo-Jung Su 2213cff842bSKuo-Jung Su /* B.1 Select slave device (7bits Address + 1bit R/W) */ 222*49f4c762SKuo-Jung Su writel(I2C_RD(dev), ®s->dr); 2233cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 224*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2253cff842bSKuo-Jung Su if (ret) 2263cff842bSKuo-Jung Su return ret; 2273cff842bSKuo-Jung Su 2283cff842bSKuo-Jung Su /* B.2 Get register data */ 2293cff842bSKuo-Jung Su for (pos = 0; pos < len; ++pos) { 2303cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2313cff842bSKuo-Jung Su uint32_t stat = SR_DR; 2323cff842bSKuo-Jung Su 2333cff842bSKuo-Jung Su if (pos == len - 1) { 2343cff842bSKuo-Jung Su ctrl |= CR_NAK | CR_STOP; 2353cff842bSKuo-Jung Su stat |= SR_ACK; 2363cff842bSKuo-Jung Su } 2373cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 238*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, stat); 2393cff842bSKuo-Jung Su if (ret) 2403cff842bSKuo-Jung Su break; 2413cff842bSKuo-Jung Su buf[pos] = (uchar)(readl(®s->dr) & 0xFF); 2423cff842bSKuo-Jung Su } 2433cff842bSKuo-Jung Su 2443cff842bSKuo-Jung Su return ret; 2453cff842bSKuo-Jung Su } 2463cff842bSKuo-Jung Su 247*49f4c762SKuo-Jung Su static int fti2c010_write(struct i2c_adapter *adap, 248*49f4c762SKuo-Jung Su u8 dev, uint addr, int alen, u8 *buf, int len) 2493cff842bSKuo-Jung Su { 250*49f4c762SKuo-Jung Su struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 251*49f4c762SKuo-Jung Su struct fti2c010_regs *regs = chip->regs; 2523cff842bSKuo-Jung Su int ret, pos; 2533cff842bSKuo-Jung Su uchar paddr[4]; 2543cff842bSKuo-Jung Su 2553cff842bSKuo-Jung Su paddr[0] = (addr >> 0) & 0xFF; 2563cff842bSKuo-Jung Su paddr[1] = (addr >> 8) & 0xFF; 2573cff842bSKuo-Jung Su paddr[2] = (addr >> 16) & 0xFF; 2583cff842bSKuo-Jung Su paddr[3] = (addr >> 24) & 0xFF; 2593cff842bSKuo-Jung Su 2603cff842bSKuo-Jung Su /* 2613cff842bSKuo-Jung Su * Phase A. Set register address 2623cff842bSKuo-Jung Su * 2633cff842bSKuo-Jung Su * A.1 Select slave device (7bits Address + 1bit R/W) 2643cff842bSKuo-Jung Su */ 265*49f4c762SKuo-Jung Su writel(I2C_WR(dev), ®s->dr); 2663cff842bSKuo-Jung Su writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 267*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2683cff842bSKuo-Jung Su if (ret) 2693cff842bSKuo-Jung Su return ret; 2703cff842bSKuo-Jung Su 2713cff842bSKuo-Jung Su /* A.2 Select device register */ 2723cff842bSKuo-Jung Su for (pos = 0; pos < alen; ++pos) { 2733cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2743cff842bSKuo-Jung Su 2753cff842bSKuo-Jung Su writel(paddr[pos], ®s->dr); 2763cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 277*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2783cff842bSKuo-Jung Su if (ret) 2793cff842bSKuo-Jung Su return ret; 2803cff842bSKuo-Jung Su } 2813cff842bSKuo-Jung Su 2823cff842bSKuo-Jung Su /* 2833cff842bSKuo-Jung Su * Phase B. Set register data 2843cff842bSKuo-Jung Su */ 2853cff842bSKuo-Jung Su for (pos = 0; pos < len; ++pos) { 2863cff842bSKuo-Jung Su uint32_t ctrl = CR_ENABLE | CR_TBEN; 2873cff842bSKuo-Jung Su 2883cff842bSKuo-Jung Su if (pos == len - 1) 2893cff842bSKuo-Jung Su ctrl |= CR_STOP; 2903cff842bSKuo-Jung Su writel(buf[pos], ®s->dr); 2913cff842bSKuo-Jung Su writel(ctrl, ®s->cr); 292*49f4c762SKuo-Jung Su ret = fti2c010_wait(chip, SR_DT); 2933cff842bSKuo-Jung Su if (ret) 2943cff842bSKuo-Jung Su break; 2953cff842bSKuo-Jung Su } 2963cff842bSKuo-Jung Su 2973cff842bSKuo-Jung Su return ret; 2983cff842bSKuo-Jung Su } 2993cff842bSKuo-Jung Su 300*49f4c762SKuo-Jung Su static unsigned int fti2c010_set_bus_speed(struct i2c_adapter *adap, 301*49f4c762SKuo-Jung Su unsigned int speed) 3023cff842bSKuo-Jung Su { 303*49f4c762SKuo-Jung Su struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 304*49f4c762SKuo-Jung Su int ret; 305*49f4c762SKuo-Jung Su 306*49f4c762SKuo-Jung Su fti2c010_reset(chip); 307*49f4c762SKuo-Jung Su ret = set_i2c_bus_speed(chip, speed); 308*49f4c762SKuo-Jung Su 309*49f4c762SKuo-Jung Su return ret; 3103cff842bSKuo-Jung Su } 3113cff842bSKuo-Jung Su 3123cff842bSKuo-Jung Su /* 313*49f4c762SKuo-Jung Su * Register i2c adapters 3143cff842bSKuo-Jung Su */ 315*49f4c762SKuo-Jung Su U_BOOT_I2C_ADAP_COMPLETE(i2c_0, fti2c010_init, fti2c010_probe, fti2c010_read, 316*49f4c762SKuo-Jung Su fti2c010_write, fti2c010_set_bus_speed, 317*49f4c762SKuo-Jung Su CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 318*49f4c762SKuo-Jung Su 0) 319*49f4c762SKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE1 320*49f4c762SKuo-Jung Su U_BOOT_I2C_ADAP_COMPLETE(i2c_1, fti2c010_init, fti2c010_probe, fti2c010_read, 321*49f4c762SKuo-Jung Su fti2c010_write, fti2c010_set_bus_speed, 322*49f4c762SKuo-Jung Su CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 323*49f4c762SKuo-Jung Su 1) 324*49f4c762SKuo-Jung Su #endif 325*49f4c762SKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE2 326*49f4c762SKuo-Jung Su U_BOOT_I2C_ADAP_COMPLETE(i2c_2, fti2c010_init, fti2c010_probe, fti2c010_read, 327*49f4c762SKuo-Jung Su fti2c010_write, fti2c010_set_bus_speed, 328*49f4c762SKuo-Jung Su CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 329*49f4c762SKuo-Jung Su 2) 330*49f4c762SKuo-Jung Su #endif 331*49f4c762SKuo-Jung Su #ifdef CONFIG_FTI2C010_BASE3 332*49f4c762SKuo-Jung Su U_BOOT_I2C_ADAP_COMPLETE(i2c_3, fti2c010_init, fti2c010_probe, fti2c010_read, 333*49f4c762SKuo-Jung Su fti2c010_write, fti2c010_set_bus_speed, 334*49f4c762SKuo-Jung Su CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 335*49f4c762SKuo-Jung Su 3) 336*49f4c762SKuo-Jung Su #endif 337