Merge commit 'a849088aa1' from rmk/fixes into cleanup/io-pci

As Stephen Rothwell reports, a849088aa1 ("ARM: Fix ioremap() of
address zero") from the arm-current tree and commit c279443709 ("ARM:
Add fixed PCI i/o mapping") from the arm-soc tree conflict in
a nontrivial way in arch/arm/mm/mmu.c.

Rob Herring explains:
The PCI i/o reserved area has a dummy physical address of 0 and
needs to be skipped by ioremap searches. So we don't set
VM_ARM_STATIC_MAPPING to prevent matches by ioremap. The vm_struct
settings don't really matter when we do the real mapping of the
i/o space.

Since commit a849088aa1 is at the start of the fixes branch
in the arm tree, we can merge it into the branch that contains
the other ioremap changes.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Arnd Bergmann
2012-09-04 15:01:37 +02:00
7952 changed files with 469936 additions and 201262 deletions

View File

@@ -133,7 +133,7 @@ config I2C_PIIX4
ATI IXP300
ATI IXP400
ATI SB600
ATI SB700
ATI SB700/SP5100
ATI SB800
AMD Hudson-2
Serverworks OSB4
@@ -143,6 +143,10 @@ config I2C_PIIX4
Serverworks HT-1100
SMSC Victory66
Some AMD chipsets contain two PIIX4-compatible SMBus
controllers. This driver will attempt to use both controllers
on the SB700/SP5100, if they have been initialized by the BIOS.
This driver can also be built as a module. If so, the module
will be called i2c-piix4.
@@ -458,7 +462,7 @@ config I2C_MPC
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller"
depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
depends on (MV64X60 || PLAT_ORION)
help
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.
@@ -479,10 +483,11 @@ config I2C_MXS
config I2C_NOMADIK
tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
depends on PLAT_NOMADIK
depends on ARM_AMBA
help
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
tristate "NUC900 I2C Driver"

View File

@@ -531,15 +531,7 @@ static struct pci_driver ali1535_driver = {
.remove = __devexit_p(ali1535_remove),
};
static int __init i2c_ali1535_init(void)
{
return pci_register_driver(&ali1535_driver);
}
static void __exit i2c_ali1535_exit(void)
{
pci_unregister_driver(&ali1535_driver);
}
module_pci_driver(ali1535_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
@@ -547,6 +539,3 @@ MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"and Dan Eaton <dan.eaton@rocketlogix.com>");
MODULE_DESCRIPTION("ALI1535 SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_ali1535_init);
module_exit(i2c_ali1535_exit);

View File

@@ -431,18 +431,6 @@ static struct pci_driver ali1563_pci_driver = {
.remove = __devexit_p(ali1563_remove),
};
static int __init ali1563_init(void)
{
return pci_register_driver(&ali1563_pci_driver);
}
module_init(ali1563_init);
static void __exit ali1563_exit(void)
{
pci_unregister_driver(&ali1563_pci_driver);
}
module_exit(ali1563_exit);
module_pci_driver(ali1563_pci_driver);
MODULE_LICENSE("GPL");

View File

@@ -513,21 +513,10 @@ static struct pci_driver ali15x3_driver = {
.remove = __devexit_p(ali15x3_remove),
};
static int __init i2c_ali15x3_init(void)
{
return pci_register_driver(&ali15x3_driver);
}
static void __exit i2c_ali15x3_exit(void)
{
pci_unregister_driver(&ali15x3_driver);
}
module_pci_driver(ali15x3_driver);
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
"and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("ALI15X3 SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_ali15x3_init);
module_exit(i2c_ali15x3_exit);

View File

@@ -410,21 +410,10 @@ static struct pci_driver amd756_driver = {
.remove = __devexit_p(amd756_remove),
};
static int __init amd756_init(void)
{
return pci_register_driver(&amd756_driver);
}
static void __exit amd756_exit(void)
{
pci_unregister_driver(&amd756_driver);
}
module_pci_driver(amd756_driver);
MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(amd756_smbus);
module_init(amd756_init)
module_exit(amd756_exit)

View File

@@ -491,15 +491,4 @@ static struct pci_driver amd8111_driver = {
.remove = __devexit_p(amd8111_remove),
};
static int __init i2c_amd8111_init(void)
{
return pci_register_driver(&amd8111_driver);
}
static void __exit i2c_amd8111_exit(void)
{
pci_unregister_driver(&amd8111_driver);
}
module_init(i2c_amd8111_init);
module_exit(i2c_amd8111_exit);
module_pci_driver(amd8111_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... */
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);
return 0;
}
static int at91_i2c_resume(struct platform_device *pdev)
static int at91_i2c_resume(struct device *dev)
{
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
#define at91_i2c_suspend NULL
#define at91_i2c_resume NULL
#define AT91_I2C_PM NULL
#endif
static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe,
.remove = __devexit_p(at91_i2c_remove),
.suspend = at91_i2c_suspend,
.resume = at91_i2c_resume,
.driver = {
.name = "at91_i2c",
.owner = THIS_MODULE,
.pm = AT91_I2C_PM,
},
};

View File

