Thu, Mar 13, 2008 at 11:07 AM, Darius <[EMAIL PROTECTED]> wrote:

> Almost written from scratch - only small piece of code leaved from old
>  driver, witch never was originally in vanilla kernel.
>  SMB is NOT supported currently.
>  Tested on the MXLADS v2.0 board with i2c client driver (driver for
>  NT7651 LCD controller). All works fine, stable.

needs a signed-off-by line and --- separator

>
> diff -uprN -X linux-2.6.24.3-vanilla/Documentation/dontdiff 
> linux-2.6.24.3-vanilla/drivers/i2c/busses/i2c-imx.c 
> linux-2.6.24.3/drivers/i2c/busses/i2c-imx.c
>  --- linux-2.6.24.3-vanilla/drivers/i2c/busses/i2c-imx.c 1970-01-01 
> 03:00:00.000000000 +0300
>  +++ linux-2.6.24.3/drivers/i2c/busses/i2c-imx.c 2008-03-13 
> 17:50:52.000000000 +0200
>  +/* These defines are missed in imx-regs.h */
>  +#define IMX_I2C_IADR   (0x00)  /* i2c slave address */
>  +#define IMX_I2C_IFDR           (0x04)  /* i2c frequency divider */
>  +#define IMX_I2C_I2CR           (0x08)  /* i2c control */
>  +#define IMX_I2C_I2SR    (0x0C) /* i2c status */
>  +#define IMX_I2C_I2DR    (0x10) /* i2c transfer data */

why put the defines in here if all the other register defines are in imx-regs.h?

>  +/* bits in IMX_I2C_I2SR register */
>  +#define I2SR_RXAK      0x01
>  +#define I2SR_IIF       0x02
>  +#define I2SR_SRW       0x04
>  +#define I2SR_IAL       0x10
>  +#define I2SR_IBB       0x20
>  +#define I2SR_IAAS      0x40
>  +#define I2SR_ICF       0x80
>  +
>  +/* bits in IMX_I2C_I2CR register */
>  +#define I2CR_RSTA      0x04
>  +#define I2CR_TXAK      0x08
>  +#define I2CR_MTX       0x10
>  +#define I2CR_MSTA      0x20
>  +#define I2CR_IIEN      0x40
>  +#define I2CR_IEN       0x80

ditto above for the bit definitions

>  +static struct i2c_imx_clk_div_pair i2c_imx_clk_div_tbl[64] = { /* FIXME */
...
>  +};

anything with FIXME in comments probably should be addressed :-)

probably don't need the array size specifier

a reference to the datasheet page this table comes from would good
(table 26-5 in the rev. 4 version of the ref. manual)

a note should mention the code depends on the entries being sorted
with the dividers in order

structure can be marked as __init now as it no longer can be
referenced at any time other than startup


>  +    #ifdef CONFIG_I2C_DEBUG_BUS
>  +        printk("I2C: <i2c_imx_bus_busy>\n");
>  +    #endif

dev_debug() would be a lot easier to read than this mess of #ifdefs

