On 11/29/2017 06:59 AM, Heiko Schocher wrote: > Hello Marek, > > Am 29.11.2017 um 03:48 schrieb Marek Vasut: >> Add driver for the RCar IIC or DVFS I2C controller. This driver is based >> on the SH I2C driver, but supports DM and DT probing as well as modern >> I2C framework API. >> >> Signed-off-by: Marek Vasut <marek.vasut+rene...@gmail.com> >> Cc: Nobuhiro Iwamatsu <iwama...@nigauri.org> >> --- >> drivers/i2c/Kconfig | 6 ++ >> drivers/i2c/Makefile | 1 + >> drivers/i2c/rcar_iic.c | 271 >> +++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 278 insertions(+) >> create mode 100644 drivers/i2c/rcar_iic.c > > Reviewed-by: Heiko Schocher <h...@denx.de> > > Just some dummy question below... > > [...] >> diff --git a/drivers/i2c/rcar_iic.c b/drivers/i2c/rcar_iic.c >> new file mode 100644 >> index 0000000000..57ae2f51fc >> --- /dev/null >> +++ b/drivers/i2c/rcar_iic.c >> @@ -0,0 +1,271 @@ >> +/* >> + * Renesas RCar IIC driver >> + * >> + * Copyright (C) 2017 Marek Vasut <marek.va...@gmail.com> >> + * >> + * Based on >> + * Copyright (C) 2011, 2013 Renesas Solutions Corp. >> + * Copyright (C) 2011, 2013 Nobuhiro Iwamatsu >> <nobuhiro.iwamatsu...@renesas.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#include <common.h> >> +#include <clk.h> >> +#include <dm.h> >> +#include <i2c.h> >> +#include <asm/io.h> >> + >> +struct rcar_iic_priv { >> + void __iomem *base; >> + struct clk clk; >> + u8 iccl; >> + u8 icch; >> +}; >> + >> +#define RCAR_IIC_ICDR 0x00 >> +#define RCAR_IIC_ICCR 0x04 >> +#define RCAR_IIC_ICSR 0x08 >> +#define RCAR_IIC_ICIC 0x0c >> +#define RCAR_IIC_ICCL 0x10 >> +#define RCAR_IIC_ICCH 0x14 >> + >> +/* ICCR */ >> +#define RCAR_IIC_ICCR_ICE BIT(7) >> +#define RCAR_IIC_ICCR_RACK BIT(6) >> +#define RCAR_IIC_ICCR_RTS BIT(4) >> +#define RCAR_IIC_ICCR_BUSY BIT(2) >> +#define RCAR_IIC_ICCR_SCP BIT(0) >> + >> +/* ICSR / ICIC */ >> +#define RCAR_IC_BUSY BIT(4) >> +#define RCAR_IC_TACK BIT(2) >> +#define RCAR_IC_DTE BIT(0) >> + >> +#define IRQ_WAIT 1000 >> + >> +static void sh_irq_dte(struct udevice *dev) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + int i; >> + >> + for (i = 0; i < IRQ_WAIT; i++) { >> + if (RCAR_IC_DTE & readb(priv->base + RCAR_IIC_ICSR)) >> + break; >> + udelay(10); >> + } >> +} >> + >> +static int sh_irq_dte_with_tack(struct udevice *dev) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + int i; >> + >> + for (i = 0; i < IRQ_WAIT; i++) { >> + if (RCAR_IC_DTE & readb(priv->base + RCAR_IIC_ICSR)) >> + break; >> + if (RCAR_IC_TACK & readb(priv->base + RCAR_IIC_ICSR)) >> + return -ETIMEDOUT; >> + udelay(10); >> + } >> + return 0; >> +} >> + >> +static void sh_irq_busy(struct udevice *dev) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + int i; >> + >> + for (i = 0; i < IRQ_WAIT; i++) { >> + if (!(RCAR_IC_BUSY & readb(priv->base + RCAR_IIC_ICSR))) >> + break; >> + udelay(10); >> + } >> +} >> + >> +static int rcar_iic_set_addr(struct udevice *dev, u8 chip, u8 read) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + >> + clrbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE); >> + setbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE); >> + >> + writeb(priv->iccl, priv->base + RCAR_IIC_ICCL); >> + writeb(priv->icch, priv->base + RCAR_IIC_ICCH); >> + writeb(RCAR_IC_TACK, priv->base + RCAR_IIC_ICIC); >> + >> + writeb(RCAR_IIC_ICCR_ICE | RCAR_IIC_ICCR_RTS | RCAR_IIC_ICCR_BUSY, >> + priv->base + RCAR_IIC_ICCR); >> + sh_irq_dte(dev); >> + >> + clrbits_8(priv->base + RCAR_IIC_ICSR, RCAR_IC_TACK); >> + writeb(chip << 1 | read, priv->base + RCAR_IIC_ICDR); >> + return sh_irq_dte_with_tack(dev); >> +} >> + >> +static void rcar_iic_finish(struct udevice *dev) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + >> + writeb(0, priv->base + RCAR_IIC_ICSR); >> + clrbits_8(priv->base + RCAR_IIC_ICCR, RCAR_IIC_ICCR_ICE); >> +} >> + >> +static int rcar_iic_read_common(struct udevice *dev, struct i2c_msg >> *msg) >> +{ >> + struct rcar_iic_priv *priv = dev_get_priv(dev); >> + int i, ret = -EREMOTEIO; >> + >> + if (rcar_iic_set_addr(dev, msg->addr, 1) != 0) >> + goto err; >> + >> + udelay(10); > > There are a lot of places with udelay(10) ... Is this documented in the > docs?
Nope, but it is needed. > Does it work with different i2c bus clock settings? Yes, 100 and 400 kHz operation works. -- Best regards, Marek Vasut _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot