Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux

Pull embedded i2c changes from Wolfram Sang:
 "Changes for the "embedded" part of the I2C subsystem:

   - lots of devicetree conversions of drivers (and preparations for
     that)
   - big cleanups for drivers for OMAP, Tegra, Nomadik, Blackfin
   - Rafael's struct dev_pm_ops conversion patches for I2C
   - usual driver cleanups and fixes

  All patches have been in linux-next for an apropriate time and all
  patches touching files outside of i2c-folders should have proper acks
  from the maintainers."

* 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux: (60 commits)
  Revert "i2c: tegra: convert normal suspend/resume to *_noirq"
  I2C: MV64XYZ: Add Device Tree support
  i2c: stu300: use devm managed resources
  i2c: i2c-ocores: support for 16bit and 32bit IO
  V4L/DVB: mfd: use reg_shift instead of regstep
  i2c: i2c-ocores: Use reg-shift property
  i2c: i2c-ocores: DT bindings and minor fixes.
  i2c: mv64xxxx: remove EXPERIMENTAL tag
  i2c-s3c2410: Use plain pm_runtime_put()
  i2c: s3c2410: Fix pointer type passed to of_match_node()
  i2c: mxs: Set I2C timing registers for mxs-i2c
  i2c: i2c-bfin-twi: Move blackfin TWI register access Macro to head file.
  i2c: i2c-bfin-twi: Move TWI peripheral pin request array to platform data.
  i2c:i2c-bfin-twi: include twi head file
  i2c:i2c-bfin-twi: TWI fails to restart next transfer in high system load.
  i2c: i2c-bfin-twi: Tighten condition when failing I2C transfer if MEN bit is reset unexpectedly.
  i2c: i2c-bfin-twi: Break dead waiting loop if i2c device misbehaves.
  i2c: i2c-bfin-twi: Improve the patch for bug "Illegal i2c bus lock upon certain transfer scenarios".
  i2c: i2c-bfin-twi: Illegal i2c bus lock upon certain transfer scenarios.
  i2c-mv64xxxx: allow more than one driver instance
  ...

Conflicts:
	drivers/i2c/busses/i2c-nomadik.c
This commit is contained in:
Linus Torvalds 2012-07-28 13:43:12 -07:00
commit a410963ba4
25 changed files with 692 additions and 566 deletions

View File

@ -4,6 +4,8 @@ Required properties:
- compatible: Should be "fsl,<chip>-i2c" - compatible: Should be "fsl,<chip>-i2c"
- reg: Should contain registers location and length - reg: Should contain registers location and length
- interrupts: Should contain ERROR and DMA interrupts - interrupts: Should contain ERROR and DMA interrupts
- clock-frequency: Desired I2C bus clock frequency in Hz.
Only 100000Hz and 400000Hz modes are supported.
Examples: Examples:
@ -13,4 +15,5 @@ i2c0: i2c@80058000 {
compatible = "fsl,imx28-i2c"; compatible = "fsl,imx28-i2c";
reg = <0x80058000 2000>; reg = <0x80058000 2000>;
interrupts = <111 68>; interrupts = <111 68>;
clock-frequency = <100000>;
}; };

View File

@ -0,0 +1,33 @@
Device tree configuration for i2c-ocores
Required properties:
- compatible : "opencores,i2c-ocores"
- reg : bus address start and address range size of device
- interrupts : interrupt number
- clock-frequency : frequency of bus clock in Hz
- #address-cells : should be <1>
- #size-cells : should be <0>
Optional properties:
- reg-shift : device register offsets are shifted by this value
- reg-io-width : io register width in bytes (1, 2 or 4)
- regstep : deprecated, use reg-shift above
Example:
i2c0: ocores@a0000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "opencores,i2c-ocores";
reg = <0xa0000000 0x8>;
interrupts = <10>;
clock-frequency = <20000000>;
reg-shift = <0>; /* 8 bit registers */
reg-io-width = <1>; /* 8 bit read/write */
dummy@60 {
compatible = "dummy";
reg = <0x60>;
};
};

View File

@ -1,4 +1,4 @@
* I2C * Marvell MMP I2C controller
Required properties : Required properties :
@ -32,3 +32,20 @@ Examples:
interrupts = <58>; interrupts = <58>;
}; };
* Marvell MV64XXX I2C controller
Required properties :
- reg : Offset and length of the register set for the device
- compatible : Should be "marvell,mv64xxx-i2c"
- interrupts : The interrupt number
- clock-frequency : Desired I2C bus clock frequency in Hz.
Examples:
i2c@11000 {
compatible = "marvell,mv64xxx-i2c";
reg = <0x11000 0x20>;
interrupts = <29>;
clock-frequency = <100000>;
};

View File

@ -660,6 +660,7 @@
compatible = "fsl,imx28-i2c"; compatible = "fsl,imx28-i2c";
reg = <0x80058000 2000>; reg = <0x80058000 2000>;
interrupts = <111 68>; interrupts = <111 68>;
clock-frequency = <100000>;
status = "disabled"; status = "disabled";
}; };
@ -669,6 +670,7 @@
compatible = "fsl,imx28-i2c"; compatible = "fsl,imx28-i2c";
reg = <0x8005a000 2000>; reg = <0x8005a000 2000>;
interrupts = <110 69>; interrupts = <110 69>;
clock-frequency = <100000>;
status = "disabled"; status = "disabled";
}; };

View File

@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_data/i2c-nomadik.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/pl022.h> #include <linux/amba/pl022.h>
@ -40,7 +41,6 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <plat/i2c.h>
#include <plat/ste_dma40.h> #include <plat/ste_dma40.h>
#include <plat/gpio-nomadik.h> #include <plat/gpio-nomadik.h>

View File

@ -12,7 +12,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/sys_soc.h> #include <linux/sys_soc.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <plat/i2c.h> #include <linux/platform_data/i2c-nomadik.h>
#include <mach/crypto-ux500.h> #include <mach/crypto-ux500.h>
struct spi_master_cntlr; struct spi_master_cntlr;
@ -56,27 +56,15 @@ dbx500_add_uart(struct device *parent, const char *name, resource_size_t base,
struct nmk_i2c_controller; struct nmk_i2c_controller;
static inline struct platform_device * static inline struct amba_device *
dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq,
struct nmk_i2c_controller *data) struct nmk_i2c_controller *data)
{ {
struct resource res[] = { /* Conjure a name similar to what the platform device used to have */
DEFINE_RES_MEM(base, SZ_4K), char name[16];
DEFINE_RES_IRQ(irq),
};
struct platform_device_info pdevinfo = { snprintf(name, sizeof(name), "nmk-i2c.%d", id);
.parent = parent, return amba_apb_device_add(parent, name, base, SZ_4K, irq, 0, data, 0);
.name = "nmk-i2c",
.id = id,
.res = res,
.num_res = ARRAY_SIZE(res),
.data = data,
.size_data = sizeof(*data),
.dma_mask = DMA_BIT_MASK(32),
};
return platform_device_register_full(&pdevinfo);
} }
static inline struct amba_device * static inline struct amba_device *

View File

@ -15,7 +15,7 @@
* *
**/ **/
struct imxi2c_platform_data { struct imxi2c_platform_data {
int bitrate; u32 bitrate;
}; };
#endif /* __ASM_ARCH_I2C_H_ */ #endif /* __ASM_ARCH_I2C_H_ */

View File

@ -462,7 +462,7 @@ config I2C_MPC
config I2C_MV64XXX config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller" tristate "Marvell mv64xxx I2C Controller"
depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL depends on (MV64X60 || PLAT_ORION)
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges. built-in I2C interface on the Marvell 64xxx line of host bridges.
@ -483,10 +483,11 @@ config I2C_MXS
config I2C_NOMADIK config I2C_NOMADIK
tristate "ST-Ericsson Nomadik/Ux500 I2C Controller" tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
depends on PLAT_NOMADIK depends on ARM_AMBA
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
as well as the STA2X11 PCIe I/O HUB.
config I2C_NUC900 config I2C_NUC900
tristate "NUC900 I2C Driver" tristate "NUC900 I2C Driver"

View File

@ -279,30 +279,31 @@ static int __devexit at91_i2c_remove(struct platform_device *pdev)
/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */ /* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) static int at91_i2c_suspend(struct device *dev)
{ {
clk_disable(twi_clk); clk_disable(twi_clk);
return 0; return 0;
} }
static int at91_i2c_resume(struct platform_device *pdev) static int at91_i2c_resume(struct device *dev)
{ {
return clk_enable(twi_clk); return clk_enable(twi_clk);
} }
static SIMPLE_DEV_PM_OPS(at91_i2c_pm, at91_i2c_suspend, at91_i2c_resume);
#define AT91_I2C_PM (&at91_i2c_pm)
#else #else
#define at91_i2c_suspend NULL #define AT91_I2C_PM NULL
#define at91_i2c_resume NULL
#endif #endif
static struct platform_driver at91_i2c_driver = { static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe, .probe = at91_i2c_probe,
.remove = __devexit_p(at91_i2c_remove), .remove = __devexit_p(at91_i2c_remove),
.suspend = at91_i2c_suspend,
.resume = at91_i2c_resume,
.driver = { .driver = {
.name = "at91_i2c", .name = "at91_i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = AT91_I2C_PM,
}, },
}; };

View File

@ -25,6 +25,7 @@
#include <asm/blackfin.h> #include <asm/blackfin.h>
#include <asm/portmux.h> #include <asm/portmux.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/bfin_twi.h>
/* SMBus mode*/ /* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 1 #define TWI_I2C_MODE_STANDARD 1
@ -32,56 +33,6 @@
#define TWI_I2C_MODE_COMBINED 3 #define TWI_I2C_MODE_COMBINED 3
#define TWI_I2C_MODE_REPEAT 4 #define TWI_I2C_MODE_REPEAT 4
struct bfin_twi_iface {
int irq;
spinlock_t lock;
char read_write;
u8 command;
u8 *transPtr;
int readNum;
int writeNum;
int cur_mode;
int manual_stop;
int result;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
int msg_num;
int cur_msg;
u16 saved_clkdiv;
u16 saved_control;
void __iomem *regs_base;
};
#define DEFINE_TWI_REG(reg, off) \
static inline u16 read_##reg(struct bfin_twi_iface *iface) \
{ return bfin_read16(iface->regs_base + (off)); } \
static inline void write_##reg(struct bfin_twi_iface *iface, u16 v) \
{ bfin_write16(iface->regs_base + (off), v); }
DEFINE_TWI_REG(CLKDIV, 0x00)
DEFINE_TWI_REG(CONTROL, 0x04)
DEFINE_TWI_REG(SLAVE_CTL, 0x08)
DEFINE_TWI_REG(SLAVE_STAT, 0x0C)
DEFINE_TWI_REG(SLAVE_ADDR, 0x10)
DEFINE_TWI_REG(MASTER_CTL, 0x14)
DEFINE_TWI_REG(MASTER_STAT, 0x18)
DEFINE_TWI_REG(MASTER_ADDR, 0x1C)
DEFINE_TWI_REG(INT_STAT, 0x20)
DEFINE_TWI_REG(INT_MASK, 0x24)
DEFINE_TWI_REG(FIFO_CTL, 0x28)
DEFINE_TWI_REG(FIFO_STAT, 0x2C)
DEFINE_TWI_REG(XMT_DATA8, 0x80)
DEFINE_TWI_REG(XMT_DATA16, 0x84)
DEFINE_TWI_REG(RCV_DATA8, 0x88)
DEFINE_TWI_REG(RCV_DATA16, 0x8C)
static const u16 pin_req[2][3] = {
{P_TWI0_SCL, P_TWI0_SDA, 0},
{P_TWI1_SCL, P_TWI1_SDA, 0},
};
static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
unsigned short twi_int_status) unsigned short twi_int_status)
{ {
@ -99,7 +50,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
*/ */
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | MDIR | RSTART); read_MASTER_CTL(iface) | MDIR);
else if (iface->manual_stop) else if (iface->manual_stop)
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | STOP); read_MASTER_CTL(iface) | STOP);
@ -107,10 +58,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
iface->cur_msg + 1 < iface->msg_num) { iface->cur_msg + 1 < iface->msg_num) {
if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART | MDIR); read_MASTER_CTL(iface) | MDIR);
else else
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) | RSTART) & ~MDIR); read_MASTER_CTL(iface) & ~MDIR);
} }
} }
if (twi_int_status & RCVSERV) { if (twi_int_status & RCVSERV) {
@ -130,17 +81,25 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
} }
iface->transPtr++; iface->transPtr++;
iface->readNum--; iface->readNum--;
} else if (iface->manual_stop) { }
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | STOP); if (iface->readNum == 0) {
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && if (iface->manual_stop) {
iface->cur_msg + 1 < iface->msg_num) { /* Temporary workaround to avoid possible bus stall -
if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) * Flush FIFO before issuing the STOP condition
*/
read_RCV_DATA16(iface);
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART | MDIR); read_MASTER_CTL(iface) | STOP);
else } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
write_MASTER_CTL(iface, iface->cur_msg + 1 < iface->msg_num) {
(read_MASTER_CTL(iface) | RSTART) & ~MDIR); if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | MDIR);
else
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~MDIR);
}
} }
} }
if (twi_int_status & MERR) { if (twi_int_status & MERR) {
@ -193,7 +152,8 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
return; return;
} }
if (twi_int_status & MCOMP) { if (twi_int_status & MCOMP) {
if ((read_MASTER_CTL(iface) & MEN) == 0 && if (twi_int_status & (XMTSERV | RCVSERV) &&
(read_MASTER_CTL(iface) & MEN) == 0 &&
(iface->cur_mode == TWI_I2C_MODE_REPEAT || (iface->cur_mode == TWI_I2C_MODE_REPEAT ||
iface->cur_mode == TWI_I2C_MODE_COMBINED)) { iface->cur_mode == TWI_I2C_MODE_COMBINED)) {
iface->result = -1; iface->result = -1;
@ -221,7 +181,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART); read_MASTER_CTL(iface) & ~RSTART);
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num) { iface->cur_msg + 1 < iface->msg_num) {
iface->cur_msg++; iface->cur_msg++;
iface->transPtr = iface->pmsg[iface->cur_msg].buf; iface->transPtr = iface->pmsg[iface->cur_msg].buf;
iface->writeNum = iface->readNum = iface->writeNum = iface->readNum =
@ -241,27 +201,29 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
} }
} }
if (iface->pmsg[iface->cur_msg].len <= 255) if (iface->pmsg[iface->cur_msg].len <= 255) {
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) & (read_MASTER_CTL(iface) &
(~(0xff << 6))) | (~(0xff << 6))) |
(iface->pmsg[iface->cur_msg].len << 6)); (iface->pmsg[iface->cur_msg].len << 6));
else { iface->manual_stop = 0;
} else {
write_MASTER_CTL(iface, write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) | (read_MASTER_CTL(iface) |
(0xff << 6))); (0xff << 6)));
iface->manual_stop = 1; iface->manual_stop = 1;
} }
/* remove restart bit and enable master receive */ /* remove restart bit before last message */
write_MASTER_CTL(iface, if (iface->cur_msg + 1 == iface->msg_num)
read_MASTER_CTL(iface) & ~RSTART); write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
} else { } else {
iface->result = 1; iface->result = 1;
write_INT_MASK(iface, 0); write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0); write_MASTER_CTL(iface, 0);
} }
complete(&iface->complete);
} }
complete(&iface->complete);
} }
/* Interrupt handler */ /* Interrupt handler */
@ -298,8 +260,8 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
if (!(read_CONTROL(iface) & TWI_ENA)) if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO; return -ENXIO;
while (read_MASTER_STAT(iface) & BUSBUSY) if (read_MASTER_STAT(iface) & BUSBUSY)
yield(); return -EAGAIN;
iface->pmsg = msgs; iface->pmsg = msgs;
iface->msg_num = num; iface->msg_num = num;
@ -311,7 +273,8 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
return -EINVAL; return -EINVAL;
} }
iface->cur_mode = TWI_I2C_MODE_REPEAT; if (iface->msg_num > 1)
iface->cur_mode = TWI_I2C_MODE_REPEAT;
iface->manual_stop = 0; iface->manual_stop = 0;
iface->transPtr = pmsg->buf; iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len; iface->writeNum = iface->readNum = pmsg->len;
@ -356,6 +319,7 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
/* Master enable */ /* Master enable */
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
(iface->msg_num > 1 ? RSTART : 0) |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
SSYNC(); SSYNC();
@ -398,8 +362,8 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
if (!(read_CONTROL(iface) & TWI_ENA)) if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO; return -ENXIO;
while (read_MASTER_STAT(iface) & BUSBUSY) if (read_MASTER_STAT(iface) & BUSBUSY)
yield(); return -EAGAIN;
iface->writeNum = 0; iface->writeNum = 0;
iface->readNum = 0; iface->readNum = 0;
@ -520,7 +484,7 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
else else
write_MASTER_CTL(iface, 0x1 << 6); write_MASTER_CTL(iface, 0x1 << 6);
/* Master enable */ /* Master enable */
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | RSTART |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
break; break;
default: default:
@ -611,9 +575,9 @@ static struct i2c_algorithm bfin_twi_algorithm = {
.functionality = bfin_twi_functionality, .functionality = bfin_twi_functionality,
}; };
static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state) static int i2c_bfin_twi_suspend(struct device *dev)
{ {
struct bfin_twi_iface *iface = platform_get_drvdata(pdev); struct bfin_twi_iface *iface = dev_get_drvdata(dev);
iface->saved_clkdiv = read_CLKDIV(iface); iface->saved_clkdiv = read_CLKDIV(iface);
iface->saved_control = read_CONTROL(iface); iface->saved_control = read_CONTROL(iface);
@ -626,14 +590,14 @@ static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state
return 0; return 0;
} }
static int i2c_bfin_twi_resume(struct platform_device *pdev) static int i2c_bfin_twi_resume(struct device *dev)
{ {
struct bfin_twi_iface *iface = platform_get_drvdata(pdev); struct bfin_twi_iface *iface = dev_get_drvdata(dev);
int rc = request_irq(iface->irq, bfin_twi_interrupt_entry, int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
0, pdev->name, iface); 0, to_platform_device(dev)->name, iface);
if (rc) { if (rc) {
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); dev_err(dev, "Can't get IRQ %d !\n", iface->irq);
return -ENODEV; return -ENODEV;
} }
@ -646,6 +610,9 @@ static int i2c_bfin_twi_resume(struct platform_device *pdev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(i2c_bfin_twi_pm,
i2c_bfin_twi_suspend, i2c_bfin_twi_resume);
static int i2c_bfin_twi_probe(struct platform_device *pdev) static int i2c_bfin_twi_probe(struct platform_device *pdev)
{ {
struct bfin_twi_iface *iface; struct bfin_twi_iface *iface;
@ -695,7 +662,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
p_adap->timeout = 5 * HZ; p_adap->timeout = 5 * HZ;
p_adap->retries = 3; p_adap->retries = 3;
rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); rc = peripheral_request_list((unsigned short *)pdev->dev.platform_data,
"i2c-bfin-twi");
if (rc) { if (rc) {
dev_err(&pdev->dev, "Can't setup pin mux!\n"); dev_err(&pdev->dev, "Can't setup pin mux!\n");
goto out_error_pin_mux; goto out_error_pin_mux;
@ -742,7 +710,7 @@ out_error_add_adapter:
free_irq(iface->irq, iface); free_irq(iface->irq, iface);
out_error_req_irq: out_error_req_irq:
out_error_no_irq: out_error_no_irq:
peripheral_free_list(pin_req[pdev->id]); peripheral_free_list((unsigned short *)pdev->dev.platform_data);
out_error_pin_mux: out_error_pin_mux:
iounmap(iface->regs_base); iounmap(iface->regs_base);
out_error_ioremap: out_error_ioremap:
@ -760,7 +728,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
i2c_del_adapter(&(iface->adap)); i2c_del_adapter(&(iface->adap));
free_irq(iface->irq, iface); free_irq(iface->irq, iface);
peripheral_free_list(pin_req[pdev->id]); peripheral_free_list((unsigned short *)pdev->dev.platform_data);
iounmap(iface->regs_base); iounmap(iface->regs_base);
kfree(iface); kfree(iface);
@ -770,11 +738,10 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
static struct platform_driver i2c_bfin_twi_driver = { static struct platform_driver i2c_bfin_twi_driver = {
.probe = i2c_bfin_twi_probe, .probe = i2c_bfin_twi_probe,
.remove = i2c_bfin_twi_remove, .remove = i2c_bfin_twi_remove,
.suspend = i2c_bfin_twi_suspend,
.resume = i2c_bfin_twi_resume,
.driver = { .driver = {
.name = "i2c-bfin-twi", .name = "i2c-bfin-twi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &i2c_bfin_twi_pm,
}, },
}; };

View File

@ -117,10 +117,8 @@ static u16 __initdata i2c_clk_div[50][2] = {
struct imx_i2c_struct { struct imx_i2c_struct {
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct resource *res;
struct clk *clk; struct clk *clk;
void __iomem *base; void __iomem *base;
int irq;
wait_queue_head_t queue; wait_queue_head_t queue;
unsigned long i2csr; unsigned long i2csr;
unsigned int disable_delay; unsigned int disable_delay;
@ -472,9 +470,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
struct imxi2c_platform_data *pdata = pdev->dev.platform_data; struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
void __iomem *base; void __iomem *base;
resource_size_t res_size; int irq, ret;
int irq, bitrate; u32 bitrate;
int ret;
dev_dbg(&pdev->dev, "<%s>\n", __func__); dev_dbg(&pdev->dev, "<%s>\n", __func__);
@ -489,25 +486,15 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
return -ENOENT; return -ENOENT;
} }
res_size = resource_size(res); base = devm_request_and_ioremap(&pdev->dev, res);
if (!base)
if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
dev_err(&pdev->dev, "request_mem_region failed\n");
return -EBUSY; return -EBUSY;
}
base = ioremap(res->start, res_size); i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct),
if (!base) { GFP_KERNEL);
dev_err(&pdev->dev, "ioremap failed\n");
ret = -EIO;
goto fail1;
}
i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL);
if (!i2c_imx) { if (!i2c_imx) {
dev_err(&pdev->dev, "can't allocate interface\n"); dev_err(&pdev->dev, "can't allocate interface\n");
ret = -ENOMEM; return -ENOMEM;
goto fail2;
} }
/* Setup i2c_imx driver structure */ /* Setup i2c_imx driver structure */
@ -517,29 +504,27 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx->adapter.dev.parent = &pdev->dev; i2c_imx->adapter.dev.parent = &pdev->dev;
i2c_imx->adapter.nr = pdev->id; i2c_imx->adapter.nr = pdev->id;
i2c_imx->adapter.dev.of_node = pdev->dev.of_node; i2c_imx->adapter.dev.of_node = pdev->dev.of_node;
i2c_imx->irq = irq;
i2c_imx->base = base; i2c_imx->base = base;
i2c_imx->res = res;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev); pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) { if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl); dev_err(&pdev->dev, "can't get/select pinctrl\n");
goto fail3; return PTR_ERR(pinctrl);
} }
/* Get I2C clock */ /* Get I2C clock */
i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c_imx->clk)) { if (IS_ERR(i2c_imx->clk)) {
ret = PTR_ERR(i2c_imx->clk);
dev_err(&pdev->dev, "can't get I2C clock\n"); dev_err(&pdev->dev, "can't get I2C clock\n");
goto fail3; return PTR_ERR(i2c_imx->clk);
} }
/* Request IRQ */ /* Request IRQ */
ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
pdev->name, i2c_imx);
if (ret) { if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); dev_err(&pdev->dev, "can't claim irq %d\n", irq);
goto fail4; return ret;
} }
/* Init queue */ /* Init queue */
@ -564,7 +549,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_imx->adapter); ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "registration failed\n"); dev_err(&pdev->dev, "registration failed\n");
goto fail5; return ret;
} }
of_i2c_register_devices(&i2c_imx->adapter); of_i2c_register_devices(&i2c_imx->adapter);
@ -572,28 +557,16 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
/* Set up platform driver data */ /* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx); platform_set_drvdata(pdev, i2c_imx);
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",
i2c_imx->res->start, i2c_imx->res->end); res->start, res->end);
dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",
res_size, i2c_imx->res->start); resource_size(res), res->start);
dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
i2c_imx->adapter.name); i2c_imx->adapter.name);
dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
return 0; /* Return OK */ return 0; /* Return OK */
fail5:
free_irq(i2c_imx->irq, i2c_imx);
fail4:
clk_put(i2c_imx->clk);
fail3:
kfree(i2c_imx);
fail2:
iounmap(base);
fail1:
release_mem_region(res->start, resource_size(res));
return ret; /* Return error number */
} }
static int __exit i2c_imx_remove(struct platform_device *pdev) static int __exit i2c_imx_remove(struct platform_device *pdev)
@ -605,20 +578,12 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c_imx->adapter); i2c_del_adapter(&i2c_imx->adapter);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
/* free interrupt */
free_irq(i2c_imx->irq, i2c_imx);
/* setup chip registers to defaults */ /* setup chip registers to defaults */
writeb(0, i2c_imx->base + IMX_I2C_IADR); writeb(0, i2c_imx->base + IMX_I2C_IADR);
writeb(0, i2c_imx->base + IMX_I2C_IFDR); writeb(0, i2c_imx->base + IMX_I2C_IFDR);
writeb(0, i2c_imx->base + IMX_I2C_I2CR); writeb(0, i2c_imx->base + IMX_I2C_I2CR);
writeb(0, i2c_imx->base + IMX_I2C_I2SR); writeb(0, i2c_imx->base + IMX_I2C_I2SR);
clk_put(i2c_imx->clk);
iounmap(i2c_imx->base);
release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
kfree(i2c_imx);
return 0; return 0;
} }