@@ -25,6 +25,7 @@
#include <asm/blackfin.h>
#include <asm/portmux.h>
#include <asm/irq.h>
#include <asm/bfin_twi.h>
/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 1
@@ -32,56 +33,6 @@
#define TWI_I2C_MODE_COMBINED 3
#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,
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)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | MDIR | RSTART);
read_MASTER_CTL(iface) | MDIR);
else if (iface->manual_stop)
write_MASTER_CTL(iface,
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) {
if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART | MDIR);
read_MASTER_CTL(iface) | MDIR);
else
write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
read_MASTER_CTL(iface) & ~MDIR);
}
}
if (twi_int_status & RCVSERV) {
@@ -130,17 +81,25 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
}
iface->transPtr++;
iface->readNum--;
} else if (iface->manual_stop) {
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | STOP);
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg + 1 < iface->msg_num) {
if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
}
if (iface->readNum == 0) {
if (iface->manual_stop) {
/* Temporary workaround to avoid possible bus stall -
* Flush FIFO before issuing the STOP condition
*/
read_RCV_DATA16(iface);
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART | MDIR);
else
write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
read_MASTER_CTL(iface) | STOP);
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg + 1 < iface->msg_num) {
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) {
@@ -193,7 +152,8 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
return;
}
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_COMBINED)) {
iface->result = -1;
@@ -221,7 +181,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
} 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->transPtr = iface->pmsg[iface->cur_msg].buf;
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)
write_MASTER_CTL(iface,
if (iface->pmsg[iface->cur_msg].len <= 255) {
write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) &
(~(0xff << 6))) |
(iface->pmsg[iface->cur_msg].len << 6));
else {
(iface->pmsg[iface->cur_msg].len << 6));
iface->manual_stop = 0;
} else {
write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) |
(0xff << 6)));
iface->manual_stop = 1;
}
/* remove restart bit and enable master receive */
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
/* remove restart bit before last message */
if (iface->cur_msg + 1 == iface->msg_num)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
} else {
iface->result = 1;
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
}
complete(&iface->complete);
}
complete(&iface->complete);
}
/* Interrupt handler */
@@ -298,8 +260,8 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO;
while (read_MASTER_STAT(iface) & BUSBUSY)
yield();
if (read_MASTER_STAT(iface) & BUSBUSY)
return -EAGAIN;
iface->pmsg = msgs;
iface->msg_num = num;
@@ -311,7 +273,8 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
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->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
@@ -356,6 +319,7 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
/* Master enable */
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
(iface->msg_num > 1 ? RSTART : 0) |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
SSYNC();
@@ -398,8 +362,8 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO;
while (read_MASTER_STAT(iface) & BUSBUSY)
yield();
if (read_MASTER_STAT(iface) & BUSBUSY)
return -EAGAIN;
iface->writeNum = 0;
iface->readNum = 0;
@@ -520,7 +484,7 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
else
write_MASTER_CTL(iface, 0x1 << 6);
/* 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));
break;
default:
@@ -611,9 +575,9 @@ static struct i2c_algorithm bfin_twi_algorithm = {
.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_control = read_CONTROL(iface);
@@ -626,14 +590,14 @@ static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state
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,
0, pdev->name, iface);
0, to_platform_device(dev)->name, iface);
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;
}
@@ -646,6 +610,9 @@ static int i2c_bfin_twi_resume(struct platform_device *pdev)
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)
{
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->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) {
dev_err(&pdev->dev, "Can't setup pin mux!\n");
goto out_error_pin_mux;
@@ -742,7 +710,7 @@ out_error_add_adapter:
free_irq(iface->irq, iface);
out_error_req_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:
iounmap(iface->regs_base);
out_error_ioremap:
@@ -760,7 +728,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
i2c_del_adapter(&(iface->adap));
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);
kfree(iface);
@@ -770,11 +738,10 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
static struct platform_driver i2c_bfin_twi_driver = {
.probe = i2c_bfin_twi_probe,
.remove = i2c_bfin_twi_remove,
.suspend = i2c_bfin_twi_suspend,
.resume = i2c_bfin_twi_resume,
.driver = {
.name = "i2c-bfin-twi",
.owner = THIS_MODULE,
.pm = &i2c_bfin_twi_pm,
},
};

View File

@@ -374,17 +374,7 @@ static struct pci_driver dw_i2c_driver = {
},
};
static int __init dw_i2c_init_driver(void)
{
return pci_register_driver(&dw_i2c_driver);
}
module_init(dw_i2c_init_driver);
static void __exit dw_i2c_exit_driver(void)
{
pci_unregister_driver(&dw_i2c_driver);
}
module_exit(dw_i2c_exit_driver);
module_pci_driver(dw_i2c_driver);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");

View File

@@ -405,6 +405,7 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
}
}
}
ret = num;
abort:
sret = diolan_i2c_stop(dev);
if (sret < 0 && ret >= 0)
@@ -517,6 +518,6 @@ static struct usb_driver diolan_u2c_driver = {
module_usb_driver(diolan_u2c_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION(DRIVER_NAME " driver");
MODULE_LICENSE("GPL");

View File

@@ -953,17 +953,7 @@ static struct pci_driver pch_pcidriver = {
.resume = pch_i2c_resume
};
static int __init pch_pci_init(void)
{
return pci_register_driver(&pch_pcidriver);
}
module_init(pch_pci_init);
static void __exit pch_pci_exit(void)
{
pci_unregister_driver(&pch_pcidriver);
}
module_exit(pch_pci_exit);
module_pci_driver(pch_pcidriver);
MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
MODULE_LICENSE("GPL");

View File

@@ -156,23 +156,8 @@ static struct pci_driver hydra_driver = {
.remove = __devexit_p(hydra_remove),
};
static int __init i2c_hydra_init(void)
{
return pci_register_driver(&hydra_driver);
}
static void __exit i2c_hydra_exit(void)
{
pci_unregister_driver(&hydra_driver);
}
module_pci_driver(hydra_driver);
MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O");
MODULE_LICENSE("GPL");
module_init(i2c_hydra_init);
module_exit(i2c_hydra_exit);

View File

@@ -60,10 +60,12 @@
Block process call transaction no
I2C block read transaction yes (doesn't use the block buffer)
Slave mode no
Interrupt processing yes
See the file Documentation/i2c/busses/i2c-i801 for details.
*/
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@@ -76,6 +78,7 @@
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/wait.h>
/* I801 SMBus address offsets */
#define SMBHSTSTS(p) (0 + (p)->smba)
@@ -91,8 +94,12 @@
/* PCI Address Constants */
#define SMBBAR 4
#define SMBPCISTS 0x006
#define SMBHSTCFG 0x040
/* Host status bits for SMBPCISTS */
#define SMBPCISTS_INTS 0x08
/* Host configuration bits for SMBHSTCFG */
#define SMBHSTCFG_HST_EN 1
#define SMBHSTCFG_SMB_SMI_EN 2
@@ -102,12 +109,8 @@
#define SMBAUXCTL_CRC 1
#define SMBAUXCTL_E32B 2
/* kill bit for SMBHSTCNT */
#define SMBHSTCNT_KILL 2
/* Other settings */
#define MAX_RETRIES 400
#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
/* I801 command constants */
#define I801_QUICK 0x00
@@ -117,10 +120,13 @@
#define I801_PROC_CALL 0x10 /* unimplemented */
#define I801_BLOCK_DATA 0x14
#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
#define I801_BLOCK_LAST 0x34
#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
#define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH3 and later */
/* I801 Host Control register bits */
#define SMBHSTCNT_INTREN 0x01
#define SMBHSTCNT_KILL 0x02
#define SMBHSTCNT_LAST_BYTE 0x20
#define SMBHSTCNT_START 0x40
#define SMBHSTCNT_PEC_EN 0x80 /* ICH3 and later */
/* I801 Hosts Status register bits */
#define SMBHSTSTS_BYTE_DONE 0x80
@@ -132,9 +138,11 @@
#define SMBHSTSTS_INTR 0x02
#define SMBHSTSTS_HOST_BUSY 0x01
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
SMBHSTSTS_INTR)
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
SMBHSTSTS_DEV_ERR)
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
STATUS_ERROR_FLAGS)
/* Older devices have their ID defined in <linux/pci_ids.h> */
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
@@ -154,6 +162,17 @@ struct i801_priv {
unsigned char original_hstcfg;
struct pci_dev *pci_dev;
unsigned int features;
/* isr processing */
wait_queue_head_t waitq;
u8 status;
/* Command state used by isr for byte-by-byte block transactions */
u8 cmd;
bool is_read;
int count;
int len;
u8 *data;
};
static struct pci_driver i801_driver;
@@ -162,6 +181,7 @@ static struct pci_driver i801_driver;
#define FEATURE_BLOCK_BUFFER (1 << 1)
#define FEATURE_BLOCK_PROC (1 << 2)
#define FEATURE_I2C_BLOCK_READ (1 << 3)
#define FEATURE_IRQ (1 << 4)
/* Not really a feature, but it's convenient to handle it as such */
#define FEATURE_IDF (1 << 15)
@@ -170,6 +190,7 @@ static const char *i801_feature_names[] = {
"Block buffer",
"Block process call",
"I2C block read",
"Interrupt",
};
static unsigned int disable_features;
@@ -205,13 +226,22 @@ static int i801_check_pre(struct i801_priv *priv)
return 0;
}
/* Convert the status register to an error code, and clear it. */
static int i801_check_post(struct i801_priv *priv, int status, int timeout)
/*
* Convert the status register to an error code, and clear it.
* Note that status only contains the bits we want to clear, not the
* actual register value.
*/
static int i801_check_post(struct i801_priv *priv, int status)
{
int result = 0;
/* If the SMBus is still busy, we give up */
if (timeout) {
/*
* If the SMBus is still busy, we give up
* Note: This timeout condition only happens when using polling
* transactions. For interrupt operation, NAK/timeout is indicated by
* DEV_ERR.
*/
if (unlikely(status < 0)) {
dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
/* try to stop the current command */
dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
@@ -244,64 +274,76 @@ static int i801_check_post(struct i801_priv *priv, int status, int timeout)
dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
}
if (result) {
/* Clear error flags */
outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
if (status) {
dev_warn(&priv->pci_dev->dev, "Failed clearing status "
"flags at end of transaction (%02x)\n",
status);
}
}
/* Clear status flags except BYTE_DONE, to be cleared by caller */
outb_p(status, SMBHSTSTS(priv));
return result;
}
/* Wait for BUSY being cleared and either INTR or an error flag being set */
static int i801_wait_intr(struct i801_priv *priv)
{
int timeout = 0;
int status;
/* We will always wait for a fraction of a second! */
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while (((status & SMBHSTSTS_HOST_BUSY) ||
!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) &&
(timeout++ < MAX_RETRIES));
if (timeout > MAX_RETRIES) {
dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n");
return -ETIMEDOUT;
}
return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR);
}
/* Wait for either BYTE_DONE or an error flag being set */
static int i801_wait_byte_done(struct i801_priv *priv)
{
int timeout = 0;
int status;
/* We will always wait for a fraction of a second! */
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) &&
(timeout++ < MAX_RETRIES));
if (timeout > MAX_RETRIES) {
dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n");
return -ETIMEDOUT;
}
return status & STATUS_ERROR_FLAGS;
}
static int i801_transaction(struct i801_priv *priv, int xact)
{
int status;
int result;
int timeout = 0;
result = i801_check_pre(priv);
if (result < 0)
return result;
if (priv->features & FEATURE_IRQ) {
outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
SMBHSTCNT(priv));
wait_event(priv->waitq, (status = priv->status));
priv->status = 0;
return i801_check_post(priv, status);
}
/* the current contents of SMBHSTCNT can be overwritten, since PEC,
* INTREN, SMBSCMD are passed in xact */
outb_p(xact | I801_START, SMBHSTCNT(priv));
* SMBSCMD are passed in xact */
outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
/* We will always wait for a fraction of a second! */
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
result = i801_check_post(priv, status, timeout > MAX_RETRIES);
if (result < 0)
return result;
outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
return 0;
}
/* wait for INTR bit as advised by Intel */
static void i801_wait_hwpec(struct i801_priv *priv)
{
int timeout = 0;
int status;
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while ((!(status & SMBHSTSTS_INTR))
&& (timeout++ < MAX_RETRIES));
if (timeout > MAX_RETRIES)
dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n");
outb_p(status, SMBHSTSTS(priv));
status = i801_wait_intr(priv);
return i801_check_post(priv, status);
}
static int i801_block_transaction_by_block(struct i801_priv *priv,
@@ -321,8 +363,8 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
outb_p(data->block[i+1], SMBBLKDAT(priv));
}
status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 |
I801_PEC_EN * hwpec);
status = i801_transaction(priv, I801_BLOCK_DATA |
(hwpec ? SMBHSTCNT_PEC_EN : 0));
if (status)
return status;
@@ -338,6 +380,98 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
return 0;
}
static void i801_isr_byte_done(struct i801_priv *priv)
{
if (priv->is_read) {
/* For SMBus block reads, length is received with first byte */
if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
(priv->count == 0)) {
priv->len = inb_p(SMBHSTDAT0(priv));
if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
dev_err(&priv->pci_dev->dev,
"Illegal SMBus block read size %d\n",
priv->len);
/* FIXME: Recover */
priv->len = I2C_SMBUS_BLOCK_MAX;
} else {
dev_dbg(&priv->pci_dev->dev,
"SMBus block read size is %d\n",
priv->len);
}
priv->data[-1] = priv->len;
}
/* Read next byte */
if (priv->count < priv->len)
priv->data[priv->count++] = inb(SMBBLKDAT(priv));
else
dev_dbg(&priv->pci_dev->dev,
"Discarding extra byte on block read\n");
/* Set LAST_BYTE for last byte of read transaction */
if (priv->count == priv->len - 1)
outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE,
SMBHSTCNT(priv));
} else if (priv->count < priv->len - 1) {
/* Write next byte, except for IRQ after last byte */
outb_p(priv->data[++priv->count], SMBBLKDAT(priv));
}
/* Clear BYTE_DONE to continue with next byte */
outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
}
/*
* There are two kinds of interrupts:
*
* 1) i801 signals transaction completion with one of these interrupts:
* INTR - Success
* DEV_ERR - Invalid command, NAK or communication timeout
* BUS_ERR - SMI# transaction collision
* FAILED - transaction was canceled due to a KILL request
* When any of these occur, update ->status and wake up the waitq.
* ->status must be cleared before kicking off the next transaction.
*
* 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt
* occurs for each byte of a byte-by-byte to prepare the next byte.
*/
static irqreturn_t i801_isr(int irq, void *dev_id)
{
struct i801_priv *priv = dev_id;
u16 pcists;
u8 status;
/* Confirm this is our interrupt */
pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists);
if (!(pcists & SMBPCISTS_INTS))
return IRQ_NONE;
status = inb_p(SMBHSTSTS(priv));
if (status != 0x42)
dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status);
if (status & SMBHSTSTS_BYTE_DONE)
i801_isr_byte_done(priv);
/*
* Clear irq sources and report transaction result.
* ->status must be cleared before the next transaction is started.
*/
status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
if (status) {
outb_p(status, SMBHSTSTS(priv));
priv->status |= status;
wake_up(&priv->waitq);
}
return IRQ_HANDLED;
}
/*
* For "byte-by-byte" block transactions:
* I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1
* I2C read uses cmd=I801_I2C_BLOCK_DATA
*/
static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
union i2c_smbus_data *data,
char read_write, int command,
@@ -347,7 +481,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
int smbcmd;
int status;
int result;
int timeout;
result = i801_check_pre(priv);
if (result < 0)
@@ -360,36 +493,39 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
outb_p(data->block[1], SMBBLKDAT(priv));
}
if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
read_write == I2C_SMBUS_READ)
smbcmd = I801_I2C_BLOCK_DATA;
else
smbcmd = I801_BLOCK_DATA;
if (priv->features & FEATURE_IRQ) {
priv->is_read = (read_write == I2C_SMBUS_READ);
if (len == 1 && priv->is_read)
smbcmd |= SMBHSTCNT_LAST_BYTE;
priv->cmd = smbcmd | SMBHSTCNT_INTREN;
priv->len = len;
priv->count = 0;
priv->data = &data->block[1];
outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
wait_event(priv->waitq, (status = priv->status));
priv->status = 0;
return i801_check_post(priv, status);
}
for (i = 1; i <= len; i++) {
if (i == len && read_write == I2C_SMBUS_READ) {
if (command == I2C_SMBUS_I2C_BLOCK_DATA)
smbcmd = I801_I2C_BLOCK_LAST;
else
smbcmd = I801_BLOCK_LAST;
} else {
if (command == I2C_SMBUS_I2C_BLOCK_DATA
&& read_write == I2C_SMBUS_READ)
smbcmd = I801_I2C_BLOCK_DATA;
else
smbcmd = I801_BLOCK_DATA;
}
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
if (i == len && read_write == I2C_SMBUS_READ)
smbcmd |= SMBHSTCNT_LAST_BYTE;
outb_p(smbcmd, SMBHSTCNT(priv));
if (i == 1)
outb_p(inb(SMBHSTCNT(priv)) | I801_START,
outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
SMBHSTCNT(priv));
/* We will always wait for a fraction of a second! */
timeout = 0;
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while ((!(status & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_RETRIES));
result = i801_check_post(priv, status, timeout > MAX_RETRIES);
if (result < 0)
return result;
status = i801_wait_byte_done(priv);
if (status)
goto exit;
if (i == 1 && read_write == I2C_SMBUS_READ
&& command != I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -416,10 +552,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
outb_p(data->block[i+1], SMBBLKDAT(priv));
/* signals SMBBLKDAT ready */
outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
}
return 0;
status = i801_wait_intr(priv);
exit:
return i801_check_post(priv, status);
}
static int i801_set_block_buffer_mode(struct i801_priv *priv)
@@ -474,9 +612,6 @@ static int i801_block_transaction(struct i801_priv *priv,
read_write,
command, hwpec);
if (result == 0 && hwpec)
i801_wait_hwpec(priv);
if (command == I2C_SMBUS_I2C_BLOCK_DATA
&& read_write == I2C_SMBUS_WRITE) {
/* restore saved configuration register value */
@@ -564,7 +699,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
ret = i801_block_transaction(priv, data, read_write, size,
hwpec);
else
ret = i801_transaction(priv, xact | ENABLE_INT9);
ret = i801_transaction(priv, xact);
/* Some BIOSes don't like it when PEC is enabled at reboot or resume
time, so we forcibly disable it after every transaction. Turn off
@@ -799,6 +934,16 @@ static int __devinit i801_probe(struct pci_dev *dev,
break;
}
/* IRQ processing tested on CougarPoint PCH, ICH5, ICH7-M and ICH10 */
if (dev->device == PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS ||
dev->device == PCI_DEVICE_ID_INTEL_82801EB_3 ||
dev->device == PCI_DEVICE_ID_INTEL_ICH7_17 ||
dev->device == PCI_DEVICE_ID_INTEL_ICH8_5 ||
dev->device == PCI_DEVICE_ID_INTEL_ICH9_6 ||
dev->device == PCI_DEVICE_ID_INTEL_ICH10_4 ||
dev->device == PCI_DEVICE_ID_INTEL_ICH10_5)
priv->features |= FEATURE_IRQ;
/* Disable features on user request */
for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
if (priv->features & disable_features & (1 << i))
@@ -846,16 +991,30 @@ static int __devinit i801_probe(struct pci_dev *dev,
}
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
if (temp & SMBHSTCFG_SMB_SMI_EN)
if (temp & SMBHSTCFG_SMB_SMI_EN) {
dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
else
dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
/* Disable SMBus interrupt feature if SMBus using SMI# */
priv->features &= ~FEATURE_IRQ;
}
/* Clear special mode bits */
if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
outb_p(inb_p(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
if (priv->features & FEATURE_IRQ) {
init_waitqueue_head(&priv->waitq);
err = request_irq(dev->irq, i801_isr, IRQF_SHARED,
i801_driver.name, priv);
if (err) {
dev_err(&dev->dev, "Failed to allocate irq %d: %d\n",
dev->irq, err);
goto exit_release;
}
dev_info(&dev->dev, "SMBus using PCI Interrupt\n");
}
/* set up the sysfs linkage to our parent device */
priv->adapter.dev.parent = &dev->dev;
@@ -867,14 +1026,18 @@ static int __devinit i801_probe(struct pci_dev *dev,
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
goto exit_release;
goto exit_free_irq;
}
i801_probe_optional_slaves(priv);
pci_set_drvdata(dev, priv);
return 0;
exit_free_irq:
if (priv->features & FEATURE_IRQ)
free_irq(dev->irq, priv);
exit_release:
pci_release_region(dev, SMBBAR);
exit:
@@ -888,7 +1051,11 @@ static void __devexit i801_remove(struct pci_dev *dev)
i2c_del_adapter(&priv->adapter);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
if (priv->features & FEATURE_IRQ)
free_irq(dev->irq, priv);
pci_release_region(dev, SMBBAR);
pci_set_drvdata(dev, NULL);
kfree(priv);
/*

View File

@@ -53,7 +53,6 @@
#include <linux/of_i2c.h>
#include <linux/pinctrl/consumer.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/i2c.h>
@@ -118,10 +117,8 @@ static u16 __initdata i2c_clk_div[50][2] = {
struct imx_i2c_struct {
struct i2c_adapter adapter;
struct resource *res;
struct clk *clk;
void __iomem *base;
int irq;
wait_queue_head_t queue;
unsigned long i2csr;
unsigned int disable_delay;
@@ -473,9 +470,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
struct pinctrl *pinctrl;
void __iomem *base;
resource_size_t res_size;
int irq, bitrate;
int ret;
int irq, ret;
u32 bitrate;
dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -490,25 +486,15 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
return -ENOENT;
}
res_size = resource_size(res);
if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
dev_err(&pdev->dev, "request_mem_region failed\n");
base = devm_request_and_ioremap(&pdev->dev, res);
if (!base)
return -EBUSY;
}
base = ioremap(res->start, res_size);
if (!base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -EIO;
goto fail1;
}
i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL);
i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct),
GFP_KERNEL);
if (!i2c_imx) {
dev_err(&pdev->dev, "can't allocate interface\n");
ret = -ENOMEM;
goto fail2;
return -ENOMEM;
}
/* Setup i2c_imx driver structure */
@@ -518,29 +504,27 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx->adapter.dev.parent = &pdev->dev;
i2c_imx->adapter.nr = pdev->id;
i2c_imx->adapter.dev.of_node = pdev->dev.of_node;
i2c_imx->irq = irq;
i2c_imx->base = base;
i2c_imx->res = res;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
goto fail3;
dev_err(&pdev->dev, "can't get/select pinctrl\n");
return PTR_ERR(pinctrl);
}
/* 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)) {
ret = PTR_ERR(i2c_imx->clk);
dev_err(&pdev->dev, "can't get I2C clock\n");
goto fail3;
return PTR_ERR(i2c_imx->clk);
}
/* 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) {
dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq);
goto fail4;
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
return ret;
}
/* Init queue */
@@ -565,7 +549,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "registration failed\n");
goto fail5;
return ret;
}
of_i2c_register_devices(&i2c_imx->adapter);
@@ -573,28 +557,16 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
/* Set up platform driver data */
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",
i2c_imx->res->start, i2c_imx->res->end);
dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n",
res_size, i2c_imx->res->start);
res->start, res->end);
dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",
resource_size(res), res->start);
dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
i2c_imx->adapter.name);
dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
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)
@@ -606,20 +578,12 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c_imx->adapter);
platform_set_drvdata(pdev, NULL);
/* free interrupt */
free_irq(i2c_imx->irq, i2c_imx);
/* setup chip registers to defaults */
writeb(0, i2c_imx->base + IMX_I2C_IADR);
writeb(0, i2c_imx->base + IMX_I2C_IFDR);
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
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;
}

