1 /* 2 * Faraday I2C Controller 3 * 4 * (C) Copyright 2010 Faraday Technology 5 * Dante Su <dantesu@faraday-tech.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 * 9 * NOTE: This driver should be converted to driver model before June 2017. 10 * Please see doc/driver-model/i2c-howto.txt for instructions. 11 */ 12 13 #include <common.h> 14 #include <asm/io.h> 15 #include <i2c.h> 16 17 #include "fti2c010.h" 18 19 #ifndef CONFIG_SYS_I2C_SPEED 20 #define CONFIG_SYS_I2C_SPEED 5000 21 #endif 22 23 #ifndef CONFIG_SYS_I2C_SLAVE 24 #define CONFIG_SYS_I2C_SLAVE 0 25 #endif 26 27 #ifndef CONFIG_FTI2C010_CLOCK 28 #define CONFIG_FTI2C010_CLOCK clk_get_rate("I2C") 29 #endif 30 31 #ifndef CONFIG_FTI2C010_TIMEOUT 32 #define CONFIG_FTI2C010_TIMEOUT 10 /* ms */ 33 #endif 34 35 /* 7-bit dev address + 1-bit read/write */ 36 #define I2C_RD(dev) ((((dev) << 1) & 0xfe) | 1) 37 #define I2C_WR(dev) (((dev) << 1) & 0xfe) 38 39 struct fti2c010_chip { 40 struct fti2c010_regs *regs; 41 }; 42 43 static struct fti2c010_chip chip_list[] = { 44 { 45 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE, 46 }, 47 #ifdef CONFIG_FTI2C010_BASE1 48 { 49 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE1, 50 }, 51 #endif 52 #ifdef CONFIG_FTI2C010_BASE2 53 { 54 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE2, 55 }, 56 #endif 57 #ifdef CONFIG_FTI2C010_BASE3 58 { 59 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE3, 60 }, 61 #endif 62 }; 63 64 static int fti2c010_reset(struct fti2c010_chip *chip) 65 { 66 ulong ts; 67 int ret = -1; 68 struct fti2c010_regs *regs = chip->regs; 69 70 writel(CR_I2CRST, ®s->cr); 71 for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) { 72 if (!(readl(®s->cr) & CR_I2CRST)) { 73 ret = 0; 74 break; 75 } 76 } 77 78 if (ret) 79 printf("fti2c010: reset timeout\n"); 80 81 return ret; 82 } 83 84 static int fti2c010_wait(struct fti2c010_chip *chip, uint32_t mask) 85 { 86 int ret = -1; 87 uint32_t stat, ts; 88 struct fti2c010_regs *regs = chip->regs; 89 90 for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) { 91 stat = readl(®s->sr); 92 if ((stat & mask) == mask) { 93 ret = 0; 94 break; 95 } 96 } 97 98 return ret; 99 } 100 101 static unsigned int set_i2c_bus_speed(struct fti2c010_chip *chip, 102 unsigned int speed) 103 { 104 struct fti2c010_regs *regs = chip->regs; 105 unsigned int clk = CONFIG_FTI2C010_CLOCK; 106 unsigned int gsr = 0; 107 unsigned int tsr = 32; 108 unsigned int div, rate; 109 110 for (div = 0; div < 0x3ffff; ++div) { 111 /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */ 112 rate = clk / (2 * (div + 2) + gsr); 113 if (rate <= speed) 114 break; 115 } 116 117 writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), ®s->tgsr); 118 writel(CDR_DIV(div), ®s->cdr); 119 120 return rate; 121 } 122 123 /* 124 * Initialization, must be called once on start up, may be called 125 * repeatedly to change the speed and slave addresses. 126 */ 127 static void fti2c010_init(struct i2c_adapter *adap, int speed, int slaveaddr) 128 { 129 struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 130 131 if (adap->init_done) 132 return; 133 134 #ifdef CONFIG_SYS_I2C_INIT_BOARD 135 /* Call board specific i2c bus reset routine before accessing the 136 * environment, which might be in a chip on that bus. For details 137 * about this problem see doc/I2C_Edge_Conditions. 138 */ 139 i2c_init_board(); 140 #endif 141 142 /* master init */ 143 144 fti2c010_reset(chip); 145 146 set_i2c_bus_speed(chip, speed); 147 148 /* slave init, don't care */ 149 } 150 151 /* 152 * Probe the given I2C chip address. Returns 0 if a chip responded, 153 * not 0 on failure. 154 */ 155 static int fti2c010_probe(struct i2c_adapter *adap, u8 dev) 156 { 157 struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 158 struct fti2c010_regs *regs = chip->regs; 159 int ret; 160 161 /* 1. Select slave device (7bits Address + 1bit R/W) */ 162 writel(I2C_WR(dev), ®s->dr); 163 writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 164 ret = fti2c010_wait(chip, SR_DT); 165 if (ret) 166 return ret; 167 168 /* 2. Select device register */ 169 writel(0, ®s->dr); 170 writel(CR_ENABLE | CR_TBEN, ®s->cr); 171 ret = fti2c010_wait(chip, SR_DT); 172 173 return ret; 174 } 175 176 static void to_i2c_addr(u8 *buf, uint32_t addr, int alen) 177 { 178 int i, shift; 179 180 if (!buf || alen <= 0) 181 return; 182 183 /* MSB first */ 184 i = 0; 185 shift = (alen - 1) * 8; 186 while (alen-- > 0) { 187 buf[i] = (u8)(addr >> shift); 188 shift -= 8; 189 } 190 } 191 192 static int fti2c010_read(struct i2c_adapter *adap, 193 u8 dev, uint addr, int alen, uchar *buf, int len) 194 { 195 struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 196 struct fti2c010_regs *regs = chip->regs; 197 int ret, pos; 198 uchar paddr[4] = { 0 }; 199 200 to_i2c_addr(paddr, addr, alen); 201 202 /* 203 * Phase A. Set register address 204 */ 205 206 /* A.1 Select slave device (7bits Address + 1bit R/W) */ 207 writel(I2C_WR(dev), ®s->dr); 208 writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 209 ret = fti2c010_wait(chip, SR_DT); 210 if (ret) 211 return ret; 212 213 /* A.2 Select device register */ 214 for (pos = 0; pos < alen; ++pos) { 215 uint32_t ctrl = CR_ENABLE | CR_TBEN; 216 217 writel(paddr[pos], ®s->dr); 218 writel(ctrl, ®s->cr); 219 ret = fti2c010_wait(chip, SR_DT); 220 if (ret) 221 return ret; 222 } 223 224 /* 225 * Phase B. Get register data 226 */ 227 228 /* B.1 Select slave device (7bits Address + 1bit R/W) */ 229 writel(I2C_RD(dev), ®s->dr); 230 writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 231 ret = fti2c010_wait(chip, SR_DT); 232 if (ret) 233 return ret; 234 235 /* B.2 Get register data */ 236 for (pos = 0; pos < len; ++pos) { 237 uint32_t ctrl = CR_ENABLE | CR_TBEN; 238 uint32_t stat = SR_DR; 239 240 if (pos == len - 1) { 241 ctrl |= CR_NAK | CR_STOP; 242 stat |= SR_ACK; 243 } 244 writel(ctrl, ®s->cr); 245 ret = fti2c010_wait(chip, stat); 246 if (ret) 247 break; 248 buf[pos] = (uchar)(readl(®s->dr) & 0xFF); 249 } 250 251 return ret; 252 } 253 254 static int fti2c010_write(struct i2c_adapter *adap, 255 u8 dev, uint addr, int alen, u8 *buf, int len) 256 { 257 struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 258 struct fti2c010_regs *regs = chip->regs; 259 int ret, pos; 260 uchar paddr[4] = { 0 }; 261 262 to_i2c_addr(paddr, addr, alen); 263 264 /* 265 * Phase A. Set register address 266 * 267 * A.1 Select slave device (7bits Address + 1bit R/W) 268 */ 269 writel(I2C_WR(dev), ®s->dr); 270 writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr); 271 ret = fti2c010_wait(chip, SR_DT); 272 if (ret) 273 return ret; 274 275 /* A.2 Select device register */ 276 for (pos = 0; pos < alen; ++pos) { 277 uint32_t ctrl = CR_ENABLE | CR_TBEN; 278 279 writel(paddr[pos], ®s->dr); 280 writel(ctrl, ®s->cr); 281 ret = fti2c010_wait(chip, SR_DT); 282 if (ret) 283 return ret; 284 } 285 286 /* 287 * Phase B. Set register data 288 */ 289 for (pos = 0; pos < len; ++pos) { 290 uint32_t ctrl = CR_ENABLE | CR_TBEN; 291 292 if (pos == len - 1) 293 ctrl |= CR_STOP; 294 writel(buf[pos], ®s->dr); 295 writel(ctrl, ®s->cr); 296 ret = fti2c010_wait(chip, SR_DT); 297 if (ret) 298 break; 299 } 300 301 return ret; 302 } 303 304 static unsigned int fti2c010_set_bus_speed(struct i2c_adapter *adap, 305 unsigned int speed) 306 { 307 struct fti2c010_chip *chip = chip_list + adap->hwadapnr; 308 int ret; 309 310 fti2c010_reset(chip); 311 ret = set_i2c_bus_speed(chip, speed); 312 313 return ret; 314 } 315 316 /* 317 * Register i2c adapters 318 */ 319 U_BOOT_I2C_ADAP_COMPLETE(i2c_0, fti2c010_init, fti2c010_probe, fti2c010_read, 320 fti2c010_write, fti2c010_set_bus_speed, 321 CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 322 0) 323 #ifdef CONFIG_FTI2C010_BASE1 324 U_BOOT_I2C_ADAP_COMPLETE(i2c_1, fti2c010_init, fti2c010_probe, fti2c010_read, 325 fti2c010_write, fti2c010_set_bus_speed, 326 CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 327 1) 328 #endif 329 #ifdef CONFIG_FTI2C010_BASE2 330 U_BOOT_I2C_ADAP_COMPLETE(i2c_2, fti2c010_init, fti2c010_probe, fti2c010_read, 331 fti2c010_write, fti2c010_set_bus_speed, 332 CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 333 2) 334 #endif 335 #ifdef CONFIG_FTI2C010_BASE3 336 U_BOOT_I2C_ADAP_COMPLETE(i2c_3, fti2c010_init, fti2c010_probe, fti2c010_read, 337 fti2c010_write, fti2c010_set_bus_speed, 338 CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 339 3) 340 #endif 341