View File

@ -18,6 +18,11 @@
#include <linux/mv643xx_i2c.h> #include <linux/mv643xx_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_i2c.h>
#include <linux/clk.h>
#include <linux/err.h>
/* Register defines */ /* Register defines */
#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00
@ -98,6 +103,9 @@ struct mv64xxx_i2c_data {
int rc; int rc;
u32 freq_m; u32 freq_m;
u32 freq_n; u32 freq_n;
#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
#endif
wait_queue_head_t waitq; wait_queue_head_t waitq;
spinlock_t lock; spinlock_t lock;
struct i2c_msg *msg; struct i2c_msg *msg;
@ -521,6 +529,82 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
drv_data->reg_base_p = 0; drv_data->reg_base_p = 0;
} }
#ifdef CONFIG_OF
static int __devinit
mv64xxx_calc_freq(const int tclk, const int n, const int m)
{
return tclk / (10 * (m + 1) * (2 << n));
}
static bool __devinit
mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
u32 *best_m)
{
int freq, delta, best_delta = INT_MAX;
int m, n;
for (n = 0; n <= 7; n++)
for (m = 0; m <= 15; m++) {
freq = mv64xxx_calc_freq(tclk, n, m);
delta = req_freq - freq;
if (delta >= 0 && delta < best_delta) {
*best_m = m;
*best_n = n;
best_delta = delta;
}
if (best_delta == 0)
return true;
}
if (best_delta == INT_MAX)
return false;
return true;
}
static int __devinit
mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
struct device_node *np)
{
u32 bus_freq, tclk;
int rc = 0;
/* CLK is mandatory when using DT to describe the i2c bus. We
* need to know tclk in order to calculate bus clock
* factors.
*/
#if !defined(CONFIG_HAVE_CLK)
/* Have OF but no CLK */
return -ENODEV;
#else
if (IS_ERR(drv_data->clk)) {
rc = -ENODEV;
goto out;
}
tclk = clk_get_rate(drv_data->clk);
of_property_read_u32(np, "clock-frequency", &bus_freq);
if (!mv64xxx_find_baud_factors(bus_freq, tclk,
&drv_data->freq_n, &drv_data->freq_m)) {
rc = -EINVAL;
goto out;
}
drv_data->irq = irq_of_parse_and_map(np, 0);
/* Its not yet defined how timeouts will be specified in device tree.
* So hard code the value to 1 second.
*/
drv_data->adapter.timeout = HZ;
out:
return rc;
#endif
}
#else /* CONFIG_OF */
static int __devinit
mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
struct device_node *np)
{
return -ENODEV;
}
#endif /* CONFIG_OF */
static int __devinit static int __devinit
mv64xxx_i2c_probe(struct platform_device *pd) mv64xxx_i2c_probe(struct platform_device *pd)
{ {
@ -528,7 +612,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data;
int rc; int rc;
if ((pd->id != 0) || !pdata) if ((!pdata && !pd->dev.of_node))
return -ENODEV; return -ENODEV;
drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
@ -546,19 +630,35 @@ mv64xxx_i2c_probe(struct platform_device *pd)
init_waitqueue_head(&drv_data->waitq); init_waitqueue_head(&drv_data->waitq);
spin_lock_init(&drv_data->lock); spin_lock_init(&drv_data->lock);
drv_data->freq_m = pdata->freq_m; #if defined(CONFIG_HAVE_CLK)
drv_data->freq_n = pdata->freq_n; /* Not all platforms have a clk */
drv_data->irq = platform_get_irq(pd, 0); drv_data->clk = clk_get(&pd->dev, NULL);
if (!IS_ERR(drv_data->clk)) {
clk_prepare(drv_data->clk);
clk_enable(drv_data->clk);
}
#endif
if (pdata) {
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
} else if (pd->dev.of_node) {
rc = mv64xxx_of_config(drv_data, pd->dev.of_node);
if (rc)
goto exit_unmap_regs;
}
if (drv_data->irq < 0) { if (drv_data->irq < 0) {
rc = -ENXIO; rc = -ENXIO;
goto exit_unmap_regs; goto exit_unmap_regs;
} }
drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE; drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
drv_data->adapter.nr = pd->id; drv_data->adapter.nr = pd->id;
drv_data->adapter.dev.of_node = pd->dev.of_node;
platform_set_drvdata(pd, drv_data); platform_set_drvdata(pd, drv_data);
i2c_set_adapdata(&drv_data->adapter, drv_data); i2c_set_adapdata(&drv_data->adapter, drv_data);
@ -577,11 +677,20 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_free_irq; goto exit_free_irq;
} }
of_i2c_register_devices(&drv_data->adapter);
return 0; return 0;
exit_free_irq: exit_free_irq:
free_irq(drv_data->irq, drv_data); free_irq(drv_data->irq, drv_data);
exit_unmap_regs: exit_unmap_regs:
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk)) {
clk_disable(drv_data->clk);
clk_unprepare(drv_data->clk);
}
#endif
mv64xxx_i2c_unmap_regs(drv_data); mv64xxx_i2c_unmap_regs(drv_data);
exit_kfree: exit_kfree:
kfree(drv_data); kfree(drv_data);
@ -597,17 +706,31 @@ mv64xxx_i2c_remove(struct platform_device *dev)
rc = i2c_del_adapter(&drv_data->adapter); rc = i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, drv_data); free_irq(drv_data->irq, drv_data);
mv64xxx_i2c_unmap_regs(drv_data); mv64xxx_i2c_unmap_regs(drv_data);
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk)) {
clk_disable(drv_data->clk);
clk_unprepare(drv_data->clk);
}
#endif
kfree(drv_data); kfree(drv_data);
return rc; return rc;
} }
static const struct of_device_id mv64xxx_i2c_of_match_table[] __devinitdata = {
{ .compatible = "marvell,mv64xxx-i2c", },
{}
};
MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
static struct platform_driver mv64xxx_i2c_driver = { static struct platform_driver mv64xxx_i2c_driver = {
.probe = mv64xxx_i2c_probe, .probe = mv64xxx_i2c_probe,
.remove = __devexit_p(mv64xxx_i2c_remove), .remove = __devexit_p(mv64xxx_i2c_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = MV64XXX_I2C_CTLR_NAME, .name = MV64XXX_I2C_CTLR_NAME,
.of_match_table = of_match_ptr(mv64xxx_i2c_of_match_table),
}, },
}; };

View File

@ -46,6 +46,10 @@
#define MXS_I2C_CTRL0_DIRECTION 0x00010000 #define MXS_I2C_CTRL0_DIRECTION 0x00010000
#define MXS_I2C_CTRL0_XFER_COUNT(v) ((v) & 0x0000FFFF) #define MXS_I2C_CTRL0_XFER_COUNT(v) ((v) & 0x0000FFFF)
#define MXS_I2C_TIMING0 (0x10)
#define MXS_I2C_TIMING1 (0x20)
#define MXS_I2C_TIMING2 (0x30)
#define MXS_I2C_CTRL1 (0x40) #define MXS_I2C_CTRL1 (0x40)
#define MXS_I2C_CTRL1_SET (0x44) #define MXS_I2C_CTRL1_SET (0x44)
#define MXS_I2C_CTRL1_CLR (0x48) #define MXS_I2C_CTRL1_CLR (0x48)
@ -97,6 +101,35 @@
#define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \ #define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
MXS_I2C_CTRL0_MASTER_MODE) MXS_I2C_CTRL0_MASTER_MODE)
struct mxs_i2c_speed_config {
uint32_t timing0;
uint32_t timing1;
uint32_t timing2;
};
/*
* Timing values for the default 24MHz clock supplied into the i2c block.
*
* The bus can operate at 95kHz or at 400kHz with the following timing
* register configurations. The 100kHz mode isn't present because it's
* values are not stated in the i.MX233/i.MX28 datasheet. The 95kHz mode
* shall be close enough replacement. Therefore when the bus is configured
* for 100kHz operation, 95kHz timing settings are actually loaded.
*
* For details, see i.MX233 [25.4.2 - 25.4.4] and i.MX28 [27.5.2 - 27.5.4].
*/
static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
.timing0 = 0x00780030,
.timing1 = 0x00800030,
.timing2 = 0x00300030,
};
static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
.timing0 = 0x000f0007,
.timing1 = 0x001f000f,
.timing2 = 0x00300030,
};
/** /**
* struct mxs_i2c_dev - per device, private MXS-I2C data * struct mxs_i2c_dev - per device, private MXS-I2C data
* *
@ -112,11 +145,17 @@ struct mxs_i2c_dev {
struct completion cmd_complete; struct completion cmd_complete;
u32 cmd_err; u32 cmd_err;
struct i2c_adapter adapter; struct i2c_adapter adapter;
const struct mxs_i2c_speed_config *speed;
}; };
static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
{ {
stmp_reset_block(i2c->regs); stmp_reset_block(i2c->regs);
writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
i2c->regs + MXS_I2C_QUEUECTRL_SET); i2c->regs + MXS_I2C_QUEUECTRL_SET);
@ -193,7 +232,7 @@ static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
{ {
u32 data; u32 uninitialized_var(data);
int i; int i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@ -319,6 +358,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
.functionality = mxs_i2c_func, .functionality = mxs_i2c_func,
}; };
static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
{
uint32_t speed;
struct device *dev = i2c->dev;
struct device_node *node = dev->of_node;
int ret;
if (!node)
return -EINVAL;
i2c->speed = &mxs_i2c_95kHz_config;
ret = of_property_read_u32(node, "clock-frequency", &speed);
if (ret)
dev_warn(dev, "No I2C speed selected, using 100kHz\n");
else if (speed == 400000)
i2c->speed = &mxs_i2c_400kHz_config;
else if (speed != 100000)
dev_warn(dev, "Unsupported I2C speed selected, using 100kHz\n");
return 0;
}
static int __devinit mxs_i2c_probe(struct platform_device *pdev) static int __devinit mxs_i2c_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -358,6 +419,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
return err; return err;
i2c->dev = dev; i2c->dev = dev;
err = mxs_i2c_get_ofdata(i2c);
if (err)
return err;
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
/* Do reset to enforce correct startup after pinmuxing */ /* Do reset to enforce correct startup after pinmuxing */

