m68knommu: driver for Freescale Coldfire I2C controller.
Subsystems (2)
PATCH 1/1 m68knommu: driver for Freescale Coldfire I2C controller.
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
drivers/i2c/busses/Kconfig | 11 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-mcf.c | 463 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+), 0 deletions(-)
drivers/i2c/busses/Kconfig +3 -0
@@ -429,6 +429,17 @@ config I2C_MPC This driver can also be built as a module. If so, the module will be called i2c-mpc. +config I2C_MCF + tristate "Freescale Coldfire I2C driver" + depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M528x ||
M5307 || M532x || M5407)
+ help
+ This driver supports the I2C interface availible on some Freescale + Coldfire processors (M520x, M523x, M5249, M5271, M5275, M528x, + M5307, M532x, M5407).
+
+ This driver can be built as a module. If so, the module
+ will be called i2c-mcf.
+
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller" depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
drivers/i2c/busses/Makefile +1 -0
@@ -41,6 +41,7 @@ obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o +obj-$(CONFIG_I2C_MCF) += i2c-mcf.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
drivers/i2c/busses/i2c-mcf.c new file +463 -0
463 lines not on this page · raw message
Quoted 7 lines · Steven King
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
Signed-off-by Steven King <[email protected]>drivers/i2c/busses/Kconfig | 11 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-mcf.c | 463 ++++++++++++++++++++++++++++++++++++++++++
Please come up with a longer name. i2c-coldfire, for example.
Signature · 1 line
Jean Delvare
PATCH v2 1/1 m68knommu: driver for Freescale Coldfire I2C controller.
Changes for this version:
rename drivers/i2c/busses/i2c-mcf.c to drivers/i2c/busses/i2c-coldfire.c
use I2C_COLDFIRE in drivers/i2c/busses/{Kconfig,Makefile}------
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
drivers/i2c/busses/Kconfig | 11 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-coldfire.c | 463 +++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+), 0 deletions(-)
drivers/i2c/busses/Kconfig +11 -0
@@ -320,6 +320,17 @@ config I2C_BLACKFIN_TWI_CLK_KHZ help The unit of the TWI clock is kHz. +config I2C_COLDFIRE + tristate "Freescale Coldfire I2C driver" + depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M528x || M5307 || M532x || M5407) + help + This driver supports the I2C interface available on some Freescale + Coldfire processors (M520x, M523x, M5249, M5271, M5275, M528x, + M5307, M532x, M5407). + + This driver can be built as a module. If so, the module + will be called i2c-coldfire. + config I2C_CPM tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" depends on (CPM1 || CPM2) && OF_I2C
drivers/i2c/busses/Makefile +1 -0
@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o +obj-$(CONFIG_I2C_COLDFIRE) += i2c-coldfire.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o
drivers/i2c/busses/i2c-coldfire.c new file +463 -0
463 lines not on this page · raw message
Quoted 9 lines · Steven King
Changes for this version:
rename drivers/i2c/busses/i2c-mcf.c to drivers/i2c/busses/i2c-coldfire.c use I2C_COLDFIRE in drivers/i2c/busses/{Kconfig,Makefile}------
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
Signed-off-by Steven King <[email protected]>
The commit messsage should go first, the changelog and other stuff that won't go in should go beflore the --- line.
Quoted 126 lines
drivers/i2c/busses/Kconfig | 11 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-coldfire.c | 463 +++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+), 0 deletions(-)drivers/i2c/busses/Kconfig +11
-0@@ -320,6 +320,17 @@ config I2C_BLACKFIN_TWI_CLK_KHZ help The unit of the TWI clock is kHz. +config I2C_COLDFIRE + tristate "Freescale Coldfire I2C driver" + depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M528x || M5307 || M532x || M5407) + help + This driver supports the I2C interface available on some Freescale + Coldfire processors (M520x, M523x, M5249, M5271, M5275, M528x, + M5307, M532x, M5407). + + This driver can be built as a module. If so, the module + will be called i2c-coldfire. + config I2C_CPM tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" depends on (CPM1 || CPM2) && OF_I2Cdrivers/i2c/busses/Makefile +1
-0@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o +obj-$(CONFIG_I2C_COLDFIRE) += i2c-coldfire.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.odrivers/i2c/busses/i2c-coldfire.c new file +81
-0@@ -0,0 +1,463 @@ +/* Freescale/Motorola Coldfire I2C driver. +* +* Copyright 2010 Steven King <[email protected]> +* +* 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. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/i2c.h> + +#include <asm/mcfi2c.h> + +#define DRIVER_NAME "mcfi2c" + +#define MCFI2C_ADR 0x00 +#define MCFI2C_FDR 0x04 +#define MCFI2C_CR 0x08 +#define MCFI2C_CR_IEN 0x80 +#define MCFI2C_CR_IIEN 0x40 +#define MCFI2C_CR_MSTA 0x20 +#define MCFI2C_CR_MTX 0x10 +#define MCFI2C_CR_TXAK 0x08 +#define MCFI2C_CR_RSTA 0x04 +#define MCFI2C_DR 0x10 +#define MCFI2C_SR 0x0C +#define MCFI2C_SR_ICF 0x80 +#define MCFI2C_SR_IAAS 0x40 +#define MCFI2C_SR_IBB 0x20 +#define MCFI2C_SR_IAL 0x10 +#define MCFI2C_SR_SRW 0x04 +#define MCFI2C_SR_IIF 0x02 +#define MCFI2C_SR_RXAK 0x01 + +#define DEFAULT_I2C_BUS_SPEED 100000 + +struct mcfi2c { +struct i2c_adapter adapter; +void __iomem *iobase; +int irq; +struct clk *clk; +struct completion completion; +}; + +static u8 mcfi2c_rd_cr (struct mcfi2c *mcfi2c) +{ +return readb (mcfi2c->iobase +MCFI2C_CR ); +} + +static void mcfi2c_wr_cr (struct mcfi2c *mcfi2c,u8 val) +{ +writeb (val, mcfi2c->iobase +MCFI2C_CR ); +} + +static u8 mcfi2c_rd_sr (struct mcfi2c *mcfi2c) +{ +return readb (mcfi2c->iobase +MCFI2C_SR ); +} + +static void mcfi2c_wr_sr (struct mcfi2c *mcfi2c,u8 val) +{ +writeb (val, mcfi2c->iobase +MCFI2C_SR ); +}
drivers/i2c/busses/i2c-coldfire.c line 91
Quoted 10 lines
drivers/i2c/busses/i2c-coldfire.c new file +10
-0+ +static u8 mcfi2c_rd_dr (struct mcfi2c *mcfi2c) +{ +return readb (mcfi2c->iobase +MCFI2C_DR ); +} + +static void mcfi2c_wr_dr (struct mcfi2c *mcfi2c,u8 val) +{ +writeb (val, mcfi2c->iobase +MCFI2C_DR ); +}
not entirely sure why you bother wrapping these accesses, but I'm not going to block this driver just becuase I don't like it.
Quoted 28 lines
drivers/i2c/busses/i2c-coldfire.c new file +28
-0+static void mcfi2c_start (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN |MCFI2C_CR_IIEN |MCFI2C_CR_MSTA | +MCFI2C_CR_MTX ); +} + +static void mcfi2c_repeat_start (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN |MCFI2C_CR_IIEN |MCFI2C_CR_MSTA | +MCFI2C_CR_MTX |MCFI2C_CR_RSTA ); +} + +static void mcfi2c_stop (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN ); +} + +static void mcfi2c_tx_ack (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN |MCFI2C_CR_IIEN |MCFI2C_CR_MSTA ); +} + +static void mcfi2c_tx_nak (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN |MCFI2C_CR_IIEN |MCFI2C_CR_MSTA | +MCFI2C_CR_TXAK ); +} +
drivers/i2c/busses/i2c-coldfire.c line 130
Quoted 10 lines
drivers/i2c/busses/i2c-coldfire.c new file +10
-0+static irqreturn_t mcfi2c_irq_handler (int this_irq,void *dev_id) +{ +struct mcfi2c *mcfi2c = dev_id; + +/* clear interrupt */ +mcfi2c_wr_sr (mcfi2c,0 ); +complete (&mcfi2c->completion); + +return IRQ_HANDLED ; +}
I'm interested in why you don't just handle the interrupt here and wake the thread once all the data is handled?
Quoted 186 lines
drivers/i2c/busses/i2c-coldfire.c new file +186
-0+static void mcfi2c_reset (struct mcfi2c *mcfi2c) +{ +mcfi2c_wr_cr (mcfi2c,0 ); +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN |MCFI2C_CR_MSTA ); +mcfi2c_rd_dr (mcfi2c); +mcfi2c_wr_sr (mcfi2c,0 ); +mcfi2c_wr_cr (mcfi2c,0 ); +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN ); +} + +static void mcfi2c_wait_for_bus_idle (struct mcfi2c *mcfi2c) +{ +if (mcfi2c_rd_sr (mcfi2c) &MCFI2C_SR_IBB ) { +unsigned long timeout = jiffies +HZ /2 ; +do { +cond_resched (); +if (time_after (jiffies, timeout)) { +mcfi2c_reset (mcfi2c); +break ; + } + }while (mcfi2c_rd_sr (mcfi2c) &MCFI2C_SR_IBB ); + } +} + +static int mcfi2c_wait_for_bus_busy (struct mcfi2c *mcfi2c) +{ +u8 sr; +while (!((sr =mcfi2c_rd_sr (mcfi2c)) &MCFI2C_SR_IBB )) +if (sr &MCFI2C_SR_IAL ) { +mcfi2c_reset (mcfi2c); +return -EIO ; + } +return 0 ; +} + +static int mcfi2c_xmit (struct mcfi2c *mcfi2c,u16 addr,u16 flags,u8 *buf, +u16 len,int timeout,int more) +{ +if (!(mcfi2c_rd_cr (mcfi2c) &MCFI2C_CR_MSTA )) { +mcfi2c_wait_for_bus_idle (mcfi2c); + +INIT_COMPLETION (mcfi2c->completion); +mcfi2c_start (mcfi2c); + +if (mcfi2c_wait_for_bus_busy (mcfi2c)) +return -EIO ; + } + +mcfi2c_wr_dr (mcfi2c, (addr <<1 ) | (flags &I2C_M_RD )); +while (wait_for_completion_timeout (&mcfi2c->completion, timeout)) { +u8 sr =mcfi2c_rd_sr (mcfi2c); +if (sr &MCFI2C_SR_IAL ) { +mcfi2c_wr_sr (mcfi2c, ~MCFI2C_SR_IAL ); +return -EIO ; + }else if (mcfi2c_rd_cr (mcfi2c) &MCFI2C_CR_MTX ) { +if (sr &MCFI2C_SR_RXAK ) { +mcfi2c_stop (mcfi2c); +return -EIO ; + }else if (flags &I2C_M_RD ) { +if (len >1 ) +mcfi2c_tx_ack (mcfi2c); +else +mcfi2c_tx_nak (mcfi2c); +/* dummy read */ +mcfi2c_rd_dr (mcfi2c); + }else if (len--) { +mcfi2c_wr_dr (mcfi2c, *buf++); + }else { +if (more) +mcfi2c_repeat_start (mcfi2c); +else +mcfi2c_stop (mcfi2c); +return 0 ; + } + }else if (--len) { +if (!(len >1 )) +mcfi2c_tx_nak (mcfi2c); + *buf++ =mcfi2c_rd_dr (mcfi2c); + }else { +if (more) +mcfi2c_repeat_start (mcfi2c); +else +mcfi2c_stop (mcfi2c); + *buf++ =mcfi2c_rd_dr (mcfi2c); +return 0 ; + } + } +mcfi2c_stop (mcfi2c); + +return -ETIMEDOUT ; +} + +static int mcfi2c_xfer (struct i2c_adapter *adapter,struct i2c_msg *msgs, +int num) +{ +struct mcfi2c *mcfi2c =i2c_get_adapdata (adapter); +int cnt =0 ; +int status; +int retries; + +while (num--) { + retries = adapter->retries; +if (msgs->flags & ~I2C_M_RD ) +return -EINVAL ; +do { + status =mcfi2c_xmit (mcfi2c, msgs->addr, msgs->flags, + msgs->buf, msgs->len, + adapter->timeout, num); + }while (status && retries--); +if (status) +return status; + ++cnt; + ++msgs; + } + +return cnt; +} + +static u32 mcfi2c_func (struct i2c_adapter *adapter) +{ +return I2C_FUNC_I2C |I2C_FUNC_SMBUS_EMUL ; +} + +static const struct i2c_algorithm mcfi2c_algo = { + .master_xfer = mcfi2c_xfer, + .functionality = mcfi2c_func, +}; + +static const u16 mcfi2c_fdr[] = { +28 ,30 ,34 ,40 ,44 ,48 ,56 ,68 , +80 ,88 ,104 ,128 ,144 ,160 ,192 ,240 , +288 ,320 ,384 ,480 ,576 ,640 ,768 ,960 , +1152 ,1280 ,1536 ,1920 ,2304 ,2560 ,3072 ,3840 , +20 ,22 ,24 ,26 ,28 ,32 ,36 ,40 , +48 ,56 ,64 ,72 ,80 ,96 ,112 ,128 , +160 ,192 ,224 ,256 ,320 ,384 ,448 ,512 , +640 ,768 ,896 ,1024 ,1280 ,1536 ,1792 ,2048 +}; + +static u8 __devinit mcfi2c_calc_fdr (struct mcfi2c *mcfi2c, +struct mcfi2c_platform_data *pdata) +{ +u32 bitrate = (pdata && pdata->bitrate) ? + pdata->bitrate :DEFAULT_I2C_BUS_SPEED ; +int div =clk_get_rate (mcfi2c->clk)/bitrate; +int r =0 , i =0 ; + +do +if (abs (mcfi2c_fdr[i] - div) <abs (mcfi2c_fdr[r] - div)) + r = i; +while (++i <ARRAY_SIZE (mcfi2c_fdr)); + +return r; +} + +static int __devinit mcfi2c_probe (struct platform_device *pdev) +{ +struct mcfi2c *mcfi2c; +struct resource *res; +int status; + + mcfi2c =kzalloc (sizeof (*mcfi2c),GFP_KERNEL ); +if (!mcfi2c) { +dev_dbg (&pdev->dev,"kzalloc failed\n" ); + +return -ENOMEM ; + } + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +dev_dbg (&pdev->dev,"platform_get_resource failed\n" ); + status = -ENXIO ; + goto fail0; + } + +if (!request_mem_region (res->start,resource_size (res), pdev->name)) { +dev_dbg (&pdev->dev,"request_mem_region failed\n" ); + status = -EBUSY ; + goto fail0; + } + + mcfi2c->iobase =ioremap (res->start,resource_size (res)); +if (!mcfi2c->iobase) { +dev_dbg (&pdev->dev,"ioremap failed\n" ); + status = -ENOMEM ; + goto fail1;
drivers/i2c/busses/i2c-coldfire.c line 327
Quoted 10 lines
drivers/i2c/busses/i2c-coldfire.c new file +10
-0+ } + + mcfi2c->irq =platform_get_irq (pdev,0 ); +if (mcfi2c->irq <0 ) { +dev_dbg (&pdev->dev,"platform_get_irq failed\n" ); + status = -ENXIO ; + goto fail2; + } + status =request_irq (mcfi2c->irq, mcfi2c_irq_handler,IRQF_DISABLED , + pdev->name, mcfi2c);
do you really need IRQF_DISABLED here? your irq handler hardly does anything.
drivers/i2c/busses/i2c-coldfire.c line 333
Quoted 6 lines
drivers/i2c/busses/i2c-coldfire.c new file +6
-0+if (status) { +dev_dbg (&pdev->dev,"request_irq failed\n" ); + goto fail2; + } + + mcfi2c->clk =clk_get (&pdev->dev,"i2c_clk" );
hmm, think the default device clock should be findable by clk_get(dev, NULL).
Quoted 130 lines
drivers/i2c/busses/i2c-coldfire.c new file +130
-0+if (IS_ERR (mcfi2c->clk)) { +dev_dbg (&pdev->dev,"clk_get failed\n" ); + status =PTR_ERR (mcfi2c->clk); + goto fail3; + } +clk_enable (mcfi2c->clk); + +platform_set_drvdata (pdev, mcfi2c); + +init_completion (&mcfi2c->completion); + +writeb (mcfi2c_calc_fdr (mcfi2c, pdev->dev.platform_data), + mcfi2c->iobase +MCFI2C_FDR ); + +writeb (0x00 , mcfi2c->iobase +MCFI2C_ADR ); + +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN ); + +/* if the bus busy (IBB) is set, reset the controller */ +if (mcfi2c_rd_sr (mcfi2c) &MCFI2C_SR_IBB ) +mcfi2c_reset (mcfi2c); + + mcfi2c->adapter.algo = &mcfi2c_algo; + mcfi2c->adapter.class =I2C_CLASS_HWMON |I2C_CLASS_SPD ; + mcfi2c->adapter.dev.parent = &pdev->dev; + mcfi2c->adapter.nr = pdev->id; + mcfi2c->adapter.retries =2 ; +snprintf (mcfi2c->adapter.name,sizeof (mcfi2c->adapter.name), +DRIVER_NAME ".%d" , pdev->id); + +i2c_set_adapdata (&mcfi2c->adapter, mcfi2c); + + status =i2c_add_numbered_adapter (&mcfi2c->adapter); +if (status <0 ) { +dev_dbg (&pdev->dev,"i2c_add_numbered_adapter failed\n" ); + goto fail4; + } +dev_info (&pdev->dev,"Coldfire I2C bus driver\n" ); + +return 0 ; + +fail4: +clk_disable (mcfi2c->clk); +clk_put (mcfi2c->clk); +fail3: +free_irq (mcfi2c->irq, mcfi2c); +fail2: +iounmap (mcfi2c->iobase); +fail1: +release_mem_region (res->start,resource_size (res)); +fail0: +kfree (mcfi2c); + +return status; +} + +static int __devexit mcfi2c_remove(struct platform_device *pdev) +{ +struct mcfi2c *mcfi2c =platform_get_drvdata (pdev); +struct resource *res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + +/* disable the hardware */ +mcfi2c_wr_cr (mcfi2c,0 ); + +platform_set_drvdata (pdev,NULL ); +i2c_del_adapter (&mcfi2c->adapter); +clk_disable (mcfi2c->clk); +clk_put (mcfi2c->clk); +free_irq (mcfi2c->irq, mcfi2c); +iounmap (mcfi2c->iobase); +release_mem_region (res->start,resource_size (res)); +kfree (mcfi2c); + +return 0 ; +} + +#ifdef CONFIG_PM +static int mcfi2c_suspend (struct device *dev) +{ +struct mcfi2c *mcfi2c =platform_get_drvdata (to_platform_device (dev)); + +mcfi2c_wr_cr (mcfi2c,0 ); +clk_disable (mcfi2c->clk); + +return 0 ; +} + +static int mcfi2c_resume (struct device *dev) +{ +struct mcfi2c *mcfi2c =platform_get_drvdata (to_platform_device (dev)); + +clk_enable (mcfi2c->clk); +mcfi2c_wr_cr (mcfi2c,MCFI2C_CR_IEN ); + +return 0 ; +} + +static struct dev_pm_ops mcfi2c_dev_pm_ops = { + .suspend = mcfi2c_suspend, + .resume = mcfi2c_resume, +}; + +#define MCFI2C_DEV_PM_OPS (&mcfi2c_dev_pm_ops) +#else +#define MCFI2C_DEV_PM_OPS NULL +#endif + +static struct platform_driver mcfi2c_driver = { + .driver.name =DRIVER_NAME , + .driver.owner =THIS_MODULE , + .driver.pm =MCFI2C_DEV_PM_OPS , + .remove =__devexit_p (mcfi2c_remove), +}; + +static int __init mcfi2c_init (void ) +{ +return platform_driver_probe (&mcfi2c_driver, mcfi2c_probe); +} +module_init (mcfi2c_init); + +static void __exit mcfi2c_exit(void) +{ +platform_driver_unregister (&mcfi2c_driver); +} +module_exit (mcfi2c_exit); + +MODULE_AUTHOR ("Steven King <[email protected]>" ); +MODULE_DESCRIPTION ("I2C-Bus support for Freescale Coldfire processors" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:" DRIVER_NAME );
Signature · 3 lines
Ben ([email protected], http://www.fluff.org/) 'a smiley only costs 4 bytes'
Quoted 7 lines · On Sunday 24 January 2010 07:15:19 you wrote:
Quoted 6 lines · Steven King
Changes for this version:
rename drivers/i2c/busses/i2c-mcf.c to drivers/i2c/busses/i2c-coldfire.c use I2C_COLDFIRE in drivers/i2c/busses/{Kconfig,Makefile}------
Quoted 7 lines
Quoted 4 lines
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
Signed-off-by Steven King <[email protected]>The commit messsage should go first, the changelog and other stuff that won't go in should go beflore the --- line.
My bad, I think I was paying more attention to making sure this mailer didn't line wrap on me. I can repost if you want.
Quoted 5 lines
Quoted 5 lines
drivers/i2c/busses/i2c-coldfire.c new file +5
-0+static irqreturn_t mcfi2c_irq_handler (int this_irq,void *dev_id) +{ +struct mcfi2c *mcfi2c = dev_id; + +/* clear interrupt */
Quoted 8 lines
drivers/i2c/busses/i2c-coldfire.c line 130
Quoted 5 lines
drivers/i2c/busses/i2c-coldfire.c new file +5
-0+mcfi2c_wr_sr (mcfi2c,0 ); +complete (&mcfi2c->completion); + +return IRQ_HANDLED ; +}I'm interested in why you don't just handle the interrupt here and wake the thread once all the data is handled?
No particular reason; when I started working on this I looked at how some of the other drivers in drivers/i2c/busses were implemented, found one whose workings I could understand without knowing anything about that particular SoC (which one I don't remember) and used it as a model to adapt the i2c code I use with other Freescale/Motorola MCUs that don't run linux (there is very little difference in the i2c controller on an 8-bit hc08, 16 bit hc11/12, 32bit Coldfire v1 and the Coldfire v2[+] that are currently supported). So other than having easy to understand (for me atleast) code that shared a lot of similarity with the code I use for the some of the other systems I code for, no real reason. That and I find statefull irq handlers disconcerting.
Quoted 5 lines
drivers/i2c/busses/i2c-coldfire.c line 327
Quoted 2 lines
drivers/i2c/busses/i2c-coldfire.c new file +2
-0+ status =request_irq (mcfi2c->irq, mcfi2c_irq_handler,IRQF_DISABLED , + pdev->name, mcfi2c);do you really need
IRQF_DISABLEDhere? your irq handler hardly does anything.
Yes, without it, I was getting a spurious interrupt (been there, done that).
Quoted 9 lines
drivers/i2c/busses/i2c-coldfire.c line 333
Quoted 6 lines
drivers/i2c/busses/i2c-coldfire.c new file +6
-0+if (status) { +dev_dbg (&pdev->dev,"request_irq failed\n" ); + goto fail2; + } + + mcfi2c->clk =clk_get (&pdev->dev,"i2c_clk" );hmm, think the default device clock should be findable by
clk_get(dev, NULL).
Interesting. Again, I had looked at the existing code in drivers/i2c/busses
to see what the other drivers were doing and most were passing an id string.
Its a trivial change so its no big deal, but I'm curious, absent anything in Documentation, if the bulk of the existing code isn't documentation for the correct use of an api, then what is?
Signature · 8 lines
Steven King -- sfking at fdwdc dot com _______________________________________________ uClinux-dev mailing list [email protected] http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by [email protected] To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev
Hello all,
Quoted 5 lines · Steven King
Quoted 5 lines
Quoted 5 lines
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
Signed-off-by Steven King <[email protected]>
What's the status of this ?
I need to use i2c for a coldfire uclinux project (with a mcf5484) and I now have 3 different coldfire i2c drivers, none of which is in mainline.
i2c-mcf.c (from uClinux-dist-20090618, but not in http://git.kernel.org/?p=linux/kernel/git/gerg/m68knommu.git;a=summary)i2c-mcf548x.c (from ltib-m5475evb-20080808, found as "Linux BSP for MCF5484LITE, MCF5475/85EVB" at http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MCF548X&fpsp=1&tab=Design_Tools_Tab)i2c-coldfire.c (from http://lkml.org/lkml/2010/1/11/165)
I like to work with mainline sources to be be able to contribute to and benefit from collective work.
Which one has the best chances to be put in mainline ?
Best regards
Philippe
_______________________________________________
uClinux-dev mailing list [email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected] To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev
Quoted 7 lines · Philippe De Muyter
Hello all,
Quoted 4 lines · Steven King
Quoted 4 lines
Quoted 4 lines
Add support for the I2C controller used on Freescale/Motorola Coldfire MCUs.
Quoted 8 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Signed-off-by Steven King <[email protected]>What's the status of this ?
I need to use i2c for a coldfire uclinux project (with a mcf5484) and I now have 3 different coldfire i2c drivers, none of which is in mainline.
i2c-mcf.c(from uClinux-dist-20090618, but not in http://git.kernel.org/?p=linux/kernel/git/gerg/m68knommu.git;a=summary)
It seems I use that one based on the filename.
Quoted 7 lines
i2c-mcf548x.c(from ltib-m5475evb-20080808, found as "Linux BSP for MCF5484LITE, MCF5475/85EVB" at http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MCF548X&fpsp=1&tab=Design_Tools_Tab)i2c-coldfire.c(from http://lkml.org/lkml/2010/1/11/165)I like to work with mainline sources to be be able to contribute to and benefit from collective work.
Which one has the best chances to be put in mainline ?
No idea.
I am using this one on a 5271:
http://www.bitshrine.org/gpp/0006-I2C-device-driver.patch
http://www.bitshrine.org/gpp/0043-I2C-bug-fix.patch
No problems so far.
This is the patch that I use on top ofgit://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
arch/m68k/include/asm/m527xsim.h +39 -0
@@ -248,5 +248,44 @@#define MCF_RCR_SWRESET 0x80/* Software reset bit */ #define MCF_RCR_FRCSTOUT 0x40/* Force external reset */ +/********************************************************************* +* +* I2C Module (I2C) (Stolen from m5301xsim.h) +* +*********************************************************************/ +/* Register read/write macros */ +#ifdef CONFIG_M5271 +#define MCF_I2C_I2ADR (volatile unsigned char *)(MCF_MBAR + 0x300) +#define MCF_I2C_I2FDR (volatile unsigned char *)(MCF_MBAR + 0x304) +#define MCF_I2C_I2CR (volatile unsigned char *)(MCF_MBAR + 0x308) +#define MCF_I2C_I2SR (volatile unsigned char *)(MCF_MBAR + 0x30C) +#define MCF_I2C_I2DR (volatile unsigned char *)(MCF_MBAR + 0x310) + +/* Bit definitions and macros for I2AR */ +#define MCF_I2C_I2AR_ADR (x) (((x)&0x7F)<<1) + +/* Bit definitions and macros for I2FDR */ +#define MCF_I2C_I2FDR_IC (x) (((x)&0x3F)) + +/* Bit definitions and macros for I2CR */ +#define MCF_I2C_I2CR_RSTA (0x04) +#define MCF_I2C_I2CR_TXAK (0x08) +#define MCF_I2C_I2CR_MTX (0x10) +#define MCF_I2C_I2CR_MSTA (0x20) +#define MCF_I2C_I2CR_IIEN (0x40) +#define MCF_I2C_I2CR_IEN (0x80) + +/* Bit definitions and macros for I2SR */ +#define MCF_I2C_I2SR_RXAK (0x01) +#define MCF_I2C_I2SR_IIF (0x02) +#define MCF_I2C_I2SR_SRW (0x04) +#define MCF_I2C_I2SR_IAL (0x10) +#define MCF_I2C_I2SR_IBB (0x20) +#define MCF_I2C_I2SR_IAAS (0x40) +#define MCF_I2C_I2SR_ICF (0x80) + +/* Bit definitions and macros for I2DR */ +#define MCF_I2C_I2DR_DATA (x) (x) +#endif /* I2C Module for CONFIG_M5271 */ /****************************************************************************/ #endif /* m527xsim_h */
drivers/i2c/busses/Kconfig +10 -0
@@ -417,6 +417,16 @@ This driver is deprecated and will be dropped soon. Use i2c-gpio instead. +config I2C_MCF + tristate "MCF ColdFire" + depends on I2C && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + I2C on most ColdFire CPUs + + This driver can also be built as a module. If so, the module + will be called i2c-mcf. + config I2C_MPC tristate "MPC107/824x/85xx/52xx/86xx" depends on PPC32
drivers/i2c/busses/Makefile +1 -0
@@ -71,6 +71,7 @@ obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o +obj-$(CONFIG_I2C_MCF) += i2c-mcf.o ifeq ($(CONFIG_I2C_DEBUG_BUS),y) EXTRA_CFLAGS += -DDEBUG
drivers/i2c/busses/i2c-mcf.c +601 -0
601 lines not on this page · raw message
drivers/i2c/busses/i2c-mcf.h +52 -0
52 lines not on this page · raw message
I think that __I2C_MCF5282_H__ should be __I2C_MCF_H__ instead, but well what can you do.
Signature · 8 lines
Len Sorensen _______________________________________________ uClinux-dev mailing list [email protected] http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by [email protected] To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev