/* * drivers/i2c/rcar_i2c.c * * Copyright (C) 2013 Renesas Electronics Corporation * Copyright (C) 2013 Nobuhiro Iwamatsu * * SPDX-License-Identifier: GPL-2.0 */ #include #include #include DECLARE_GLOBAL_DATA_PTR; struct rcar_i2c { u32 icscr; u32 icmcr; u32 icssr; u32 icmsr; u32 icsier; u32 icmier; u32 icccr; u32 icsar; u32 icmar; u32 icrxdtxd; u32 icccr2; u32 icmpr; u32 ichpr; u32 iclpr; }; #define MCR_MDBS 0x80 /* non-fifo mode switch */ #define MCR_FSCL 0x40 /* override SCL pin */ #define MCR_FSDA 0x20 /* override SDA pin */ #define MCR_OBPC 0x10 /* override pins */ #define MCR_MIE 0x08 /* master if enable */ #define MCR_TSBE 0x04 #define MCR_FSB 0x02 /* force stop bit */ #define MCR_ESG 0x01 /* en startbit gen. */ #define MSR_MASK 0x7f #define MSR_MNR 0x40 /* nack received */ #define MSR_MAL 0x20 /* arbitration lost */ #define MSR_MST 0x10 /* sent a stop */ #define MSR_MDE 0x08 #define MSR_MDT 0x04 #define MSR_MDR 0x02 #define MSR_MAT 0x01 /* slave addr xfer done */ static const struct rcar_i2c *i2c_dev[CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS] = { (struct rcar_i2c *)CONFIG_SYS_RCAR_I2C0_BASE, (struct rcar_i2c *)CONFIG_SYS_RCAR_I2C1_BASE, (struct rcar_i2c *)CONFIG_SYS_RCAR_I2C2_BASE, (struct rcar_i2c *)CONFIG_SYS_RCAR_I2C3_BASE, }; static void rcar_i2c_raw_rw_common(struct rcar_i2c *dev, u8 chip, uint addr) { /* set slave address */ writel(chip << 1, &dev->icmar); /* set register address */ writel(addr, &dev->icrxdtxd); /* clear status */ writel(0, &dev->icmsr); /* start master send */ writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr); while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDE)) != (MSR_MAT | MSR_MDE)) udelay(10); /* clear ESG */ writel(MCR_MDBS | MCR_MIE, &dev->icmcr); /* start SCLclk */ writel(~(MSR_MAT | MSR_MDE), &dev->icmsr); while (!(readl(&dev->icmsr) & MSR_MDE)) udelay(10); } static void rcar_i2c_raw_rw_finish(struct rcar_i2c *dev) { while (!(readl(&dev->icmsr) & MSR_MST)) udelay(10); writel(0, &dev->icmcr); } static int rcar_i2c_raw_write(struct rcar_i2c *dev, u8 chip, uint addr, u8 *val, int size) { rcar_i2c_raw_rw_common(dev, chip, addr); /* set send date */ writel(*val, &dev->icrxdtxd); /* start SCLclk */ writel(~MSR_MDE, &dev->icmsr); while (!(readl(&dev->icmsr) & MSR_MDE)) udelay(10); /* set stop condition */ writel(MCR_MDBS | MCR_MIE | MCR_FSB, &dev->icmcr); /* start SCLclk */ writel(~MSR_MDE, &dev->icmsr); rcar_i2c_raw_rw_finish(dev); return 0; } static u8 rcar_i2c_raw_read(struct rcar_i2c *dev, u8 chip, uint addr) { u8 ret; rcar_i2c_raw_rw_common(dev, chip, addr); /* set slave address, receive */ writel((chip << 1) | 1, &dev->icmar); /* start master receive */ writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr); /* clear status */ writel(0, &dev->icmsr); while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDR)) != (MSR_MAT | MSR_MDR)) udelay(10); /* clear ESG */ writel(MCR_MDBS | MCR_MIE, &dev->icmcr); /* prepare stop condition */ writel(MCR_MDBS | MCR_MIE | MCR_FSB, &dev->icmcr); /* start SCLclk */ writel(~(MSR_MAT | MSR_MDR), &dev->icmsr); while (!(readl(&dev->icmsr) & MSR_MDR)) udelay(10); /* get receive data */ ret = (u8)readl(&dev->icrxdtxd); /* start SCLclk */ writel(~MSR_MDR, &dev->icmsr); rcar_i2c_raw_rw_finish(dev); return ret; } /* * SCL = iicck / (20 + SCGD * 8 + F[(ticf + tr + intd) * iicck]) * iicck : I2C internal clock < 20 MHz * ticf : I2C SCL falling time: 35 ns * tr : I2C SCL rising time: 200 ns * intd : LSI internal delay: I2C0: 50 ns I2C1-3: 5 * F[n] : n rounded up to an integer */ static u32 rcar_clock_gen(int i2c_no, u32 bus_speed) { u32 iicck, f, scl, scgd; u32 intd = 5; int bit = 0, cdf_width = 3; for (bit = 0; bit < (1 << cdf_width); bit++) { iicck = CONFIG_HP_CLK_FREQ / (1 + bit); if (iicck < 20000000) break; } if (bit > (1 << cdf_width)) { puts("rcar-i2c: Can not get CDF\n"); return 0; } if (i2c_no == 0) intd = 50; f = (35 + 200 + intd) * (iicck / 1000000000); for (scgd = 0; scgd < 0x40; scgd++) { scl = iicck / (20 + (scgd * 8) + f); if (scl <= bus_speed) break; } if (scgd > 0x40) { puts("rcar-i2c: Can not get SDGB\n"); return 0; } debug("%s: scl: %d\n", __func__, scl); debug("%s: bit %x\n", __func__, bit); debug("%s: scgd %x\n", __func__, scgd); debug("%s: iccr %x\n", __func__, (scgd << (cdf_width) | bit)); return scgd << (cdf_width) | bit; } static void rcar_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr]; u32 icccr = 0; /* No i2c support prior to relocation */ if (!(gd->flags & GD_FLG_RELOC)) return; /* * reset slave mode. * slave mode is not used on this driver */ writel(0, &dev->icsier); writel(0, &dev->icsar); writel(0, &dev->icscr); writel(0, &dev->icssr); /* reset master mode */ writel(0, &dev->icmier); writel(0, &dev->icmcr); writel(0, &dev->icmsr); writel(0, &dev->icmar); icccr = rcar_clock_gen(adap->hwadapnr, adap->speed); if (icccr == 0) puts("I2C: Init failed\n"); else writel(icccr, &dev->icccr); } static int rcar_i2c_read(struct i2c_adapter *adap, uint8_t chip, uint addr, int alen, u8 *data, int len) { struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr]; int i; for (i = 0; i < len; i++) data[i] = rcar_i2c_raw_read(dev, chip, addr + i); return 0; } static int rcar_i2c_write(struct i2c_adapter *adap, uint8_t chip, uint addr, int alen, u8 *data, int len) { struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr]; return rcar_i2c_raw_write(dev, chip, addr, data, len); } static int rcar_i2c_probe(struct i2c_adapter *adap, u8 dev) { return rcar_i2c_read(adap, dev, 0, 0, NULL, 0); } static unsigned int rcar_i2c_set_bus_speed(struct i2c_adapter *adap, unsigned int speed) { struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr]; u32 icccr; int ret = 0; rcar_i2c_raw_rw_finish(dev); icccr = rcar_clock_gen(adap->hwadapnr, speed); if (icccr == 0) { puts("I2C: Init failed\n"); ret = -1; } else { writel(icccr, &dev->icccr); } return ret; } /* * Register RCAR i2c adapters */ U_BOOT_I2C_ADAP_COMPLETE(rcar_0, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read, rcar_i2c_write, rcar_i2c_set_bus_speed, CONFIG_SYS_RCAR_I2C0_SPEED, 0, 0) U_BOOT_I2C_ADAP_COMPLETE(rcar_1, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read, rcar_i2c_write, rcar_i2c_set_bus_speed, CONFIG_SYS_RCAR_I2C1_SPEED, 0, 1) U_BOOT_I2C_ADAP_COMPLETE(rcar_2, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read, rcar_i2c_write, rcar_i2c_set_bus_speed, CONFIG_SYS_RCAR_I2C2_SPEED, 0, 2) U_BOOT_I2C_ADAP_COMPLETE(rcar_3, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read, rcar_i2c_write, rcar_i2c_set_bus_speed, CONFIG_SYS_RCAR_I2C3_SPEED, 0, 3)