View File

@ -14,7 +14,8 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/amba/bus.h>
#include <linux/atomic.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c.h> #include <linux/i2c.h>
@ -23,8 +24,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/platform_data/i2c-nomadik.h>
#include <plat/i2c.h>
#define DRIVER_NAME "nmk-i2c" #define DRIVER_NAME "nmk-i2c"
@ -136,7 +136,7 @@ struct i2c_nmk_client {
/** /**
* struct nmk_i2c_dev - private data structure of the controller. * struct nmk_i2c_dev - private data structure of the controller.
* @pdev: parent platform device. * @adev: parent amba device.
* @adap: corresponding I2C adapter. * @adap: corresponding I2C adapter.
* @irq: interrupt line for the controller. * @irq: interrupt line for the controller.
* @virtbase: virtual io memory area. * @virtbase: virtual io memory area.
@ -150,7 +150,7 @@ struct i2c_nmk_client {
* @busy: Busy doing transfer. * @busy: Busy doing transfer.
*/ */
struct nmk_i2c_dev { struct nmk_i2c_dev {
struct platform_device *pdev; struct amba_device *adev;
struct i2c_adapter adap; struct i2c_adapter adap;
int irq; int irq;
void __iomem *virtbase; void __iomem *virtbase;
@ -217,7 +217,7 @@ static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
} }
} }
dev_err(&dev->pdev->dev, dev_err(&dev->adev->dev,
"flushing operation timed out giving up after %d attempts", "flushing operation timed out giving up after %d attempts",
LOOP_ATTEMPTS); LOOP_ATTEMPTS);
@ -276,15 +276,32 @@ exit:
/** /**
* load_i2c_mcr_reg() - load the MCR register * load_i2c_mcr_reg() - load the MCR register
* @dev: private data of controller * @dev: private data of controller
* @flags: message flags
*/ */
static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev) static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev, u16 flags)
{ {
u32 mcr = 0; u32 mcr = 0;
unsigned short slave_adr_3msb_bits;
/* 7-bit address transaction */
mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1); mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1);
if (unlikely(flags & I2C_M_TEN)) {
/* 10-bit address transaction */
mcr |= GEN_MASK(2, I2C_MCR_AM, 12);
/*
* Get the top 3 bits.
* EA10 represents extended address in MCR. This includes
* the extension (MSB bits) of the 7 bit address loaded
* in A7
*/
slave_adr_3msb_bits = (dev->cli.slave_adr >> 7) & 0x7;
mcr |= GEN_MASK(slave_adr_3msb_bits, I2C_MCR_EA10, 8);
} else {
/* 7-bit address transaction */
mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
}
/* start byte procedure not applied */ /* start byte procedure not applied */
mcr |= GEN_MASK(0, I2C_MCR_SB, 11); mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
@ -364,7 +381,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
* and high speed (up to 3.4 Mb/s) * and high speed (up to 3.4 Mb/s)
*/ */
if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
dev_err(&dev->pdev->dev, dev_err(&dev->adev->dev,
"do not support this mode defaulting to std. mode\n"); "do not support this mode defaulting to std. mode\n");
brcr2 = i2c_clk/(100000 * 2) & 0xffff; brcr2 = i2c_clk/(100000 * 2) & 0xffff;
writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
@ -381,19 +398,20 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
/** /**
* read_i2c() - Read from I2C client device * read_i2c() - Read from I2C client device
* @dev: private data of I2C Driver * @dev: private data of I2C Driver
* @flags: message flags
* *
* This function reads from i2c client device when controller is in * This function reads from i2c client device when controller is in
* master mode. There is a completion timeout. If there is no transfer * master mode. There is a completion timeout. If there is no transfer
* before timeout error is returned. * before timeout error is returned.
*/ */
static int read_i2c(struct nmk_i2c_dev *dev) static int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
{ {
u32 status = 0; u32 status = 0;
u32 mcr; u32 mcr;
u32 irq_mask = 0; u32 irq_mask = 0;
int timeout; int timeout;
mcr = load_i2c_mcr_reg(dev); mcr = load_i2c_mcr_reg(dev, flags);
writel(mcr, dev->virtbase + I2C_MCR); writel(mcr, dev->virtbase + I2C_MCR);
/* load the current CR value */ /* load the current CR value */
@ -423,7 +441,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
&dev->xfer_complete, dev->adap.timeout); &dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) { if (timeout < 0) {
dev_err(&dev->pdev->dev, dev_err(&dev->adev->dev,
"wait_for_completion_timeout " "wait_for_completion_timeout "
"returned %d waiting for event\n", timeout); "returned %d waiting for event\n", timeout);
status = timeout; status = timeout;
@ -431,7 +449,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
if (timeout == 0) { if (timeout == 0) {
/* Controller timed out */ /* Controller timed out */
dev_err(&dev->pdev->dev, "read from slave 0x%x timed out\n", dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n",
dev->cli.slave_adr); dev->cli.slave_adr);
status = -ETIMEDOUT; status = -ETIMEDOUT;
} }
@ -459,17 +477,18 @@ static void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes)
/** /**
* write_i2c() - Write data to I2C client. * write_i2c() - Write data to I2C client.
* @dev: private data of I2C Driver * @dev: private data of I2C Driver
* @flags: message flags
* *
* This function writes data to I2C client * This function writes data to I2C client
*/ */
static int write_i2c(struct nmk_i2c_dev *dev) static int write_i2c(struct nmk_i2c_dev *dev, u16 flags)
{ {
u32 status = 0; u32 status = 0;
u32 mcr; u32 mcr;
u32 irq_mask = 0; u32 irq_mask = 0;
int timeout; int timeout;
mcr = load_i2c_mcr_reg(dev); mcr = load_i2c_mcr_reg(dev, flags);
writel(mcr, dev->virtbase + I2C_MCR); writel(mcr, dev->virtbase + I2C_MCR);
@ -510,7 +529,7 @@ static int write_i2c(struct nmk_i2c_dev *dev)
&dev->xfer_complete, dev->adap.timeout); &dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) { if (timeout < 0) {
dev_err(&dev->pdev->dev, dev_err(&dev->adev->dev,
"wait_for_completion_timeout " "wait_for_completion_timeout "
"returned %d waiting for event\n", timeout); "returned %d waiting for event\n", timeout);
status = timeout; status = timeout;
@ -518,7 +537,7 @@ static int write_i2c(struct nmk_i2c_dev *dev)
if (timeout == 0) { if (timeout == 0) {
/* Controller timed out */ /* Controller timed out */
dev_err(&dev->pdev->dev, "write to slave 0x%x timed out\n", dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n",
dev->cli.slave_adr); dev->cli.slave_adr);
status = -ETIMEDOUT; status = -ETIMEDOUT;
} }
@ -538,11 +557,11 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
if (flags & I2C_M_RD) { if (flags & I2C_M_RD) {
/* read operation */ /* read operation */
dev->cli.operation = I2C_READ; dev->cli.operation = I2C_READ;
status = read_i2c(dev); status = read_i2c(dev, flags);
} else { } else {
/* write operation */ /* write operation */
dev->cli.operation = I2C_WRITE; dev->cli.operation = I2C_WRITE;
status = write_i2c(dev); status = write_i2c(dev, flags);
} }
if (status || (dev->result)) { if (status || (dev->result)) {
@ -557,7 +576,7 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
if (((i2c_sr >> 2) & 0x3) == 0x3) { if (((i2c_sr >> 2) & 0x3) == 0x3) {
/* get the abort cause */ /* get the abort cause */
cause = (i2c_sr >> 4) & 0x7; cause = (i2c_sr >> 4) & 0x7;
dev_err(&dev->pdev->dev, "%s\n", dev_err(&dev->adev->dev, "%s\n",
cause >= ARRAY_SIZE(abort_causes) ? cause >= ARRAY_SIZE(abort_causes) ?
"unknown reason" : "unknown reason" :
abort_causes[cause]); abort_causes[cause]);
@ -630,7 +649,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
if (dev->regulator) if (dev->regulator)
regulator_enable(dev->regulator); regulator_enable(dev->regulator);
pm_runtime_get_sync(&dev->pdev->dev); pm_runtime_get_sync(&dev->adev->dev);
clk_enable(dev->clk); clk_enable(dev->clk);
@ -644,13 +663,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
setup_i2c_controller(dev); setup_i2c_controller(dev);
for (i = 0; i < num_msgs; i++) { for (i = 0; i < num_msgs; i++) {
if (unlikely(msgs[i].flags & I2C_M_TEN)) {
dev_err(&dev->pdev->dev,
"10 bit addressing not supported\n");
status = -EINVAL;
goto out;
}
dev->cli.slave_adr = msgs[i].addr; dev->cli.slave_adr = msgs[i].addr;
dev->cli.buffer = msgs[i].buf; dev->cli.buffer = msgs[i].buf;
dev->cli.count = msgs[i].len; dev->cli.count = msgs[i].len;
@ -667,7 +679,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
out: out:
clk_disable(dev->clk); clk_disable(dev->clk);
pm_runtime_put_sync(&dev->pdev->dev); pm_runtime_put_sync(&dev->adev->dev);
if (dev->regulator) if (dev->regulator)
regulator_disable(dev->regulator); regulator_disable(dev->regulator);
@ -790,7 +802,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
if (dev->cli.count) { if (dev->cli.count) {
dev->result = -EIO; dev->result = -EIO;
dev_err(&dev->pdev->dev, dev_err(&dev->adev->dev,
"%lu bytes still remain to be xfered\n", "%lu bytes still remain to be xfered\n",
dev->cli.count); dev->cli.count);
(void) init_hw(dev); (void) init_hw(dev);
@ -834,7 +846,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
dev->result = -EIO; dev->result = -EIO;
(void) init_hw(dev); (void) init_hw(dev);
dev_err(&dev->pdev->dev, "Tx Fifo Over run\n"); dev_err(&dev->adev->dev, "Tx Fifo Over run\n");
complete(&dev->xfer_complete); complete(&dev->xfer_complete);
break; break;
@ -847,10 +859,10 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
case I2C_IT_RFSE: case I2C_IT_RFSE:
case I2C_IT_WTSR: case I2C_IT_WTSR:
case I2C_IT_STD: case I2C_IT_STD:
dev_err(&dev->pdev->dev, "unhandled Interrupt\n"); dev_err(&dev->adev->dev, "unhandled Interrupt\n");
break; break;
default: default:
dev_err(&dev->pdev->dev, "spurious Interrupt..\n"); dev_err(&dev->adev->dev, "spurious Interrupt..\n");
break; break;
} }
@ -861,8 +873,8 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int nmk_i2c_suspend(struct device *dev) static int nmk_i2c_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct amba_device *adev = to_amba_device(dev);
struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
if (nmk_i2c->busy) if (nmk_i2c->busy)
return -EBUSY; return -EBUSY;
@ -891,7 +903,7 @@ static const struct dev_pm_ops nmk_i2c_pm = {
static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap)
{ {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
} }
static const struct i2c_algorithm nmk_i2c_algo = { static const struct i2c_algorithm nmk_i2c_algo = {
@ -899,78 +911,69 @@ static const struct i2c_algorithm nmk_i2c_algo = {
.functionality = nmk_i2c_functionality .functionality = nmk_i2c_functionality
}; };
static int __devinit nmk_i2c_probe(struct platform_device *pdev) static atomic_t adapter_id = ATOMIC_INIT(0);
static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
{ {
int ret = 0; int ret = 0;
struct resource *res;
struct nmk_i2c_controller *pdata = struct nmk_i2c_controller *pdata =
pdev->dev.platform_data; adev->dev.platform_data;
struct nmk_i2c_dev *dev; struct nmk_i2c_dev *dev;
struct i2c_adapter *adap; struct i2c_adapter *adap;
if (!pdata) {
dev_warn(&adev->dev, "no platform data\n");
return -ENODEV;
}
dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);
if (!dev) { if (!dev) {
dev_err(&pdev->dev, "cannot allocate memory\n"); dev_err(&adev->dev, "cannot allocate memory\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_no_mem; goto err_no_mem;
} }
dev->busy = false; dev->busy = false;
dev->pdev = pdev; dev->adev = adev;
platform_set_drvdata(pdev, dev); amba_set_drvdata(adev, dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
if (!res) {
ret = -ENOENT;
goto err_no_resource;
}
if (request_mem_region(res->start, resource_size(res),
DRIVER_NAME "I/O region") == NULL) {
ret = -EBUSY;
goto err_no_region;
}
dev->virtbase = ioremap(res->start, resource_size(res));
if (!dev->virtbase) { if (!dev->virtbase) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_no_ioremap; goto err_no_ioremap;
} }
dev->irq = platform_get_irq(pdev, 0); dev->irq = adev->irq[0];
ret = request_irq(dev->irq, i2c_irq_handler, 0, ret = request_irq(dev->irq, i2c_irq_handler, 0,
DRIVER_NAME, dev); DRIVER_NAME, dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq); dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq);
goto err_irq; goto err_irq;
} }
dev->regulator = regulator_get(&pdev->dev, "v-i2c"); dev->regulator = regulator_get(&adev->dev, "v-i2c");
if (IS_ERR(dev->regulator)) { if (IS_ERR(dev->regulator)) {
dev_warn(&pdev->dev, "could not get i2c regulator\n"); dev_warn(&adev->dev, "could not get i2c regulator\n");
dev->regulator = NULL; dev->regulator = NULL;
} }
pm_suspend_ignore_children(&pdev->dev, true); pm_suspend_ignore_children(&adev->dev, true);
pm_runtime_enable(&pdev->dev);
dev->clk = clk_get(&pdev->dev, NULL); dev->clk = clk_get(&adev->dev, NULL);
if (IS_ERR(dev->clk)) { if (IS_ERR(dev->clk)) {
dev_err(&pdev->dev, "could not get i2c clock\n"); dev_err(&adev->dev, "could not get i2c clock\n");
ret = PTR_ERR(dev->clk); ret = PTR_ERR(dev->clk);
goto err_no_clk; goto err_no_clk;
} }
adap = &dev->adap; adap = &dev->adap;
adap->dev.parent = &pdev->dev; adap->dev.parent = &adev->dev;
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &nmk_i2c_algo; adap->algo = &nmk_i2c_algo;
adap->timeout = msecs_to_jiffies(pdata->timeout); adap->timeout = msecs_to_jiffies(pdata->timeout);
adap->nr = atomic_read(&adapter_id);
snprintf(adap->name, sizeof(adap->name), snprintf(adap->name, sizeof(adap->name),
"Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start); "Nomadik I2C%d at %pR", adap->nr, &adev->res);
atomic_inc(&adapter_id);
/* fetch the controller id */
adap->nr = pdev->id;
/* fetch the controller configuration from machine */ /* fetch the controller configuration from machine */
dev->cfg.clk_freq = pdata->clk_freq; dev->cfg.clk_freq = pdata->clk_freq;
@ -981,16 +984,18 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
dev_info(&pdev->dev, dev_info(&adev->dev,
"initialize %s on virtual base %p\n", "initialize %s on virtual base %p\n",
adap->name, dev->virtbase); adap->name, dev->virtbase);
ret = i2c_add_numbered_adapter(adap); ret = i2c_add_numbered_adapter(adap);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add adapter\n"); dev_err(&adev->dev, "failed to add adapter\n");
goto err_add_adap; goto err_add_adap;
} }
pm_runtime_put(&adev->dev);
return 0; return 0;
err_add_adap: err_add_adap:
@ -998,25 +1003,21 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
err_no_clk: err_no_clk:
if (dev->regulator) if (dev->regulator)
regulator_put(dev->regulator); regulator_put(dev->regulator);
pm_runtime_disable(&pdev->dev);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
err_irq: err_irq:
iounmap(dev->virtbase); iounmap(dev->virtbase);
err_no_ioremap: err_no_ioremap:
release_mem_region(res->start, resource_size(res)); amba_set_drvdata(adev, NULL);
err_no_region:
platform_set_drvdata(pdev, NULL);
err_no_resource:
kfree(dev); kfree(dev);
err_no_mem: err_no_mem:
return ret; return ret;
} }
static int __devexit nmk_i2c_remove(struct platform_device *pdev) static int nmk_i2c_remove(struct amba_device *adev)
{ {
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *res = &adev->res;
struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); struct nmk_i2c_dev *dev = amba_get_drvdata(adev);
i2c_del_adapter(&dev->adap); i2c_del_adapter(&dev->adap);
flush_i2c_fifo(dev); flush_i2c_fifo(dev);
@ -1031,31 +1032,46 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev)
clk_put(dev->clk); clk_put(dev->clk);
if (dev->regulator) if (dev->regulator)
regulator_put(dev->regulator); regulator_put(dev->regulator);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&adev->dev);
platform_set_drvdata(pdev, NULL); amba_set_drvdata(adev, NULL);
kfree(dev); kfree(dev);
return 0; return 0;
} }
static struct platform_driver nmk_i2c_driver = { static struct amba_id nmk_i2c_ids[] = {
.driver = { {
.id = 0x00180024,
.mask = 0x00ffffff,
},
{
.id = 0x00380024,
.mask = 0x00ffffff,
},
{},
};
MODULE_DEVICE_TABLE(amba, nmk_i2c_ids);
static struct amba_driver nmk_i2c_driver = {
.drv = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pm = &nmk_i2c_pm, .pm = &nmk_i2c_pm,
}, },
.id_table = nmk_i2c_ids,
.probe = nmk_i2c_probe, .probe = nmk_i2c_probe,
.remove = __devexit_p(nmk_i2c_remove), .remove = nmk_i2c_remove,
}; };
static int __init nmk_i2c_init(void) static int __init nmk_i2c_init(void)
{ {
return platform_driver_register(&nmk_i2c_driver); return amba_driver_register(&nmk_i2c_driver);
} }
static void __exit nmk_i2c_exit(void) static void __exit nmk_i2c_exit(void)
{ {
platform_driver_unregister(&nmk_i2c_driver); amba_driver_unregister(&nmk_i2c_driver);
} }
subsys_initcall(nmk_i2c_init); subsys_initcall(nmk_i2c_init);
@ -1064,4 +1080,3 @@ module_exit(nmk_i2c_exit);
MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR");
MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);