>  +static int i2c_imx_set_clk      (struct imx_i2c_struct *i2c_imx, unsigned 
> int rate) {

function only gets called at init time, so add __init

>  +       unsigned int hclk, sysclk;
>  +       unsigned int desired_div;
>  +       int i;
>  +
>  +    #ifdef CONFIG_I2C_DEBUG_BUS
>  +        printk("I2C: <i2c_imx_set_clk>\n");
>  +    #endif
>  +
>  +       sysclk = imx_get_system_clk ();
>  +       hclk = imx_get_hclk();
>  +       desired_div = (hclk << 1) / rate;
>  +    #ifdef CONFIG_I2C_DEBUG_BUS
>  +        printk("I2C: <i2c_imx_set_clk> SYSCLK=%d, HCLK=%d, DIV=%d\n", 
> sysclk, hclk, desired_div);
>  +    #endif

printing desired_div here gives the wrong result - it's 2x what it should be.

>  +       if (desired_div & 0x01)
>  +               desired_div++;
>  +       desired_div >>= 1;

Should be printed here after rounding.

>  +       if (desired_div < 22)
>  +               desired_div = 22;
>  +       if (desired_div > 3840)
>  +               return -EINVAL;
>  +       for (i=0; i<64; i++) {
>  +               if (i2c_imx_clk_div_tbl[i].divider >= desired_div)
>  +                       break;
>  +       }

should get rid of magic constants 64, 22, and 3840 - 64 is # entries
in the table, 22 is smallest divisor and 3840 is largest divisor
allowed by h/w.


>  +static int i2c_imx_xfer         (struct i2c_adapter *adapter, struct 
> i2c_msg *msgs, int num) {
>  +
>  +       int i, temp;
>  +       int err = 0;
>  +       struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
>  +
>  +       #ifdef CONFIG_I2C_DEBUG_BUS
>  +        printk("I2C: <i2c_imx_xfer>\n");
>  +       #endif
>  +
>  +       // chech or i2c bus is not busy

c++ comment and misspelling

>  +       err = i2c_imx_bus_busy(i2c_imx);
>  +       if (err)
>  +               goto fail0;
>  +
>  +    // Enable i2c
>  +    i2c_imx_enable(i2c_imx);
>  +
>  +    /* Start I2C transfer */
>  +    i2c_imx_start (i2c_imx);
>  +
>  +    #ifdef CONFIG_I2C_DEBUG_BUS
>  +        temp = readb (i2c_imx->base + IMX_I2C_I2CR);
>  +        printk("I2C: <i2c_imx_xfer> CONTROL: IEN=%d, IIEN=%d, MSTA=%d, 
> MTX=%d, TXAK=%d, RSTA=%d\n",
>  +            
> (temp&I2CR_IEN?1:0),(temp&I2CR_IIEN?1:0),(temp&I2CR_MSTA?1:0),(temp&I2CR_MTX?1:0),
>  +            (temp&I2CR_TXAK?1:0),(temp&I2CR_RSTA?1:0));
>  +        temp = readb (i2c_imx->base + IMX_I2C_I2SR);
>  +        printk("I2C: <i2c_imx_xfer> STATUS: ICF=%d, IAAS=%d, IBB=%d, 
> IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n",
>  +            
> (temp&I2SR_ICF?1:0),(temp&I2SR_IAAS?1:0),(temp&I2SR_IBB?1:0),(temp&I2SR_IAL?1:0),
>  +            (temp&I2SR_SRW?1:0),(temp&I2SR_IIF?1:0),(temp&I2SR_RXAK?1:0));
>  +    #endif
>  +
>  +       // read/write data
>  +       for (i=0; i<num; i++) {
>  +
>  +               if (i) {
>  +            #ifdef CONFIG_I2C_DEBUG_BUS
>  +                printk("I2C: <i2c_imx_read> repeated start\n");
>  +            #endif
>  +            temp = readb(i2c_imx->base + IMX_I2C_I2CR);
>  +            temp |= I2CR_RSTA;
>  +            writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
>  +               }
>  +               #ifdef CONFIG_I2C_DEBUG_BUS
>  +            printk("I2C: <i2c_imx_xfer> transfer message: %d\n", i);
>  +        #endif
>  +               /* write/read data */
>  +               if (!(msgs[i].flags & I2C_M_RD))
>  +                       err = i2c_imx_write (i2c_imx, &msgs[i]);
>  +               else
>  +            err = i2c_imx_read  (i2c_imx, &msgs[i]);
>  +       }
>  +
>  +fail0:
>  +       /* Stop bus */
>  +       i2c_imx_stop (i2c_imx);
>  +       /* disable i2c bus */
>  +       i2c_imx_disable (i2c_imx);
>  +    #ifdef CONFIG_I2C_DEBUG_BUS
>  +        printk("I2C: <i2c_imx_xfer> exit with: %s: %d\n", (err < 
> 0)?"error":"succes msg", (err < 0)?err:num);

misspelling - success

>  +    #endif
>  +       return (err < 0) ? err : num;
>  +}
>  +
>  +static u32 i2c_imx_func         (struct i2c_adapter *adapter) {
>  +       return I2C_FUNC_I2C;
>  +}
>  +
>  +static int __init i2c_imx_probe (struct platform_device *pdev) {
>  +
>  +    struct imx_i2c_struct *i2c_imx;
>  +    struct resource *res;
>  +    void   __iomem     *base;
>  +    int irq;
>  +       int res_size;
>  +       int ret;
>  +
>  +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  +       irq = platform_get_irq(pdev, 0);
>  +       if (!res) {
>  +        printk("I2C: can't get device resources!\n");

should probably use dev_err macro for these error messages

>  +        return -ENODEV;
>  +       }
>  +       if (irq < 0) {
>  +        printk("I2C: can't get irq number!\n");
>  +        return -ENODEV;
>  +       }
>  +
>  +       res_size = (res->end) - (res->start) + 1;
>  +       if (!request_mem_region(res->start, res_size, res->name)) {
>  +               printk("I2C: can't allocate %d bytes at %d address!\n", 
> res_size, res->start);
>  +               return -ENOMEM;
>  +       }
>  +
>  +       base = ioremap (res->start, res_size);
>  +       if (!base) {
>  +           printk("I2C: ioremap failed!\n");
>  +               ret = -EIO;
>  +               goto fail0;
>  +       }
>  +
>  +       i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL);
>  +       if (!i2c_imx) {
>  +               printk("I2C: can't allocate inteface!\n");
>  +               ret = -ENOMEM;
>  +               goto fail1;
>  +       }
>  +
>  +    // Setup i2c_imx driver structure

c++ comment

>  +
>  +       printk("I2C: %s: IMX I2C adapter registered\n", 
> i2c_imx->adapter.dev.bus_id);
>  +       return 0;   // Return OK */

mixed c++ and normal comment?

>  --- linux-2.6.24.3-vanilla/drivers/i2c/busses/Kconfig   2008-01-25 
> 00:58:37.000000000 +0200
>  +++ linux-2.6.24.3/drivers/i2c/busses/Kconfig   2008-03-13 
> 17:29:43.000000000 +0200
>  @@ -249,6 +249,16 @@ config I2C_IBM_IIC
>           This driver can also be built as a module.  If so, the module
>           will be called i2c-ibm_iic.
>
>  +config I2C_IMX
>  +       tristate "IMX I2C interface"
>  +       depends on ARCH_IMX
>  +       help
>  +         Say Y here if you want to use the IIC bus controller on
>  +         the Freescale IMX processors.

it's i.MX - I think this will only work with i.MX1, i.MXL, and i.MXS.
I think the i.MX21, 21S, 27, and 31 are a bit different.

-- 
Hardware, n.:
 The parts of a computer system that can be kicked.

_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c

Reply via email to