[U-Boot] [PATCH] i2c: adding driver for pxa27x, pxa3xx, pxa25x

Andrew Ruder andrew.ruder at elecsyscorp.com
Wed Aug 12 22:19:43 CEST 2015



> On Aug 12, 2015, at 2:34 PM, Marek Vasut <marex at denx.de> wrote:
> 
> On Wednesday, August 12, 2015 at 08:43:52 PM, Andrew Ruder wrote:
> 
> Commit message is missing :'-(

I actually was going with subject being sufficient on this one. I'll fill in some more info on this as far as origin and what it has been tested on and send in again.

> 
>> Cc: Marek Vasut <marex at denx.de>
>> Cc: Heiko Schocher <hs at denx.de>
>> Signed-off-by: Andrew Ruder <andrew.ruder at elecsyscorp.com>
>> ---
>> 
>> This driver was written before the driver model stuff was really around (or
>> at least based on a U-Boot version that only had very preliminary support)
>> so there might be some older conventions in use here.  I have tested on a
>> PXA270 board running upstream master with this driver, however - so to
>> some extent this all still works fine.  Let me know if things need to
>> change to be accepted, and I'll try to find some time to update!
>> 
>> drivers/i2c/Makefile  |   1 +
>> drivers/i2c/pxa_i2c.c | 796
>> ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 797
>> insertions(+)
>> create mode 100644 drivers/i2c/pxa_i2c.c
>> 
>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>> index 9b45248..cf2c8a8 100644
>> --- a/drivers/i2c/Makefile
>> +++ b/drivers/i2c/Makefile
>> @@ -30,6 +30,7 @@ obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o
>> obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
>> obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o
>> obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
>> +obj-$(CONFIG_SYS_I2C_PXA) += pxa_i2c.o
>> obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o
>> obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o
>> obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
>> diff --git a/drivers/i2c/pxa_i2c.c b/drivers/i2c/pxa_i2c.c
>> new file mode 100644
>> index 0000000..859d6cf
>> --- /dev/null
>> +++ b/drivers/i2c/pxa_i2c.c
>> @@ -0,0 +1,796 @@
>> +/*
>> + *  pxa_i2c.c
>> + *
>> + *  I2C adapter for the PXA I2C bus access.
>> + *
>> + *  Copyright (C) 2002 Intrinsyc Software Inc.
>> + *  Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
>> + *  Copyright (C) 2014 Andrew Ruder
>> + *
>> + *  This program is free software; you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License version 2 as
>> + *  published by the Free Software Foundation.
>> + *
>> + *  This is a heavily modified version of the PXA I2C driver from the
>> Linux + *  kernel 3.15.10.
>> + */
>> +
>> +#include <common.h>
>> +#include <compiler.h>
>> +#include <i2c.h>
>> +#include <asm/arch/pxa-regs.h>
>> +
>> +#include <asm/errno.h>
>> +#include <asm/io.h>
>> +
>> +#define MAX_TRANSFER_MS 5000
>> +#define WAIT_MASTER_MS 64
>> +#define ABORT_LENGTH_MS 50
>> +
>> +/* Set up some defaults for various configurable pieces of this driver
>> + * so that most of the time we don't need extra things defined
> 
> Multiline comment should be of the form:
> 
> /*
> * foo
> * bar
> */
> 
>> + */
>> +#if !defined(CONFIG_SYS_PXA_STD_I2C_SPEED)
>> +#define CONFIG_SYS_PXA_STD_I2C_SPEED 100000
>> +#endif
>> +
>> +#if !defined(CONFIG_SYS_PXA_STD_I2C_SLAVE)
>> +#define CONFIG_SYS_PXA_STD_I2C_SLAVE 1
>> +#endif
>> +
>> +#if !defined(CONFIG_SYS_PXA_PWR_I2C_SPEED)
>> +#define CONFIG_SYS_PXA_PWR_I2C_SPEED 40000
>> +#endif
>> +
>> +#if !defined(CONFIG_SYS_PXA_PWR_I2C_SLAVE)
>> +#define CONFIG_SYS_PXA_PWR_I2C_SLAVE 1
>> +#endif
> 
> Please remove all this stuff, it's only going to hide bugs.
> 
>> +#if defined(CONFIG_CPU_MONAHANS) && defined(CONFIG_PXA_PWR_I2C)
>> +#warning Monahans + PWRI2C is unlikely to work without additional testing
>> +#endif
>> +
> 
> [...]
> 
>> +#define ISR_ITE        (1 << 6)       /* tx buffer empty */
>> +#define ISR_IRF        (1 << 7)       /* rx buffer full */
>> +#define ISR_GCAD    (1 << 8)       /* general call address detected */
>> +#define ISR_SAD        (1 << 9)       /* slave address detected */
>> +#define ISR_BED        (1 << 10)       /* bus error no ACK/NAK */
>> +
>> +struct pxa_i2c_msg {
>> +    u16 addr;
>> +    u16 flags;
>> +#define I2C_M_TEN        0x0010    /* this is a ten bit chip address */
> 
> Be consistent about using 1 << n or 0x0n00 please. Just use the BIT(n) macro.
> 
>> +#define I2C_M_RD        0x0001    /* read data, from slave to master */
>> +#define I2C_M_STOP        0x8000    /* if I2C_FUNC_PROTOCOL_MANGLING */
>> +#define I2C_M_NOSTART        0x4000    /* if I2C_FUNC_NOSTART */
>> +#define I2C_M_REV_DIR_ADDR    0x2000    /* if I2C_FUNC_PROTOCOL_MANGLING */
>> +#define I2C_M_IGNORE_NAK    0x1000    /* if I2C_FUNC_PROTOCOL_MANGLING */
>> +#define I2C_M_NO_RD_ACK        0x0800    /* if I2C_FUNC_PROTOCOL_MANGLING
> */
>> +#define I2C_M_RECV_LEN        0x0400    /* length will be first received
> byte */
>> +#define I2C_M_FIRST        0x0800    /* First message in a chain */
>> +    u16 len;
>> +    u8 *buf;
>> +};
>> +
>> +struct pxa_i2c_state {
>> +    struct pxa_i2c_msg    *msg;
>> +    unsigned int        msg_num;
>> +    unsigned int        msg_ptr;
>> +};
>> +
>> +#define STD_I2C_BASE 0x40301680
>> +#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_PXA25X)
>> +#define PWR_I2C_BASE    0x40f00180
>> +#define IBMR_OFFSET    0x00
>> +#define IDBR_OFFSET    0x08
>> +#define ICR_OFFSET    0x10
>> +#define ISR_OFFSET    0x18
>> +#define ISAR_OFFSET    0x20
>> +#elif defined(CONFIG_CPU_MONAHANS)
>> +#define PWR_I2C_BASE    0x40f500c0
>> +#define IBMR_OFFSET    0x00
>> +#define IDBR_OFFSET    0x04
>> +#define ICR_OFFSET    0x08
>> +#define ISR_OFFSET    0x0c
>> +#define ISAR_OFFSET    0x10
>> +#endif
>> +
>> +static inline void __iomem *
>> +pxa_i2c_base(const struct i2c_adapter *adap)
>> +{
>> +    return (adap->hwadapnr == 0) ? (void *)STD_I2C_BASE : (void
>> *)PWR_I2C_BASE; +}
>> +
>> +static inline void __iomem *
>> +pxa_i2c_ibmr(const struct i2c_adapter *adap)
>> +{
>> +    return (void *)((char *)pxa_i2c_base(adap) + IBMR_OFFSET);
> 
> No need for these hideous casts, just use pxa_i2c_base() + OFFSET in the code.
> 
>> +}
> 
> [...]
> 
>> +static void
>> +i2c_pxa_abort(struct i2c_adapter *adap)
>> +{
>> +    unsigned long long end;
>> +
>> +    end = get_ticks() + (get_tbclk() / 1000) * ABORT_LENGTH_MS;
>> +
>> +    while ((get_ticks() < end) &&
> 
> Please use get_timer() to implement the delay loop.
> 
> time = get_timer(0);
> while (true) {
>    reg = readl();
>    if (reg & bit)
>        break;
> 
>    if (get_timer(time) > timeout)
>        return -ETIMEDOUT;
> }
> 
> Also, the lpc32xx patches recently implemented a wait_for_bit() function.
> If you make this generic, that'd be really cool.
> 
>> +           (readl(_IBMR(adap)) & 0x1) == 0) {
>> +        unsigned long icr = readl(_ICR(adap));
>> +
>> +        icr &= ~ICR_START;
>> +        icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
>> +
>> +        writel(icr, _ICR(adap));
>> +
>> +        show_state(adap);
>> +
>> +        mdelay(1);
>> +    }
>> +
>> +    writel(readl(_ICR(adap)) & ~(ICR_MA | ICR_START | ICR_STOP),
>> +           _ICR(adap));
> 
> Please use clrsetbits_le32();
> 
>> +}
> [...]


More information about the U-Boot mailing list