View File

@ -10,40 +10,9 @@
*/ */
/* /*
* Device tree configuration: * This driver can be used from the device tree, see
* * Documentation/devicetree/bindings/i2c/ocore-i2c.txt
* Required properties:
* - compatible : "opencores,i2c-ocores"
* - reg : bus address start and address range size of device
* - interrupts : interrupt number
* - regstep : size of device registers in bytes
* - clock-frequency : frequency of bus clock in Hz
*
* Example:
*
* i2c0: ocores@a0000000 {
* compatible = "opencores,i2c-ocores";
* reg = <0xa0000000 0x8>;
* interrupts = <10>;
*
* regstep = <1>;
* clock-frequency = <20000000>;
*
* -- Devices connected on this I2C bus get
* -- defined here; address- and size-cells
* -- apply to these child devices
*
* #address-cells = <1>;
* #size-cells = <0>;
*
* dummy@60 {
* compatible = "dummy";
* reg = <60>;
* };
* };
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
@ -56,10 +25,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_i2c.h> #include <linux/of_i2c.h>
#include <linux/log2.h>
struct ocores_i2c { struct ocores_i2c {
void __iomem *base; void __iomem *base;
int regstep; u32 reg_shift;
u32 reg_io_width;
wait_queue_head_t wait; wait_queue_head_t wait;
struct i2c_adapter adap; struct i2c_adapter adap;
struct i2c_msg *msg; struct i2c_msg *msg;
@ -102,12 +73,22 @@ struct ocores_i2c {
static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
{ {
iowrite8(value, i2c->base + reg * i2c->regstep); if (i2c->reg_io_width == 4)
iowrite32(value, i2c->base + (reg << i2c->reg_shift));
else if (i2c->reg_io_width == 2)
iowrite16(value, i2c->base + (reg << i2c->reg_shift));
else
iowrite8(value, i2c->base + (reg << i2c->reg_shift));
} }
static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
{ {
return ioread8(i2c->base + reg * i2c->regstep); if (i2c->reg_io_width == 4)
return ioread32(i2c->base + (reg << i2c->reg_shift));
else if (i2c->reg_io_width == 2)
return ioread16(i2c->base + (reg << i2c->reg_shift));
else
return ioread8(i2c->base + (reg << i2c->reg_shift));
} }
static void ocores_process(struct ocores_i2c *i2c) static void ocores_process(struct ocores_i2c *i2c)
@ -247,26 +228,35 @@ static struct i2c_adapter ocores_adapter = {
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int ocores_i2c_of_probe(struct platform_device* pdev, static int ocores_i2c_of_probe(struct platform_device *pdev,
struct ocores_i2c* i2c) struct ocores_i2c *i2c)
{ {
const __be32* val; struct device_node *np = pdev->dev.of_node;
u32 val;
val = of_get_property(pdev->dev.of_node, "regstep", NULL); if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
if (!val) { /* no 'reg-shift', check for deprecated 'regstep' */
dev_err(&pdev->dev, "Missing required parameter 'regstep'"); if (!of_property_read_u32(np, "regstep", &val)) {
return -ENODEV; if (!is_power_of_2(val)) {
dev_err(&pdev->dev, "invalid regstep %d\n",
val);
return -EINVAL;
}
i2c->reg_shift = ilog2(val);
dev_warn(&pdev->dev,
"regstep property deprecated, use reg-shift\n");
}
} }
i2c->regstep = be32_to_cpup(val);
val = of_get_property(pdev->dev.of_node, "clock-frequency", NULL); if (of_property_read_u32(np, "clock-frequency", &val)) {
if (!val) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Missing required parameter 'clock-frequency'"); "Missing required parameter 'clock-frequency'\n");
return -ENODEV; return -ENODEV;
} }
i2c->clock_khz = be32_to_cpup(val) / 1000; i2c->clock_khz = val / 1000;
of_property_read_u32(pdev->dev.of_node, "reg-io-width",
&i2c->reg_io_width);
return 0; return 0;
} }
#else #else
@ -308,7 +298,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
if (pdata) { if (pdata) {
i2c->regstep = pdata->regstep; i2c->reg_shift = pdata->reg_shift;
i2c->reg_io_width = pdata->reg_io_width;
i2c->clock_khz = pdata->clock_khz; i2c->clock_khz = pdata->clock_khz;
} else { } else {
ret = ocores_i2c_of_probe(pdev, i2c); ret = ocores_i2c_of_probe(pdev, i2c);
@ -316,6 +307,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return ret; return ret;
} }
if (i2c->reg_io_width == 0)
i2c->reg_io_width = 1; /* Set to default value */
ocores_init(i2c); ocores_init(i2c);
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
@ -351,7 +345,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __devexit ocores_i2c_remove(struct platform_device* pdev) static int __devexit ocores_i2c_remove(struct platform_device *pdev)
{ {
struct ocores_i2c *i2c = platform_get_drvdata(pdev); struct ocores_i2c *i2c = platform_get_drvdata(pdev);
@ -367,9 +361,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state) static int ocores_i2c_suspend(struct device *dev)
{ {
struct ocores_i2c *i2c = platform_get_drvdata(pdev); struct ocores_i2c *i2c = dev_get_drvdata(dev);
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* make sure the device is disabled */ /* make sure the device is disabled */
@ -378,17 +372,19 @@ static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state)
return 0; return 0;
} }
static int ocores_i2c_resume(struct platform_device *pdev) static int ocores_i2c_resume(struct device *dev)
{ {
struct ocores_i2c *i2c = platform_get_drvdata(pdev); struct ocores_i2c *i2c = dev_get_drvdata(dev);
ocores_init(i2c); ocores_init(i2c);
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
#define OCORES_I2C_PM (&ocores_i2c_pm)
#else #else
#define ocores_i2c_suspend NULL #define OCORES_I2C_PM NULL
#define ocores_i2c_resume NULL
#endif #endif
static struct of_device_id ocores_i2c_match[] = { static struct of_device_id ocores_i2c_match[] = {
@ -400,12 +396,11 @@ MODULE_DEVICE_TABLE(of, ocores_i2c_match);
static struct platform_driver ocores_i2c_driver = { static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe, .probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove), .remove = __devexit_p(ocores_i2c_remove),
.suspend = ocores_i2c_suspend,
.resume = ocores_i2c_resume,
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ocores-i2c", .name = "ocores-i2c",
.of_match_table = ocores_i2c_match, .of_match_table = ocores_i2c_match,
.pm = OCORES_I2C_PM,
}, },
}; };