View File

@@ -1116,18 +1116,7 @@ static struct pci_driver intel_mid_i2c_driver = {
.remove = __devexit_p(intel_mid_i2c_remove),
};
static int __init intel_mid_i2c_init(void)
{
return pci_register_driver(&intel_mid_i2c_driver);
}
static void __exit intel_mid_i2c_exit(void)
{
pci_unregister_driver(&intel_mid_i2c_driver);
}
module_init(intel_mid_i2c_init);
module_exit(intel_mid_i2c_exit);
module_pci_driver(intel_mid_i2c_driver);
MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
MODULE_DESCRIPTION("I2C driver for Moorestown Platform");

View File

@@ -18,6 +18,11 @@
#include <linux/mv643xx_i2c.h>
#include <linux/platform_device.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 */
#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00
@@ -98,6 +103,9 @@ struct mv64xxx_i2c_data {
int rc;
u32 freq_m;
u32 freq_n;
#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
#endif
wait_queue_head_t waitq;
spinlock_t lock;
struct i2c_msg *msg;
@@ -521,6 +529,82 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
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
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;
int rc;
if ((pd->id != 0) || !pdata)
if ((!pdata && !pd->dev.of_node))
return -ENODEV;
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);
spin_lock_init(&drv_data->lock);
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
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) {
rc = -ENXIO;
goto exit_unmap_regs;
}
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
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.dev.of_node = pd->dev.of_node;
platform_set_drvdata(pd, 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;
}
of_i2c_register_devices(&drv_data->adapter);
return 0;
exit_free_irq:
free_irq(drv_data->irq, drv_data);
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);
exit_kfree:
kfree(drv_data);
@@ -597,17 +706,31 @@ mv64xxx_i2c_remove(struct platform_device *dev)
rc = i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, 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);
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 = {
.probe = mv64xxx_i2c_probe,
.remove = __devexit_p(mv64xxx_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.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_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_SET (0x44)
#define MXS_I2C_CTRL1_CLR (0x48)
@@ -97,6 +101,35 @@
#define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
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
*
@@ -112,11 +145,17 @@ struct mxs_i2c_dev {
struct completion cmd_complete;
u32 cmd_err;
struct i2c_adapter adapter;
const struct mxs_i2c_speed_config *speed;
};
static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
{
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_QUEUECTRL_PIO_QUEUE_MODE,
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)
{
u32 data;
u32 uninitialized_var(data);
int i;
for (i = 0; i < len; i++) {
@@ -319,6 +358,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
.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)
{
struct device *dev = &pdev->dev;
@@ -358,6 +419,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
return err;
i2c->dev = dev;
err = mxs_i2c_get_ofdata(i2c);
if (err)
return err;
platform_set_drvdata(pdev, i2c);
/* Do reset to enforce correct startup after pinmuxing */

View File

@@ -453,16 +453,4 @@ static struct pci_driver nforce2_driver = {
.remove = __devexit_p(nforce2_remove),
};
static int __init nforce2_init(void)
{
return pci_register_driver(&nforce2_driver);
}
static void __exit nforce2_exit(void)
{
pci_unregister_driver(&nforce2_driver);
}
module_init(nforce2_init);
module_exit(nforce2_exit);
module_pci_driver(nforce2_driver);

View File

@@ -14,7 +14,8 @@
*/
#include <linux/init.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/interrupt.h>
#include <linux/i2c.h>
@@ -23,8 +24,7 @@
#include <linux/io.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <plat/i2c.h>
#include <linux/platform_data/i2c-nomadik.h>
#define DRIVER_NAME "nmk-i2c"
@@ -136,7 +136,7 @@ struct i2c_nmk_client {
/**
* struct nmk_i2c_dev - private data structure of the controller.
* @pdev: parent platform device.
* @adev: parent amba device.
* @adap: corresponding I2C adapter.
* @irq: interrupt line for the controller.
* @virtbase: virtual io memory area.
@@ -150,7 +150,7 @@ struct i2c_nmk_client {
* @busy: Busy doing transfer.
*/
struct nmk_i2c_dev {
struct platform_device *pdev;
struct amba_device *adev;
struct i2c_adapter adap;
int irq;
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",
LOOP_ATTEMPTS);
@@ -276,15 +276,32 @@ exit:
/**
* load_i2c_mcr_reg() - load the MCR register
* @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;
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);
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 */
mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
@@ -333,10 +350,6 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
i2c_clk = clk_get_rate(dev->clk);
/* fallback to std. mode if machine has not provided it */
if (dev->cfg.clk_freq == 0)
dev->cfg.clk_freq = 100000;
/*
* The spec says, in case of std. mode the divider is
* 2 whereas it is 3 for fast and fastplus mode of
@@ -364,7 +377,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
* and high speed (up to 3.4 Mb/s)
*/
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");
brcr2 = i2c_clk/(100000 * 2) & 0xffff;
writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
@@ -381,19 +394,20 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
/**
* read_i2c() - Read from I2C client device
* @dev: private data of I2C Driver
* @flags: message flags
*
* This function reads from i2c client device when controller is in
* master mode. There is a completion timeout. If there is no transfer
* 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 mcr;
u32 irq_mask = 0;
int timeout;
mcr = load_i2c_mcr_reg(dev);
mcr = load_i2c_mcr_reg(dev, flags);
writel(mcr, dev->virtbase + I2C_MCR);
/* load the current CR value */
@@ -423,7 +437,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
&dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) {
dev_err(&dev->pdev->dev,
dev_err(&dev->adev->dev,
"wait_for_completion_timeout "
"returned %d waiting for event\n", timeout);
status = timeout;
@@ -431,7 +445,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
if (timeout == 0) {
/* 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);
status = -ETIMEDOUT;
}
@@ -459,17 +473,18 @@ static void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes)
/**
* write_i2c() - Write data to I2C client.
* @dev: private data of I2C Driver
* @flags: message flags
*
* 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 mcr;
u32 irq_mask = 0;
int timeout;
mcr = load_i2c_mcr_reg(dev);
mcr = load_i2c_mcr_reg(dev, flags);
writel(mcr, dev->virtbase + I2C_MCR);
@@ -510,7 +525,7 @@ static int write_i2c(struct nmk_i2c_dev *dev)
&dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) {
dev_err(&dev->pdev->dev,
dev_err(&dev->adev->dev,
"wait_for_completion_timeout "
"returned %d waiting for event\n", timeout);
status = timeout;
@@ -518,7 +533,7 @@ static int write_i2c(struct nmk_i2c_dev *dev)
if (timeout == 0) {
/* 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);
status = -ETIMEDOUT;
}
@@ -538,11 +553,11 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
if (flags & I2C_M_RD) {
/* read operation */
dev->cli.operation = I2C_READ;
status = read_i2c(dev);
status = read_i2c(dev, flags);
} else {
/* write operation */
dev->cli.operation = I2C_WRITE;
status = write_i2c(dev);
status = write_i2c(dev, flags);
}
if (status || (dev->result)) {
@@ -557,7 +572,7 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
if (((i2c_sr >> 2) & 0x3) == 0x3) {
/* get the abort cause */
cause = (i2c_sr >> 4) & 0x7;
dev_err(&dev->pdev->dev, "%s\n",
dev_err(&dev->adev->dev, "%s\n",
cause >= ARRAY_SIZE(abort_causes) ?
"unknown reason" :
abort_causes[cause]);
@@ -630,7 +645,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
if (dev->regulator)
regulator_enable(dev->regulator);
pm_runtime_get_sync(&dev->pdev->dev);
pm_runtime_get_sync(&dev->adev->dev);
clk_enable(dev->clk);
@@ -644,13 +659,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
setup_i2c_controller(dev);
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.buffer = msgs[i].buf;
dev->cli.count = msgs[i].len;
@@ -667,7 +675,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
out:
clk_disable(dev->clk);
pm_runtime_put_sync(&dev->pdev->dev);
pm_runtime_put_sync(&dev->adev->dev);
if (dev->regulator)
regulator_disable(dev->regulator);
@@ -790,7 +798,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
if (dev->cli.count) {
dev->result = -EIO;
dev_err(&dev->pdev->dev,
dev_err(&dev->adev->dev,
"%lu bytes still remain to be xfered\n",
dev->cli.count);
(void) init_hw(dev);
@@ -834,7 +842,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
dev->result = -EIO;
(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);
break;
@@ -847,10 +855,10 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
case I2C_IT_RFSE:
case I2C_IT_WTSR:
case I2C_IT_STD:
dev_err(&dev->pdev->dev, "unhandled Interrupt\n");
dev_err(&dev->adev->dev, "unhandled Interrupt\n");
break;
default:
dev_err(&dev->pdev->dev, "spurious Interrupt..\n");
dev_err(&dev->adev->dev, "spurious Interrupt..\n");
break;
}
@@ -861,8 +869,8 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
#ifdef CONFIG_PM
static int nmk_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev);
struct amba_device *adev = to_amba_device(dev);
struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
if (nmk_i2c->busy)
return -EBUSY;
@@ -891,7 +899,7 @@ static const struct dev_pm_ops nmk_i2c_pm = {
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 = {
@@ -899,79 +907,81 @@ static const struct i2c_algorithm nmk_i2c_algo = {
.functionality = nmk_i2c_functionality
};
static int __devinit nmk_i2c_probe(struct platform_device *pdev)
static struct nmk_i2c_controller u8500_i2c = {
/*
* Slave data setup time; 250ns, 100ns, and 10ns, which
* is 14, 6 and 2 respectively for a 48Mhz i2c clock.
*/
.slsu = 0xe,
.tft = 1, /* Tx FIFO threshold */
.rft = 8, /* Rx FIFO threshold */
.clk_freq = 400000, /* fast mode operation */
.timeout = 200, /* Slave response timeout(ms) */
.sm = I2C_FREQ_MODE_FAST,
};
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;
struct resource *res;
struct nmk_i2c_controller *pdata =
pdev->dev.platform_data;
struct nmk_i2c_controller *pdata = adev->dev.platform_data;
struct nmk_i2c_dev *dev;
struct i2c_adapter *adap;
if (!pdata)
/* No i2c configuration found, using the default. */
pdata = &u8500_i2c;
dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);
if (!dev) {
dev_err(&pdev->dev, "cannot allocate memory\n");
dev_err(&adev->dev, "cannot allocate memory\n");
ret = -ENOMEM;
goto err_no_mem;
}
dev->busy = false;
dev->pdev = pdev;
platform_set_drvdata(pdev, dev);
dev->adev = adev;
amba_set_drvdata(adev, dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
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));
dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
if (!dev->virtbase) {
ret = -ENOMEM;
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,
DRIVER_NAME, dev);
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;
}
dev->regulator = regulator_get(&pdev->dev, "v-i2c");
dev->regulator = regulator_get(&adev->dev, "v-i2c");
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;
}
pm_suspend_ignore_children(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
pm_suspend_ignore_children(&adev->dev, true);
dev->clk = clk_get(&pdev->dev, NULL);
dev->clk = clk_get(&adev->dev, NULL);
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);
goto err_no_clk;
}
adap = &dev->adap;
adap->dev.parent = &pdev->dev;
adap->dev.parent = &adev->dev;
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &nmk_i2c_algo;
adap->timeout = pdata->timeout ? msecs_to_jiffies(pdata->timeout) :
msecs_to_jiffies(20000);
adap->timeout = msecs_to_jiffies(pdata->timeout);
adap->nr = atomic_read(&adapter_id);
snprintf(adap->name, sizeof(adap->name),
"Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start);
/* fetch the controller id */
adap->nr = pdev->id;
"Nomadik I2C%d at %pR", adap->nr, &adev->res);
atomic_inc(&adapter_id);
/* fetch the controller configuration from machine */
dev->cfg.clk_freq = pdata->clk_freq;
@@ -982,16 +992,18 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, dev);
dev_info(&pdev->dev,
dev_info(&adev->dev,
"initialize %s on virtual base %p\n",
adap->name, dev->virtbase);
ret = i2c_add_numbered_adapter(adap);
if (ret) {
dev_err(&pdev->dev, "failed to add adapter\n");
dev_err(&adev->dev, "failed to add adapter\n");
goto err_add_adap;
}
pm_runtime_put(&adev->dev);
return 0;
err_add_adap:
@@ -999,25 +1011,21 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
err_no_clk:
if (dev->regulator)
regulator_put(dev->regulator);
pm_runtime_disable(&pdev->dev);
free_irq(dev->irq, dev);
err_irq:
iounmap(dev->virtbase);
err_no_ioremap:
release_mem_region(res->start, resource_size(res));
err_no_region:
platform_set_drvdata(pdev, NULL);
err_no_resource:
amba_set_drvdata(adev, NULL);
kfree(dev);
err_no_mem:
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 nmk_i2c_dev *dev = platform_get_drvdata(pdev);
struct resource *res = &adev->res;
struct nmk_i2c_dev *dev = amba_get_drvdata(adev);
i2c_del_adapter(&dev->adap);
flush_i2c_fifo(dev);
@@ -1032,31 +1040,46 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev)
clk_put(dev->clk);
if (dev->regulator)
regulator_put(dev->regulator);
pm_runtime_disable(&pdev->dev);
platform_set_drvdata(pdev, NULL);
pm_runtime_disable(&adev->dev);
amba_set_drvdata(adev, NULL);
kfree(dev);
return 0;
}
static struct platform_driver nmk_i2c_driver = {
.driver = {
static struct amba_id nmk_i2c_ids[] = {
{
.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,
.name = DRIVER_NAME,
.pm = &nmk_i2c_pm,
},
.id_table = nmk_i2c_ids,
.probe = nmk_i2c_probe,
.remove = __devexit_p(nmk_i2c_remove),
.remove = nmk_i2c_remove,
};
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)
{
platform_driver_unregister(&nmk_i2c_driver);
amba_driver_unregister(&nmk_i2c_driver);
}
subsys_initcall(nmk_i2c_init);
@@ -1065,4 +1088,3 @@ module_exit(nmk_i2c_exit);
MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR");
MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);

View File

@@ -10,40 +10,9 @@
*/
/*
* Device tree configuration:
*
* 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>;
* };
* };
*
* This driver can be used from the device tree, see
* Documentation/devicetree/bindings/i2c/ocore-i2c.txt
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -56,10 +25,12 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of_i2c.h>
#include <linux/log2.h>
struct ocores_i2c {
void __iomem *base;
int regstep;
u32 reg_shift;
u32 reg_io_width;
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_msg *msg;
@@ -102,12 +73,22 @@ struct ocores_i2c {
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)
{
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)
@@ -247,26 +228,35 @@ static struct i2c_adapter ocores_adapter = {
};
#ifdef CONFIG_OF
static int ocores_i2c_of_probe(struct platform_device* pdev,
struct ocores_i2c* i2c)
static int ocores_i2c_of_probe(struct platform_device *pdev,
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 (!val) {
dev_err(&pdev->dev, "Missing required parameter 'regstep'");
return -ENODEV;
if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
/* no 'reg-shift', check for deprecated 'regstep' */
if (!of_property_read_u32(np, "regstep", &val)) {
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 (!val) {
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev,
"Missing required parameter 'clock-frequency'");
"Missing required parameter 'clock-frequency'\n");
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;
}
#else
@@ -308,7 +298,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
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;
} else {
ret = ocores_i2c_of_probe(pdev, i2c);
@@ -316,6 +307,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return ret;
}
if (i2c->reg_io_width == 0)
i2c->reg_io_width = 1; /* Set to default value */
ocores_init(i2c);
init_waitqueue_head(&i2c->wait);
@@ -351,7 +345,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
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);
@@ -367,9 +361,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
}
#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);
/* 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;
}
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);
return 0;
}
static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
#define OCORES_I2C_PM (&ocores_i2c_pm)
#else
#define ocores_i2c_suspend NULL
#define ocores_i2c_resume NULL
#define OCORES_I2C_PM NULL
#endif
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 = {
.probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove),
.suspend = ocores_i2c_suspend,
.resume = ocores_i2c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "ocores-i2c",
.of_match_table = ocores_i2c_match,
.pm = OCORES_I2C_PM,
},
};

View File

@@ -2,7 +2,7 @@
* (C) Copyright 2009-2010
* Nokia Siemens Networks, michael.lawnick.ext@nsn.com
*
* Portions Copyright (C) 2010 Cavium Networks, Inc.
* Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
*
* This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
*
@@ -11,17 +11,18 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_i2c.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>
#include <asm/octeon/octeon.h>
@@ -65,7 +66,7 @@ struct octeon_i2c {
wait_queue_head_t queue;
struct i2c_adapter adap;
int irq;
int twsi_freq;
u32 twsi_freq;
int sys_freq;
resource_size_t twsi_phys;
void __iomem *twsi_base;
@@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
*/
static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
{
u64 tmp;
__raw_writeq(data, i2c->twsi_base + TWSI_INT);
tmp = __raw_readq(i2c->twsi_base + TWSI_INT);
__raw_readq(i2c->twsi_base + TWSI_INT);
}
/**
@@ -515,7 +514,6 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
{
int irq, result = 0;
struct octeon_i2c *i2c;
struct octeon_i2c_data *i2c_data;
struct resource *res_mem;
/* All adaptors have an irq. */
@@ -523,86 +521,90 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "kzalloc failed\n");
result = -ENOMEM;
goto out;
}
i2c->dev = &pdev->dev;
i2c_data = pdev->dev.platform_data;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem == NULL) {
dev_err(i2c->dev, "found no memory resource\n");
result = -ENXIO;
goto fail_region;
goto out;
}
if (i2c_data == NULL) {
dev_err(i2c->dev, "no I2C frequency data\n");
result = -ENXIO;
goto fail_region;
}
i2c->twsi_phys = res_mem->start;
i2c->regsize = resource_size(res_mem);
i2c->twsi_freq = i2c_data->i2c_freq;
i2c->sys_freq = i2c_data->sys_freq;
if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) {
dev_err(i2c->dev, "request_mem_region failed\n");
goto fail_region;
/*
* "clock-rate" is a legacy binding, the official binding is
* "clock-frequency". Try the official one first and then
* fall back if it doesn't exist.
*/
if (of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &i2c->twsi_freq) &&
of_property_read_u32(pdev->dev.of_node,
"clock-rate", &i2c->twsi_freq)) {
dev_err(i2c->dev,
"no I2C 'clock-rate' or 'clock-frequency' property\n");
result = -ENXIO;
goto out;
}
i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize);
i2c->sys_freq = octeon_get_io_clock_rate();
if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize,
res_mem->name)) {
dev_err(i2c->dev, "request_mem_region failed\n");
goto out;
}
i2c->twsi_base = devm_ioremap(&pdev->dev, i2c->twsi_phys, i2c->regsize);
init_waitqueue_head(&i2c->queue);
i2c->irq = irq;
result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c);
result = devm_request_irq(&pdev->dev, i2c->irq,
octeon_i2c_isr, 0, DRV_NAME, i2c);
if (result < 0) {
dev_err(i2c->dev, "failed to attach interrupt\n");
goto fail_irq;
goto out;
}
result = octeon_i2c_initlowlevel(i2c);
if (result) {
dev_err(i2c->dev, "init low level failed\n");
goto fail_add;
goto out;
}
result = octeon_i2c_setclock(i2c);
if (result) {
dev_err(i2c->dev, "clock init failed\n");
goto fail_add;
goto out;
}
i2c->adap = octeon_i2c_ops;
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
i2c->adap.dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c);
result = i2c_add_numbered_adapter(&i2c->adap);
result = i2c_add_adapter(&i2c->adap);
if (result < 0) {
dev_err(i2c->dev, "failed to add adapter\n");
goto fail_add;
}
dev_info(i2c->dev, "version %s\n", DRV_VERSION);
return result;
of_i2c_register_devices(&i2c->adap);
return 0;
fail_add:
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
fail_irq:
iounmap(i2c->twsi_base);
release_mem_region(i2c->twsi_phys, i2c->regsize);
fail_region:
kfree(i2c);
out:
return result;
};
@@ -613,19 +615,24 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c->adap);
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
iounmap(i2c->twsi_base);
release_mem_region(i2c->twsi_phys, i2c->regsize);
kfree(i2c);
return 0;
};
static struct of_device_id octeon_i2c_match[] = {
{
.compatible = "cavium,octeon-3860-twsi",
},
{},
};
MODULE_DEVICE_TABLE(of, octeon_i2c_match);
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
.remove = __devexit_p(octeon_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
.of_match_table = octeon_i2c_match,
},
};
@@ -635,4 +642,3 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_NAME);

