1*34374699SSimon Glass /* 2*34374699SSimon Glass * (C) Copyright 2015 Google, Inc 3*34374699SSimon Glass * 4*34374699SSimon Glass * (C) Copyright 2008-2014 Rockchip Electronics 5*34374699SSimon Glass * Peter, Software Engineering, <superpeter.cai@gmail.com>. 6*34374699SSimon Glass * 7*34374699SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 8*34374699SSimon Glass */ 9*34374699SSimon Glass 10*34374699SSimon Glass #include <common.h> 11*34374699SSimon Glass #include <clk.h> 12*34374699SSimon Glass #include <dm.h> 13*34374699SSimon Glass #include <errno.h> 14*34374699SSimon Glass #include <i2c.h> 15*34374699SSimon Glass #include <asm/io.h> 16*34374699SSimon Glass #include <asm/arch/clock.h> 17*34374699SSimon Glass #include <asm/arch/i2c.h> 18*34374699SSimon Glass #include <asm/arch/periph.h> 19*34374699SSimon Glass #include <dm/pinctrl.h> 20*34374699SSimon Glass #include <linux/sizes.h> 21*34374699SSimon Glass 22*34374699SSimon Glass DECLARE_GLOBAL_DATA_PTR; 23*34374699SSimon Glass 24*34374699SSimon Glass /* i2c timerout */ 25*34374699SSimon Glass #define I2C_TIMEOUT_MS 100 26*34374699SSimon Glass #define I2C_RETRY_COUNT 3 27*34374699SSimon Glass 28*34374699SSimon Glass /* rk i2c fifo max transfer bytes */ 29*34374699SSimon Glass #define RK_I2C_FIFO_SIZE 32 30*34374699SSimon Glass 31*34374699SSimon Glass struct rk_i2c { 32*34374699SSimon Glass struct udevice *clk; 33*34374699SSimon Glass struct udevice *pinctrl; 34*34374699SSimon Glass struct i2c_regs *regs; 35*34374699SSimon Glass unsigned int speed; 36*34374699SSimon Glass enum periph_id id; 37*34374699SSimon Glass }; 38*34374699SSimon Glass 39*34374699SSimon Glass static inline void rk_i2c_get_div(int div, int *divh, int *divl) 40*34374699SSimon Glass { 41*34374699SSimon Glass *divl = div / 2; 42*34374699SSimon Glass if (div % 2 == 0) 43*34374699SSimon Glass *divh = div / 2; 44*34374699SSimon Glass else 45*34374699SSimon Glass *divh = DIV_ROUND_UP(div, 2); 46*34374699SSimon Glass } 47*34374699SSimon Glass 48*34374699SSimon Glass /* 49*34374699SSimon Glass * SCL Divisor = 8 * (CLKDIVL+1 + CLKDIVH+1) 50*34374699SSimon Glass * SCL = PCLK / SCLK Divisor 51*34374699SSimon Glass * i2c_rate = PCLK 52*34374699SSimon Glass */ 53*34374699SSimon Glass static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32_t scl_rate) 54*34374699SSimon Glass { 55*34374699SSimon Glass uint32_t i2c_rate; 56*34374699SSimon Glass int div, divl, divh; 57*34374699SSimon Glass 58*34374699SSimon Glass /* First get i2c rate from pclk */ 59*34374699SSimon Glass i2c_rate = clk_get_periph_rate(i2c->clk, i2c->id); 60*34374699SSimon Glass 61*34374699SSimon Glass div = DIV_ROUND_UP(i2c_rate, scl_rate * 8) - 2; 62*34374699SSimon Glass divh = 0; 63*34374699SSimon Glass divl = 0; 64*34374699SSimon Glass if (div >= 0) 65*34374699SSimon Glass rk_i2c_get_div(div, &divh, &divl); 66*34374699SSimon Glass writel(I2C_CLKDIV_VAL(divl, divh), &i2c->regs->clkdiv); 67*34374699SSimon Glass 68*34374699SSimon Glass debug("rk_i2c_set_clk: i2c rate = %d, scl rate = %d\n", i2c_rate, 69*34374699SSimon Glass scl_rate); 70*34374699SSimon Glass debug("set i2c clk div = %d, divh = %d, divl = %d\n", div, divh, divl); 71*34374699SSimon Glass debug("set clk(I2C_CLKDIV: 0x%08x)\n", readl(&i2c->regs->clkdiv)); 72*34374699SSimon Glass } 73*34374699SSimon Glass 74*34374699SSimon Glass static void rk_i2c_show_regs(struct i2c_regs *regs) 75*34374699SSimon Glass { 76*34374699SSimon Glass #ifdef DEBUG 77*34374699SSimon Glass uint i; 78*34374699SSimon Glass 79*34374699SSimon Glass debug("i2c_con: 0x%08x\n", readl(®s->con)); 80*34374699SSimon Glass debug("i2c_clkdiv: 0x%08x\n", readl(®s->clkdiv)); 81*34374699SSimon Glass debug("i2c_mrxaddr: 0x%08x\n", readl(®s->mrxaddr)); 82*34374699SSimon Glass debug("i2c_mrxraddR: 0x%08x\n", readl(®s->mrxraddr)); 83*34374699SSimon Glass debug("i2c_mtxcnt: 0x%08x\n", readl(®s->mtxcnt)); 84*34374699SSimon Glass debug("i2c_mrxcnt: 0x%08x\n", readl(®s->mrxcnt)); 85*34374699SSimon Glass debug("i2c_ien: 0x%08x\n", readl(®s->ien)); 86*34374699SSimon Glass debug("i2c_ipd: 0x%08x\n", readl(®s->ipd)); 87*34374699SSimon Glass debug("i2c_fcnt: 0x%08x\n", readl(®s->fcnt)); 88*34374699SSimon Glass for (i = 0; i < 8; i++) 89*34374699SSimon Glass debug("i2c_txdata%d: 0x%08x\n", i, readl(®s->txdata[i])); 90*34374699SSimon Glass for (i = 0; i < 8; i++) 91*34374699SSimon Glass debug("i2c_rxdata%d: 0x%08x\n", i, readl(®s->rxdata[i])); 92*34374699SSimon Glass #endif 93*34374699SSimon Glass } 94*34374699SSimon Glass 95*34374699SSimon Glass static int rk_i2c_send_start_bit(struct rk_i2c *i2c) 96*34374699SSimon Glass { 97*34374699SSimon Glass struct i2c_regs *regs = i2c->regs; 98*34374699SSimon Glass ulong start; 99*34374699SSimon Glass 100*34374699SSimon Glass debug("I2c Send Start bit.\n"); 101*34374699SSimon Glass writel(I2C_IPD_ALL_CLEAN, ®s->ipd); 102*34374699SSimon Glass 103*34374699SSimon Glass writel(I2C_CON_EN | I2C_CON_START, ®s->con); 104*34374699SSimon Glass writel(I2C_STARTIEN, ®s->ien); 105*34374699SSimon Glass 106*34374699SSimon Glass start = get_timer(0); 107*34374699SSimon Glass while (1) { 108*34374699SSimon Glass if (readl(®s->ipd) & I2C_STARTIPD) { 109*34374699SSimon Glass writel(I2C_STARTIPD, ®s->ipd); 110*34374699SSimon Glass break; 111*34374699SSimon Glass } 112*34374699SSimon Glass if (get_timer(start) > I2C_TIMEOUT_MS) { 113*34374699SSimon Glass debug("I2C Send Start Bit Timeout\n"); 114*34374699SSimon Glass rk_i2c_show_regs(regs); 115*34374699SSimon Glass return -ETIMEDOUT; 116*34374699SSimon Glass } 117*34374699SSimon Glass udelay(1); 118*34374699SSimon Glass } 119*34374699SSimon Glass 120*34374699SSimon Glass return 0; 121*34374699SSimon Glass } 122*34374699SSimon Glass 123*34374699SSimon Glass static int rk_i2c_send_stop_bit(struct rk_i2c *i2c) 124*34374699SSimon Glass { 125*34374699SSimon Glass struct i2c_regs *regs = i2c->regs; 126*34374699SSimon Glass ulong start; 127*34374699SSimon Glass 128*34374699SSimon Glass debug("I2c Send Stop bit.\n"); 129*34374699SSimon Glass writel(I2C_IPD_ALL_CLEAN, ®s->ipd); 130*34374699SSimon Glass 131*34374699SSimon Glass writel(I2C_CON_EN | I2C_CON_STOP, ®s->con); 132*34374699SSimon Glass writel(I2C_CON_STOP, ®s->ien); 133*34374699SSimon Glass 134*34374699SSimon Glass start = get_timer(0); 135*34374699SSimon Glass while (1) { 136*34374699SSimon Glass if (readl(®s->ipd) & I2C_STOPIPD) { 137*34374699SSimon Glass writel(I2C_STOPIPD, ®s->ipd); 138*34374699SSimon Glass break; 139*34374699SSimon Glass } 140*34374699SSimon Glass if (get_timer(start) > I2C_TIMEOUT_MS) { 141*34374699SSimon Glass debug("I2C Send Start Bit Timeout\n"); 142*34374699SSimon Glass rk_i2c_show_regs(regs); 143*34374699SSimon Glass return -ETIMEDOUT; 144*34374699SSimon Glass } 145*34374699SSimon Glass udelay(1); 146*34374699SSimon Glass } 147*34374699SSimon Glass 148*34374699SSimon Glass return 0; 149*34374699SSimon Glass } 150*34374699SSimon Glass 151*34374699SSimon Glass static inline void rk_i2c_disable(struct rk_i2c *i2c) 152*34374699SSimon Glass { 153*34374699SSimon Glass writel(0, &i2c->regs->con); 154*34374699SSimon Glass } 155*34374699SSimon Glass 156*34374699SSimon Glass static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, 157*34374699SSimon Glass uchar *buf, uint b_len) 158*34374699SSimon Glass { 159*34374699SSimon Glass struct i2c_regs *regs = i2c->regs; 160*34374699SSimon Glass uchar *pbuf = buf; 161*34374699SSimon Glass uint bytes_remain_len = b_len; 162*34374699SSimon Glass uint bytes_xferred = 0; 163*34374699SSimon Glass uint words_xferred = 0; 164*34374699SSimon Glass ulong start; 165*34374699SSimon Glass uint con = 0; 166*34374699SSimon Glass uint rxdata; 167*34374699SSimon Glass uint i, j; 168*34374699SSimon Glass int err; 169*34374699SSimon Glass 170*34374699SSimon Glass debug("rk_i2c_read: chip = %d, reg = %d, r_len = %d, b_len = %d\n", 171*34374699SSimon Glass chip, reg, r_len, b_len); 172*34374699SSimon Glass 173*34374699SSimon Glass err = rk_i2c_send_start_bit(i2c); 174*34374699SSimon Glass if (err) 175*34374699SSimon Glass return err; 176*34374699SSimon Glass 177*34374699SSimon Glass writel(I2C_MRXADDR_SET(1, chip << 1 | 1), ®s->mrxaddr); 178*34374699SSimon Glass if (r_len == 0) { 179*34374699SSimon Glass writel(0, ®s->mrxraddr); 180*34374699SSimon Glass } else if (r_len < 4) { 181*34374699SSimon Glass writel(I2C_MRXRADDR_SET(r_len, reg), ®s->mrxraddr); 182*34374699SSimon Glass } else { 183*34374699SSimon Glass debug("I2C Read: addr len %d not supported\n", r_len); 184*34374699SSimon Glass return -EIO; 185*34374699SSimon Glass } 186*34374699SSimon Glass 187*34374699SSimon Glass while (bytes_remain_len) { 188*34374699SSimon Glass if (bytes_remain_len > RK_I2C_FIFO_SIZE) { 189*34374699SSimon Glass con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX); 190*34374699SSimon Glass bytes_xferred = 32; 191*34374699SSimon Glass } else { 192*34374699SSimon Glass con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) | 193*34374699SSimon Glass I2C_CON_LASTACK; 194*34374699SSimon Glass bytes_xferred = bytes_remain_len; 195*34374699SSimon Glass } 196*34374699SSimon Glass words_xferred = DIV_ROUND_UP(bytes_xferred, 4); 197*34374699SSimon Glass 198*34374699SSimon Glass writel(con, ®s->con); 199*34374699SSimon Glass writel(bytes_xferred, ®s->mrxcnt); 200*34374699SSimon Glass writel(I2C_MBRFIEN | I2C_NAKRCVIEN, ®s->ien); 201*34374699SSimon Glass 202*34374699SSimon Glass start = get_timer(0); 203*34374699SSimon Glass while (1) { 204*34374699SSimon Glass if (readl(®s->ipd) & I2C_NAKRCVIPD) { 205*34374699SSimon Glass writel(I2C_NAKRCVIPD, ®s->ipd); 206*34374699SSimon Glass err = -EREMOTEIO; 207*34374699SSimon Glass } 208*34374699SSimon Glass if (readl(®s->ipd) & I2C_MBRFIPD) { 209*34374699SSimon Glass writel(I2C_MBRFIPD, ®s->ipd); 210*34374699SSimon Glass break; 211*34374699SSimon Glass } 212*34374699SSimon Glass if (get_timer(start) > I2C_TIMEOUT_MS) { 213*34374699SSimon Glass debug("I2C Read Data Timeout\n"); 214*34374699SSimon Glass err = -ETIMEDOUT; 215*34374699SSimon Glass rk_i2c_show_regs(regs); 216*34374699SSimon Glass goto i2c_exit; 217*34374699SSimon Glass } 218*34374699SSimon Glass udelay(1); 219*34374699SSimon Glass } 220*34374699SSimon Glass 221*34374699SSimon Glass for (i = 0; i < words_xferred; i++) { 222*34374699SSimon Glass rxdata = readl(®s->rxdata[i]); 223*34374699SSimon Glass debug("I2c Read RXDATA[%d] = 0x%x\n", i, rxdata); 224*34374699SSimon Glass for (j = 0; j < 4; j++) { 225*34374699SSimon Glass if ((i * 4 + j) == bytes_xferred) 226*34374699SSimon Glass break; 227*34374699SSimon Glass *pbuf++ = (rxdata >> (j * 8)) & 0xff; 228*34374699SSimon Glass } 229*34374699SSimon Glass } 230*34374699SSimon Glass 231*34374699SSimon Glass bytes_remain_len -= bytes_xferred; 232*34374699SSimon Glass debug("I2C Read bytes_remain_len %d\n", bytes_remain_len); 233*34374699SSimon Glass } 234*34374699SSimon Glass 235*34374699SSimon Glass i2c_exit: 236*34374699SSimon Glass rk_i2c_send_stop_bit(i2c); 237*34374699SSimon Glass rk_i2c_disable(i2c); 238*34374699SSimon Glass 239*34374699SSimon Glass return err; 240*34374699SSimon Glass } 241*34374699SSimon Glass 242*34374699SSimon Glass static int rk_i2c_write(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, 243*34374699SSimon Glass uchar *buf, uint b_len) 244*34374699SSimon Glass { 245*34374699SSimon Glass struct i2c_regs *regs = i2c->regs; 246*34374699SSimon Glass int err; 247*34374699SSimon Glass uchar *pbuf = buf; 248*34374699SSimon Glass uint bytes_remain_len = b_len + r_len + 1; 249*34374699SSimon Glass uint bytes_xferred = 0; 250*34374699SSimon Glass uint words_xferred = 0; 251*34374699SSimon Glass ulong start; 252*34374699SSimon Glass uint txdata; 253*34374699SSimon Glass uint i, j; 254*34374699SSimon Glass 255*34374699SSimon Glass debug("rk_i2c_write: chip = %d, reg = %d, r_len = %d, b_len = %d\n", 256*34374699SSimon Glass chip, reg, r_len, b_len); 257*34374699SSimon Glass err = rk_i2c_send_start_bit(i2c); 258*34374699SSimon Glass if (err) 259*34374699SSimon Glass return err; 260*34374699SSimon Glass 261*34374699SSimon Glass while (bytes_remain_len) { 262*34374699SSimon Glass if (bytes_remain_len > RK_I2C_FIFO_SIZE) 263*34374699SSimon Glass bytes_xferred = 32; 264*34374699SSimon Glass else 265*34374699SSimon Glass bytes_xferred = bytes_remain_len; 266*34374699SSimon Glass words_xferred = DIV_ROUND_UP(bytes_xferred, 4); 267*34374699SSimon Glass 268*34374699SSimon Glass for (i = 0; i < words_xferred; i++) { 269*34374699SSimon Glass txdata = 0; 270*34374699SSimon Glass for (j = 0; j < 4; j++) { 271*34374699SSimon Glass if ((i * 4 + j) == bytes_xferred) 272*34374699SSimon Glass break; 273*34374699SSimon Glass 274*34374699SSimon Glass if (i == 0 && j == 0) { 275*34374699SSimon Glass txdata |= (chip << 1); 276*34374699SSimon Glass } else if (i == 0 && j <= r_len) { 277*34374699SSimon Glass txdata |= (reg & 278*34374699SSimon Glass (0xff << ((j - 1) * 8))) << 8; 279*34374699SSimon Glass } else { 280*34374699SSimon Glass txdata |= (*pbuf++)<<(j * 8); 281*34374699SSimon Glass } 282*34374699SSimon Glass writel(txdata, ®s->txdata[i]); 283*34374699SSimon Glass } 284*34374699SSimon Glass debug("I2c Write TXDATA[%d] = 0x%x\n", i, txdata); 285*34374699SSimon Glass } 286*34374699SSimon Glass 287*34374699SSimon Glass writel(I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TX), ®s->con); 288*34374699SSimon Glass writel(bytes_xferred, ®s->mtxcnt); 289*34374699SSimon Glass writel(I2C_MBTFIEN | I2C_NAKRCVIEN, ®s->ien); 290*34374699SSimon Glass 291*34374699SSimon Glass start = get_timer(0); 292*34374699SSimon Glass while (1) { 293*34374699SSimon Glass if (readl(®s->ipd) & I2C_NAKRCVIPD) { 294*34374699SSimon Glass writel(I2C_NAKRCVIPD, ®s->ipd); 295*34374699SSimon Glass err = -EREMOTEIO; 296*34374699SSimon Glass } 297*34374699SSimon Glass if (readl(®s->ipd) & I2C_MBTFIPD) { 298*34374699SSimon Glass writel(I2C_MBTFIPD, ®s->ipd); 299*34374699SSimon Glass break; 300*34374699SSimon Glass } 301*34374699SSimon Glass if (get_timer(start) > I2C_TIMEOUT_MS) { 302*34374699SSimon Glass debug("I2C Write Data Timeout\n"); 303*34374699SSimon Glass err = -ETIMEDOUT; 304*34374699SSimon Glass rk_i2c_show_regs(regs); 305*34374699SSimon Glass goto i2c_exit; 306*34374699SSimon Glass } 307*34374699SSimon Glass udelay(1); 308*34374699SSimon Glass } 309*34374699SSimon Glass 310*34374699SSimon Glass bytes_remain_len -= bytes_xferred; 311*34374699SSimon Glass debug("I2C Write bytes_remain_len %d\n", bytes_remain_len); 312*34374699SSimon Glass } 313*34374699SSimon Glass 314*34374699SSimon Glass i2c_exit: 315*34374699SSimon Glass rk_i2c_send_stop_bit(i2c); 316*34374699SSimon Glass rk_i2c_disable(i2c); 317*34374699SSimon Glass 318*34374699SSimon Glass return err; 319*34374699SSimon Glass } 320*34374699SSimon Glass 321*34374699SSimon Glass static int rockchip_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, 322*34374699SSimon Glass int nmsgs) 323*34374699SSimon Glass { 324*34374699SSimon Glass struct rk_i2c *i2c = dev_get_priv(bus); 325*34374699SSimon Glass int ret; 326*34374699SSimon Glass 327*34374699SSimon Glass debug("i2c_xfer: %d messages\n", nmsgs); 328*34374699SSimon Glass for (; nmsgs > 0; nmsgs--, msg++) { 329*34374699SSimon Glass debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); 330*34374699SSimon Glass if (msg->flags & I2C_M_RD) { 331*34374699SSimon Glass ret = rk_i2c_read(i2c, msg->addr, 0, 0, msg->buf, 332*34374699SSimon Glass msg->len); 333*34374699SSimon Glass } else { 334*34374699SSimon Glass ret = rk_i2c_write(i2c, msg->addr, 0, 0, msg->buf, 335*34374699SSimon Glass msg->len); 336*34374699SSimon Glass } 337*34374699SSimon Glass if (ret) { 338*34374699SSimon Glass debug("i2c_write: error sending\n"); 339*34374699SSimon Glass return -EREMOTEIO; 340*34374699SSimon Glass } 341*34374699SSimon Glass } 342*34374699SSimon Glass 343*34374699SSimon Glass return 0; 344*34374699SSimon Glass } 345*34374699SSimon Glass 346*34374699SSimon Glass int rockchip_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) 347*34374699SSimon Glass { 348*34374699SSimon Glass struct rk_i2c *i2c = dev_get_priv(bus); 349*34374699SSimon Glass 350*34374699SSimon Glass rk_i2c_set_clk(i2c, speed); 351*34374699SSimon Glass 352*34374699SSimon Glass return 0; 353*34374699SSimon Glass } 354*34374699SSimon Glass 355*34374699SSimon Glass static int rockchip_i2c_probe(struct udevice *bus) 356*34374699SSimon Glass { 357*34374699SSimon Glass struct rk_i2c *i2c = dev_get_priv(bus); 358*34374699SSimon Glass int ret; 359*34374699SSimon Glass 360*34374699SSimon Glass ret = uclass_get_device(UCLASS_PINCTRL, 0, &i2c->pinctrl); 361*34374699SSimon Glass if (ret) 362*34374699SSimon Glass return ret; 363*34374699SSimon Glass ret = uclass_get_device(UCLASS_CLK, 0, &i2c->clk); 364*34374699SSimon Glass if (ret) 365*34374699SSimon Glass return ret; 366*34374699SSimon Glass ret = pinctrl_get_periph_id(i2c->pinctrl, bus); 367*34374699SSimon Glass if (ret < 0) 368*34374699SSimon Glass return ret; 369*34374699SSimon Glass i2c->id = ret; 370*34374699SSimon Glass i2c->regs = (void *)dev_get_addr(bus); 371*34374699SSimon Glass return pinctrl_request(i2c->pinctrl, i2c->id, 0); 372*34374699SSimon Glass } 373*34374699SSimon Glass 374*34374699SSimon Glass static const struct dm_i2c_ops rockchip_i2c_ops = { 375*34374699SSimon Glass .xfer = rockchip_i2c_xfer, 376*34374699SSimon Glass .set_bus_speed = rockchip_i2c_set_bus_speed, 377*34374699SSimon Glass }; 378*34374699SSimon Glass 379*34374699SSimon Glass static const struct udevice_id rockchip_i2c_ids[] = { 380*34374699SSimon Glass { .compatible = "rockchip,rk3288-i2c" }, 381*34374699SSimon Glass { } 382*34374699SSimon Glass }; 383*34374699SSimon Glass 384*34374699SSimon Glass U_BOOT_DRIVER(i2c_rockchip) = { 385*34374699SSimon Glass .name = "i2c_rockchip", 386*34374699SSimon Glass .id = UCLASS_I2C, 387*34374699SSimon Glass .of_match = rockchip_i2c_ids, 388*34374699SSimon Glass .probe = rockchip_i2c_probe, 389*34374699SSimon Glass .priv_auto_alloc_size = sizeof(struct rk_i2c), 390*34374699SSimon Glass .ops = &rockchip_i2c_ops, 391*34374699SSimon Glass }; 392