View File

@ -49,8 +49,8 @@
/* I2C controller revisions present on specific hardware */ /* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_2430 0x36
#define OMAP_I2C_REV_ON_3430 0x3C #define OMAP_I2C_REV_ON_3430_3530 0x3C
#define OMAP_I2C_REV_ON_3530_4430 0x40 #define OMAP_I2C_REV_ON_3630_4430 0x40
/* timeout waiting for the controller to respond */ /* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@ -173,7 +173,7 @@ enum {
/* Errata definitions */ /* Errata definitions */
#define I2C_OMAP_ERRATA_I207 (1 << 0) #define I2C_OMAP_ERRATA_I207 (1 << 0)
#define I2C_OMAP3_1P153 (1 << 1) #define I2C_OMAP_ERRATA_I462 (1 << 1)
struct omap_i2c_dev { struct omap_i2c_dev {
struct device *dev; struct device *dev;
@ -269,47 +269,6 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
(i2c_dev->regs[reg] << i2c_dev->reg_shift)); (i2c_dev->regs[reg] << i2c_dev->reg_shift));
} }
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate);
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate);
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
}
/*
* Don't write to this register if the IE state is 0 as it can
* cause deadlock.
*/
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
}
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
else
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev < OMAP_I2C_OMAP1_REV_2) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
/* Flush posted write */
omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
}
}
static int omap_i2c_init(struct omap_i2c_dev *dev) static int omap_i2c_init(struct omap_i2c_dev *dev)
{ {
u16 psc = 0, scll = 0, sclh = 0, buf = 0; u16 psc = 0, scll = 0, sclh = 0, buf = 0;
@ -346,7 +305,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
SYSC_AUTOIDLE_MASK); SYSC_AUTOIDLE_MASK);
} else if (dev->rev >= OMAP_I2C_REV_ON_3430) { } else if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) {
dev->syscstate = SYSC_AUTOIDLE_MASK; dev->syscstate = SYSC_AUTOIDLE_MASK;
dev->syscstate |= SYSC_ENAWAKEUP_MASK; dev->syscstate |= SYSC_ENAWAKEUP_MASK;
dev->syscstate |= (SYSC_IDLEMODE_SMART << dev->syscstate |= (SYSC_IDLEMODE_SMART <<
@ -468,11 +427,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
/* Take the I2C module out of reset: */ /* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
dev->errata = 0;
if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
dev->errata |= I2C_OMAP_ERRATA_I207;
/* Enable interrupts */ /* Enable interrupts */
dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
@ -514,7 +468,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
struct i2c_msg *msg, int stop) struct i2c_msg *msg, int stop)
{ {
struct omap_i2c_dev *dev = i2c_get_adapdata(adap); struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
int r; unsigned long timeout;
u16 w; u16 w;
dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@ -536,7 +490,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR; w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w); omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
init_completion(&dev->cmd_complete); INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0; dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
@ -584,12 +538,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
* REVISIT: We should abort the transfer on signals, but the bus goes * REVISIT: We should abort the transfer on signals, but the bus goes
* into arbitration and we're currently unable to recover from it. * into arbitration and we're currently unable to recover from it.
*/ */
r = wait_for_completion_timeout(&dev->cmd_complete, timeout = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT); OMAP_I2C_TIMEOUT);
dev->buf_len = 0; dev->buf_len = 0;
if (r < 0) if (timeout == 0) {
return r;
if (r == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev); omap_i2c_init(dev);
return -ETIMEDOUT; return -ETIMEDOUT;
@ -630,7 +582,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
int i; int i;
int r; int r;
pm_runtime_get_sync(dev->dev); r = pm_runtime_get_sync(dev->dev);
if (IS_ERR_VALUE(r))
return r;
r = omap_i2c_wait_for_bb(dev); r = omap_i2c_wait_for_bb(dev);
if (r < 0) if (r < 0)
@ -767,11 +721,11 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id)
#endif #endif
/* /*
* OMAP3430 Errata 1.153: When an XRDY/XDR is hit, wait for XUDF before writing * OMAP3430 Errata i462: When an XRDY/XDR is hit, wait for XUDF before writing
* data to DATA_REG. Otherwise some data bytes can be lost while transferring * data to DATA_REG. Otherwise some data bytes can be lost while transferring
* them from the memory to the I2C interface. * them from the memory to the I2C interface.
*/ */
static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) static int errata_omap3_i462(struct omap_i2c_dev *dev, u16 *stat, int *err)
{ {
unsigned long timeout = 10000; unsigned long timeout = 10000;
@ -779,7 +733,6 @@ static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err)
if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY | omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
OMAP_I2C_STAT_XDR)); OMAP_I2C_STAT_XDR));
*err |= OMAP_I2C_STAT_XUDF;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -792,6 +745,7 @@ static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err)
return 0; return 0;
} }
*err |= OMAP_I2C_STAT_XUDF;
return 0; return 0;
} }
@ -930,8 +884,8 @@ complete:
break; break;
} }
if ((dev->errata & I2C_OMAP3_1P153) && if ((dev->errata & I2C_OMAP_ERRATA_I462) &&
errata_omap3_1p153(dev, &stat, &err)) errata_omap3_i462(dev, &stat, &err))
goto complete; goto complete;
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
@ -1048,6 +1002,7 @@ omap_i2c_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
init_completion(&dev->cmd_complete);
dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
@ -1057,12 +1012,19 @@ omap_i2c_probe(struct platform_device *pdev)
dev->regs = (u8 *)reg_map_ip_v1; dev->regs = (u8 *)reg_map_ip_v1;
pm_runtime_enable(dev->dev); pm_runtime_enable(dev->dev);
pm_runtime_get_sync(dev->dev); r = pm_runtime_get_sync(dev->dev);
if (IS_ERR_VALUE(r))
goto err_free_mem;
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
if (dev->rev <= OMAP_I2C_REV_ON_3430) dev->errata = 0;
dev->errata |= I2C_OMAP3_1P153;
if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
dev->errata |= I2C_OMAP_ERRATA_I207;
if (dev->rev <= OMAP_I2C_REV_ON_3430_3530)
dev->errata |= I2C_OMAP_ERRATA_I462;
if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) { if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) {
u16 s; u16 s;
@ -1079,7 +1041,7 @@ omap_i2c_probe(struct platform_device *pdev)
dev->fifo_size = (dev->fifo_size / 2); dev->fifo_size = (dev->fifo_size / 2);
if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) if (dev->rev >= OMAP_I2C_REV_ON_3630_4430)
dev->b_hw = 0; /* Disable hardware fixes */ dev->b_hw = 0; /* Disable hardware fixes */
else else
dev->b_hw = 1; /* Enable hardware fixes */ dev->b_hw = 1; /* Enable hardware fixes */
@ -1095,7 +1057,7 @@ omap_i2c_probe(struct platform_device *pdev)
isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr : isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
omap_i2c_isr; omap_i2c_isr;
r = request_irq(dev->irq, isr, 0, pdev->name, dev); r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
if (r) { if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
@ -1105,8 +1067,6 @@ omap_i2c_probe(struct platform_device *pdev)
dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id, dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
pm_runtime_put(dev->dev);
adap = &dev->adapter; adap = &dev->adapter;
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
@ -1126,6 +1086,8 @@ omap_i2c_probe(struct platform_device *pdev)
of_i2c_register_devices(adap); of_i2c_register_devices(adap);
pm_runtime_put(dev->dev);
return 0; return 0;
err_free_irq: err_free_irq:
@ -1134,6 +1096,7 @@ err_unuse_clocks:
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
pm_runtime_put(dev->dev); pm_runtime_put(dev->dev);
iounmap(dev->base); iounmap(dev->base);
pm_runtime_disable(&pdev->dev);
err_free_mem: err_free_mem:
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(dev); kfree(dev);
@ -1143,17 +1106,23 @@ err_release_region:
return r; return r;
} }
static int static int __devexit omap_i2c_remove(struct platform_device *pdev)
omap_i2c_remove(struct platform_device *pdev)
{ {
struct omap_i2c_dev *dev = platform_get_drvdata(pdev); struct omap_i2c_dev *dev = platform_get_drvdata(pdev);
struct resource *mem; struct resource *mem;
int ret;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
i2c_del_adapter(&dev->adapter); i2c_del_adapter(&dev->adapter);
ret = pm_runtime_get_sync(&pdev->dev);
if (IS_ERR_VALUE(ret))
return ret;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
iounmap(dev->base); iounmap(dev->base);
kfree(dev); kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -1161,13 +1130,26 @@ omap_i2c_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
static int omap_i2c_runtime_suspend(struct device *dev) static int omap_i2c_runtime_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
u16 iv;
omap_i2c_idle(_dev); _dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0);
if (_dev->rev < OMAP_I2C_OMAP1_REV_2) {
iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate);
/* Flush posted write */
omap_i2c_read_reg(_dev, OMAP_I2C_STAT_REG);
}
return 0; return 0;
} }
@ -1177,23 +1159,40 @@ static int omap_i2c_runtime_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
omap_i2c_unidle(_dev); if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0);
omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate);
omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate);
omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate);
omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
}
/*
* Don't write to this register if the IE state is 0 as it can
* cause deadlock.
*/
if (_dev->iestate)
omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate);
return 0; return 0;
} }
#endif /* CONFIG_PM_RUNTIME */
static struct dev_pm_ops omap_i2c_pm_ops = { static struct dev_pm_ops omap_i2c_pm_ops = {
.runtime_suspend = omap_i2c_runtime_suspend, SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
.runtime_resume = omap_i2c_runtime_resume, omap_i2c_runtime_resume, NULL)
}; };
#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) #define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
#else #else
#define OMAP_I2C_PM_OPS NULL #define OMAP_I2C_PM_OPS NULL
#endif #endif /* CONFIG_PM */
static struct platform_driver omap_i2c_driver = { static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe, .probe = omap_i2c_probe,
.remove = omap_i2c_remove, .remove = __devexit_p(omap_i2c_remove),
.driver = { .driver = {
.name = "omap_i2c", .name = "omap_i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -587,25 +587,27 @@ static struct i2c_algorithm pnx_algorithm = {
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int i2c_pnx_controller_suspend(struct platform_device *pdev, static int i2c_pnx_controller_suspend(struct device *dev)
pm_message_t state)
{ {
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
clk_disable(alg_data->clk); clk_disable(alg_data->clk);
return 0; return 0;
} }
static int i2c_pnx_controller_resume(struct platform_device *pdev) static int i2c_pnx_controller_resume(struct device *dev)
{ {
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
return clk_enable(alg_data->clk); return clk_enable(alg_data->clk);
} }
static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
i2c_pnx_controller_suspend, i2c_pnx_controller_resume);
#define PNX_I2C_PM (&i2c_pnx_pm)
#else #else
#define i2c_pnx_controller_suspend NULL #define PNX_I2C_PM NULL
#define i2c_pnx_controller_resume NULL
#endif #endif
static int __devinit i2c_pnx_probe(struct platform_device *pdev) static int __devinit i2c_pnx_probe(struct platform_device *pdev)
@ -783,11 +785,10 @@ static struct platform_driver i2c_pnx_driver = {
.name = "pnx-i2c", .name = "pnx-i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(i2c_pnx_of_match), .of_match_table = of_match_ptr(i2c_pnx_of_match),
.pm = PNX_I2C_PM,
}, },
.probe = i2c_pnx_probe, .probe = i2c_pnx_probe,
.remove = __devexit_p(i2c_pnx_remove), .remove = __devexit_p(i2c_pnx_remove),
.suspend = i2c_pnx_controller_suspend,
.resume = i2c_pnx_controller_resume,
}; };
static int __init i2c_adap_pnx_init(void) static int __init i2c_adap_pnx_init(void)