View File

@@ -49,8 +49,8 @@
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36
#define OMAP_I2C_REV_ON_3430 0x3C
#define OMAP_I2C_REV_ON_3530_4430 0x40
#define OMAP_I2C_REV_ON_3430_3530 0x3C
#define OMAP_I2C_REV_ON_3630_4430 0x40
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -173,7 +173,7 @@ enum {
/* Errata definitions */
#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 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));
}
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)
{
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,
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_ENAWAKEUP_MASK;
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: */
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 */
dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
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 omap_i2c_dev *dev = i2c_get_adapdata(adap);
int r;
unsigned long timeout;
u16 w;
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;
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
init_completion(&dev->cmd_complete);
INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
@@ -545,6 +499,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
if (dev->speed > 400)
w |= OMAP_I2C_CON_OPMODE_HS;
if (msg->flags & I2C_M_STOP)
stop = 1;
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
@@ -582,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
* into arbitration and we're currently unable to recover from it.
*/
r = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
timeout = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
if (r == 0) {
if (timeout == 0) {
dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev);
return -ETIMEDOUT;
@@ -628,7 +582,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
int i;
int r;
pm_runtime_get_sync(dev->dev);
r = pm_runtime_get_sync(dev->dev);
if (IS_ERR_VALUE(r))
goto out;
r = omap_i2c_wait_for_bb(dev);
if (r < 0)
@@ -658,7 +614,8 @@ out:
static u32
omap_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
I2C_FUNC_PROTOCOL_MANGLING;
}
static inline void
@@ -764,11 +721,11 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id)
#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
* 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;
@@ -776,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)) {
omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
OMAP_I2C_STAT_XDR));
*err |= OMAP_I2C_STAT_XUDF;
return -ETIMEDOUT;
}
@@ -789,6 +745,7 @@ static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err)
return 0;
}
*err |= OMAP_I2C_STAT_XUDF;
return 0;
}
@@ -927,8 +884,8 @@ complete:
break;
}
if ((dev->errata & I2C_OMAP3_1P153) &&
errata_omap3_1p153(dev, &stat, &err))
if ((dev->errata & I2C_OMAP_ERRATA_I462) &&
errata_omap3_i462(dev, &stat, &err))
goto complete;
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
@@ -1045,6 +1002,7 @@ omap_i2c_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, dev);
init_completion(&dev->cmd_complete);
dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
@@ -1054,12 +1012,19 @@ omap_i2c_probe(struct platform_device *pdev)
dev->regs = (u8 *)reg_map_ip_v1;
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;
if (dev->rev <= OMAP_I2C_REV_ON_3430)
dev->errata |= I2C_OMAP3_1P153;
dev->errata = 0;
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)) {
u16 s;
@@ -1076,7 +1041,7 @@ omap_i2c_probe(struct platform_device *pdev)
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 */
else
dev->b_hw = 1; /* Enable hardware fixes */
@@ -1092,7 +1057,7 @@ omap_i2c_probe(struct platform_device *pdev)
isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_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) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
@@ -1102,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->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
pm_runtime_put(dev->dev);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
@@ -1123,6 +1086,8 @@ omap_i2c_probe(struct platform_device *pdev)
of_i2c_register_devices(adap);
pm_runtime_put(dev->dev);
return 0;
err_free_irq:
@@ -1131,6 +1096,7 @@ err_unuse_clocks:
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
pm_runtime_put(dev->dev);
iounmap(dev->base);
pm_runtime_disable(&pdev->dev);
err_free_mem:
platform_set_drvdata(pdev, NULL);
kfree(dev);
@@ -1140,17 +1106,23 @@ err_release_region:
return r;
}
static int
omap_i2c_remove(struct platform_device *pdev)
static int __devexit omap_i2c_remove(struct platform_device *pdev)
{
struct omap_i2c_dev *dev = platform_get_drvdata(pdev);
struct resource *mem;
int ret;
platform_set_drvdata(pdev, NULL);
free_irq(dev->irq, dev);
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);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
iounmap(dev->base);
kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1158,13 +1130,26 @@ omap_i2c_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_RUNTIME
static int omap_i2c_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
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;
}
@@ -1174,23 +1159,40 @@ static int omap_i2c_runtime_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
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;
}
#endif /* CONFIG_PM_RUNTIME */
static struct dev_pm_ops omap_i2c_pm_ops = {
.runtime_suspend = omap_i2c_runtime_suspend,
.runtime_resume = omap_i2c_runtime_resume,
SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
omap_i2c_runtime_resume, NULL)
};
#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
#else
#define OMAP_I2C_PM_OPS NULL
#endif
#endif /* CONFIG_PM */
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
.remove = omap_i2c_remove,
.remove = __devexit_p(omap_i2c_remove),
.driver = {
.name = "omap_i2c",
.owner = THIS_MODULE,

View File

@@ -415,19 +415,8 @@ static struct pci_driver pasemi_smb_driver = {
.remove = __devexit_p(pasemi_smb_remove),
};
static int __init pasemi_smb_init(void)
{
return pci_register_driver(&pasemi_smb_driver);
}
static void __exit pasemi_smb_exit(void)
{
pci_unregister_driver(&pasemi_smb_driver);
}
module_pci_driver(pasemi_smb_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
module_init(pasemi_smb_init);
module_exit(pasemi_smb_exit);

View File

@@ -21,11 +21,12 @@
Supports:
Intel PIIX4, 440MX
Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
AMD Hudson-2
SMSC Victory66
Note: we assume there can only be one device, with one SMBus interface.
Note: we assume there can only be one device, with one or more
SMBus interfaces.
*/
#include <linux/module.h>
@@ -94,10 +95,8 @@ MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. "
"EXTREMELY DANGEROUS!");
static unsigned short piix4_smba;
static int srvrworks_csb5_delay;
static struct pci_driver piix4_driver;
static struct i2c_adapter piix4_adapter;
static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
{
@@ -127,10 +126,15 @@ static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = {
{ },
};
struct i2c_piix4_adapdata {
unsigned short smba;
};
static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
const struct pci_device_id *id)
{
unsigned char temp;
unsigned short piix4_smba;
if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
(PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
@@ -206,7 +210,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
dev_err(&PIIX4_dev->dev,
"Host SMBus controller not enabled!\n");
release_region(piix4_smba, SMBIOSIZE);
piix4_smba = 0;
return -ENODEV;
}
}
@@ -224,12 +227,13 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
"SMBus Host Controller at 0x%x, revision %d\n",
piix4_smba, temp);
return 0;
return piix4_smba;
}
static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
const struct pci_device_id *id)
{
unsigned short piix4_smba;
unsigned short smba_idx = 0xcd6;
u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
@@ -273,7 +277,6 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
"0x%x already in use!\n", piix4_smba + i2ccfg_offset);
release_region(piix4_smba, SMBIOSIZE);
piix4_smba = 0;
return -EBUSY;
}
i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
@@ -288,30 +291,72 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
"SMBus Host Controller at 0x%x, revision %d\n",
piix4_smba, i2ccfg >> 4);
return 0;
return piix4_smba;
}
static int piix4_transaction(void)
static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev,
const struct pci_device_id *id,
unsigned short base_reg_addr)
{
/* Set up auxiliary SMBus controllers found on some
* AMD chipsets e.g. SP5100 (SB700 derivative) */
unsigned short piix4_smba;
/* Read address of auxiliary SMBus controller */
pci_read_config_word(PIIX4_dev, base_reg_addr, &piix4_smba);
if ((piix4_smba & 1) == 0) {
dev_dbg(&PIIX4_dev->dev,
"Auxiliary SMBus controller not enabled\n");
return -ENODEV;
}
piix4_smba &= 0xfff0;
if (piix4_smba == 0) {
dev_dbg(&PIIX4_dev->dev,
"Auxiliary SMBus base address uninitialized\n");
return -ENODEV;
}
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
return -ENODEV;
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "Auxiliary SMBus region 0x%x "
"already in use!\n", piix4_smba);
return -EBUSY;
}
dev_info(&PIIX4_dev->dev,
"Auxiliary SMBus Host Controller at 0x%x\n",
piix4_smba);
return piix4_smba;
}
static int piix4_transaction(struct i2c_adapter *piix4_adapter)
{
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
unsigned short piix4_smba = adapdata->smba;
int temp;
int result = 0;
int timeout = 0;
dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
dev_dbg(&piix4_adapter->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));
/* Make sure the SMBus host is ready to start transmitting */
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). "
dev_dbg(&piix4_adapter->dev, "SMBus busy (%02x). "
"Resetting...\n", temp);
outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
dev_err(&piix4_adapter->dev, "Failed! (%02x)\n", temp);
return -EBUSY;
} else {
dev_dbg(&piix4_adapter.dev, "Successful!\n");
dev_dbg(&piix4_adapter->dev, "Successful!\n");
}
}
@@ -330,35 +375,35 @@ static int piix4_transaction(void)
/* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT) {
dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
dev_err(&piix4_adapter->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
if (temp & 0x10) {
result = -EIO;
dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
dev_err(&piix4_adapter->dev, "Error: Failed bus transaction\n");
}
if (temp & 0x08) {
result = -EIO;
dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
dev_dbg(&piix4_adapter->dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}
if (temp & 0x04) {
result = -ENXIO;
dev_dbg(&piix4_adapter.dev, "Error: no response!\n");
dev_dbg(&piix4_adapter->dev, "Error: no response!\n");
}
if (inb_p(SMBHSTSTS) != 0x00)
outb_p(inb(SMBHSTSTS), SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
dev_err(&piix4_adapter.dev, "Failed reset at end of "
dev_err(&piix4_adapter->dev, "Failed reset at end of "
"transaction (%02x)\n", temp);
}
dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
dev_dbg(&piix4_adapter->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));
@@ -370,6 +415,8 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
unsigned short piix4_smba = adapdata->smba;
int i, len;
int status;
@@ -426,7 +473,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
status = piix4_transaction();
status = piix4_transaction(adap);
if (status)
return status;
@@ -466,12 +513,6 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = piix4_func,
};
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
@@ -496,6 +537,57 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
MODULE_DEVICE_TABLE (pci, piix4_ids);
static struct i2c_adapter *piix4_main_adapter;
static struct i2c_adapter *piix4_aux_adapter;
static int __devinit piix4_add_adapter(struct pci_dev *dev,
unsigned short smba,
struct i2c_adapter **padap)
{
struct i2c_adapter *adap;
struct i2c_piix4_adapdata *adapdata;
int retval;
adap = kzalloc(sizeof(*adap), GFP_KERNEL);
if (adap == NULL) {
release_region(smba, SMBIOSIZE);
return -ENOMEM;
}
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &smbus_algorithm;
adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL);
if (adapdata == NULL) {
kfree(adap);
release_region(smba, SMBIOSIZE);
return -ENOMEM;
}
adapdata->smba = smba;
/* set up the sysfs linkage to our parent device */
adap->dev.parent = &dev->dev;
snprintf(adap->name, sizeof(adap->name),
"SMBus PIIX4 adapter at %04x", smba);
i2c_set_adapdata(adap, adapdata);
retval = i2c_add_adapter(adap);
if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
kfree(adapdata);
kfree(adap);
release_region(smba, SMBIOSIZE);
return retval;
}
*padap = adap;
return 0;
}
static int __devinit piix4_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
@@ -510,30 +602,52 @@ static int __devinit piix4_probe(struct pci_dev *dev,
else
retval = piix4_setup(dev, id);
if (retval)
/* If no main SMBus found, give up */
if (retval < 0)
return retval;
/* set up the sysfs linkage to our parent device */
piix4_adapter.dev.parent = &dev->dev;
/* Try to register main SMBus adapter, give up if we can't */
retval = piix4_add_adapter(dev, retval, &piix4_main_adapter);
if (retval < 0)
return retval;
snprintf(piix4_adapter.name, sizeof(piix4_adapter.name),
"SMBus PIIX4 adapter at %04x", piix4_smba);
if ((retval = i2c_add_adapter(&piix4_adapter))) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
release_region(piix4_smba, SMBIOSIZE);
piix4_smba = 0;
/* Check for auxiliary SMBus on some AMD chipsets */
if (dev->vendor == PCI_VENDOR_ID_ATI &&
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
dev->revision < 0x40) {
retval = piix4_setup_aux(dev, id, 0x58);
if (retval > 0) {
/* Try to add the aux adapter if it exists,
* piix4_add_adapter will clean up if this fails */
piix4_add_adapter(dev, retval, &piix4_aux_adapter);
}
}
return retval;
return 0;
}
static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
{
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
if (adapdata->smba) {
i2c_del_adapter(adap);
release_region(adapdata->smba, SMBIOSIZE);
kfree(adapdata);
kfree(adap);
}
}
static void __devexit piix4_remove(struct pci_dev *dev)
{
if (piix4_smba) {
i2c_del_adapter(&piix4_adapter);
release_region(piix4_smba, SMBIOSIZE);
piix4_smba = 0;
if (piix4_main_adapter) {
piix4_adap_remove(piix4_main_adapter);
piix4_main_adapter = NULL;
}
if (piix4_aux_adapter) {
piix4_adap_remove(piix4_aux_adapter);
piix4_aux_adapter = NULL;
}
}
@@ -544,20 +658,9 @@ static struct pci_driver piix4_driver = {
.remove = __devexit_p(piix4_remove),
};
static int __init i2c_piix4_init(void)
{
return pci_register_driver(&piix4_driver);
}
static void __exit i2c_piix4_exit(void)
{
pci_unregister_driver(&piix4_driver);
}
module_pci_driver(piix4_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
"Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("PIIX4 SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_piix4_init);
module_exit(i2c_piix4_exit);

View File

@@ -306,8 +306,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
if (pmcmsptwi_data.irq) {
rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
pldev->name, &pmcmsptwi_data);
IRQF_SHARED, pldev->name, &pmcmsptwi_data);
if (rc == 0) {
/*
* Enable 'DONE' interrupt only.

View File

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

View File

@@ -227,28 +227,138 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
return 0;
}
static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
struct pmac_i2c_bus *bus,
struct device_node *node)
{
const __be32 *prop;
int len;
/* First check for valid "reg" */
prop = of_get_property(node, "reg", &len);
if (prop && (len >= sizeof(int)))
return (be32_to_cpup(prop) & 0xff) >> 1;
/* Then check old-style "i2c-address" */
prop = of_get_property(node, "i2c-address", &len);
if (prop && (len >= sizeof(int)))
return (be32_to_cpup(prop) & 0xff) >> 1;
/* Now handle some devices with missing "reg" properties */
if (!strcmp(node->name, "cereal"))
return 0x60;
else if (!strcmp(node->name, "deq"))
return 0x34;
dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name);
return 0xffffffff;
}
static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
const char *type,
u32 addr)
{
struct i2c_board_info info = {};
struct i2c_client *newdev;
strncpy(info.type, type, sizeof(info.type));
info.addr = addr;
newdev = i2c_new_device(adap, &info);
if (!newdev)
dev_err(&adap->dev,
"i2c-powermac: Failure to register missing %s\n",
type);
}
static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
struct pmac_i2c_bus *bus,
bool found_onyx)
{
struct device_node *busnode = pmac_i2c_get_bus_node(bus);
int rc;
/* Check for the onyx audio codec */
#define ONYX_REG_CONTROL 67
if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
union i2c_smbus_data data;
rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
&data);
if (rc >= 0)
i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
&data);
if (rc >= 0)
i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
}
}
static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
struct device_node *node,
u32 addr, char *type, int type_size)
{
char tmp[16];
/* Note: we to _NOT_ want the standard
* i2c drivers to match with any of our powermac stuff
* unless they have been specifically modified to handle
* it on a case by case basis. For example, for thermal
* control, things like lm75 etc... shall match with their
* corresponding windfarm drivers, _NOT_ the generic ones,
* so we force a prefix of AAPL, onto the modalias to
* make that happen
*/
/* First try proper modalias */
if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
snprintf(type, type_size, "MAC,%s", tmp);
return true;
}
/* Now look for known workarounds */
if (!strcmp(node->name, "deq")) {
/* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
if (addr == 0x34) {
snprintf(type, type_size, "MAC,tas3001");
return true;
} else if (addr == 0x35) {
snprintf(type, type_size, "MAC,tas3004");
return true;
}
}
dev_err(&adap->dev, "i2c-powermac: modalias failure"
" on %s\n", node->full_name);
return false;
}
static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
struct pmac_i2c_bus *bus)
{
struct i2c_client *newdev;
struct device_node *node;
bool found_onyx = 0;
/*
* In some cases we end up with the via-pmu node itself, in this
* case we skip this function completely as the device-tree will
* not contain anything useful.
*/
if (!strcmp(adap->dev.of_node->name, "via-pmu"))
return;
for_each_child_of_node(adap->dev.of_node, node) {
struct i2c_board_info info = {};
struct dev_archdata dev_ad = {};
const __be32 *reg;
char tmp[16];
u32 addr;
int len;
/* Get address & channel */
reg = of_get_property(node, "reg", &len);
if (!reg || (len < sizeof(int))) {
dev_err(&adap->dev, "i2c-powermac: invalid reg on %s\n",
node->full_name);
addr = i2c_powermac_get_addr(adap, bus, node);
if (addr == 0xffffffff)
continue;
}
addr = be32_to_cpup(reg);
/* Multibus setup, check channel */
if (!pmac_i2c_match_adapter(node, adap))
@@ -257,27 +367,23 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
node->full_name);
/* Make up a modalias. Note: we to _NOT_ want the standard
* i2c drivers to match with any of our powermac stuff
* unless they have been specifically modified to handle
* it on a case by case basis. For example, for thermal
* control, things like lm75 etc... shall match with their
* corresponding windfarm drivers, _NOT_ the generic ones,
* so we force a prefix of AAPL, onto the modalias to
* make that happen
/*
* Keep track of some device existence to handle
* workarounds later.
*/
if (of_modalias_node(node, tmp, sizeof(tmp)) < 0) {
dev_err(&adap->dev, "i2c-powermac: modalias failure"
" on %s\n", node->full_name);
if (of_device_is_compatible(node, "pcm3052"))
found_onyx = true;
/* Make up a modalias */
if (!i2c_powermac_get_type(adap, node, addr,
info.type, sizeof(info.type))) {
continue;
}
snprintf(info.type, sizeof(info.type), "MAC,%s", tmp);
/* Fill out the rest of the info structure */
info.addr = (addr & 0xff) >> 1;
info.addr = addr;
info.irq = irq_of_parse_and_map(node, 0);
info.of_node = of_node_get(node);
info.archdata = &dev_ad;
newdev = i2c_new_device(adap, &info);
if (!newdev) {
@@ -292,6 +398,9 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
continue;
}
}
/* Additional workarounds */
i2c_powermac_add_missing(adap, bus, found_onyx);
}
static int __devinit i2c_powermac_probe(struct platform_device *dev)

