Re: M5282 Coldfire & I2C
Greg Ungerer <[email protected]>
| Newsgroups | gmane.linux.uclinux.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Steven, The ColdFire platform parts look ok to me. I would like to apply them to the m68knommu git tree. Can I have your signed-off-by for that part? They don't apply cleanly to the for-next branch, due to clashes with recent qspi changes, but the fixup is simple. The drivers/i2c/busses changes will need to go via [email protected] Regards Greg On 01/07/14 02:53, Steven King wrote: > On Monday 30 June 2014 8:16:01 am Nic Roets wrote: >> The patch I tried (dated 2012) did not include the platform support: > I was just going to suggest that in reply to you earlier message. > > This is the current version of the patch for kernel v3.15-rc7; It has all > the clocks and what not needed for more recent kernels. > > if this doesnt work I'd be very interested in seeing the details of your > setup. > > > --- > arch/m68k/include/asm/m5206sim.h | 8 + > arch/m68k/include/asm/m520xsim.h | 7 + > arch/m68k/include/asm/m523xsim.h | 10 +- > arch/m68k/include/asm/m527xsim.h | 8 + > arch/m68k/include/asm/m528xsim.h | 9 + > arch/m68k/include/asm/m5307sim.h | 9 +- > arch/m68k/include/asm/m53xxsim.h | 7 + > arch/m68k/include/asm/m5407sim.h | 8 + > arch/m68k/include/asm/m54xxsim.h | 10 + > arch/m68k/include/asm/mcfi2c.h | 15 + > arch/m68k/platform/coldfire/device.c | 193 +++++++++++++ > arch/m68k/platform/coldfire/m5206.c | 12 + > arch/m68k/platform/coldfire/m520x.c | 18 +- > arch/m68k/platform/coldfire/m523x.c | 18 ++ > arch/m68k/platform/coldfire/m5249.c | 25 ++ > arch/m68k/platform/coldfire/m525x.c | 6 +- > arch/m68k/platform/coldfire/m527x.c | 28 ++ > arch/m68k/platform/coldfire/m528x.c | 18 ++ > arch/m68k/platform/coldfire/m5307.c | 14 + > arch/m68k/platform/coldfire/m53xx.c | 15 +- > arch/m68k/platform/coldfire/m5407.c | 14 + > arch/m68k/platform/coldfire/m54xx.c | 17 ++ > drivers/i2c/busses/Kconfig | 10 + > drivers/i2c/busses/Makefile | 1 + > drivers/i2c/busses/i2c-coldfire.c | 496 ++++++++++++++++++++++++++++++++++ > 25 files changed, 971 insertions(+), 5 deletions(-) > > diff --git a/arch/m68k/include/asm/m5206sim.h b/arch/m68k/include/asm/m5206sim.h > index 4cf864f..0ddf3ef 100644 > --- a/arch/m68k/include/asm/m5206sim.h > +++ b/arch/m68k/include/asm/m5206sim.h > @@ -110,6 +110,7 @@ > /* > * Define system peripheral IRQ usage. > */ > +#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */ > #define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */ > #define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */ > #define MCF_IRQ_UART0 73 /* UART0 */ > @@ -138,6 +139,7 @@ > #define MCFSIM_SWDICR MCFSIM_ICR8 /* Watchdog timer ICR */ > #define MCFSIM_TIMER1ICR MCFSIM_ICR9 /* Timer 1 ICR */ > #define MCFSIM_TIMER2ICR MCFSIM_ICR10 /* Timer 2 ICR */ > +#define MCFSIM_I2CICR MCFSIM_ICR11 /* I2C ICR */ > #define MCFSIM_UART1ICR MCFSIM_ICR12 /* UART 1 ICR */ > #define MCFSIM_UART2ICR MCFSIM_ICR13 /* UART 2 ICR */ > #ifdef CONFIG_M5206e > @@ -145,5 +147,11 @@ > #define MCFSIM_DMA2ICR MCFSIM_ICR15 /* DMA 2 ICR */ > #endif > > +/* > + * I2C Controller > +*/ > +#define MCFI2C_BASE0 (MCF_MBAR + 0x1e0) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m5206sim_h */ > diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h > index db3f8ee..505a614 100644 > --- a/arch/m68k/include/asm/m520xsim.h > +++ b/arch/m68k/include/asm/m520xsim.h > @@ -50,6 +50,7 @@ > #define MCFINT_UART0 26 /* Interrupt number for UART0 */ > #define MCFINT_UART1 27 /* Interrupt number for UART1 */ > #define MCFINT_UART2 28 /* Interrupt number for UART2 */ > +#define MCFINT_I2C0 30 /* Interrupt number for I2C */ > #define MCFINT_QSPI 31 /* Interrupt number for QSPI */ > #define MCFINT_FECRX0 36 /* Interrupt number for FEC RX */ > #define MCFINT_FECTX0 40 /* Interrupt number for FEC RX */ > @@ -67,6 +68,7 @@ > #define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI) > #define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1) > > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0) > /* > * SDRAM configuration registers. > */ > @@ -199,6 +201,11 @@ > #define MCFPM_PPMHR0 0xfc040030 > #define MCFPM_PPMLR0 0xfc040034 > #define MCFPM_LPCR 0xfc0a0007 > +/* > + * I2C module. > +*/ > +#define MCFI2C_BASE0 0xFC058000 > +#define MCFI2C_SIZE0 0x40 > > /****************************************************************************/ > #endif /* m520xsim_h */ > diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h > index 5e06b4e..50f6c3f 100644 > --- a/arch/m68k/include/asm/m523xsim.h > +++ b/arch/m68k/include/asm/m523xsim.h > @@ -37,7 +37,8 @@ > #define MCFINT_UART0 13 /* Interrupt number for UART0 */ > #define MCFINT_UART1 14 /* Interrupt number for UART1 */ > #define MCFINT_UART2 15 /* Interrupt number for UART2 */ > -#define MCFINT_QSPI 18 /* Interrupt number for QSPI */ > +#define MCFINT_I2C0 17 /* Interrupt number for I2C */ > +#define MCFINT_QSPI 18 /* Interrupt number for QSPI */ > #define MCFINT_FECRX0 23 /* Interrupt number for FEC */ > #define MCFINT_FECTX0 27 /* Interrupt number for FEC */ > #define MCFINT_FECENTC0 29 /* Interrupt number for FEC */ > @@ -53,6 +54,7 @@ > > #define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI) > #define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1) > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0) > > /* > * SDRAM configuration registers. > @@ -208,5 +210,11 @@ > #define MCFDMA_BASE2 (MCF_IPSBAR + 0x180) > #define MCFDMA_BASE3 (MCF_IPSBAR + 0x1C0) > > +/* > + * I2C module. > +*/ > +#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m523xsim_h */ > diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h > index 1bebbe7..a3a5d83 100644 > --- a/arch/m68k/include/asm/m527xsim.h > +++ b/arch/m68k/include/asm/m527xsim.h > @@ -37,6 +37,7 @@ > #define MCFINT_UART0 13 /* Interrupt number for UART0 */ > #define MCFINT_UART1 14 /* Interrupt number for UART1 */ > #define MCFINT_UART2 15 /* Interrupt number for UART2 */ > +#define MCFINT_I2C0 17 /* Interrupt number for I2C */ > #define MCFINT_QSPI 18 /* Interrupt number for QSPI */ > #define MCFINT_FECRX0 23 /* Interrupt number for FEC0 */ > #define MCFINT_FECTX0 27 /* Interrupt number for FEC0 */ > @@ -61,6 +62,7 @@ > > #define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI) > #define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1) > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0) > > /* > * SDRAM configuration registers. > @@ -351,5 +353,11 @@ > #define MCF_RCR_SWRESET 0x80 /* Software reset bit */ > #define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */ > > +/* > + * I2C module. > +*/ > +#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m527xsim_h */ > diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h > index cf68ca0..df223e6 100644 > --- a/arch/m68k/include/asm/m528xsim.h > +++ b/arch/m68k/include/asm/m528xsim.h > @@ -37,6 +37,7 @@ > #define MCFINT_UART0 13 /* Interrupt number for UART0 */ > #define MCFINT_UART1 14 /* Interrupt number for UART1 */ > #define MCFINT_UART2 15 /* Interrupt number for UART2 */ > +#define MCFINT_I2C0 17 /* Interrupt number for I2C */ > #define MCFINT_QSPI 18 /* Interrupt number for QSPI */ > #define MCFINT_FECRX0 23 /* Interrupt number for FEC */ > #define MCFINT_FECTX0 27 /* Interrupt number for FEC */ > @@ -53,6 +54,8 @@ > > #define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI) > #define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1) > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0) > + > /* > * SDRAM configuration registers. > */ > @@ -242,5 +245,11 @@ > #define MCF_RCR_SWRESET 0x80 /* Software reset bit */ > #define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */ > > +/* > + * I2C module > +*/ > +#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m528xsim_h */ > diff --git a/arch/m68k/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h > index 5d0bb7e..baa9304 100644 > --- a/arch/m68k/include/asm/m5307sim.h > +++ b/arch/m68k/include/asm/m5307sim.h > @@ -148,6 +148,7 @@ > #define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */ > #define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */ > #define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */ > +#define MCFSIM_I2CICR MCFSIM_ICR3 /* I2C ICR */ > #define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */ > #define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */ > #define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */ > @@ -155,7 +156,6 @@ > #define MCFSIM_DMA2ICR MCFSIM_ICR8 /* DMA 2 ICR */ > #define MCFSIM_DMA3ICR MCFSIM_ICR9 /* DMA 3 ICR */ > > - > /* > * Some symbol defines for the Parallel Port Pin Assignment Register > */ > @@ -174,10 +174,17 @@ > /* > * Define system peripheral IRQ usage. > */ > +#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */ > #define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */ > #define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */ > #define MCF_IRQ_UART0 73 /* UART0 */ > #define MCF_IRQ_UART1 74 /* UART1 */ > > +/* > + * I2C module > +*/ > +#define MCFI2C_BASE0 (MCF_MBAR + 0x280) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m5307sim_h */ > diff --git a/arch/m68k/include/asm/m53xxsim.h b/arch/m68k/include/asm/m53xxsim.h > index faa1a21..c35ca07 100644 > --- a/arch/m68k/include/asm/m53xxsim.h > +++ b/arch/m68k/include/asm/m53xxsim.h > @@ -19,6 +19,7 @@ > #define MCFINT_UART0 26 /* Interrupt number for UART0 */ > #define MCFINT_UART1 27 /* Interrupt number for UART1 */ > #define MCFINT_UART2 28 /* Interrupt number for UART2 */ > +#define MCFINT_I2C0 30 /* Interrupt number for I2C */ > #define MCFINT_QSPI 31 /* Interrupt number for QSPI */ > #define MCFINT_FECRX0 36 /* Interrupt number for FEC */ > #define MCFINT_FECTX0 40 /* Interrupt number for FEC */ > @@ -32,6 +33,7 @@ > #define MCF_IRQ_FECTX0 (MCFINT_VECBASE + MCFINT_FECTX0) > #define MCF_IRQ_FECENTC0 (MCFINT_VECBASE + MCFINT_FECENTC0) > > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0) > #define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI) > > #define MCF_WTM_WCR 0xFC098000 > @@ -1237,5 +1239,10 @@ > #define MCFEPORT_EPPDR (0xFC094005) > #define MCFEPORT_EPFR (0xFC094006) > > +/* > + * I2C Module > + */ > +#define MCFI2C_BASE0 (0xFc058000) > +#define MCFI2C_SIZE0 0x40 > /********************************************************************/ > #endif /* m53xxsim_h */ > diff --git a/arch/m68k/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h > index a7550bc..018c535 100644 > --- a/arch/m68k/include/asm/m5407sim.h > +++ b/arch/m68k/include/asm/m5407sim.h > @@ -112,6 +112,7 @@ > #define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */ > #define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */ > #define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */ > +#define MCFSIM_I2CICR MCFSIM_ICR3 /* I2C ICR */ > #define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */ > #define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */ > #define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */ > @@ -137,10 +138,17 @@ > /* > * Define system peripheral IRQ usage. > */ > +#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */ > #define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */ > #define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */ > #define MCF_IRQ_UART0 73 /* UART0 */ > #define MCF_IRQ_UART1 74 /* UART1 */ > > +/* > + * I2C module > +*/ > +#define MCFI2C_BASE0 (MCF_MBAR + 0x280) > +#define MCFI2C_SIZE0 0x40 > + > /****************************************************************************/ > #endif /* m5407sim_h */ > diff --git a/arch/m68k/include/asm/m54xxsim.h b/arch/m68k/include/asm/m54xxsim.h > index d3bd838..5edaf22 100644 > --- a/arch/m68k/include/asm/m54xxsim.h > +++ b/arch/m68k/include/asm/m54xxsim.h > @@ -41,6 +41,7 @@ > */ > #define MCF_IRQ_TIMER (MCFINT_VECBASE + 54) /* Slice Timer 0 */ > #define MCF_IRQ_PROFILER (MCFINT_VECBASE + 53) /* Slice Timer 1 */ > +#define MCF_IRQ_I2C0 (MCFINT_VECBASE + 40) > #define MCF_IRQ_UART0 (MCFINT_VECBASE + 35) > #define MCF_IRQ_UART1 (MCFINT_VECBASE + 34) > #define MCF_IRQ_UART2 (MCFINT_VECBASE + 33) > @@ -97,4 +98,13 @@ > #define MCF_PAR_PSC_RTS_RTS (0x30) > #define MCF_PAR_PSC_CANRX (0x40) > > +#define MCF_PAR_FECI2CIRQ (MCF_MBAR + 0x00000a44) /* FEC/I2C/IRQ */ > +#define MCF_PAR_FECI2CIRQ_SDA (1 << 3) > +#define MCF_PAR_FECI2CIRQ_SCL (1 << 2) > +/* > + * I2C module. > +*/ > +#define MCFI2C_BASE0 (MCF_MBAR + 0x8f00) > +#define MCFI2C_SIZE0 0x40 > + > #endif /* m54xxsim_h */ > diff --git a/arch/m68k/include/asm/mcfi2c.h b/arch/m68k/include/asm/mcfi2c.h > new file mode 100644 > index 0000000..24b0453 > --- /dev/null > +++ b/arch/m68k/include/asm/mcfi2c.h > @@ -0,0 +1,15 @@ > +/* > + * Definitions for Coldfire I2C interface > +*/ > +#ifndef mcfi2c_h > +#define mcfi2c_h > + > +/** > + * struct mcfi2c_platform_data - platform data for the coldfire i2c driver > + * @bitrate: bitrate to use for this i2c controller. > +*/ > +struct mcfi2c_platform_data { > + u32 bitrate; > +}; > + > +#endif /* mcfi2c_h */ > diff --git a/arch/m68k/platform/coldfire/device.c b/arch/m68k/platform/coldfire/device.c > index 71ea4c0..7d20603 100644 > --- a/arch/m68k/platform/coldfire/device.c > +++ b/arch/m68k/platform/coldfire/device.c > @@ -19,6 +19,7 @@ > #include <asm/mcfsim.h> > #include <asm/mcfuart.h> > #include <asm/mcfqspi.h> > +#include <asm/mcfi2c.h> > > /* > * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. > @@ -327,6 +328,180 @@ static struct platform_device mcf_qspi = { > }; > #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */ > > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > +static struct resource mcf_i2c0_resources[] = { > + { > + .start = MCFI2C_BASE0, > + .end = MCFI2C_BASE0 + MCFI2C_SIZE0 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C0, > + .end = MCF_IRQ_I2C0, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c0_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c0 = { > + .name = "mcfi2c", > + .id = 0, > + .num_resources = ARRAY_SIZE(mcf_i2c0_resources), > + .resource = mcf_i2c0_resources, > + .dev.platform_data = &mcf_i2c0_platform_data, > +}; > +#ifdef MCFI2C_BASE1 > + > +static struct resource mcf_i2c1_resources[] = { > + { > + .start = MCFI2C_BASE1, > + .end = MCFI2C_BASE1 + MCFI2C_SIZE1 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C1, > + .end = MCF_IRQ_I2C1, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c1_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c1 = { > + .name = "mcfi2c", > + .id = 1, > + .num_resources = ARRAY_SIZE(mcf_i2c1_resources), > + .resource = mcf_i2c1_resources, > + .dev.platform_data = &mcf_i2c1_platform_data, > +}; > + > +#endif /* MCFI2C_BASE1 */ > + > +#ifdef MCFI2C_BASE2 > + > +static struct resource mcf_i2c2_resources[] = { > + { > + .start = MCFI2C_BASE2, > + .end = MCFI2C_BASE2 + MCFI2C_SIZE2 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C2, > + .end = MCF_IRQ_I2C2, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c2_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c2 = { > + .name = "mcfi2c", > + .id = 2, > + .num_resources = ARRAY_SIZE(mcf_i2c2_resources), > + .resource = mcf_i2c2_resources, > + .dev.platform_data = &mcf_i2c2_platform_data, > +}; > + > +#endif /* MCFI2C_BASE2 */ > + > +#ifdef MCFI2C_BASE3 > + > +static struct resource mcf_i2c3_resources[] = { > + { > + .start = MCFI2C_BASE3, > + .end = MCFI2C_BASE3 + MCFI2C_SIZE3 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C3, > + .end = MCF_IRQ_I2C3, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c3_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c3 = { > + .name = "mcfi2c", > + .id = 3, > + .num_resources = ARRAY_SIZE(mcf_i2c3_resources), > + .resource = mcf_i2c3_resources, > + .dev.platform_data = &mcf_i2c3_platform_data, > +}; > + > +#endif /* MCFI2C_BASE3 */ > + > +#ifdef MCFI2C_BASE4 > + > +static struct resource mcf_i2c4_resources[] = { > + { > + .start = MCFI2C_BASE4, > + .end = MCFI2C_BASE4 + MCFI2C_SIZE4 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C4, > + .end = MCF_IRQ_I2C4, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c4_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c4 = { > + .name = "mcfi2c", > + .id = 4, > + .num_resources = ARRAY_SIZE(mcf_i2c4_resources), > + .resource = mcf_i2c4_resources, > + .dev.platform_data = &mcf_i2c4_platform_data, > +}; > + > +#endif /* MCFI2C_BASE4 */ > + > +#ifdef MCFI2C_BASE5 > + > +static struct resource mcf_i2c5_resources[] = { > + { > + .start = MCFI2C_BASE5, > + .end = MCFI2C_BASE5 + MCFI2C_SIZE5 - 1, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = MCF_IRQ_I2C5, > + .end = MCF_IRQ_I2C5, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct mcfi2c_platform_data mcf_i2c5_platform_data = { > + .bitrate = 100000, > +}; > + > +static struct platform_device mcf_i2c5 = { > + .name = "mcfi2c", > + .id = 5, > + .num_resources = ARRAY_SIZE(mcf_i2c5_resources), > + .resource = mcf_i2c5_resources, > + .dev.platform_data = &mcf_i2c5_platform_data, > +}; > + > +#endif /* MCFI2C_BASE5 */ > + > + > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > + > + > static struct platform_device *mcf_devices[] __initdata = { > &mcf_uart, > #ifdef CONFIG_FEC > @@ -338,6 +513,24 @@ static struct platform_device *mcf_devices[] __initdata = { > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > &mcf_qspi, > #endif > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + &mcf_i2c0, > +#ifdef MCFI2C_BASE1 > + &mcf_i2c1, > +#endif > +#ifdef MCFI2C_BASE2 > + &mcf_i2c2, > +#endif > +#ifdef MCFI2C_BASE3 > + &mcf_i2c3, > +#endif > +#ifdef MCFI2C_BASE4 > + &mcf_i2c4, > +#endif > +#ifdef MCFI2C_BASE5 > + &mcf_i2c5, > +#endif > +#endif > }; > > /* > diff --git a/arch/m68k/platform/coldfire/m5206.c b/arch/m68k/platform/coldfire/m5206.c > index 0e55f44..f3d6258 100644 > --- a/arch/m68k/platform/coldfire/m5206.c > +++ b/arch/m68k/platform/coldfire/m5206.c > @@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); > DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -34,11 +35,21 @@ struct clk *mcf_clks[] = { > &clk_mcftmr1, > &clk_mcfuart0, > &clk_mcfuart1, > + &clk_mcfi2c0, > NULL > }; > > /***************************************************************************/ > > +static void __init m5206_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, > + MCFSIM_I2CICR); > + mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > void __init config_BSP(char *commandp, int size) > { > #if defined(CONFIG_NETtel) > @@ -53,6 +64,7 @@ void __init config_BSP(char *commandp, int size) > mcf_mapirq2imr(25, MCFINTC_EINT1); > mcf_mapirq2imr(28, MCFINTC_EINT4); > mcf_mapirq2imr(31, MCFINTC_EINT7); > + m5206_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m520x.c b/arch/m68k/platform/coldfire/m520x.c > index ea1be0e..2becf2d 100644 > --- a/arch/m68k/platform/coldfire/m520x.c > +++ b/arch/m68k/platform/coldfire/m520x.c > @@ -71,7 +71,7 @@ struct clk *mcf_clks[] = { > &__clk_0_40, /* sys.0 */ > &__clk_0_41, /* gpio.0 */ > &__clk_0_42, /* sdram.0 */ > -NULL, > + NULL, > }; > > static struct clk * const enable_clks[] __initconst = { > @@ -135,6 +135,21 @@ static void __init m520x_qspi_init(void) > > /***************************************************************************/ > > +static void __init m520x_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + u8 par; > + > + /* setup Port FECI2C Pin Assignment Register for I2C */ > + /* set PAR_SCL to SCL and PAR_SDA to SDA */ > + par = readb(MCF_GPIO_PAR_FECI2C); > + par |= 0x0f; > + writeb(par, MCF_GPIO_PAR_FECI2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void __init m520x_uarts_init(void) > { > u16 par; > @@ -179,6 +194,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m520x_qspi_init(); > #endif > + m520x_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m523x.c b/arch/m68k/platform/coldfire/m523x.c > index 2b10e9f..0139703 100644 > --- a/arch/m68k/platform/coldfire/m523x.c > +++ b/arch/m68k/platform/coldfire/m523x.c > @@ -33,6 +33,7 @@ DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); > DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -45,6 +46,7 @@ struct clk *mcf_clks[] = { > &clk_mcfuart1, > &clk_mcfuart2, > &clk_fec0, > + &clk_mcfi2c0, > NULL > }; > > @@ -68,6 +70,21 @@ static void __init m523x_qspi_init(void) > > /***************************************************************************/ > > +static void __init m523x_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + u8 par; > + > + /* setup Port AS Pin Assignment Register for I2C */ > + /* set PASPA0 to SCL and PASPA1 to SDA */ > + par = readb(MCFGPIO_PAR_FECI2C); > + par |= 0x0f; > + writeb(par, MCFGPIO_PAR_FECI2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void __init m523x_fec_init(void) > { > /* Set multi-function pins to ethernet use */ > @@ -83,6 +100,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m523x_qspi_init(); > #endif > + m523x_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m5249.c b/arch/m68k/platform/coldfire/m5249.c > index c80b5e5..eb4d9f5 100644 > --- a/arch/m68k/platform/coldfire/m5249.c > +++ b/arch/m68k/platform/coldfire/m5249.c > @@ -26,6 +26,8 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); > DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c1, "mcfi2c.1", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -34,6 +36,8 @@ struct clk *mcf_clks[] = { > &clk_mcftmr1, > &clk_mcfuart0, > &clk_mcfuart1, > + &clk_mcfi2c0, > + &clk_mcfi2c1, > NULL > }; > > @@ -85,6 +89,26 @@ static void __init m5249_qspi_init(void) > > /***************************************************************************/ > > +static void __init m5249_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + u32 r; > + > + /* first I2C controller uses regular irq setup */ > + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, > + MCFSIM_I2CICR); > + mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C); > + > + /* second I2C controller is completely different */ > + r = readl(MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1)); > + r &= ~MCFINTC2_INTPRI_BITS(0xf, MCF_IRQ_I2C1); > + r |= MCFINTC2_INTPRI_BITS(0x5, MCF_IRQ_I2C1); > + writel(r, MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1)); > +#endif > +} > + > +/***************************************************************************/ > + > #ifdef CONFIG_M5249C3 > > static void __init m5249_smc91x_init(void) > @@ -113,6 +137,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m5249_qspi_init(); > #endif > + m5249_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m525x.c b/arch/m68k/platform/coldfire/m525x.c > index 5b9f657..ce149e4 100644 > --- a/arch/m68k/platform/coldfire/m525x.c > +++ b/arch/m68k/platform/coldfire/m525x.c > @@ -26,6 +26,8 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); > DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c1, "mcfi2c.1", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -34,6 +36,8 @@ struct clk *mcf_clks[] = { > &clk_mcftmr1, > &clk_mcfuart0, > &clk_mcfuart1, > + &clk_mcfi2c0, > + &clk_mcfi2c1, > NULL > }; > > @@ -62,7 +66,7 @@ static void __init m525x_i2c_init(void) > > /* first I2C controller uses regular irq setup */ > writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, > - MCFSIM_I2CICR); > + MCFSIM_I2CICR); > mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C); > > /* second I2C controller is completely different */ > diff --git a/arch/m68k/platform/coldfire/m527x.c b/arch/m68k/platform/coldfire/m527x.c > index 6fbfe909..625cb9a 100644 > --- a/arch/m68k/platform/coldfire/m527x.c > +++ b/arch/m68k/platform/coldfire/m527x.c > @@ -35,6 +35,7 @@ DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); > DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); > DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -48,6 +49,7 @@ struct clk *mcf_clks[] = { > &clk_mcfuart2, > &clk_fec0, > &clk_fec1, > + &clk_mcfi2c0, > NULL > }; > > @@ -76,6 +78,31 @@ static void __init m527x_qspi_init(void) > > /***************************************************************************/ > > +static void __init m527x_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > +#if defined(CONFIG_M5271) > + u8 par; > + > + /* setup Port FECI2C Pin Assignment Register for I2C */ > + /* set PAR_SCL to SCL and PAR_SDA to SDA */ > + par = readb(MCFGPIO_PAR_FECI2C); > + par |= 0x0f; > + writeb(par, MCFGPIO_PAR_FECI2C); > +#elif defined(CONFIG_M5275) > + u16 par; > + > + /* setup Port FECI2C Pin Assignment Register for I2C */ > + /* set PAR_SCL to SCL and PAR_SDA to SDA */ > + par = readw(MCFGPIO_PAR_FECI2C); > + par |= 0x0f; > + writew(par, MCFGPIO_PAR_FECI2C); > +#endif > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void __init m527x_uarts_init(void) > { > u16 sepmask; > @@ -123,6 +150,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m527x_qspi_init(); > #endif > + m527x_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m528x.c b/arch/m68k/platform/coldfire/m528x.c > index b03a9d2..e2f8b3e 100644 > --- a/arch/m68k/platform/coldfire/m528x.c > +++ b/arch/m68k/platform/coldfire/m528x.c > @@ -35,6 +35,7 @@ DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); > DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -47,6 +48,7 @@ struct clk *mcf_clks[] = { > &clk_mcfuart1, > &clk_mcfuart2, > &clk_fec0, > + &clk_mcfi2c0, > NULL > }; > > @@ -64,6 +66,21 @@ static void __init m528x_qspi_init(void) > > /***************************************************************************/ > > +static void __init m528x_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + u16 paspar; > + > + /* setup Port AS Pin Assignment Register for I2C */ > + /* set PASPA0 to SCL and PASPA1 to SDA */ > + paspar = readw(MCFGPIO_PASPAR); > + paspar |= 0xF; > + writew(paspar, MCFGPIO_PASPAR); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void __init m528x_uarts_init(void) > { > u8 port; > @@ -129,6 +146,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m528x_qspi_init(); > #endif > + m528x_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m5307.c b/arch/m68k/platform/coldfire/m5307.c > index 8874353..1f844ba 100644 > --- a/arch/m68k/platform/coldfire/m5307.c > +++ b/arch/m68k/platform/coldfire/m5307.c > @@ -35,6 +35,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); > DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -43,11 +44,23 @@ struct clk *mcf_clks[] = { > &clk_mcftmr1, > &clk_mcfuart0, > &clk_mcfuart1, > + &clk_mcfi2c0, > NULL > }; > > /***************************************************************************/ > > +static void __init m5307_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, > + MCFSIM_I2CICR); > + mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > void __init config_BSP(char *commandp, int size) > { > #if defined(CONFIG_NETtel) || \ > @@ -73,6 +86,7 @@ void __init config_BSP(char *commandp, int size) > */ > wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); > #endif > + m5307_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m53xx.c b/arch/m68k/platform/coldfire/m53xx.c > index 5286f98..22c532b 100644 > --- a/arch/m68k/platform/coldfire/m53xx.c > +++ b/arch/m68k/platform/coldfire/m53xx.c > @@ -178,6 +178,19 @@ static void __init m53xx_qspi_init(void) > > /***************************************************************************/ > > +static void __init m53xx_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + /* setup Port AS Pin Assignment Register for I2C */ > + /* set PASPA0 to SCL and PASPA1 to SDA */ > + u8 r = readb(MCFGPIO_PAR_FECI2C); > + r |= 0x0f; > + writeb(r, MCFGPIO_PAR_FECI2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void __init m53xx_uarts_init(void) > { > /* UART GPIO initialization */ > @@ -222,7 +235,7 @@ void __init config_BSP(char *commandp, int size) > #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) > m53xx_qspi_init(); > #endif > - > + m53xx_i2c_init(); > #ifdef CONFIG_BDM_DISABLE > /* > * Disable the BDM clocking. This also turns off most of the rest of > diff --git a/arch/m68k/platform/coldfire/m5407.c b/arch/m68k/platform/coldfire/m5407.c > index 2fb3cdb..3588212 100644 > --- a/arch/m68k/platform/coldfire/m5407.c > +++ b/arch/m68k/platform/coldfire/m5407.c > @@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); > DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -34,11 +35,23 @@ struct clk *mcf_clks[] = { > &clk_mcftmr1, > &clk_mcfuart0, > &clk_mcfuart1, > + &clk_mcfi2c0, > NULL > }; > > /***************************************************************************/ > > +static void __init m5407_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, > + MCFSIM_I2CICR); > + mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > void __init config_BSP(char *commandp, int size) > { > mach_sched_init = hw_timer_init; > @@ -48,6 +61,7 @@ void __init config_BSP(char *commandp, int size) > mcf_mapirq2imr(27, MCFINTC_EINT3); > mcf_mapirq2imr(29, MCFINTC_EINT5); > mcf_mapirq2imr(31, MCFINTC_EINT7); > + m5407_i2c_init(); > } > > /***************************************************************************/ > diff --git a/arch/m68k/platform/coldfire/m54xx.c b/arch/m68k/platform/coldfire/m54xx.c > index 952da53..67f047b 100644 > --- a/arch/m68k/platform/coldfire/m54xx.c > +++ b/arch/m68k/platform/coldfire/m54xx.c > @@ -38,6 +38,7 @@ DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); > DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); > DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); > DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK); > +DEFINE_CLK(mcfi2c0, "mcfi2c.0", MCF_BUSCLK); > > struct clk *mcf_clks[] = { > &clk_pll, > @@ -48,6 +49,7 @@ struct clk *mcf_clks[] = { > &clk_mcfuart1, > &clk_mcfuart2, > &clk_mcfuart3, > + &clk_mcfi2c0, > NULL > }; > > @@ -66,6 +68,20 @@ static void __init m54xx_uarts_init(void) > > /***************************************************************************/ > > +static void __init m54xx_i2c_init(void) > +{ > +#if IS_ENABLED(CONFIG_I2C_COLDFIRE) > + u32 r; > + > + /* set the fec/i2c/irq pin assignment register for i2c */ > + r = readl(MCF_PAR_FECI2CIRQ); > + r |= MCF_PAR_FECI2CIRQ_SDA | MCF_PAR_FECI2CIRQ_SCL; > + writel(r, MCF_PAR_FECI2CIRQ); > +#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */ > +} > + > +/***************************************************************************/ > + > static void mcf54xx_reset(void) > { > /* disable interrupts and enable the watchdog */ > @@ -124,6 +140,7 @@ void __init config_BSP(char *commandp, int size) > mach_reset = mcf54xx_reset; > mach_sched_init = hw_timer_init; > m54xx_uarts_init(); > + m54xx_i2c_init(); > } > > /***************************************************************************/ > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig > index c94db1c..30d250c 100644 > --- a/drivers/i2c/busses/Kconfig > +++ b/drivers/i2c/busses/Kconfig > @@ -393,6 +393,16 @@ config I2C_CBUS_GPIO > This driver can also be built as a module. If so, the module > will be called i2c-cbus-gpio. > > +config I2C_COLDFIRE > + tristate "Freescale Coldfire I2C driver" > + depends on !M5272 > + help > + This driver supports the I2C interface availible on most Freescale > + Coldfire processors. > + > + 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 > diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile > index 18d18ff..e9e951e 100644 > --- a/drivers/i2c/busses/Makefile > +++ b/drivers/i2c/busses/Makefile > @@ -35,6 +35,7 @@ obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o > obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o > obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o > obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.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_CORE) += i2c-designware-core.o > diff --git a/drivers/i2c/busses/i2c-coldfire.c b/drivers/i2c/busses/i2c-coldfire.c > new file mode 100644 > index 0000000..165a29e > --- /dev/null > +++ b/drivers/i2c/busses/i2c-coldfire.c > @@ -0,0 +1,496 @@ > +/* Freescale/Motorola Coldfire I2C driver. > + * > + * Copyright 2010, 2012 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 <linux/slab.h> > +#include <linux/pm_runtime.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; > + > + u8 *buf; > + u16 flags; > + u16 len; > + int more; > + int status; > +}; > + > +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); > +} > + > +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); > +} > + > +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); > +} > + > +static irqreturn_t mcfi2c_irq_handler(int this_irq, void *dev_id) > +{ > + struct mcfi2c *mcfi2c = dev_id; > + u8 sr; > + > + if (pm_runtime_suspended(&mcfi2c->adapter.dev)) > + return IRQ_NONE; > + > + /* clear interrupt */ > + mcfi2c_wr_sr(mcfi2c, 0); > + > + sr = mcfi2c_rd_sr(mcfi2c); > + if (sr & MCFI2C_SR_IAL) { > + mcfi2c_wr_sr(mcfi2c, ~MCFI2C_SR_IAL); > + mcfi2c->status = -EAGAIN; > + } else { > + if (mcfi2c_rd_cr(mcfi2c) & MCFI2C_CR_MTX) { > + if (sr & MCFI2C_SR_RXAK) { > + mcfi2c_stop(mcfi2c); > + mcfi2c->status = -EIO; > + } else if (mcfi2c->flags & I2C_M_RD) { > + if (mcfi2c->len > 1) > + mcfi2c_tx_ack(mcfi2c); > + else > + mcfi2c_tx_nak(mcfi2c); > + /* dummy read */ > + mcfi2c_rd_dr(mcfi2c); > + goto not_complete; > + > + } else if (mcfi2c->len--) { > + mcfi2c_wr_dr(mcfi2c, *(mcfi2c->buf++)); > + goto not_complete; > + } else { > + if (mcfi2c->more) > + mcfi2c_repeat_start(mcfi2c); > + else > + mcfi2c_stop(mcfi2c); > + } > + } else { > + if (--mcfi2c->len) { > + if (!(mcfi2c->len > 1)) > + mcfi2c_tx_nak(mcfi2c); > + *(mcfi2c->buf++) = mcfi2c_rd_dr(mcfi2c); > + goto not_complete; > + } else { > + if (mcfi2c->more) > + mcfi2c_repeat_start(mcfi2c); > + else > + mcfi2c_stop(mcfi2c); > + *(mcfi2c->buf++) = mcfi2c_rd_dr(mcfi2c); > + } > + } > + } > + complete(&mcfi2c->completion); > +not_complete: > + return IRQ_HANDLED; > +} > + > +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 int mcfi2c_wait_for_bus_idle(struct mcfi2c *mcfi2c) > +{ > + unsigned long timeout = jiffies + HZ / 2; > + while (mcfi2c_rd_sr(mcfi2c) & MCFI2C_SR_IBB) { > + if (time_after(jiffies, timeout)) > + return -EAGAIN; /* bus is busy, try again */ > + cond_resched(); > + } > + return 0; > +} > + > +static int mcfi2c_wait_for_bus_busy(struct mcfi2c *mcfi2c) > +{ > + unsigned long timeout = jiffies + HZ / 10; > + u8 sr; > + while (!((sr = mcfi2c_rd_sr(mcfi2c)) & MCFI2C_SR_IBB)) { > + if (sr & MCFI2C_SR_IAL) > + return -EAGAIN; /* lost arbitration, try again */ > + if (time_after(jiffies, timeout)) { > + /* if we dont get bus busy and dont get an arbitration > + * loss, then the bus is probably glitched, see if we > + * can recover. > + */ > + dev_dbg(&mcfi2c->adapter.dev, > + "unable to send START, trying to reset the bus\n"); > + mcfi2c_reset(mcfi2c); > + return -EAGAIN; > + } > + cond_resched(); > + } > + return 0; > +} > + > +static int mcfi2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, > + int num) > +{ > + struct mcfi2c *mcfi2c = i2c_get_adapdata(adapter); > + int cnt = 0; > + > + pm_runtime_get_sync(&adapter->dev); > + > + while (num--) { > + if (msgs->flags & ~I2C_M_RD) { > + mcfi2c->status = -EINVAL; > + goto done; > + } > + mcfi2c->flags = msgs->flags; > + mcfi2c->buf = msgs->buf; > + mcfi2c->len = msgs->len; > + mcfi2c->more = num; > + mcfi2c->status = 0; > + > + if (!(mcfi2c_rd_cr(mcfi2c) & MCFI2C_CR_MSTA)) { > + mcfi2c->status = mcfi2c_wait_for_bus_idle(mcfi2c); > + if (mcfi2c->status) > + continue; > + > + init_completion(&mcfi2c->completion); > + mcfi2c_start(mcfi2c); > + > + mcfi2c->status = mcfi2c_wait_for_bus_busy(mcfi2c); > + if (mcfi2c->status) > + continue; > + } > + > + mcfi2c_wr_dr(mcfi2c, (msgs->addr << 1) | > + (msgs->flags & I2C_M_RD)); > + if (!wait_for_completion_timeout(&mcfi2c->completion, > + adapter->timeout * msgs->len)) { > + mcfi2c->status = -ETIMEDOUT; > + mcfi2c_stop(mcfi2c); > + } > + > + if (mcfi2c->status) > + goto done; > + ++cnt; > + ++msgs; > + } > +done: > + pm_runtime_put(&adapter->dev); > + > + return mcfi2c->status ?: 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 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 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; > + } > + > + 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, 0, pdev->name, > + mcfi2c); > + if (status) { > + dev_dbg(&pdev->dev, "request_irq failed\n"); > + goto fail2; > + } > + > + mcfi2c->clk = clk_get(&pdev->dev, NULL); > + 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); > + > + pm_runtime_enable(&pdev->dev); > + pm_runtime_get_sync(&pdev->dev); > + > + /* 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; > + } > + > + pm_runtime_put(&pdev->dev); > + > + dev_info(&pdev->dev, "Coldfire I2C bus driver\n"); > + > + return 0; > + > +fail4: > + pm_runtime_put(&pdev->dev); > + > + 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 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_RUNTIME > +static int mcfi2c_runtime_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_runtime_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; > +} > +#endif > + > +static const struct dev_pm_ops mcfi2c_pm = { > + SET_RUNTIME_PM_OPS(mcfi2c_runtime_suspend, mcfi2c_runtime_resume, NULL) > +}; > + > +static struct platform_driver mcfi2c_driver = { > + .driver.name = DRIVER_NAME, > + .driver.owner = THIS_MODULE, > + .driver.pm = &mcfi2c_pm, > + .remove = 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); > > > > > > _______________________________________________ > 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 > _______________________________________________ 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