View File

@ -254,7 +254,7 @@ static int __devexit puv3_i2c_remove(struct platform_device *pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state) static int puv3_i2c_suspend(struct device *dev)
{ {
int poll_count; int poll_count;
/* Disable the IIC */ /* Disable the IIC */
@ -267,23 +267,20 @@ static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state)
return 0; return 0;
} }
static int puv3_i2c_resume(struct platform_device *dev) static SIMPLE_DEV_PM_OPS(puv3_i2c_pm, puv3_i2c_suspend, NULL);
{ #define PUV3_I2C_PM (&puv3_i2c_pm)
return 0 ;
}
#else #else
#define puv3_i2c_suspend NULL #define PUV3_I2C_PM NULL
#define puv3_i2c_resume NULL
#endif #endif
static struct platform_driver puv3_i2c_driver = { static struct platform_driver puv3_i2c_driver = {
.probe = puv3_i2c_probe, .probe = puv3_i2c_probe,
.remove = __devexit_p(puv3_i2c_remove), .remove = __devexit_p(puv3_i2c_remove),
.suspend = puv3_i2c_suspend,
.resume = puv3_i2c_resume,
.driver = { .driver = {
.name = "PKUnity-v3-I2C", .name = "PKUnity-v3-I2C",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = PUV3_I2C_PM,
} }
}; };

View File

@ -122,7 +122,7 @@ static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pde
{ {
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(&s3c24xx_i2c_match, pdev->dev.of_node); match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
return (unsigned int)match->data; return (unsigned int)match->data;
} }
@ -609,7 +609,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
if (ret != -EAGAIN) { if (ret != -EAGAIN) {
clk_disable(i2c->clk); clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev); pm_runtime_put(&adap->dev);
return ret; return ret;
} }
@ -619,7 +619,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
} }
clk_disable(i2c->clk); clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev); pm_runtime_put(&adap->dev);
return -EREMOTEIO; return -EREMOTEIO;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2007-2009 ST-Ericsson AB * Copyright (C) 2007-2012 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2 * License terms: GNU General Public License (GPL) version 2
* ST DDC I2C master mode driver, used in e.g. U300 series platforms. * ST DDC I2C master mode driver, used in e.g. U300 series platforms.
* Author: Linus Walleij <linus.walleij@stericsson.com> * Author: Linus Walleij <linus.walleij@stericsson.com>
@ -139,8 +139,6 @@ module_param(scl_frequency, uint, 0644);
* struct stu300_dev - the stu300 driver state holder * struct stu300_dev - the stu300 driver state holder
* @pdev: parent platform device * @pdev: parent platform device
* @adapter: corresponding I2C adapter * @adapter: corresponding I2C adapter
* @phybase: location of I/O area in memory
* @physize: size of I/O area in memory
* @clk: hardware block clock * @clk: hardware block clock
* @irq: assigned interrupt line * @irq: assigned interrupt line
* @cmd_issue_lock: this locks the following cmd_ variables * @cmd_issue_lock: this locks the following cmd_ variables
@ -155,8 +153,6 @@ module_param(scl_frequency, uint, 0644);
struct stu300_dev { struct stu300_dev {
struct platform_device *pdev; struct platform_device *pdev;
struct i2c_adapter adapter; struct i2c_adapter adapter;
resource_size_t phybase;
resource_size_t physize;
void __iomem *virtbase; void __iomem *virtbase;
struct clk *clk; struct clk *clk;
int irq; int irq;
@ -873,64 +869,44 @@ stu300_probe(struct platform_device *pdev)
int ret = 0; int ret = 0;
char clk_name[] = "I2C0"; char clk_name[] = "I2C0";
dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL);
if (!dev) { if (!dev) {
dev_err(&pdev->dev, "could not allocate device struct\n"); dev_err(&pdev->dev, "could not allocate device struct\n");
ret = -ENOMEM; return -ENOMEM;
goto err_no_devmem;
} }
bus_nr = pdev->id; bus_nr = pdev->id;
clk_name[3] += (char)bus_nr; clk_name[3] += (char)bus_nr;
dev->clk = clk_get(&pdev->dev, clk_name); dev->clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(dev->clk)) { if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
dev_err(&pdev->dev, "could not retrieve i2c bus clock\n"); dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
goto err_no_clk; return PTR_ERR(dev->clk);
} }
dev->pdev = pdev; dev->pdev = pdev;
platform_set_drvdata(pdev, dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res)
ret = -ENOENT; return -ENOENT;
goto err_no_resource;
}
dev->phybase = res->start; dev->virtbase = devm_request_and_ioremap(&pdev->dev, res);
dev->physize = resource_size(res);
if (request_mem_region(dev->phybase, dev->physize,
NAME " I/O Area") == NULL) {
ret = -EBUSY;
goto err_no_ioregion;
}
dev->virtbase = ioremap(dev->phybase, dev->physize);
dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
"base %p\n", bus_nr, dev->virtbase); "base %p\n", bus_nr, dev->virtbase);
if (!dev->virtbase) { if (!dev->virtbase)
ret = -ENOMEM; return -ENOMEM;
goto err_no_ioremap;
}
dev->irq = platform_get_irq(pdev, 0); dev->irq = platform_get_irq(pdev, 0);
if (request_irq(dev->irq, stu300_irh, 0, ret = devm_request_irq(&pdev->dev, dev->irq, stu300_irh, 0, NAME, dev);
NAME, dev)) { if (ret < 0)
ret = -EIO; return ret;
goto err_no_irq;
}
dev->speed = scl_frequency; dev->speed = scl_frequency;
clk_enable(dev->clk); clk_prepare_enable(dev->clk);
ret = stu300_init_hw(dev); ret = stu300_init_hw(dev);
clk_disable(dev->clk); clk_disable(dev->clk);
if (ret != 0) { if (ret != 0) {
dev_err(&dev->pdev->dev, "error initializing hardware.\n"); dev_err(&dev->pdev->dev, "error initializing hardware.\n");
goto err_init_hw; return -EIO;
} }
/* IRQ event handling initialization */ /* IRQ event handling initialization */
@ -952,57 +928,43 @@ stu300_probe(struct platform_device *pdev)
/* i2c device drivers may be active on return from add_adapter() */ /* i2c device drivers may be active on return from add_adapter() */
ret = i2c_add_numbered_adapter(adap); ret = i2c_add_numbered_adapter(adap);
if (ret) { if (ret) {
dev_err(&dev->pdev->dev, "failure adding ST Micro DDC " dev_err(&pdev->dev, "failure adding ST Micro DDC "
"I2C adapter\n"); "I2C adapter\n");
goto err_add_adapter; return ret;
} }
return 0;
err_add_adapter: platform_set_drvdata(pdev, dev);
err_init_hw: return 0;
free_irq(dev->irq, dev);
err_no_irq:
iounmap(dev->virtbase);
err_no_ioremap:
release_mem_region(dev->phybase, dev->physize);
err_no_ioregion:
platform_set_drvdata(pdev, NULL);
err_no_resource:
clk_put(dev->clk);
err_no_clk:
kfree(dev);
err_no_devmem:
dev_err(&pdev->dev, "failed to add " NAME " adapter: %d\n",
pdev->id);
return ret;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int stu300_suspend(struct platform_device *pdev, pm_message_t state) static int stu300_suspend(struct device *device)
{ {
struct stu300_dev *dev = platform_get_drvdata(pdev); struct stu300_dev *dev = dev_get_drvdata(device);
/* Turn off everything */ /* Turn off everything */
stu300_wr8(0x00, dev->virtbase + I2C_CR); stu300_wr8(0x00, dev->virtbase + I2C_CR);
return 0; return 0;
} }
static int stu300_resume(struct platform_device *pdev) static int stu300_resume(struct device *device)
{ {
int ret = 0; int ret = 0;
struct stu300_dev *dev = platform_get_drvdata(pdev); struct stu300_dev *dev = dev_get_drvdata(device);
clk_enable(dev->clk); clk_enable(dev->clk);
ret = stu300_init_hw(dev); ret = stu300_init_hw(dev);
clk_disable(dev->clk); clk_disable(dev->clk);
if (ret != 0) if (ret != 0)
dev_err(&pdev->dev, "error re-initializing hardware.\n"); dev_err(device, "error re-initializing hardware.\n");
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(stu300_pm, stu300_suspend, stu300_resume);
#define STU300_I2C_PM (&stu300_pm)
#else #else
#define stu300_suspend NULL #define STU300_I2C_PM NULL
#define stu300_resume NULL
#endif #endif
static int __exit static int __exit
@ -1013,12 +975,7 @@ stu300_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter); i2c_del_adapter(&dev->adapter);
/* Turn off everything */ /* Turn off everything */
stu300_wr8(0x00, dev->virtbase + I2C_CR); stu300_wr8(0x00, dev->virtbase + I2C_CR);
free_irq(dev->irq, dev);
iounmap(dev->virtbase);
release_mem_region(dev->phybase, dev->physize);
clk_put(dev->clk);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(dev);
return 0; return 0;
} }
@ -1026,10 +983,9 @@ static struct platform_driver stu300_i2c_driver = {
.driver = { .driver = {
.name = NAME, .name = NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = STU300_I2C_PM,
}, },
.remove = __exit_p(stu300_remove), .remove = __exit_p(stu300_remove),
.suspend = stu300_suspend,
.resume = stu300_resume,
}; };