View File

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

View File

@@ -163,17 +163,7 @@ static struct pci_driver ce4100_i2c_driver = {
.remove = __devexit_p(ce4100_i2c_remove),
};
static int __init ce4100_i2c_init(void)
{
return pci_register_driver(&ce4100_i2c_driver);
}
module_init(ce4100_i2c_init);
static void __exit ce4100_i2c_exit(void)
{
pci_unregister_driver(&ce4100_i2c_driver);
}
module_exit(ce4100_i2c_exit);
module_pci_driver(ce4100_i2c_driver);
MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
MODULE_LICENSE("GPL v2");

View File

@@ -41,13 +41,6 @@
#include <asm/irq.h>
#ifndef CONFIG_HAVE_CLK
#define clk_get(dev, id) NULL
#define clk_put(clk) do { } while (0)
#define clk_disable(clk) do { } while (0)
#define clk_enable(clk) do { } while (0)
#endif
struct pxa_reg_layout {
u32 ibmr;
u32 idbr;

View File

@@ -122,7 +122,7 @@ static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pde
{
if (pdev->dev.of_node) {
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;
}
@@ -609,7 +609,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
if (ret != -EAGAIN) {
clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev);
pm_runtime_put(&adap->dev);
return ret;
}
@@ -619,7 +619,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
}
clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev);
pm_runtime_put(&adap->dev);
return -EREMOTEIO;
}

