123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- */
- #include <dm/device_compat.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/io.h>
- #include <linux/sizes.h>
- #include <linux/types.h>
- #include <dm.h>
- #include <fdtdec.h>
- #include <i2c.h>
- #include <clk.h>
- #define REG_BSR 0x0
- #define REG_BCR 0x4
- #define REG_CCR 0x8
- #define REG_ADR 0xc
- #define REG_DAR 0x10
- #define REG_CSR 0x14
- #define REG_FSR 0x18
- #define REG_BC2R 0x1c
- /* I2C register bit definitions */
- #define BSR_FBT BIT(0) // First Byte Transfer
- #define BSR_GCA BIT(1) // General Call Address
- #define BSR_AAS BIT(2) // Address as Slave
- #define BSR_TRX BIT(3) // Transfer/Receive
- #define BSR_LRB BIT(4) // Last Received Bit
- #define BSR_AL BIT(5) // Arbitration Lost
- #define BSR_RSC BIT(6) // Repeated Start Cond.
- #define BSR_BB BIT(7) // Bus Busy
- #define BCR_INT BIT(0) // Interrupt
- #define BCR_INTE BIT(1) // Interrupt Enable
- #define BCR_GCAA BIT(2) // Gen. Call Access Ack.
- #define BCR_ACK BIT(3) // Acknowledge
- #define BCR_MSS BIT(4) // Master Slave Select
- #define BCR_SCC BIT(5) // Start Condition Cont.
- #define BCR_BEIE BIT(6) // Bus Error Int Enable
- #define BCR_BER BIT(7) // Bus Error
- #define CCR_CS_MASK (0x1f) // CCR Clock Period Sel.
- #define CCR_EN BIT(5) // Enable
- #define CCR_FM BIT(6) // Speed Mode Select
- #define CSR_CS_MASK (0x3f) // CSR Clock Period Sel.
- #define BC2R_SCLL BIT(0) // SCL Low Drive
- #define BC2R_SDAL BIT(1) // SDA Low Drive
- #define BC2R_SCLS BIT(4) // SCL Status
- #define BC2R_SDAS BIT(5) // SDA Status
- /* PCLK frequency */
- #define BUS_CLK_FR(rate) (((rate) / 20000000) + 1)
- #define I2C_CLK_DEF 62500000
- /* STANDARD MODE frequency */
- #define CLK_MASTER_STD(rate) \
- DIV_ROUND_UP(DIV_ROUND_UP((rate), I2C_SPEED_STANDARD_RATE) - 2, 2)
- /* FAST MODE frequency */
- #define CLK_MASTER_FAST(rate) \
- DIV_ROUND_UP((DIV_ROUND_UP((rate), I2C_SPEED_FAST_RATE) - 2) * 2, 3)
- /* (clkrate <= 18000000) */
- /* calculate the value of CS bits in CCR register on standard mode */
- #define CCR_CS_STD_MAX_18M(rate) \
- ((CLK_MASTER_STD(rate) - 65) \
- & CCR_CS_MASK)
- /* calculate the value of CS bits in CSR register on standard mode */
- #define CSR_CS_STD_MAX_18M(rate) 0x00
- /* calculate the value of CS bits in CCR register on fast mode */
- #define CCR_CS_FAST_MAX_18M(rate) \
- ((CLK_MASTER_FAST(rate) - 1) \
- & CCR_CS_MASK)
- /* calculate the value of CS bits in CSR register on fast mode */
- #define CSR_CS_FAST_MAX_18M(rate) 0x00
- /* (clkrate > 18000000) */
- /* calculate the value of CS bits in CCR register on standard mode */
- #define CCR_CS_STD_MIN_18M(rate) \
- ((CLK_MASTER_STD(rate) - 1) \
- & CCR_CS_MASK)
- /* calculate the value of CS bits in CSR register on standard mode */
- #define CSR_CS_STD_MIN_18M(rate) \
- (((CLK_MASTER_STD(rate) - 1) >> 5) \
- & CSR_CS_MASK)
- /* calculate the value of CS bits in CCR register on fast mode */
- #define CCR_CS_FAST_MIN_18M(rate) \
- ((CLK_MASTER_FAST(rate) - 1) \
- & CCR_CS_MASK)
- /* calculate the value of CS bits in CSR register on fast mode */
- #define CSR_CS_FAST_MIN_18M(rate) \
- (((CLK_MASTER_FAST(rate) - 1) >> 5) \
- & CSR_CS_MASK)
- /* min I2C clock frequency 14M */
- #define MIN_CLK_RATE (14 * 1000000)
- /* max I2C clock frequency 200M */
- #define MAX_CLK_RATE (200 * 1000000)
- /* I2C clock frequency 18M */
- #define CLK_RATE_18M (18 * 1000000)
- #define SPEED_FM 400 // Fast Mode
- #define SPEED_SM 100 // Standard Mode
- DECLARE_GLOBAL_DATA_PTR;
- struct synquacer_i2c {
- void __iomem *base;
- unsigned long pclkrate;
- unsigned long speed_khz;
- };
- static int wait_irq(struct udevice *dev)
- {
- struct synquacer_i2c *i2c = dev_get_priv(dev);
- int timeout = 500000;
- do {
- if (readb(i2c->base + REG_BCR) & BCR_INT)
- return 0;
- } while (timeout--);
- pr_err("%s: timeout\n", __func__);
- return -1;
- }
- static int synquacer_i2c_xfer_start(struct synquacer_i2c *i2c,
- int addr, int read)
- {
- u8 bsr, bcr;
- writeb((addr << 1) | (read ? 1 : 0), i2c->base + REG_DAR);
- bsr = readb(i2c->base + REG_BSR);
- bcr = readb(i2c->base + REG_BCR);
- if ((bsr & BSR_BB) && !(bcr & BCR_MSS))
- return -EBUSY;
- if (bsr & BSR_BB) {
- writeb(bcr | BCR_SCC, i2c->base + REG_BCR);
- } else {
- if (bcr & BCR_MSS)
- return -EAGAIN;
- /* Start Condition + Enable Interrupts */
- writeb(bcr | BCR_MSS | BCR_INTE | BCR_BEIE, i2c->base + REG_BCR);
- }
- udelay(100);
- return 0;
- }
- static int synquacer_i2c_xfer(struct udevice *bus,
- struct i2c_msg *msg, int nmsgs)
- {
- struct synquacer_i2c *i2c = dev_get_priv(bus);
- u8 bsr, bcr;
- int idx;
- for (; nmsgs > 0; nmsgs--, msg++) {
- synquacer_i2c_xfer_start(i2c, msg->addr, msg->flags & I2C_M_RD);
- if (wait_irq(bus))
- return -EREMOTEIO;
- bsr = readb(i2c->base + REG_BSR);
- if (bsr & BSR_LRB) {
- debug("%s: No ack received\n", __func__);
- return -EREMOTEIO;
- }
- idx = 0;
- do {
- bsr = readb(i2c->base + REG_BSR);
- bcr = readb(i2c->base + REG_BCR);
- if (bcr & BCR_BER) {
- debug("%s: Bus error detected\n", __func__);
- return -EREMOTEIO;
- }
- if ((bsr & BSR_AL) || !(bcr & BCR_MSS)) {
- debug("%s: Arbitration lost\n", __func__);
- return -EREMOTEIO;
- }
- if (msg->flags & I2C_M_RD) {
- bcr = BCR_MSS | BCR_INTE | BCR_BEIE;
- if (idx < msg->len - 1)
- bcr |= BCR_ACK;
- writeb(bcr, i2c->base + REG_BCR);
- if (wait_irq(bus))
- return -EREMOTEIO;
- bsr = readb(i2c->base + REG_BSR);
- if (!(bsr & BSR_FBT))
- msg->buf[idx++] = readb(i2c->base + REG_DAR);
- } else {
- writeb(msg->buf[idx++], i2c->base + REG_DAR);
- bcr = BCR_MSS | BCR_INTE | BCR_BEIE;
- writeb(bcr, i2c->base + REG_BCR);
- if (wait_irq(bus))
- return -EREMOTEIO;
- bsr = readb(i2c->base + REG_BSR);
- if (bsr & BSR_LRB) {
- debug("%s: no ack\n", __func__);
- return -EREMOTEIO;
- }
- }
- } while (idx < msg->len);
- }
- /* Force bus state to idle, terminating any ongoing transfer */
- writeb(0, i2c->base + REG_BCR);
- udelay(100);
- return 0;
- }
- static void synquacer_i2c_hw_reset(struct synquacer_i2c *i2c)
- {
- /* Disable clock */
- writeb(0, i2c->base + REG_CCR);
- writeb(0, i2c->base + REG_CSR);
- /* Set own Address */
- writeb(0, i2c->base + REG_ADR);
- /* Set PCLK frequency */
- writeb(BUS_CLK_FR(i2c->pclkrate), i2c->base + REG_FSR);
- /* clear IRQ (INT=0, BER=0), Interrupt Disable */
- writeb(0, i2c->base + REG_BCR);
- writeb(0, i2c->base + REG_BC2R);
- }
- static int synquacer_i2c_get_bus_speed(struct udevice *bus)
- {
- struct synquacer_i2c *i2c = dev_get_priv(bus);
- return i2c->speed_khz * 1000;
- }
- static int synquacer_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
- {
- struct synquacer_i2c *i2c = dev_get_priv(bus);
- u32 rt = i2c->pclkrate;
- u8 ccr_cs, csr_cs;
- /* Set PCLK frequency */
- writeb(BUS_CLK_FR(i2c->pclkrate), i2c->base + REG_FSR);
- if (speed >= SPEED_FM * 1000) {
- i2c->speed_khz = SPEED_FM;
- if (i2c->pclkrate <= CLK_RATE_18M) {
- ccr_cs = CCR_CS_FAST_MAX_18M(rt);
- csr_cs = CSR_CS_FAST_MAX_18M(rt);
- } else {
- ccr_cs = CCR_CS_FAST_MIN_18M(rt);
- csr_cs = CSR_CS_FAST_MIN_18M(rt);
- }
- /* Set Clock and enable, Set fast mode */
- writeb(ccr_cs | CCR_FM | CCR_EN, i2c->base + REG_CCR);
- writeb(csr_cs, i2c->base + REG_CSR);
- } else {
- i2c->speed_khz = SPEED_SM;
- if (i2c->pclkrate <= CLK_RATE_18M) {
- ccr_cs = CCR_CS_STD_MAX_18M(rt);
- csr_cs = CSR_CS_STD_MAX_18M(rt);
- } else {
- ccr_cs = CCR_CS_STD_MIN_18M(rt);
- csr_cs = CSR_CS_STD_MIN_18M(rt);
- }
- /* Set Clock and enable, Set standard mode */
- writeb(ccr_cs | CCR_EN, i2c->base + REG_CCR);
- writeb(csr_cs, i2c->base + REG_CSR);
- }
- return 0;
- }
- static int synquacer_i2c_of_to_plat(struct udevice *bus)
- {
- struct synquacer_i2c *priv = dev_get_priv(bus);
- struct clk ck;
- int ret;
- ret = clk_get_by_index(bus, 0, &ck);
- if (ret < 0) {
- priv->pclkrate = I2C_CLK_DEF;
- } else {
- clk_enable(&ck);
- priv->pclkrate = clk_get_rate(&ck);
- }
- return 0;
- }
- static int synquacer_i2c_probe(struct udevice *bus)
- {
- struct synquacer_i2c *i2c = dev_get_priv(bus);
- i2c->base = dev_read_addr_ptr(bus);
- synquacer_i2c_hw_reset(i2c);
- synquacer_i2c_set_bus_speed(bus, 400000); /* set default speed */
- return 0;
- }
- static const struct dm_i2c_ops synquacer_i2c_ops = {
- .xfer = synquacer_i2c_xfer,
- .set_bus_speed = synquacer_i2c_set_bus_speed,
- .get_bus_speed = synquacer_i2c_get_bus_speed,
- };
- static const struct udevice_id synquacer_i2c_ids[] = {
- {
- .compatible = "socionext,synquacer-i2c",
- },
- { }
- };
- U_BOOT_DRIVER(sni_synquacer_i2c) = {
- .name = "sni_synquacer_i2c",
- .id = UCLASS_I2C,
- .of_match = synquacer_i2c_ids,
- .of_to_plat = synquacer_i2c_of_to_plat,
- .probe = synquacer_i2c_probe,
- .priv_auto = sizeof(struct synquacer_i2c),
- .ops = &synquacer_i2c_ops,
- };
|