View File

@ -97,8 +97,21 @@
#define I2C_HEADER_10BIT_ADDR (1<<18) #define I2C_HEADER_10BIT_ADDR (1<<18)
#define I2C_HEADER_IE_ENABLE (1<<17) #define I2C_HEADER_IE_ENABLE (1<<17)
#define I2C_HEADER_REPEAT_START (1<<16) #define I2C_HEADER_REPEAT_START (1<<16)
#define I2C_HEADER_CONTINUE_XFER (1<<15)
#define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_MASTER_ADDR_SHIFT 12
#define I2C_HEADER_SLAVE_ADDR_SHIFT 1 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1
/*
* msg_end_type: The bus control which need to be send at end of transfer.
* @MSG_END_STOP: Send stop pulse at end of transfer.
* @MSG_END_REPEAT_START: Send repeat start at end of transfer.
* @MSG_END_CONTINUE: The following on message is coming and so do not send
* stop or repeat start.
*/
enum msg_end_type {
MSG_END_STOP,
MSG_END_REPEAT_START,
MSG_END_CONTINUE,
};
/** /**
* struct tegra_i2c_dev - per device i2c context * struct tegra_i2c_dev - per device i2c context
@ -106,7 +119,6 @@
* @adapter: core i2c layer adapter information * @adapter: core i2c layer adapter information
* @clk: clock reference for i2c controller * @clk: clock reference for i2c controller
* @i2c_clk: clock reference for i2c bus * @i2c_clk: clock reference for i2c bus
* @iomem: memory resource for registers
* @base: ioremapped registers cookie * @base: ioremapped registers cookie
* @cont_id: i2c controller id, used for for packet header * @cont_id: i2c controller id, used for for packet header
* @irq: irq number of transfer complete interrupt * @irq: irq number of transfer complete interrupt
@ -124,7 +136,6 @@ struct tegra_i2c_dev {
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct clk *clk; struct clk *clk;
struct clk *i2c_clk; struct clk *i2c_clk;
struct resource *iomem;
void __iomem *base; void __iomem *base;
int cont_id; int cont_id;
int irq; int irq;
@ -165,6 +176,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long reg) unsigned long reg)
{ {
writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
/* Read back register to make sure that register writes completed */
if (reg != I2C_TX_FIFO)
readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
} }
static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
@ -449,7 +464,7 @@ err:
} }
static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg, int stop) struct i2c_msg *msg, enum msg_end_type end_state)
{ {
u32 packet_header; u32 packet_header;
u32 int_mask; u32 int_mask;
@ -476,7 +491,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = I2C_HEADER_IE_ENABLE; packet_header = I2C_HEADER_IE_ENABLE;
if (!stop) if (end_state == MSG_END_CONTINUE)
packet_header |= I2C_HEADER_CONTINUE_XFER;
else if (end_state == MSG_END_REPEAT_START)
packet_header |= I2C_HEADER_REPEAT_START; packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN) { if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr; packet_header |= msg->addr;
@ -548,8 +565,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
clk_prepare_enable(i2c_dev->clk); clk_prepare_enable(i2c_dev->clk);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
int stop = (i == (num - 1)) ? 1 : 0; enum msg_end_type end_type = MSG_END_STOP;
ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop); if (i < (num - 1)) {
if (msgs[i + 1].flags & I2C_M_NOSTART)
end_type = MSG_END_CONTINUE;
else
end_type = MSG_END_REPEAT_START;
}
ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], end_type);
if (ret) if (ret)
break; break;
} }
@ -559,7 +582,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
static u32 tegra_i2c_func(struct i2c_adapter *adap) static u32 tegra_i2c_func(struct i2c_adapter *adap)
{ {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART;
} }
static const struct i2c_algorithm tegra_i2c_algo = { static const struct i2c_algorithm tegra_i2c_algo = {
@ -572,7 +596,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_dev *i2c_dev;
struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
struct resource *res; struct resource *res;
struct resource *iomem;
struct clk *clk; struct clk *clk;
struct clk *i2c_clk; struct clk *i2c_clk;
const unsigned int *prop; const unsigned int *prop;
@ -585,50 +608,41 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no mem resource\n"); dev_err(&pdev->dev, "no mem resource\n");
return -EINVAL; return -EINVAL;
} }
iomem = request_mem_region(res->start, resource_size(res), pdev->name);
if (!iomem) {
dev_err(&pdev->dev, "I2C region already claimed\n");
return -EBUSY;
}
base = ioremap(iomem->start, resource_size(iomem)); base = devm_request_and_ioremap(&pdev->dev, res);
if (!base) { if (!base) {
dev_err(&pdev->dev, "Cannot ioremap I2C region\n"); dev_err(&pdev->dev, "Cannot request/ioremap I2C registers\n");
return -ENOMEM; return -EADDRNOTAVAIL;
} }
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "no irq resource\n"); dev_err(&pdev->dev, "no irq resource\n");
ret = -EINVAL; return -EINVAL;
goto err_iounmap;
} }
irq = res->start; irq = res->start;
clk = clk_get(&pdev->dev, NULL); clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "missing controller clock"); dev_err(&pdev->dev, "missing controller clock");
ret = PTR_ERR(clk); return PTR_ERR(clk);
goto err_release_region;
} }
i2c_clk = clk_get(&pdev->dev, "i2c"); i2c_clk = devm_clk_get(&pdev->dev, "i2c");
if (IS_ERR(i2c_clk)) { if (IS_ERR(i2c_clk)) {
dev_err(&pdev->dev, "missing bus clock"); dev_err(&pdev->dev, "missing bus clock");
ret = PTR_ERR(i2c_clk); return PTR_ERR(i2c_clk);
goto err_clk_put;
} }
i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev) { if (!i2c_dev) {
ret = -ENOMEM; dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev");
goto err_i2c_clk_put; return -ENOMEM;
} }
i2c_dev->base = base; i2c_dev->base = base;
i2c_dev->clk = clk; i2c_dev->clk = clk;
i2c_dev->i2c_clk = i2c_clk; i2c_dev->i2c_clk = i2c_clk;
i2c_dev->iomem = iomem;
i2c_dev->adapter.algo = &tegra_i2c_algo; i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->irq = irq; i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id; i2c_dev->cont_id = pdev->id;
@ -657,13 +671,14 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
ret = tegra_i2c_init(i2c_dev); ret = tegra_i2c_init(i2c_dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller"); dev_err(&pdev->dev, "Failed to initialize i2c controller");
goto err_free; return ret;
} }
ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev); ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
tegra_i2c_isr, 0, pdev->name, i2c_dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
goto err_free; return ret;
} }
clk_prepare_enable(i2c_dev->i2c_clk); clk_prepare_enable(i2c_dev->i2c_clk);
@ -681,45 +696,26 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_dev->adapter); ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n"); dev_err(&pdev->dev, "Failed to add I2C adapter\n");
goto err_free_irq; clk_disable_unprepare(i2c_dev->i2c_clk);
return ret;
} }
of_i2c_register_devices(&i2c_dev->adapter); of_i2c_register_devices(&i2c_dev->adapter);
return 0; return 0;
err_free_irq:
free_irq(i2c_dev->irq, i2c_dev);
err_free:
kfree(i2c_dev);
err_i2c_clk_put:
clk_put(i2c_clk);
err_clk_put:
clk_put(clk);
err_release_region:
release_mem_region(iomem->start, resource_size(iomem));
err_iounmap:
iounmap(base);
return ret;
} }
static int __devexit tegra_i2c_remove(struct platform_device *pdev) static int __devexit tegra_i2c_remove(struct platform_device *pdev)
{ {
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adapter); i2c_del_adapter(&i2c_dev->adapter);
free_irq(i2c_dev->irq, i2c_dev);
clk_put(i2c_dev->i2c_clk);
clk_put(i2c_dev->clk);
release_mem_region(i2c_dev->iomem->start,
resource_size(i2c_dev->iomem));
iounmap(i2c_dev->base);
kfree(i2c_dev);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state) static int tegra_i2c_suspend(struct device *dev)
{ {
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
i2c_lock_adapter(&i2c_dev->adapter); i2c_lock_adapter(&i2c_dev->adapter);
i2c_dev->is_suspended = true; i2c_dev->is_suspended = true;
@ -728,9 +724,9 @@ static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state)
return 0; return 0;
} }
static int tegra_i2c_resume(struct platform_device *pdev) static int tegra_i2c_resume(struct device *dev)
{ {
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int ret; int ret;
i2c_lock_adapter(&i2c_dev->adapter); i2c_lock_adapter(&i2c_dev->adapter);
@ -748,6 +744,11 @@ static int tegra_i2c_resume(struct platform_device *pdev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
#define TEGRA_I2C_PM (&tegra_i2c_pm)
#else
#define TEGRA_I2C_PM NULL
#endif #endif
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
@ -758,21 +759,16 @@ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
{}, {},
}; };
MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
#else
#define tegra_i2c_of_match NULL
#endif #endif
static struct platform_driver tegra_i2c_driver = { static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe, .probe = tegra_i2c_probe,
.remove = __devexit_p(tegra_i2c_remove), .remove = __devexit_p(tegra_i2c_remove),
#ifdef CONFIG_PM
.suspend = tegra_i2c_suspend,
.resume = tegra_i2c_resume,
#endif
.driver = { .driver = {
.name = "tegra-i2c", .name = "tegra-i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = tegra_i2c_of_match, .of_match_table = of_match_ptr(tegra_i2c_of_match),
.pm = TEGRA_I2C_PM,
}, },
}; };

View File

@ -83,7 +83,7 @@ timberdale_xiic_platform_data = {
static __devinitdata struct ocores_i2c_platform_data static __devinitdata struct ocores_i2c_platform_data
timberdale_ocores_platform_data = { timberdale_ocores_platform_data = {
.regstep = 4, .reg_shift = 2,
.clock_khz = 62500, .clock_khz = 62500,
.devices = timberdale_i2c_board_info, .devices = timberdale_i2c_board_info,
.num_devices = ARRAY_SIZE(timberdale_i2c_board_info) .num_devices = ARRAY_SIZE(timberdale_i2c_board_info)

View File

@ -12,7 +12,8 @@
#define _LINUX_I2C_OCORES_H #define _LINUX_I2C_OCORES_H
struct ocores_i2c_platform_data { struct ocores_i2c_platform_data {
u32 regstep; /* distance between registers */ u32 reg_shift; /* register offset shift value */
u32 reg_io_width; /* register io read/write width */
u32 clock_khz; /* input clock in kHz */ u32 clock_khz; /* input clock in kHz */
u8 num_devices; /* number of devices in the devices list */ u8 num_devices; /* number of devices in the devices list */
struct i2c_board_info const *devices; /* devices connected to the bus */ struct i2c_board_info const *devices; /* devices connected to the bus */

View File

@ -5,8 +5,8 @@
* it under the terms of the GNU General Public License version 2, as * it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef __PLAT_I2C_H #ifndef __PDATA_I2C_NOMADIK_H
#define __PLAT_I2C_H #define __PDATA_I2C_NOMADIK_H
enum i2c_freq_mode { enum i2c_freq_mode {
I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */
@ -36,4 +36,4 @@ struct nmk_i2c_controller {
enum i2c_freq_mode sm; enum i2c_freq_mode sm;
}; };
#endif /* __PLAT_I2C_H */ #endif /* __PDATA_I2C_NOMADIK_H */