View File

@@ -513,21 +513,8 @@ static struct pci_driver sis630_driver = {
.remove = __devexit_p(sis630_remove),
};
static int __init i2c_sis630_init(void)
{
return pci_register_driver(&sis630_driver);
}
static void __exit i2c_sis630_exit(void)
{
pci_unregister_driver(&sis630_driver);
}
module_pci_driver(sis630_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
MODULE_DESCRIPTION("SIS630 SMBus driver");
module_init(i2c_sis630_init);
module_exit(i2c_sis630_exit);

View File

@@ -324,21 +324,8 @@ static struct pci_driver sis96x_driver = {
.remove = __devexit_p(sis96x_remove),
};
static int __init i2c_sis96x_init(void)
{
return pci_register_driver(&sis96x_driver);
}
static void __exit i2c_sis96x_exit(void)
{
pci_unregister_driver(&sis96x_driver);
}
module_pci_driver(sis96x_driver);
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
MODULE_DESCRIPTION("SiS96x SMBus driver");
MODULE_LICENSE("GPL");
/* Register initialization functions using helper macros */
module_init(i2c_sis96x_init);
module_exit(i2c_sis96x_exit);

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
* ST DDC I2C master mode driver, used in e.g. U300 series platforms.
* 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
* @pdev: parent platform device
* @adapter: corresponding I2C adapter
* @phybase: location of I/O area in memory
* @physize: size of I/O area in memory
* @clk: hardware block clock
* @irq: assigned interrupt line
* @cmd_issue_lock: this locks the following cmd_ variables
@@ -155,8 +153,6 @@ module_param(scl_frequency, uint, 0644);
struct stu300_dev {
struct platform_device *pdev;
struct i2c_adapter adapter;
resource_size_t phybase;
resource_size_t physize;
void __iomem *virtbase;
struct clk *clk;
int irq;
@@ -873,64 +869,44 @@ stu300_probe(struct platform_device *pdev)
int ret = 0;
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) {
dev_err(&pdev->dev, "could not allocate device struct\n");
ret = -ENOMEM;
goto err_no_devmem;
return -ENOMEM;
}
bus_nr = pdev->id;
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)) {
ret = PTR_ERR(dev->clk);
dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
goto err_no_clk;
return PTR_ERR(dev->clk);
}
dev->pdev = pdev;
platform_set_drvdata(pdev, dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENOENT;
goto err_no_resource;
}
if (!res)
return -ENOENT;
dev->phybase = res->start;
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->virtbase = devm_request_and_ioremap(&pdev->dev, res);
dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
"base %p\n", bus_nr, dev->virtbase);
if (!dev->virtbase) {
ret = -ENOMEM;
goto err_no_ioremap;
}
if (!dev->virtbase)
return -ENOMEM;
dev->irq = platform_get_irq(pdev, 0);
if (request_irq(dev->irq, stu300_irh, 0,
NAME, dev)) {
ret = -EIO;
goto err_no_irq;
}
ret = devm_request_irq(&pdev->dev, dev->irq, stu300_irh, 0, NAME, dev);
if (ret < 0)
return ret;
dev->speed = scl_frequency;
clk_enable(dev->clk);
clk_prepare_enable(dev->clk);
ret = stu300_init_hw(dev);
clk_disable(dev->clk);
if (ret != 0) {
dev_err(&dev->pdev->dev, "error initializing hardware.\n");
goto err_init_hw;
return -EIO;
}
/* 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() */
ret = i2c_add_numbered_adapter(adap);
if (ret) {
dev_err(&dev->pdev->dev, "failure adding ST Micro DDC "
dev_err(&pdev->dev, "failure adding ST Micro DDC "
"I2C adapter\n");
goto err_add_adapter;
return ret;
}
return 0;
err_add_adapter:
err_init_hw:
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;
platform_set_drvdata(pdev, dev);
return 0;
}
#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 */
stu300_wr8(0x00, dev->virtbase + I2C_CR);
return 0;
}
static int stu300_resume(struct platform_device *pdev)
static int stu300_resume(struct device *device)
{
int ret = 0;
struct stu300_dev *dev = platform_get_drvdata(pdev);
struct stu300_dev *dev = dev_get_drvdata(device);
clk_enable(dev->clk);
ret = stu300_init_hw(dev);
clk_disable(dev->clk);
if (ret != 0)
dev_err(&pdev->dev, "error re-initializing hardware.\n");
dev_err(device, "error re-initializing hardware.\n");
return ret;
}
static SIMPLE_DEV_PM_OPS(stu300_pm, stu300_suspend, stu300_resume);
#define STU300_I2C_PM (&stu300_pm)
#else
#define stu300_suspend NULL
#define stu300_resume NULL
#define STU300_I2C_PM NULL
#endif
static int __exit
@@ -1013,12 +975,7 @@ stu300_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter);
/* Turn off everything */
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);
kfree(dev);
return 0;
}
@@ -1026,10 +983,9 @@ static struct platform_driver stu300_i2c_driver = {
.driver = {
.name = NAME,
.owner = THIS_MODULE,
.pm = STU300_I2C_PM,
},
.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_IE_ENABLE (1<<17)
#define I2C_HEADER_REPEAT_START (1<<16)
#define I2C_HEADER_CONTINUE_XFER (1<<15)
#define I2C_HEADER_MASTER_ADDR_SHIFT 12
#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
@@ -106,7 +119,6 @@
* @adapter: core i2c layer adapter information
* @clk: clock reference for i2c controller
* @i2c_clk: clock reference for i2c bus
* @iomem: memory resource for registers
* @base: ioremapped registers cookie
* @cont_id: i2c controller id, used for for packet header
* @irq: irq number of transfer complete interrupt
@@ -124,7 +136,6 @@ struct tegra_i2c_dev {
struct i2c_adapter adapter;
struct clk *clk;
struct clk *i2c_clk;
struct resource *iomem;
void __iomem *base;
int cont_id;
int irq;
@@ -165,6 +176,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long 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)
@@ -341,7 +356,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
u32 val;
int err = 0;
clk_enable(i2c_dev->clk);
clk_prepare_enable(i2c_dev->clk);
tegra_periph_reset_assert(i2c_dev->clk);
udelay(2);
@@ -372,7 +387,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
clk_disable(i2c_dev->clk);
clk_disable_unprepare(i2c_dev->clk);
if (i2c_dev->irq_disabled) {
i2c_dev->irq_disabled = 0;
@@ -449,7 +464,7 @@ err:
}
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 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);
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;
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
@@ -546,20 +563,27 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
if (i2c_dev->is_suspended)
return -EBUSY;
clk_enable(i2c_dev->clk);
clk_prepare_enable(i2c_dev->clk);
for (i = 0; i < num; i++) {
int stop = (i == (num - 1)) ? 1 : 0;
ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop);
enum msg_end_type end_type = MSG_END_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)
break;
}
clk_disable(i2c_dev->clk);
clk_disable_unprepare(i2c_dev->clk);
return ret ?: i;
}
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 = {
@@ -572,7 +596,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
struct tegra_i2c_dev *i2c_dev;
struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
struct resource *res;
struct resource *iomem;
struct clk *clk;
struct clk *i2c_clk;
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");
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) {
dev_err(&pdev->dev, "Cannot ioremap I2C region\n");
return -ENOMEM;
dev_err(&pdev->dev, "Cannot request/ioremap I2C registers\n");
return -EADDRNOTAVAIL;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(&pdev->dev, "no irq resource\n");
ret = -EINVAL;
goto err_iounmap;
return -EINVAL;
}
irq = res->start;
clk = clk_get(&pdev->dev, NULL);
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "missing controller clock");
ret = PTR_ERR(clk);
goto err_release_region;
return PTR_ERR(clk);
}
i2c_clk = clk_get(&pdev->dev, "i2c");
i2c_clk = devm_clk_get(&pdev->dev, "i2c");
if (IS_ERR(i2c_clk)) {
dev_err(&pdev->dev, "missing bus clock");
ret = PTR_ERR(i2c_clk);
goto err_clk_put;
return PTR_ERR(i2c_clk);
}
i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL);
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev) {
ret = -ENOMEM;
goto err_i2c_clk_put;
dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev");
return -ENOMEM;
}
i2c_dev->base = base;
i2c_dev->clk = clk;
i2c_dev->i2c_clk = i2c_clk;
i2c_dev->iomem = iomem;
i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id;
@@ -657,16 +671,17 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
ret = tegra_i2c_init(i2c_dev);
if (ret) {
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) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
goto err_free;
return ret;
}
clk_enable(i2c_dev->i2c_clk);
clk_prepare_enable(i2c_dev->i2c_clk);
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
i2c_dev->adapter.owner = THIS_MODULE;
@@ -681,45 +696,26 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
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);
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)
{
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
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;
}
#ifdef CONFIG_PM
static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
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_dev->is_suspended = true;
@@ -728,9 +724,9 @@ static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state)
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;
i2c_lock_adapter(&i2c_dev->adapter);
@@ -748,6 +744,11 @@ static int tegra_i2c_resume(struct platform_device *pdev)
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
#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);
#else
#define tegra_i2c_of_match NULL
#endif
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
.remove = __devexit_p(tegra_i2c_remove),
#ifdef CONFIG_PM
.suspend = tegra_i2c_suspend,
.resume = tegra_i2c_resume,
#endif
.driver = {
.name = "tegra-i2c",
.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

@@ -143,6 +143,7 @@ static const struct i2c_algorithm usb_algorithm = {
static const struct usb_device_id i2c_tiny_usb_table[] = {
{ USB_DEVICE(0x0403, 0xc631) }, /* FTDI */
{ USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */
{ USB_DEVICE(0x1964, 0x0001) }, /* Robofuzz OSIF */
{ } /* Terminating entry */
};

View File

@@ -161,20 +161,8 @@ static struct pci_driver vt586b_driver = {
.remove = __devexit_p(vt586b_remove),
};
static int __init i2c_vt586b_init(void)
{
return pci_register_driver(&vt586b_driver);
}
static void __exit i2c_vt586b_exit(void)
{
pci_unregister_driver(&vt586b_driver);
}
module_pci_driver(vt586b_driver);
MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge");
MODULE_LICENSE("GPL");
module_init(i2c_vt586b_init);
module_exit(i2c_vt586b_exit);

View File

@@ -1311,6 +1311,37 @@ module_exit(i2c_exit);
* ----------------------------------------------------
*/
/**
* __i2c_transfer - unlocked flavor of i2c_transfer
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
* terminate the operation; each message begins with a START.
* @num: Number of messages to be executed.
*
* Returns negative errno, else the number of messages executed.
*
* Adapter lock must be held when calling this function. No debug logging
* takes place. adap->algo->master_xfer existence isn't checked.
*/
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
return ret;
}
EXPORT_SYMBOL(__i2c_transfer);
/**
* i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus
@@ -1325,8 +1356,7 @@ module_exit(i2c_exit);
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
int ret;
/* REVISIT the fault reporting model here is weak:
*
@@ -1364,15 +1394,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c_lock_adapter(adap);
}
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
ret = __i2c_transfer(adap, msgs, num);
i2c_unlock_adapter(adap);
return ret;
@@ -2122,7 +2144,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
int try;
s32 res;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
if (adapter->algo->smbus_xfer) {
i2c_lock_adapter(adapter);
@@ -2140,11 +2162,17 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
break;
}
i2c_unlock_adapter(adapter);
} else
res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
command, protocol, data);
return res;
if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
return res;
/*
* Fall back to i2c_smbus_xfer_emulated if the adapter doesn't
* implement native support for the SMBus operation.
*/
}
return i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
command, protocol, data);
}
EXPORT_SYMBOL(i2c_smbus_xfer);

View File

@@ -245,18 +245,7 @@ int i2c_handle_smbus_alert(struct i2c_client *ara)
}
EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
static int __init i2c_smbus_init(void)
{
return i2c_add_driver(&smbalert_driver);
}
static void __exit i2c_smbus_exit(void)
{
i2c_del_driver(&smbalert_driver);
}
module_init(i2c_smbus_init);
module_exit(i2c_smbus_exit);
module_i2c_driver(smbalert_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("SMBus protocol extensions support");

View File

@@ -396,6 +396,6 @@ static struct i2c_driver pca9541_driver = {
module_i2c_driver(pca9541_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
MODULE_LICENSE("GPL v2");