183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
29e75ea46SMarek Vasut /*
39e75ea46SMarek Vasut * Renesas RCar IIC driver
49e75ea46SMarek Vasut *
59e75ea46SMarek Vasut * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
69e75ea46SMarek Vasut *
79e75ea46SMarek Vasut * Based on
89e75ea46SMarek Vasut * Copyright (C) 2011, 2013 Renesas Solutions Corp.
99e75ea46SMarek Vasut * Copyright (C) 2011, 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
109e75ea46SMarek Vasut */
119e75ea46SMarek Vasut
129e75ea46SMarek Vasut #include <common.h>
139e75ea46SMarek Vasut #include <clk.h>
149e75ea46SMarek Vasut #include <dm.h>
159e75ea46SMarek Vasut #include <i2c.h>
169e75ea46SMarek Vasut #include <asm/io.h>
179e75ea46SMarek Vasut
189e75ea46SMarek Vasut struct rcar_iic_priv {
199e75ea46SMarek Vasut void __iomem *base;
209e75ea46SMarek Vasut struct clk clk;
219e75ea46SMarek Vasut u8 iccl;
229e75ea46SMarek Vasut u8 icch;
239e75ea46SMarek Vasut };
249e75ea46SMarek Vasut
259e75ea46SMarek Vasut #define RCAR_IIC_ICDR 0x00
269e75ea46SMarek Vasut #define RCAR_IIC_ICCR 0x04
279e75ea46SMarek Vasut #define RCAR_IIC_ICSR 0x08
289e75ea46SMarek Vasut #define RCAR_IIC_ICIC 0x0c
299e75ea46SMarek Vasut #define RCAR_IIC_ICCL 0x10
309e75ea46SMarek Vasut #define RCAR_IIC_ICCH 0x14
319e75ea46SMarek Vasut
329e75ea46SMarek Vasut /* ICCR */
339e75ea46SMarek Vasut #define RCAR_IIC_ICCR_ICE BIT(7)
349e75ea46SMarek Vasut #define RCAR_IIC_ICCR_RACK BIT(6)
359e75ea46SMarek Vasut #define RCAR_IIC_ICCR_RTS BIT(4)
369e75ea46SMarek Vasut #define RCAR_IIC_ICCR_BUSY BIT(2)
379e75ea46SMarek Vasut #define RCAR_IIC_ICCR_SCP BIT(0)
389e75ea46SMarek Vasut
399e75ea46SMarek Vasut /* ICSR / ICIC */
409e75ea46SMarek Vasut #define RCAR_IC_BUSY BIT(4)
419e75ea46SMarek Vasut #define RCAR_IC_TACK BIT(2)
429e75ea46SMarek Vasut #define RCAR_IC_DTE BIT(0)
439e75ea46SMarek Vasut
449e75ea46SMarek Vasut #define IRQ_WAIT 1000
459e75ea46SMarek Vasut
sh_irq_dte(struct udevice * dev)469e75ea46SMarek Vasut static void sh_irq_dte(struct udevice *dev)
479e75ea46SMarek Vasut {
489e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
499e75ea46SMarek Vasut int i;
509e75ea46SMarek Vasut
519e75ea46SMarek Vasut for (i = 0; i < IRQ_WAIT; i++) {
529e75ea46SMarek Vasut if (RCAR_IC_DTE & readb(priv->base + RCAR_IIC_ICSR))
539e75ea46SMarek Vasut break;
549e75ea46SMarek Vasut udelay(10);
559e75ea46SMarek Vasut }
569e75ea46SMarek Vasut }
579e75ea46SMarek Vasut
sh_irq_dte_with_tack(struct udevice * dev)589e75ea46SMarek Vasut static int sh_irq_dte_with_tack(struct udevice *dev)
599e75ea46SMarek Vasut {
609e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
61*eb54682eSMarek Vasut u8 icsr;
629e75ea46SMarek Vasut int i;
639e75ea46SMarek Vasut
649e75ea46SMarek Vasut for (i = 0; i < IRQ_WAIT; i++) {
65*eb54682eSMarek Vasut icsr = readb(priv->base + RCAR_IIC_ICSR);
66*eb54682eSMarek Vasut if (RCAR_IC_DTE & icsr)
679e75ea46SMarek Vasut break;
68*eb54682eSMarek Vasut if (RCAR_IC_TACK & icsr)
699e75ea46SMarek Vasut return -ETIMEDOUT;
709e75ea46SMarek Vasut udelay(10);
719e75ea46SMarek Vasut }
729e75ea46SMarek Vasut return 0;
739e75ea46SMarek Vasut }
749e75ea46SMarek Vasut
sh_irq_busy(struct udevice * dev)759e75ea46SMarek Vasut static void sh_irq_busy(struct udevice *dev)
769e75ea46SMarek Vasut {
779e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
789e75ea46SMarek Vasut int i;
799e75ea46SMarek Vasut
809e75ea46SMarek Vasut for (i = 0; i < IRQ_WAIT; i++) {
819e75ea46SMarek Vasut if (!(RCAR_IC_BUSY & readb(priv->base + RCAR_IIC_ICSR)))
829e75ea46SMarek Vasut break;
839e75ea46SMarek Vasut udelay(10);
849e75ea46SMarek Vasut }
859e75ea46SMarek Vasut }
869e75ea46SMarek Vasut
rcar_iic_set_addr(struct udevice * dev,u8 chip,u8 read)879e75ea46SMarek Vasut static int rcar_iic_set_addr(struct udevice *dev, u8 chip, u8 read)
889e75ea46SMarek Vasut {
899e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
909e75ea46SMarek Vasut
919e75ea46SMarek Vasut clrbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE);
929e75ea46SMarek Vasut setbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE);
939e75ea46SMarek Vasut
949e75ea46SMarek Vasut writeb(priv->iccl, priv->base + RCAR_IIC_ICCL);
959e75ea46SMarek Vasut writeb(priv->icch, priv->base + RCAR_IIC_ICCH);
969e75ea46SMarek Vasut writeb(RCAR_IC_TACK, priv->base + RCAR_IIC_ICIC);
979e75ea46SMarek Vasut
989e75ea46SMarek Vasut writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_RTS | RCAR_IIC_ICCR_BUSY,
999e75ea46SMarek Vasut priv->base + RCAR_IIC_ICCR);
1009e75ea46SMarek Vasut sh_irq_dte(dev);
1019e75ea46SMarek Vasut
1029e75ea46SMarek Vasut clrbits_8(priv->base + RCAR_IIC_ICSR, RCAR_IC_TACK);
1039e75ea46SMarek Vasut writeb(chip << 1 | read, priv->base + RCAR_IIC_ICDR);
1049e75ea46SMarek Vasut return sh_irq_dte_with_tack(dev);
1059e75ea46SMarek Vasut }
1069e75ea46SMarek Vasut
rcar_iic_finish(struct udevice * dev)1079e75ea46SMarek Vasut static void rcar_iic_finish(struct udevice *dev)
1089e75ea46SMarek Vasut {
1099e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
1109e75ea46SMarek Vasut
1119e75ea46SMarek Vasut writeb(0, priv->base + RCAR_IIC_ICSR);
1129e75ea46SMarek Vasut clrbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE);
1139e75ea46SMarek Vasut }
1149e75ea46SMarek Vasut
rcar_iic_read_common(struct udevice * dev,struct i2c_msg * msg)1159e75ea46SMarek Vasut static int rcar_iic_read_common(struct udevice *dev, struct i2c_msg *msg)
1169e75ea46SMarek Vasut {
1179e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
1189e75ea46SMarek Vasut int i, ret = -EREMOTEIO;
1199e75ea46SMarek Vasut
1209e75ea46SMarek Vasut if (rcar_iic_set_addr(dev, msg->addr, 1) != 0)
1219e75ea46SMarek Vasut goto err;
1229e75ea46SMarek Vasut
1239e75ea46SMarek Vasut udelay(10);
1249e75ea46SMarek Vasut
1259e75ea46SMarek Vasut writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_SCP,
1269e75ea46SMarek Vasut priv->base + RCAR_IIC_ICCR);
1279e75ea46SMarek Vasut
1289e75ea46SMarek Vasut for (i = 0; i < msg->len; i++) {
1299e75ea46SMarek Vasut if (sh_irq_dte_with_tack(dev) != 0)
1309e75ea46SMarek Vasut goto err;
1319e75ea46SMarek Vasut
1329e75ea46SMarek Vasut msg->buf[i] = readb(priv->base + RCAR_IIC_ICDR) & 0xff;
1339e75ea46SMarek Vasut
1349e75ea46SMarek Vasut if (msg->len - 1 == i) {
1359e75ea46SMarek Vasut writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_RACK,
1369e75ea46SMarek Vasut priv->base + RCAR_IIC_ICCR);
1379e75ea46SMarek Vasut }
1389e75ea46SMarek Vasut }
1399e75ea46SMarek Vasut
1409e75ea46SMarek Vasut sh_irq_busy(dev);
1419e75ea46SMarek Vasut ret = 0;
1429e75ea46SMarek Vasut
1439e75ea46SMarek Vasut err:
1449e75ea46SMarek Vasut rcar_iic_finish(dev);
1459e75ea46SMarek Vasut return ret;
1469e75ea46SMarek Vasut }
1479e75ea46SMarek Vasut
rcar_iic_write_common(struct udevice * dev,struct i2c_msg * msg)1489e75ea46SMarek Vasut static int rcar_iic_write_common(struct udevice *dev, struct i2c_msg *msg)
1499e75ea46SMarek Vasut {
1509e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
1519e75ea46SMarek Vasut int i, ret = -EREMOTEIO;
1529e75ea46SMarek Vasut
1539e75ea46SMarek Vasut if (rcar_iic_set_addr(dev, msg->addr, 0) != 0)
1549e75ea46SMarek Vasut goto err;
1559e75ea46SMarek Vasut
1569e75ea46SMarek Vasut udelay(10);
1579e75ea46SMarek Vasut
1589e75ea46SMarek Vasut for (i = 0; i < msg->len; i++) {
1599e75ea46SMarek Vasut writeb(msg->buf[i], priv->base + RCAR_IIC_ICDR);
1609e75ea46SMarek Vasut if (sh_irq_dte_with_tack(dev) != 0)
1619e75ea46SMarek Vasut goto err;
1629e75ea46SMarek Vasut }
1639e75ea46SMarek Vasut
1649e75ea46SMarek Vasut if (msg->flags & I2C_M_STOP) {
1659e75ea46SMarek Vasut writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_RTS,
1669e75ea46SMarek Vasut priv->base + RCAR_IIC_ICCR);
1679e75ea46SMarek Vasut if (sh_irq_dte_with_tack(dev) != 0)
1689e75ea46SMarek Vasut goto err;
1699e75ea46SMarek Vasut }
1709e75ea46SMarek Vasut
1719e75ea46SMarek Vasut sh_irq_busy(dev);
1729e75ea46SMarek Vasut ret = 0;
1739e75ea46SMarek Vasut
1749e75ea46SMarek Vasut err:
1759e75ea46SMarek Vasut rcar_iic_finish(dev);
1769e75ea46SMarek Vasut return ret;
1779e75ea46SMarek Vasut }
1789e75ea46SMarek Vasut
rcar_iic_xfer(struct udevice * dev,struct i2c_msg * msg,int nmsgs)1799e75ea46SMarek Vasut static int rcar_iic_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
1809e75ea46SMarek Vasut {
1819e75ea46SMarek Vasut int ret;
1829e75ea46SMarek Vasut
1839e75ea46SMarek Vasut for (; nmsgs > 0; nmsgs--, msg++) {
1849e75ea46SMarek Vasut if (msg->flags & I2C_M_RD)
1859e75ea46SMarek Vasut ret = rcar_iic_read_common(dev, msg);
1869e75ea46SMarek Vasut else
1879e75ea46SMarek Vasut ret = rcar_iic_write_common(dev, msg);
1889e75ea46SMarek Vasut
1899e75ea46SMarek Vasut if (ret)
1909e75ea46SMarek Vasut return -EREMOTEIO;
1919e75ea46SMarek Vasut }
1929e75ea46SMarek Vasut
1939e75ea46SMarek Vasut return ret;
1949e75ea46SMarek Vasut }
1959e75ea46SMarek Vasut
rcar_iic_set_speed(struct udevice * dev,uint speed)1969e75ea46SMarek Vasut static int rcar_iic_set_speed(struct udevice *dev, uint speed)
1979e75ea46SMarek Vasut {
1989e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
1999e75ea46SMarek Vasut const unsigned int ratio_high = 4;
2009e75ea46SMarek Vasut const unsigned int ratio_low = 5;
2019e75ea46SMarek Vasut int clkrate, denom;
2029e75ea46SMarek Vasut
2039e75ea46SMarek Vasut clkrate = clk_get_rate(&priv->clk);
2049e75ea46SMarek Vasut if (clkrate < 0)
2059e75ea46SMarek Vasut return clkrate;
2069e75ea46SMarek Vasut
2079e75ea46SMarek Vasut /*
2089e75ea46SMarek Vasut * Calculate the value for ICCL and ICCH. From the data sheet:
2099e75ea46SMarek Vasut * iccl = (p-clock / transfer-rate) * (L / (L + H))
2109e75ea46SMarek Vasut * icch = (p clock / transfer rate) * (H / (L + H))
2119e75ea46SMarek Vasut * where L and H are the SCL low and high ratio.
2129e75ea46SMarek Vasut */
2139e75ea46SMarek Vasut denom = speed * (ratio_high + ratio_low);
2149e75ea46SMarek Vasut priv->iccl = DIV_ROUND_CLOSEST(clkrate * ratio_low, denom);
2159e75ea46SMarek Vasut priv->icch = DIV_ROUND_CLOSEST(clkrate * ratio_high, denom);
2169e75ea46SMarek Vasut
2179e75ea46SMarek Vasut return 0;
2189e75ea46SMarek Vasut }
2199e75ea46SMarek Vasut
rcar_iic_probe_chip(struct udevice * dev,uint addr,uint flags)2209e75ea46SMarek Vasut static int rcar_iic_probe_chip(struct udevice *dev, uint addr, uint flags)
2219e75ea46SMarek Vasut {
2229e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
2239e75ea46SMarek Vasut int ret;
2249e75ea46SMarek Vasut
2259e75ea46SMarek Vasut rcar_iic_set_addr(dev, addr, 1);
2269e75ea46SMarek Vasut writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_SCP,
2279e75ea46SMarek Vasut priv->base + RCAR_IIC_ICCR);
2289e75ea46SMarek Vasut ret = sh_irq_dte_with_tack(dev);
2299e75ea46SMarek Vasut rcar_iic_finish(dev);
2309e75ea46SMarek Vasut
2319e75ea46SMarek Vasut return ret;
2329e75ea46SMarek Vasut }
2339e75ea46SMarek Vasut
rcar_iic_probe(struct udevice * dev)2349e75ea46SMarek Vasut static int rcar_iic_probe(struct udevice *dev)
2359e75ea46SMarek Vasut {
2369e75ea46SMarek Vasut struct rcar_iic_priv *priv = dev_get_priv(dev);
2379e75ea46SMarek Vasut int ret;
2389e75ea46SMarek Vasut
2399e75ea46SMarek Vasut priv->base = dev_read_addr_ptr(dev);
2409e75ea46SMarek Vasut
2419e75ea46SMarek Vasut ret = clk_get_by_index(dev, 0, &priv->clk);
2429e75ea46SMarek Vasut if (ret)
2439e75ea46SMarek Vasut return ret;
2449e75ea46SMarek Vasut
2459e75ea46SMarek Vasut ret = clk_enable(&priv->clk);
2469e75ea46SMarek Vasut if (ret)
2479e75ea46SMarek Vasut return ret;
2489e75ea46SMarek Vasut
2499e75ea46SMarek Vasut rcar_iic_finish(dev);
2509e75ea46SMarek Vasut
2519e75ea46SMarek Vasut return rcar_iic_set_speed(dev, 100000);
2529e75ea46SMarek Vasut }
2539e75ea46SMarek Vasut
2549e75ea46SMarek Vasut static const struct dm_i2c_ops rcar_iic_ops = {
2559e75ea46SMarek Vasut .xfer = rcar_iic_xfer,
2569e75ea46SMarek Vasut .probe_chip = rcar_iic_probe_chip,
2579e75ea46SMarek Vasut .set_bus_speed = rcar_iic_set_speed,
2589e75ea46SMarek Vasut };
2599e75ea46SMarek Vasut
2609e75ea46SMarek Vasut static const struct udevice_id rcar_iic_ids[] = {
2619e75ea46SMarek Vasut { .compatible = "renesas,rmobile-iic" },
2629e75ea46SMarek Vasut { }
2639e75ea46SMarek Vasut };
2649e75ea46SMarek Vasut
2659e75ea46SMarek Vasut U_BOOT_DRIVER(iic_rcar) = {
2669e75ea46SMarek Vasut .name = "iic_rcar",
2679e75ea46SMarek Vasut .id = UCLASS_I2C,
2689e75ea46SMarek Vasut .of_match = rcar_iic_ids,
2699e75ea46SMarek Vasut .probe = rcar_iic_probe,
2709e75ea46SMarek Vasut .priv_auto_alloc_size = sizeof(struct rcar_iic_priv),
2719e75ea46SMarek Vasut .ops = &rcar_iic_ops,
2729e75ea46SMarek Vasut };
273