Re: [PATCH] i2c: add Atmel AT91 driver
Hi Sascha, Thanks for your review, I'll correct these and send a v2. Raphaël 2014-07-24 11:34 GMT+02:00 Sascha Hauer : > Hi Raphaël, > > Looks mostly fine to me. Two small comments: > > On Wed, Jul 23, 2014 at 12:09:04PM -0700, Raphaël Poggi wrote: >> + >> +static int at91_twi_probe(struct device_d *dev) >> +{ >> + struct at91_twi_dev *i2c_at91; >> + struct at91_twi_pdata *i2c_data; >> + int rc; >> + u32 bus_clk_rate; >> + >> + i2c_at91 = kzalloc(sizeof(struct at91_twi_dev), GFP_KERNEL); >> + if (!i2c_at91) { >> + rc = -ENOMEM; >> + goto out_free; >> + } > > You can safely use xzalloc here and skip the result check. > >> + >> + rc = dev_get_drvdata(dev, (unsigned long *)&i2c_data); >> + if (rc) >> + goto out_free; >> + >> + i2c_at91->pdata = i2c_data; >> + >> + i2c_at91->base = dev_request_mem_region(dev, 0); >> + if (IS_ERR(i2c_at91->base)) >> + return PTR_ERR(i2c_at91->base); > > dev_request_mem_region returns NULL on error, not an error pointer. > > Sascha > > -- > Pengutronix e.K. | | > Industrial Linux Solutions | http://www.pengutronix.de/ | > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | > > ___ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Re: [PATCH] i2c: add Atmel AT91 driver
Hi Raphaël, Looks mostly fine to me. Two small comments: On Wed, Jul 23, 2014 at 12:09:04PM -0700, Raphaël Poggi wrote: > + > +static int at91_twi_probe(struct device_d *dev) > +{ > + struct at91_twi_dev *i2c_at91; > + struct at91_twi_pdata *i2c_data; > + int rc; > + u32 bus_clk_rate; > + > + i2c_at91 = kzalloc(sizeof(struct at91_twi_dev), GFP_KERNEL); > + if (!i2c_at91) { > + rc = -ENOMEM; > + goto out_free; > + } You can safely use xzalloc here and skip the result check. > + > + rc = dev_get_drvdata(dev, (unsigned long *)&i2c_data); > + if (rc) > + goto out_free; > + > + i2c_at91->pdata = i2c_data; > + > + i2c_at91->base = dev_request_mem_region(dev, 0); > + if (IS_ERR(i2c_at91->base)) > + return PTR_ERR(i2c_at91->base); dev_request_mem_region returns NULL on error, not an error pointer. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH] i2c: add Atmel AT91 driver
Signed-off-by: Raphaël Poggi --- drivers/i2c/busses/Kconfig| 4 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-at91.c | 438 ++ 3 files changed, 443 insertions(+) create mode 100644 drivers/i2c/busses/i2c-at91.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 370abb0..5b75449 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -12,6 +12,10 @@ config I2C_GPIO This is a very simple bitbanging I2C driver utilizing the arch-neutral GPIO API to control the SCL and SDA lines. +config I2C_AT91 + bool "AT91 I2C Master driver" + depends on ARCH_AT91 + config I2C_IMX bool "MPC85xx/i.MX I2C Master driver" depends on (ARCH_IMX && !ARCH_IMX1) || ARCH_MPC85XX diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 9823d1b..cc72b7c 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c new file mode 100644 index 000..d743469 --- /dev/null +++ b/drivers/i2c/busses/i2c-at91.c @@ -0,0 +1,438 @@ +/* + * i2c Support for Atmel's AT91 Two-Wire Interface (TWI) + * + * Copyright (C) 2011 Weinmann Medical GmbH + * Author: Nikolaus Voss + * + * Evolved from original work by: + * Copyright (C) 2004 Rick Bronson + * Converted to 2.6 by Andrew Victor + * + * Borrowed heavily from original work by: + * Copyright (C) 2000 Philip Edelbrock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_TWI_CLK_HZ 10 /* max 400 Kbits/s */ +#define AT91_I2C_TIMEOUT (100 * MSECOND) /* transfer timeout */ +#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ + +/* AT91 TWI register definitions */ +#defineAT91_TWI_CR 0x /* Control Register */ +#defineAT91_TWI_START 0x0001 /* Send a Start Condition */ +#defineAT91_TWI_STOP 0x0002 /* Send a Stop Condition */ +#defineAT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ +#defineAT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#defineAT91_TWI_QUICK 0x0040 /* SMBus quick command */ +#defineAT91_TWI_SWRST 0x0080 /* Software Reset */ + +#defineAT91_TWI_MMR0x0004 /* Master Mode Register */ +#defineAT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */ +#defineAT91_TWI_MREAD 0x1000 /* Master Read Direction */ + +#defineAT91_TWI_IADR 0x000c /* Internal Address Register */ + +#defineAT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */ + +#defineAT91_TWI_SR 0x0020 /* Status Register */ +#defineAT91_TWI_TXCOMP 0x0001 /* Transmission Complete */ +#defineAT91_TWI_RXRDY 0x0002 /* Receive Holding Register Ready */ +#defineAT91_TWI_TXRDY 0x0004 /* Transmit Holding Register Ready */ + +#defineAT91_TWI_OVRE 0x0040 /* Overrun Error */ +#defineAT91_TWI_UNRE 0x0080 /* Underrun Error */ +#defineAT91_TWI_NACK 0x0100 /* Not Acknowledged */ + +#defineAT91_TWI_IER0x0024 /* Interrupt Enable Register */ +#defineAT91_TWI_IDR0x0028 /* Interrupt Disable Register */ +#defineAT91_TWI_IMR0x002c /* Interrupt Mask Register */ +#defineAT91_TWI_RHR0x0030 /* Receive Holding Register */ +#defineAT91_TWI_THR0x0034 /* Transmit Holding Register */ + +struct at91_twi_pdata { + unsigned clk_max_div; + unsigned clk_offset; + bool has_unre_flag; +}; + +struct at91_twi_dev { + struct device *dev; + void __iomem *base; + struct clk *clk; + u8 *buf; + size_t buf_len; + struct i2c_msg *msg; + unsigned imr; + unsigned transfer_status; + struct i2c_adapter adapter; + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; +}; + +#define to_at91_twi_dev(a) container_of(a, struct at91_twi_dev, adapter) + +static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) +{ + return __raw_readl(dev->base + reg); +} + +static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, uns