summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-acorn.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c5
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c1
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c6
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-at91.c2
-rw-r--r--drivers/i2c/busses/i2c-au1550.c1
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c3
-rw-r--r--drivers/i2c/busses/i2c-cpm.c1
-rw-r--r--drivers/i2c/busses/i2c-elektor.c1
-rw-r--r--drivers/i2c/busses/i2c-highlander.c4
-rw-r--r--drivers/i2c/busses/i2c-hydra.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c51
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c1
-rw-r--r--drivers/i2c/busses/i2c-mpc.c1
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c1
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-omap.c420
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c1
-rw-r--r--drivers/i2c/busses/i2c-parport.c5
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c1
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c6
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c209
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c78
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c2
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c5
-rw-r--r--drivers/i2c/busses/i2c-sis630.c5
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c1
-rw-r--r--drivers/i2c/busses/i2c-via.c1
-rw-r--r--drivers/i2c/busses/i2c-viapro.c1
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c1
-rw-r--r--drivers/i2c/busses/scx200_i2c.c1
-rw-r--r--drivers/i2c/chips/Kconfig83
-rw-r--r--drivers/i2c/chips/Makefile6
-rw-r--r--drivers/i2c/chips/at24.c582
-rw-r--r--drivers/i2c/chips/eeprom.c257
-rw-r--r--drivers/i2c/chips/isp1301_omap.c1654
-rw-r--r--drivers/i2c/chips/mcu_mpc8349emitx.c209
-rw-r--r--drivers/i2c/chips/menelaus.c1285
-rw-r--r--drivers/i2c/chips/tps65010.c1072
-rw-r--r--drivers/i2c/i2c-core.c10
49 files changed, 540 insertions, 5451 deletions
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 75089febbc1..9fee3ca1734 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -83,7 +83,6 @@ static struct i2c_algo_bit_data ioc_data = {
};
static struct i2c_adapter ioc_ops = {
- .id = I2C_HW_B_IOC,
.algo_data = &ioc_data,
};
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 9cead9b9458..981e080b32a 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -476,7 +476,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI1535,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index fc3e5b02642..f70f46582c6 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -386,7 +386,6 @@ static const struct i2c_algorithm ali1563_algorithm = {
static struct i2c_adapter ali1563_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI1563,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ali1563_algorithm,
};
@@ -399,8 +398,8 @@ static int __devinit ali1563_probe(struct pci_dev * dev,
if ((error = ali1563_setup(dev)))
goto exit;
ali1563_adapter.dev.parent = &dev->dev;
- sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
- ali1563_smba);
+ snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
+ "SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
if ((error = i2c_add_adapter(&ali1563_adapter)))
goto exit_shutdown;
return 0;
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 234fdde7d40..39066dee46e 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -473,7 +473,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI15X3,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 8ba2bcf727d..378fcb5d578 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -197,8 +197,8 @@ static int __init amd756_s4882_init(void)
for (i = 1; i < 5; i++) {
s4882_algo[i] = *(amd756_smbus.algo);
s4882_adapter[i] = amd756_smbus;
- sprintf(s4882_adapter[i].name,
- "SMBus 8111 adapter (CPU%d)", i-1);
+ snprintf(s4882_adapter[i].name, sizeof(s4882_adapter[i].name),
+ "SMBus 8111 adapter (CPU%d)", i-1);
s4882_adapter[i].algo = s4882_algo+i;
s4882_adapter[i].dev.parent = amd756_smbus.dev.parent;
}
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 424dad6f18d..220f4a1eee1 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -298,7 +298,6 @@ static const struct i2c_algorithm smbus_algorithm = {
struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_AMD756,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -380,8 +379,9 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
/* set up the sysfs linkage to our parent device */
amd756_smbus.dev.parent = &pdev->dev;
- sprintf(amd756_smbus.name, "SMBus %s adapter at %04x",
- chipname[id->driver_data], amd756_ioport);
+ snprintf(amd756_smbus.name, sizeof(amd756_smbus.name),
+ "SMBus %s adapter at %04x", chipname[id->driver_data],
+ amd756_ioport);
error = i2c_add_adapter(&amd756_smbus);
if (error) {
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 3972208876b..edab51973bf 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -387,7 +387,6 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base);
- smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 9efb0213725..67d9dc5b351 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -222,7 +222,7 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev)
rc = -ENOMEM;
goto fail2;
}
- sprintf(adapter->name, "AT91");
+ snprintf(adapter->name, sizeof(adapter->name), "AT91");
adapter->algo = &at91_algorithm;
adapter->class = I2C_CLASS_HWMON;
adapter->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 66a04c2c660..f78ce523e3d 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -400,7 +400,6 @@ i2c_au1550_probe(struct platform_device *pdev)
priv->xfer_timeout = 200;
priv->ack_timeout = 200;
- priv->adap.id = I2C_HW_AU1550_PSC;
priv->adap.nr = pdev->id;
priv->adap.algo = &au1550_algo;
priv->adap.algo_data = priv;
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 3c855ff2992..fc548b3d002 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -651,12 +651,11 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
iface->timeout_timer.data = (unsigned long)iface;
p_adap = &iface->adap;
- p_adap->id = I2C_HW_BLACKFIN;
p_adap->nr = pdev->id;
strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
- p_adap->class = I2C_CLASS_ALL;
+ p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
p_adap->dev.parent = &pdev->dev;
rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 228f7572306..3fcf78e906d 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -365,6 +365,7 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
pmsg = &msgs[tptr];
if (pmsg->flags & I2C_M_RD)
ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+ (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) ||
!(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
1 * HZ);
else
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 0ed3ccb81b6..448b4bf35eb 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -202,7 +202,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- .id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
.name = "i2c-elektor",
};
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index f4d22ae9d29..e5a8dae4a28 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -92,7 +92,7 @@ static void highlander_i2c_setup(struct highlander_i2c_dev *dev)
static void smbus_write_data(u8 *src, u16 *dst, int len)
{
for (; len > 1; len -= 2) {
- *dst++ = be16_to_cpup((u16 *)src);
+ *dst++ = be16_to_cpup((__be16 *)src);
src += 2;
}
@@ -103,7 +103,7 @@ static void smbus_write_data(u8 *src, u16 *dst, int len)
static void smbus_read_data(u16 *src, u8 *dst, int len)
{
for (; len > 1; len -= 2) {
- *(u16 *)dst = cpu_to_be16p(src++);
+ *(__be16 *)dst = cpu_to_be16p(src++);
dst += 2;
}
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 648aa7baff8..bec9b845dd1 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -102,7 +102,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
static struct i2c_adapter hydra_adap = {
.owner = THIS_MODULE,
.name = "Hydra i2c",
- .id = I2C_HW_B_HYDRA,
.algo_data = &hydra_bit_data,
};
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 5123eb69a97..230238df56c 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -64,7 +64,7 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
/* I801 SMBus address offsets */
#define SMBHSTSTS (0 + i801_smba)
@@ -556,7 +556,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_I801,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -583,6 +582,40 @@ static struct pci_device_id i801_ids[] = {
MODULE_DEVICE_TABLE (pci, i801_ids);
+#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
+static unsigned char apanel_addr;
+
+/* Scan the system ROM for the signature "FJKEYINF" */
+static __init const void __iomem *bios_signature(const void __iomem *bios)
+{
+ ssize_t offset;
+ const unsigned char signature[] = "FJKEYINF";
+
+ for (offset = 0; offset < 0x10000; offset += 0x10) {
+ if (check_signature(bios + offset, signature,
+ sizeof(signature)-1))
+ return bios + offset;
+ }
+ return NULL;
+}
+
+static void __init input_apanel_init(void)
+{
+ void __iomem *bios;
+ const void __iomem *p;
+
+ bios = ioremap(0xF0000, 0x10000); /* Can't fail */
+ p = bios_signature(bios);
+ if (p) {
+ /* just use the first address */
+ apanel_addr = readb(p + 8 + 3) >> 1;
+ }
+ iounmap(bios);
+}
+#else
+static void __init input_apanel_init(void) {}
+#endif
+
static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned char temp;
@@ -667,6 +700,19 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
goto exit_release;
}
+
+ /* Register optional slaves */
+#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
+ if (apanel_addr) {
+ struct i2c_board_info info;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = apanel_addr;
+ strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
+ i2c_new_device(&i801_adapter, &info);
+ }
+#endif
+
return 0;
exit_release:
@@ -717,6 +763,7 @@ static struct pci_driver i801_driver = {
static int __init i2c_i801_init(void)
{
+ input_apanel_init();
return pci_register_driver(&i801_driver);
}
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 651f2f1ae5b..88f0db73b36 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -746,7 +746,6 @@ static int __devinit iic_probe(struct of_device *ofdev,
adap->dev.parent = &ofdev->dev;
strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev);
- adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &iic_algo;
adap->timeout = 1;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index fc2714ac0c0..3190690c26c 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -480,7 +480,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
}
memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
- new_adapter->id = I2C_HW_IOP3XX;
new_adapter->owner = THIS_MODULE;
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
new_adapter->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 05d72e98135..8e846797048 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -116,7 +116,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.udelay = 6;
drv_data->algo_data.timeout = 100;
- drv_data->adapter.id = I2C_HW_B_IXP2000,
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
sizeof(drv_data->adapter.name));
drv_data->adapter.algo_data = &drv_data->algo_data,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a9a45fcc854..aedbbe6618d 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -310,7 +310,6 @@ static const struct i2c_algorithm mpc_algo = {
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.name = "MPC adapter",
- .id = I2C_HW_MPC107,
.algo = &mpc_algo,
.timeout = 1,
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 9e8118d2fe6..eeda276f8f1 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -527,7 +527,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_unmap_regs;
}
drv_data->adapter.dev.parent = &pd->dev;
- drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 3b19bc41a60..05af6cd7f27 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -355,7 +355,6 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
return -EBUSY;
}
smbus->adapter.owner = THIS_MODULE;
- smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 608038d64f8..be8ee2cac8b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Updated to work with multiple I2C interfaces on 24xx by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ * Tony Lindgren <tony@atomide.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * Juha Yrjölä <juha.yrjola@solidboot.com>
+ * Syed Khasim <x0khasim@ti.com>
+ * Nishant Menon <nm@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,8 +36,14 @@
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/io.h>
+
+/* I2C controller revisions */
+#define OMAP_I2C_REV_2 0x20
-#include <asm/io.h>
+/* I2C controller revisions present on specific hardware */
+#define OMAP_I2C_REV_ON_2430 0x36
+#define OMAP_I2C_REV_ON_3430 0x3C
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -43,6 +52,8 @@
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
+/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
+#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
@@ -55,8 +66,11 @@
#define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
+#define OMAP_I2C_BUFSTAT_REG 0x40
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
+#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@@ -64,7 +78,8 @@
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
-#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */
+#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
+#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@@ -76,13 +91,34 @@
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
+/* I2C WE wakeup enable register */
+#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */
+#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */
+#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/
+#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */
+#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */
+#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */
+#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */
+#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */
+#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */
+#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */
+
+#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \
+ OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \
+ OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \
+ OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \
+ OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE)
+
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
+#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
+#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
+#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -91,6 +127,10 @@
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
+/* I2C SCL time value when Master */
+#define OMAP_I2C_SCLL_HSSCLL 8
+#define OMAP_I2C_SCLH_HSSCLH 8
+
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@@ -103,17 +143,19 @@
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif
-/* I2C System Status register (OMAP_I2C_SYSS): */
-#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
+/* OCP_SYSSTATUS bit definitions */
+#define SYSS_RESETDONE_MASK (1 << 0)
+
+/* OCP_SYSCONFIG bit definitions */
+#define SYSC_CLOCKACTIVITY_MASK (0x3 << 8)
+#define SYSC_SIDLEMODE_MASK (0x3 << 3)
+#define SYSC_ENAWAKEUP_MASK (1 << 2)
+#define SYSC_SOFTRESET_MASK (1 << 1)
+#define SYSC_AUTOIDLE_MASK (1 << 0)
-/* I2C System Configuration Register (OMAP_I2C_SYSC): */
-#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
+#define SYSC_IDLEMODE_SMART 0x2
+#define SYSC_CLOCKACTIVITY_FCLK 0x2
-/* REVISIT: Use platform_data instead of module parameters */
-/* Fast Mode = 400 kHz, Standard = 100 kHz */
-static int clock = 100; /* Default: 100 kHz */
-module_param(clock, int, 0);
-MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
struct omap_i2c_dev {
struct device *dev;
@@ -123,11 +165,17 @@ struct omap_i2c_dev {
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
struct resource *ioarea;
+ u32 speed; /* Speed of bus in Khz */
u16 cmd_err;
u8 *buf;
size_t buf_len;
struct i2c_adapter adapter;
- unsigned rev1:1;
+ u8 fifo_size; /* use as flag and value
+ * fifo_size==0 implies no fifo
+ * if set, should be trsh+1
+ */
+ u8 rev;
+ unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1;
u16 iestate; /* Saved interrupt register */
};
@@ -143,9 +191,9 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg);
}
-static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) {
dev->iclk = NULL;
@@ -178,25 +226,33 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
+ WARN_ON(!dev->idle);
+
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
+ dev->idle = 0;
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- dev->idle = 0;
}
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
- dev->idle = 1;
+ WARN_ON(dev->idle);
+
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev1)
- iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
- else
+ if (dev->rev < OMAP_I2C_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 before the dev->idle store occurs */
+ omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ }
+ dev->idle = 1;
clk_disable(dev->fclk);
if (dev->iclk != NULL)
clk_disable(dev->iclk);
@@ -204,18 +260,20 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
- u16 psc = 0;
+ u16 psc = 0, scll = 0, sclh = 0;
+ u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout;
+ unsigned long internal_clk = 0;
- if (!dev->rev1) {
- omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+ if (dev->rev >= OMAP_I2C_REV_2) {
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
- OMAP_I2C_SYSS_RDONE)) {
+ SYSS_RESETDONE_MASK)) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting "
"for controller reset\n");
@@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
}
msleep(1);
}
+
+ /* SYSC register is cleared by the reset; rewrite it */
+ if (dev->rev == OMAP_I2C_REV_ON_2430) {
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+ SYSC_AUTOIDLE_MASK);
+
+ } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
+ u32 v;
+
+ v = SYSC_AUTOIDLE_MASK;
+ v |= SYSC_ENAWAKEUP_MASK;
+ v |= (SYSC_IDLEMODE_SMART <<
+ __ffs(SYSC_SIDLEMODE_MASK));
+ v |= (SYSC_CLOCKACTIVITY_FCLK <<
+ __ffs(SYSC_CLOCKACTIVITY_MASK));
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+ /*
+ * Enabling all wakup sources to stop I2C freezing on
+ * WFI instruction.
+ * REVISIT: Some wkup sources might not be needed.
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+ OMAP_I2C_WE_ALL);
+
+ }
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+
+ /* HSI2C controller internal clk rate should be 19.2 Mhz */
+ internal_clk = 19200;
+ fclk_rate = clk_get_rate(dev->fclk) / 1000;
+
+ /* Compute prescaler divisor */
+ psc = fclk_rate / internal_clk;
+ psc = psc - 1;
+
+ /* If configured for High Speed */
+ if (dev->speed > 400) {
+ /* For first phase of HS mode */
+ fsscll = internal_clk / (400 * 2) - 6;
+ fssclh = internal_clk / (400 * 2) - 6;
+
+ /* For second phase of HS mode */
+ hsscll = fclk_rate / (dev->speed * 2) - 6;
+ hssclh = fclk_rate / (dev->speed * 2) - 6;
+ } else {
+ /* To handle F/S modes */
+ fsscll = internal_clk / (dev->speed * 2) - 6;
+ fssclh = internal_clk / (dev->speed * 2) - 6;
+ }
+ scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
+ sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
+ } else {
+ /* Program desired operating rate */
+ fclk_rate /= (psc + 1) * 1000;
+ if (psc > 2)
+ psc = 2;
+ scll = fclk_rate / (dev->speed * 2) - 7 + psc;
+ sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
+ }
+
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
- /* Program desired operating rate */
- fclk_rate /= (psc + 1) * 1000;
- if (psc > 2)
- psc = 2;
+ /* SCL low and high time values */
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
- fclk_rate / (clock * 2) - 7 + psc);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
- fclk_rate / (clock * 2) - 7 + psc);
+ if (dev->fifo_size)
+ /* Note: setup required fifo size - 1 */
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+ (dev->fifo_size - 1) << 8 | /* RTRSH */
+ OMAP_I2C_BUF_RXFIF_CLR |
+ (dev->fifo_size - 1) | /* XTRSH */
+ OMAP_I2C_BUF_TXFIF_CLR);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
- (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
- OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL));
+ (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+ OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -316,20 +439,59 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+ /* Clear the FIFO Buffers */
+ w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+ 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);
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+
+ /* High speed configuration */
+ if (dev->speed > 400)
+ w |= OMAP_I2C_CON_OPMODE_HS;
+
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
- if (stop)
+
+ if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
- r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- OMAP_I2C_TIMEOUT);
+ /*
+ * Don't write stt and stp together on some hardware.
+ */
+ if (dev->b_hw && stop) {
+ unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
+ u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+ while (con & OMAP_I2C_CON_STT) {
+ con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+
+ /* Let the user know if i2c is in a bad state */
+ if (time_after(jiffies, delay)) {
+ dev_err(dev->dev, "controller timed out "
+ "waiting for start condition to finish\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ w |= OMAP_I2C_CON_STP;
+ w &= ~OMAP_I2C_CON_STT;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+ }
+
+ /*
+ * 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);
dev->buf_len = 0;
if (r < 0)
return r;
@@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev);
- if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ r = omap_i2c_wait_for_bb(dev);
+ if (r < 0)
goto out;
for (i = 0; i < num; i++) {
@@ -411,6 +574,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+/* rev1 devices are apparently only on some 15xx */
+#ifdef CONFIG_ARCH_OMAP15XX
+
static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id)
{
@@ -465,6 +631,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
+#else
+#define omap_i2c_rev1_isr NULL
+#endif
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id)
@@ -472,7 +641,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
struct omap_i2c_dev *dev = dev_id;
u16 bits;
u16 stat, w;
- int count = 0;
+ int err, count = 0;
if (dev->idle)
return IRQ_NONE;
@@ -487,39 +656,96 @@ omap_i2c_isr(int this_irq, void *dev_id)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
- if (stat & OMAP_I2C_STAT_ARDY) {
- omap_i2c_complete_cmd(dev, 0);
- continue;
+ err = 0;
+ if (stat & OMAP_I2C_STAT_NACK) {
+ err |= OMAP_I2C_STAT_NACK;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+ OMAP_I2C_CON_STP);
}
- if (stat & OMAP_I2C_STAT_RRDY) {
- w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
- if (dev->buf_len) {
- *dev->buf++ = w;
- dev->buf_len--;
+ if (stat & OMAP_I2C_STAT_AL) {
+ dev_err(dev->dev, "Arbitration lost\n");
+ err |= OMAP_I2C_STAT_AL;
+ }
+ if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
+ OMAP_I2C_STAT_AL))
+ omap_i2c_complete_cmd(dev, err);
+ if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
- *dev->buf++ = w >> 8;
+ *dev->buf++ = w;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ dev_err(dev->dev,
+ "RRDY IRQ while no data"
+ " requested\n");
+ if (stat & OMAP_I2C_STAT_RDR)
+ dev_err(dev->dev,
+ "RDR IRQ while no data"
+ " requested\n");
+ break;
}
- } else
- dev_err(dev->dev, "RRDY IRQ while no data "
- "requested\n");
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
continue;
}
- if (stat & OMAP_I2C_STAT_XRDY) {
- w = 0;
- if (dev->buf_len) {
- w = *dev->buf++;
- dev->buf_len--;
+ if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = 0;
if (dev->buf_len) {
- w |= *dev->buf++ << 8;
+ w = *dev->buf++;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ dev_err(dev->dev,
+ "XRDY IRQ while no "
+ "data to send\n");
+ if (stat & OMAP_I2C_STAT_XDR)
+ dev_err(dev->dev,
+ "XDR IRQ while no "
+ "data to send\n");
+ break;
}
- } else
- dev_err(dev->dev, "XRDY IRQ while no "
- "data to send\n");
- omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
continue;
}
if (stat & OMAP_I2C_STAT_ROVR) {
@@ -527,18 +753,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
dev->cmd_err |= OMAP_I2C_STAT_ROVR;
}
if (stat & OMAP_I2C_STAT_XUDF) {
- dev_err(dev->dev, "Transmit overflow\n");
+ dev_err(dev->dev, "Transmit underflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF;
}
- if (stat & OMAP_I2C_STAT_NACK) {
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
- }
- if (stat & OMAP_I2C_STAT_AL) {
- dev_err(dev->dev, "Arbitration lost\n");
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
- }
}
return count ? IRQ_HANDLED : IRQ_NONE;
@@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int
+static int __init
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
+ irq_handler_t isr;
int r;
+ u32 speed = 0;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev)
return -EBUSY;
}
- if (clock > 200)
- clock = 400; /* Fast mode */
- else
- clock = 100; /* Standard mode */
-
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) {
r = -ENOMEM;
goto err_release_region;
}
+ if (pdev->dev.platform_data != NULL)
+ speed = *(u32 *)pdev->dev.platform_data;
+ else
+ speed = 100; /* Defualt speed */
+
+ dev->speed = speed;
+ dev->idle = 1;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -602,22 +823,39 @@ omap_i2c_probe(struct platform_device *pdev)
omap_i2c_unidle(dev);
- if (cpu_is_omap15xx())
- dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+ dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ u16 s;
+
+ /* Set up the fifo size - Get total size */
+ s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
+ dev->fifo_size = 0x8 << s;
+
+ /*
+ * Set up notification threshold as half the total available
+ * size. This is to ensure that we can handle the status on int
+ * call back latencies.
+ */
+ dev->fifo_size = (dev->fifo_size / 2);
+ dev->b_hw = 1; /* Enable hardware fixes */
+ }
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
- r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
- 0, pdev->name, dev);
+ isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+ r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
}
- r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, r >> 4, r & 0xf, clock);
+ pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+
+ omap_i2c_idle(dev);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
@@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
- omap_i2c_idle(dev);
-
return 0;
err_free_irq:
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index b2b8380f660..322c5691e38 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -115,7 +115,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
static struct i2c_adapter parport_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .id = I2C_HW_B_LP,
.algo_data = &parport_algo_data,
.name = "Parallel port adapter (light)",
};
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 59ba2086d2f..0d8998610c7 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -164,7 +164,6 @@ static void i2c_parport_attach (struct parport *port)
/* Fill the rest of the structure */
adapter->adapter.owner = THIS_MODULE;
adapter->adapter.class = I2C_CLASS_HWMON;
- adapter->adapter.id = I2C_HW_B_LP;
strlcpy(adapter->adapter.name, "Parallel port adapter",
sizeof(adapter->adapter.name));
adapter->algo_data = parport_algo_data;
@@ -189,8 +188,6 @@ static void i2c_parport_attach (struct parport *port)
if (adapter_parm[type].init.val)
line_set(port, 1, &adapter_parm[type].init);
- parport_release(adapter->pdev);
-
if (i2c_bit_add_bus(&adapter->adapter) < 0) {
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
goto ERROR1;
@@ -202,6 +199,7 @@ static void i2c_parport_attach (struct parport *port)
return;
ERROR1:
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
ERROR0:
kfree(adapter);
@@ -221,6 +219,7 @@ static void i2c_parport_detach (struct parport *port)
if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init);
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
if (prev)
prev->next = adapter->next;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 9eb76268ec7..4aa8138cb0a 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -101,7 +101,6 @@ static struct i2c_algo_pca_data pca_isa_data = {
static struct i2c_adapter pca_isa_ops = {
.owner = THIS_MODULE,
- .id = I2C_HW_A_ISA,
.algo_data = &pca_isa_data,
.name = "PCA9564 ISA Adapter",
.timeout = 100,
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index eaa9b387543..761f9dd5362 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -403,7 +403,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_PIIX4,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index dcf2045b522..0bdb2d7f057 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -486,7 +486,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
if (cmd->type == MSP_TWI_CMD_WRITE ||
cmd->type == MSP_TWI_CMD_WRITE_READ) {
- __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data);
+ u64 tmp = be64_to_cpup((__be64 *)cmd->write_data);
tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 906f9b9d715..6af68146c34 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1016,7 +1016,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
i2c->adap.nr);
- i2c->clk = clk_get(&dev->dev, "I2CCLK");
+ i2c->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(i2c->clk)) {
ret = PTR_ERR(i2c->clk);
goto eclk;
@@ -1076,10 +1076,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
#ifdef CONFIG_I2C_PXA_SLAVE
printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n",
- i2c->adap.dev.bus_id, i2c->slave_addr);
+ dev_name(&i2c->adap.dev), i2c->slave_addr);
#else
printk(KERN_INFO "I2C: %s: PXA I2C adapter\n",
- i2c->adap.dev.bus_id);
+ dev_name(&i2c->adap.dev));
#endif
return 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 1fac4e23313..5b7f95641ba 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -35,13 +35,11 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <mach/regs-gpio.h>
-#include <asm/plat-s3c/regs-iic.h>
-#include <asm/plat-s3c/iic.h>
+#include <plat/regs-iic.h>
+#include <plat/iic.h>
/* i2c controller state */
@@ -56,6 +54,7 @@ enum s3c24xx_i2c_state {
struct s3c24xx_i2c {
spinlock_t lock;
wait_queue_head_t wait;
+ unsigned int suspended:1;
struct i2c_msg *msg;
unsigned int msg_num;
@@ -63,6 +62,7 @@ struct s3c24xx_i2c {
unsigned int msg_ptr;
unsigned int tx_setup;
+ unsigned int irq;
enum s3c24xx_i2c_state state;
unsigned long clkrate;
@@ -70,7 +70,6 @@ struct s3c24xx_i2c {
void __iomem *regs;
struct clk *clk;
struct device *dev;
- struct resource *irq;
struct resource *ioarea;
struct i2c_adapter adap;
@@ -79,16 +78,7 @@ struct s3c24xx_i2c {
#endif
};
-/* default platform data to use if not supplied in the platform_device
-*/
-
-static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = {
- .flags = 0,
- .slave_addr = 0x10,
- .bus_freq = 100*1000,
- .max_freq = 400*1000,
- .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
-};
+/* default platform data removed, dev should always carry data. */
/* s3c24xx_i2c_is2440()
*
@@ -102,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
return !strcmp(pdev->name, "s3c2440-i2c");
}
-
-/* s3c24xx_i2c_get_platformdata
- *
- * get the platform data associated with the given device, or return
- * the default if there is none
-*/
-
-static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev)
-{
- if (dev->platform_data != NULL)
- return (struct s3c2410_platform_i2c *)dev->platform_data;
-
- return &s3c24xx_i2c_default_platform;
-}
-
/* s3c24xx_i2c_master_complete
*
* complete the message and wake up the caller, using the given return code,
@@ -129,7 +104,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
i2c->msg_ptr = 0;
i2c->msg = NULL;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg_num = 0;
if (ret)
i2c->msg_idx = ret;
@@ -140,19 +115,17 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
/* irq enable/disable functions */
@@ -160,7 +133,7 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -168,7 +141,7 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -176,10 +149,10 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_message_start
*
- * put the start of a message onto the bus
+ * put the start of a message onto the bus
*/
-static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
+static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
struct i2c_msg *msg)
{
unsigned int addr = (msg->addr & 0x7f) << 1;
@@ -198,15 +171,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
- // todo - check for wether ack wanted or not
+ /* todo - check for wether ack wanted or not */
s3c24xx_i2c_enable_ack(i2c);
iiccon = readl(i2c->regs + S3C2410_IICCON);
writel(stat, i2c->regs + S3C2410_IICSTAT);
-
+
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS);
-
+
/* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started */
@@ -214,8 +187,8 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON);
-
- stat |= S3C2410_IICSTAT_START;
+
+ stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT);
}
@@ -226,11 +199,11 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */
- iicstat &= ~ S3C2410_IICSTAT_START;
+ iicstat &= ~S3C2410_IICSTAT_START;
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
-
+
i2c->state = STATE_STOP;
-
+
s3c24xx_i2c_master_complete(i2c, ret);
s3c24xx_i2c_disable_irq(i2c);
}
@@ -240,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
/* is_lastmsg()
*
- * returns TRUE if the current message is the last in the set
+ * returns TRUE if the current message is the last in the set
*/
static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
@@ -288,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
- s3c24xx_i2c_disable_irq(i2c);
+ s3c24xx_i2c_disable_irq(i2c);
goto out_ack;
case STATE_START:
/* last thing we did was send a start condition on the
* bus, or started a new i2c message
*/
-
+
if (iicstat & S3C2410_IICSTAT_LASTBIT &&
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
@@ -321,7 +294,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->state == STATE_READ)
goto prepare_read;
- /* fall through to the write state, as we will need to
+ /* fall through to the write state, as we will need to
* send a byte as well */
case STATE_WRITE:
@@ -338,7 +311,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
}
}
- retry_write:
+ retry_write:
if (!is_msgend(i2c)) {
byte = i2c->msg->buf[i2c->msg_ptr++];
@@ -358,9 +331,9 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
dev_dbg(i2c->dev, "WRITE: Next Message\n");
i2c->msg_ptr = 0;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg++;
-
+
/* check to see if we need to do another message */
if (i2c->msg->flags & I2C_M_NOSTART) {
@@ -374,7 +347,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
goto retry_write;
} else {
-
/* send the new start */
s3c24xx_i2c_message_start(i2c, i2c->msg);
i2c->state = STATE_START;
@@ -388,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
break;
case STATE_READ:
- /* we have a byte of data in the data register, do
+ /* we have a byte of data in the data register, do
* something with it, and then work out wether we are
* going to do any more read/write
*/
@@ -396,13 +368,13 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte;
- prepare_read:
+ prepare_read:
if (is_msglast(i2c)) {
/* last byte of buffer */
if (is_lastmsg(i2c))
s3c24xx_i2c_disable_ack(i2c);
-
+
} else if (is_msgend(i2c)) {
/* ok, we've read the entire buffer, see if there
* is anything else we need to do */
@@ -428,7 +400,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
/* acknowlegde the IRQ and get back on with the work */
out_ack:
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
out:
@@ -449,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
status = readl(i2c->regs + S3C2410_IICSTAT);
if (status & S3C2410_IICSTAT_ARBITR) {
- // deal with arbitration loss
+ /* deal with arbitration loss */
dev_err(i2c->dev, "deal with arbitration loss\n");
}
if (i2c->state == STATE_IDLE) {
dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
goto out;
}
-
+
/* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent */
@@ -484,16 +456,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-
+
if (!(iicstat & S3C2410_IICSTAT_BUSBUSY))
return 0;
msleep(1);
}
- dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n",
- __raw_readl(S3C2410_GPEDAT));
-
return -ETIMEDOUT;
}
@@ -502,12 +471,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
* this starts an i2c transfer
*/
-static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
+static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
+ struct i2c_msg *msgs, int num)
{
unsigned long timeout;
int ret;
- if (!(readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN))
+ if (i2c->suspended)
return -EIO;
ret = s3c24xx_i2c_set_master(i2c);
@@ -528,12 +498,12 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs);
spin_unlock_irq(&i2c->lock);
-
+
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx;
- /* having these next two as dev_err() makes life very
+ /* having these next two as dev_err() makes life very
* noisy when doing an i2cdetect */
if (timeout == 0)
@@ -590,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.functionality = s3c24xx_i2c_func,
};
-static struct s3c24xx_i2c s3c24xx_i2c = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
- .tx_setup = 50,
- .adap = {
- .name = "s3c2410-i2c",
- .owner = THIS_MODULE,
- .algo = &s3c24xx_i2c_algorithm,
- .retries = 2,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- },
-};
-
/* s3c24xx_i2c_calcdivisor
*
* return the divisor settings for a given frequency
@@ -642,7 +599,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
{
int diff = freq - wanted;
- return (diff >= -2 && diff <= 2);
+ return diff >= -2 && diff <= 2;
}
/* s3c24xx_i2c_clockrate
@@ -654,7 +611,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{
- struct s3c2410_platform_i2c *pdata;
+ struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
unsigned long clkin = clk_get_rate(i2c->clk);
unsigned int divs, div1;
u32 iiccon;
@@ -662,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
int start, end;
i2c->clkrate = clkin;
-
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
clkin /= 1000; /* clkin now in KHz */
-
+
dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
@@ -773,7 +728,7 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_init
*
- * initialise the controller, set the IO lines and frequency
+ * initialise the controller, set the IO lines and frequency
*/
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
@@ -784,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* get the plafrom data */
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
+ pdata = i2c->dev->platform_data;
/* inititalise the gpio */
- s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA);
- s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(to_platform_device(i2c->dev));
/* write slave address */
-
+
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
@@ -830,12 +785,32 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
- struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
+ struct s3c24xx_i2c *i2c;
struct s3c2410_platform_i2c *pdata;
struct resource *res;
int ret;
- pdata = s3c24xx_i2c_get_platformdata(&pdev->dev);
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
+
+ i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
+ if (!i2c) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
+ i2c->adap.owner = THIS_MODULE;
+ i2c->adap.algo = &s3c24xx_i2c_algorithm;
+ i2c->adap.retries = 2;
+ i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ i2c->tx_setup = 50;
+
+ spin_lock_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */
@@ -877,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_ioarea;
}
- dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ i2c->regs, i2c->ioarea, res);
/* setup info block for the i2c core */
@@ -891,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to
- * ensure no current IRQs pending
+ * ensure no current IRQs pending
*/
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res == NULL) {
+ i2c->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
- ret = -ENOENT;
goto err_iomap;
}
- ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
- pdev->name, i2c);
+ ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+ dev_name(&pdev->dev), i2c);
if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ\n");
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap;
}
- i2c->irq = res;
-
- dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
- (unsigned long)res->start);
-
ret = s3c24xx_i2c_register_cpufreq(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
@@ -936,14 +906,14 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c);
- dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
+ dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
err_cpufreq:
s3c24xx_i2c_deregister_cpufreq(i2c);
err_irq:
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
@@ -957,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk);
err_noclk:
+ kfree(i2c);
return ret;
}
@@ -972,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);
@@ -981,22 +952,32 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
+ kfree(i2c);
return 0;
}
#ifdef CONFIG_PM
+static int s3c24xx_i2c_suspend_late(struct platform_device *dev,
+ pm_message_t msg)
+{
+ struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+ i2c->suspended = 1;
+ return 0;
+}
+
static int s3c24xx_i2c_resume(struct platform_device *dev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
- if (i2c != NULL)
- s3c24xx_i2c_init(i2c);
+ i2c->suspended = 0;
+ s3c24xx_i2c_init(i2c);
return 0;
}
#else
+#define s3c24xx_i2c_suspend_late NULL
#define s3c24xx_i2c_resume NULL
#endif
@@ -1005,6 +986,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
static struct platform_driver s3c2410_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend_late = s3c24xx_i2c_suspend_late,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
@@ -1015,6 +997,7 @@ static struct platform_driver s3c2410_i2c_driver = {
static struct platform_driver s3c2440_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend_late = s3c24xx_i2c_suspend_late,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 5e0e254976d..baa28b73ae4 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -475,7 +475,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
id->adap.nr = pdev->id;
id->adap.algo = &sh7760_i2c_algo;
- id->adap.class = I2C_CLASS_ALL;
+ id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
id->adap.retries = 3;
id->adap.algo_data = id;
id->adap.dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 640cbb23732..1c01083b01b 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -160,9 +160,39 @@ struct sh_mobile_i2c_data {
static void activate_ch(struct sh_mobile_i2c_data *pd)
{
+ unsigned long i2c_clk;
+ u_int32_t num;
+ u_int32_t denom;
+ u_int32_t tmp;
+
/* Make sure the clock is enabled */
clk_enable(pd->clk);
+ /* Get clock rate after clock is enabled */
+ i2c_clk = clk_get_rate(pd->clk);
+
+ /* Calculate the value for iccl. From the data sheet:
+ * iccl = (p clock / transfer rate) * (L / (L + H))
+ * where L and H are the SCL low/high ratio (5/4 in this case).
+ * We also round off the result.
+ */
+ num = i2c_clk * 5;
+ denom = NORMAL_SPEED * 9;
+ tmp = num * 10 / denom;
+ if (tmp % 10 >= 5)
+ pd->iccl = (u_int8_t)((num/denom) + 1);
+ else
+ pd->iccl = (u_int8_t)(num/denom);
+
+ /* Calculate the value for icch. From the data sheet:
+ icch = (p clock / transfer rate) * (H / (L + H)) */
+ num = i2c_clk * 4;
+ tmp = num * 10 / denom;
+ if (tmp % 10 >= 5)
+ pd->icch = (u_int8_t)((num/denom) + 1);
+ else
+ pd->icch = (u_int8_t)(num/denom);
+
/* Enable channel and configure rx ack */
iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
@@ -318,7 +348,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
} else
data = i2c_op(pd, OP_RX, 0);
- pd->msg->buf[real_pos] = data;
+ if (real_pos >= 0)
+ pd->msg->buf[real_pos] = data;
} while (0);
pd->pos++;
@@ -458,40 +489,6 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = {
.master_xfer = sh_mobile_i2c_xfer,
};
-static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
-{
- struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
- unsigned long peripheral_clk = clk_get_rate(pd->clk);
- u_int32_t num;
- u_int32_t denom;
- u_int32_t tmp;
-
- spin_lock_init(&pd->lock);
- init_waitqueue_head(&pd->wait);
-
- /* Calculate the value for iccl. From the data sheet:
- * iccl = (p clock / transfer rate) * (L / (L + H))
- * where L and H are the SCL low/high ratio (5/4 in this case).
- * We also round off the result.
- */
- num = peripheral_clk * 5;
- denom = NORMAL_SPEED * 9;
- tmp = num * 10 / denom;
- if (tmp % 10 >= 5)
- pd->iccl = (u_int8_t)((num/denom) + 1);
- else
- pd->iccl = (u_int8_t)(num/denom);
-
- /* Calculate the value for icch. From the data sheet:
- icch = (p clock / transfer rate) * (H / (L + H)) */
- num = peripheral_clk * 4;
- tmp = num * 10 / denom;
- if (tmp % 10 >= 5)
- pd->icch = (u_int8_t)((num/denom) + 1);
- else
- pd->icch = (u_int8_t)(num/denom);
-}
-
static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
{
struct resource *res;
@@ -503,7 +500,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
for (n = res->start; hook && n <= res->end; n++) {
if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
- dev->dev.bus_id, dev))
+ dev_name(&dev->dev), dev))
goto rollback;
}
k++;
@@ -532,6 +529,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
struct sh_mobile_i2c_data *pd;
struct i2c_adapter *adap;
struct resource *res;
+ char clk_name[8];
int size;
int ret;
@@ -541,9 +539,10 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
return -ENOMEM;
}
- pd->clk = clk_get(&dev->dev, "peripheral_clk");
+ snprintf(clk_name, sizeof(clk_name), "i2c%d", dev->id);
+ pd->clk = clk_get(&dev->dev, clk_name);
if (IS_ERR(pd->clk)) {
- dev_err(&dev->dev, "cannot get peripheral clock\n");
+ dev_err(&dev->dev, "cannot get clock \"%s\"\n", clk_name);
ret = PTR_ERR(pd->clk);
goto err;
}
@@ -585,7 +584,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
strlcpy(adap->name, dev->name, sizeof(adap->name));
- sh_mobile_i2c_setup_channel(dev);
+ spin_lock_init(&pd->lock);
+ init_waitqueue_head(&pd->wait);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 4ddefbf238e..98b1ec48915 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -155,7 +155,6 @@ static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
static struct i2c_adapter sibyte_board_adapter[2] = {
{
.owner = THIS_MODULE,
- .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[0],
@@ -164,7 +163,6 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
},
{
.owner = THIS_MODULE,
- .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[1],
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index dfc2d5eb6a6..f320ab27da4 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -365,7 +365,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS5595,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -389,8 +388,8 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
/* set up the sysfs linkage to our parent device */
sis5595_adapter.dev.parent = &dev->dev;
- sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
- sis5595_base + SMB_INDEX);
+ snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name),
+ "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX);
err = i2c_add_adapter(&sis5595_adapter);
if (err) {
release_region(sis5595_base + SMB_INDEX, 2);
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index e7c4b790da5..50c3610e602 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -464,7 +464,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS630,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -487,8 +486,8 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
/* set up the sysfs linkage to our parent device */
sis630_adapter.dev.parent = &dev->dev;
- sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
- acpi_base + SMB_STS);
+ snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
+ "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
return i2c_add_adapter(&sis630_adapter);
}
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index f1bba639664..7e1594b4057 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -241,7 +241,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis96x_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS96X,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 29cef0433f3..8b24f192103 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -83,7 +83,6 @@ static struct i2c_algo_bit_data bit_data = {
static struct i2c_adapter vt586b_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VIA,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.name = "VIA i2c",
.algo_data = &bit_data,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 9f194d9efd9..02e6f724b05 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -321,7 +321,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_VIA2,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 1d4ae26ba73..1a474acc0dd 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
static struct i2c_adapter voodoo3_i2c_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VOO,
.class = I2C_CLASS_TV_ANALOG,
.name = "I2C Voodoo3/Banshee adapter",
.algo_data = &voo_i2c_bit_data,
@@ -180,7 +179,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
static struct i2c_adapter voodoo3_ddc_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VOO,
.class = I2C_CLASS_DDC,
.name = "DDC Voodoo3/Banshee adapter",
.algo_data = &voo_ddc_bit_data,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index ed794b145a1..648ecc6f60e 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -440,7 +440,6 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
adapter->owner = THIS_MODULE;
- adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adapter->dev.parent = dev;
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index e4c98539c51..162b74a0488 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -82,7 +82,6 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
static struct i2c_adapter scx200_i2c_ops = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- .id = I2C_HW_B_SCX200,
.algo_data = &scx200_i2c_data,
.name = "NatSemi SCx200 I2C",
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 4c35702830c..c80312c1f38 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -16,43 +16,6 @@ config DS1682
This driver can also be built as a module. If so, the module
will be called ds1682.
-config AT24
- tristate "EEPROMs from most vendors"
- depends on SYSFS && EXPERIMENTAL
- help
- Enable this driver to get read/write support to most I2C EEPROMs,
- after you configure the driver to know about each EEPROM on
- your target board. Use these generic chip names, instead of
- vendor-specific ones like at24c64 or 24lc02:
-
- 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
- 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
-
- Unless you like data loss puzzles, always be sure that any chip
- you configure as a 24c32 (32 kbit) or larger is NOT really a
- 24c16 (16 kbit) or smaller, and vice versa. Marking the chip
- as read-only won't help recover from this. Also, if your chip
- has any software write-protect mechanism you may want to review the
- code to make sure this driver won't turn it on by accident.
-
- If you use this with an SMBus adapter instead of an I2C adapter,
- full functionality is not available. Only smaller devices are
- supported (24c16 and below, max 4 kByte).
-
- This driver can also be built as a module. If so, the module
- will be called at24.
-
-config SENSORS_EEPROM
- tristate "EEPROM reader"
- depends on EXPERIMENTAL
- help
- If you say yes here you get read-only access to the EEPROM data
- available on modern memory DIMMs and Sony Vaio laptops. Such
- EEPROMs could theoretically be available on other devices as well.
-
- This driver can also be built as a module. If so, the module
- will be called eeprom.
-
config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
depends on EXPERIMENTAL && GPIO_PCF857X = "n"
@@ -114,31 +77,6 @@ config SENSORS_PCF8591
These devices are hard to detect and rarely found on mainstream
hardware. If unsure, say N.
-config ISP1301_OMAP
- tristate "Philips ISP1301 with OMAP OTG"
- depends on ARCH_OMAP_OTG
- help
- If you say yes here you get support for the Philips ISP1301
- USB-On-The-Go transceiver working with the OMAP OTG controller.
- The ISP1301 is used in products including H2 and H3 development
- boards for Texas Instruments OMAP processors.
-
- This driver can also be built as a module. If so, the module
- will be called isp1301_omap.
-
-config TPS65010
- tristate "TPS6501x Power Management chips"
- depends on GPIOLIB
- default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
- help
- If you say yes here you get support for the TPS6501x series of
- Power Management chips. These include voltage regulators,
- lithium ion/polymer battery charging, and other features that
- are often used in portable devices like cell phones and cameras.
-
- This driver can also be built as a module. If so, the module
- will be called tps65010.
-
config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL
@@ -164,25 +102,4 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module
will be called tsl2550.
-config MENELAUS
- bool "TWL92330/Menelaus PM chip"
- depends on I2C=y && ARCH_OMAP24XX
- help
- If you say yes here you get support for the Texas Instruments
- TWL92330/Menelaus Power Management chip. This include voltage
- regulators, Dual slot memory card tranceivers, real-time clock
- and other features that are often used in portable devices like
- cell phones and PDAs.
-
-config MCU_MPC8349EMITX
- tristate "MPC8349E-mITX MCU driver"
- depends on I2C && PPC_83xx
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Say Y here to enable soft power-off functionality on the Freescale
- boards with the MPC8349E-mITX-compatible MCU chips. This driver will
- also register MCU GPIOs with the generic GPIO API, so you'll able
- to use MCU pins as GPIOs.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 23d2a31b0a6..d142f238a2d 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,18 +11,12 @@
#
obj-$(CONFIG_DS1682) += ds1682.o
-obj-$(CONFIG_AT24) += at24.o
-obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
-obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
-obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
-obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/at24.c b/drivers/i2c/chips/at24.c
deleted file mode 100644
index d4775528abc..00000000000
--- a/drivers/i2c/chips/at24.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * at24.c - handle most I2C EEPROMs
- *
- * Copyright (C) 2005-2007 David Brownell
- * Copyright (C) 2008 Wolfram Sang, Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/sysfs.h>
-#include <linux/mod_devicetable.h>
-#include <linux/log2.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
-
-/*
- * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
- * Differences between different vendor product lines (like Atmel AT24C or
- * MicroChip 24LC, etc) won't much matter for typical read/write access.
- * There are also I2C RAM chips, likewise interchangeable. One example
- * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes).
- *
- * However, misconfiguration can lose data. "Set 16-bit memory address"
- * to a part with 8-bit addressing will overwrite data. Writing with too
- * big a page size also loses data. And it's not safe to assume that the
- * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC
- * uses 0x51, for just one example.
- *
- * Accordingly, explicit board-specific configuration data should be used
- * in almost all cases. (One partial exception is an SMBus used to access
- * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.)
- *
- * So this driver uses "new style" I2C driver binding, expecting to be
- * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
- * similar kernel-resident tables; or, configuration data coming from
- * a bootloader.
- *
- * Other than binding model, current differences from "eeprom" driver are
- * that this one handles write access and isn't restricted to 24c02 devices.
- * It also handles larger devices (32 kbit and up) with two-byte addresses,
- * which won't work on pure SMBus systems.
- */
-
-struct at24_data {
- struct at24_platform_data chip;
- bool use_smbus;
-
- /*
- * Lock protects against activities from other Linux tasks,
- * but not from changes by other I2C masters.
- */
- struct mutex lock;
- struct bin_attribute bin;
-
- u8 *writebuf;
- unsigned write_max;
- unsigned num_addresses;
-
- /*
- * Some chips tie up multiple I2C addresses; dummy devices reserve
- * them for us, and we'll use them with SMBus calls.
- */
- struct i2c_client *client[];
-};
-
-/*
- * This parameter is to help this driver avoid blocking other drivers out
- * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C
- * clock, one 256 byte read takes about 1/43 second which is excessive;
- * but the 1/170 second it takes at 400 kHz may be quite reasonable; and
- * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible.
- *
- * This value is forced to be a power of two so that writes align on pages.
- */
-static unsigned io_limit = 128;
-module_param(io_limit, uint, 0);
-MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)");
-
-/*
- * Specs often allow 5 msec for a page write, sometimes 20 msec;
- * it's important to recover from write timeouts.
- */
-static unsigned write_timeout = 25;
-module_param(write_timeout, uint, 0);
-MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
-
-#define AT24_SIZE_BYTELEN 5
-#define AT24_SIZE_FLAGS 8
-
-#define AT24_BITMASK(x) (BIT(x) - 1)
-
-/* create non-zero magic value for given eeprom parameters */
-#define AT24_DEVICE_MAGIC(_len, _flags) \
- ((1 << AT24_SIZE_FLAGS | (_flags)) \
- << AT24_SIZE_BYTELEN | ilog2(_len))
-
-static const struct i2c_device_id at24_ids[] = {
- /* needs 8 addresses as A0-A2 are ignored */
- { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
- /* old variants can't be handled with this generic entry! */
- { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
- { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
- /* spd is a 24c02 in memory DIMMs */
- { "spd", AT24_DEVICE_MAGIC(2048 / 8,
- AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
- { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
- /* 24rf08 quirk is handled at i2c-core */
- { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
- { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
- { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
- { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
- { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
- { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
- { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
- { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },
- { "at24", 0 },
- { /* END OF LIST */ }
-};
-MODULE_DEVICE_TABLE(i2c, at24_ids);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * This routine supports chips which consume multiple I2C addresses. It
- * computes the addressing information to be used for a given r/w request.
- * Assumes that sanity checks for offset happened at sysfs-layer.
- */
-static struct i2c_client *at24_translate_offset(struct at24_data *at24,
- unsigned *offset)
-{
- unsigned i;
-
- if (at24->chip.flags & AT24_FLAG_ADDR16) {
- i = *offset >> 16;
- *offset &= 0xffff;
- } else {
- i = *offset >> 8;
- *offset &= 0xff;
- }
-
- return at24->client[i];
-}
-
-static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
- unsigned offset, size_t count)
-{
- struct i2c_msg msg[2];
- u8 msgbuf[2];
- struct i2c_client *client;
- int status, i;
-
- memset(msg, 0, sizeof(msg));
-
- /*
- * REVISIT some multi-address chips don't rollover page reads to
- * the next slave address, so we may need to truncate the count.
- * Those chips might need another quirk flag.
- *
- * If the real hardware used four adjacent 24c02 chips and that
- * were misconfigured as one 24c08, that would be a similar effect:
- * one "eeprom" file not four, but larger reads would fail when
- * they crossed certain pages.
- */
-
- /*
- * Slave address and byte offset derive from the offset. Always
- * set the byte address; on a multi-master board, another master
- * may have changed the chip's "current" address pointer.
- */
- client = at24_translate_offset(at24, &offset);
-
- if (count > io_limit)
- count = io_limit;
-
- /* Smaller eeproms can work given some SMBus extension calls */
- if (at24->use_smbus) {
- if (count > I2C_SMBUS_BLOCK_MAX)
- count = I2C_SMBUS_BLOCK_MAX;
- status = i2c_smbus_read_i2c_block_data(client, offset,
- count, buf);
- dev_dbg(&client->dev, "smbus read %zu@%d --> %d\n",
- count, offset, status);
- return (status < 0) ? -EIO : status;
- }
-
- /*
- * When we have a better choice than SMBus calls, use a combined
- * I2C message. Write address; then read up to io_limit data bytes.
- * Note that read page rollover helps us here (unlike writes).
- * msgbuf is u8 and will cast to our needs.
- */
- i = 0;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msgbuf[i++] = offset >> 8;
- msgbuf[i++] = offset;
-
- msg[0].addr = client->addr;
- msg[0].buf = msgbuf;
- msg[0].len = i;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- status = i2c_transfer(client->adapter, msg, 2);
- dev_dbg(&client->dev, "i2c read %zu@%d --> %d\n",
- count, offset, status);
-
- if (status == 2)
- return count;
- else if (status >= 0)
- return -EIO;
- else
- return status;
-}
-
-static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
-{
- struct at24_data *at24;
- ssize_t retval = 0;
-
- at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-
- if (unlikely(!count))
- return count;
-
- /*
- * Read data from chip, protecting against concurrent updates
- * from this host, but not from other I2C masters.
- */
- mutex_lock(&at24->lock);
-
- while (count) {
- ssize_t status;
-
- status = at24_eeprom_read(at24, buf, off, count);
- if (status <= 0) {
- if (retval == 0)
- retval = status;
- break;
- }
- buf += status;
- off += status;
- count -= status;
- retval += status;
- }
-
- mutex_unlock(&at24->lock);
-
- return retval;
-}
-
-
-/*
- * REVISIT: export at24_bin{read,write}() to let other kernel code use
- * eeprom data. For example, it might hold a board's Ethernet address, or
- * board-specific calibration data generated on the manufacturing floor.
- */
-
-
-/*
- * Note that if the hardware write-protect pin is pulled high, the whole
- * chip is normally write protected. But there are plenty of product
- * variants here, including OTP fuses and partial chip protect.
- *
- * We only use page mode writes; the alternative is sloooow. This routine
- * writes at most one page.
- */
-static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
- unsigned offset, size_t count)
-{
- struct i2c_client *client;
- struct i2c_msg msg;
- ssize_t status;
- unsigned long timeout, write_time;
- unsigned next_page;
-
- /* Get corresponding I2C address and adjust offset */
- client = at24_translate_offset(at24, &offset);
-
- /* write_max is at most a page */
- if (count > at24->write_max)
- count = at24->write_max;
-
- /* Never roll over backwards, to the start of this page */
- next_page = roundup(offset + 1, at24->chip.page_size);
- if (offset + count > next_page)
- count = next_page - offset;
-
- /* If we'll use I2C calls for I/O, set up the message */
- if (!at24->use_smbus) {
- int i = 0;
-
- msg.addr = client->addr;
- msg.flags = 0;
-
- /* msg.buf is u8 and casts will mask the values */
- msg.buf = at24->writebuf;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msg.buf[i++] = offset >> 8;
-
- msg.buf[i++] = offset;
- memcpy(&msg.buf[i], buf, count);
- msg.len = i + count;
- }
-
- /*
- * Writes fail if the previous one didn't complete yet. We may
- * loop a few times until this one succeeds, waiting at least
- * long enough for one entire page write to work.
- */
- timeout = jiffies + msecs_to_jiffies(write_timeout);
- do {
- write_time = jiffies;
- if (at24->use_smbus) {
- status = i2c_smbus_write_i2c_block_data(client,
- offset, count, buf);
- if (status == 0)
- status = count;
- } else {
- status = i2c_transfer(client->adapter, &msg, 1);
- if (status == 1)
- status = count;
- }
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
-
- /* REVISIT: at HZ=100, this is sloooow */
- msleep(1);
- } while (time_before(write_time, timeout));
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
-{
- struct at24_data *at24;
- ssize_t retval = 0;
-
- at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-
- if (unlikely(!count))
- return count;
-
- /*
- * Write data to chip, protecting against concurrent updates
- * from this host, but not from other I2C masters.
- */
- mutex_lock(&at24->lock);
-
- while (count) {
- ssize_t status;
-
- status = at24_eeprom_write(at24, buf, off, count);
- if (status <= 0) {
- if (retval == 0)
- retval = status;
- break;
- }
- buf += status;
- off += status;
- count -= status;
- retval += status;
- }
-
- mutex_unlock(&at24->lock);
-
- return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct at24_platform_data chip;
- bool writable;
- bool use_smbus = false;
- struct at24_data *at24;
- int err;
- unsigned i, num_addresses;
- kernel_ulong_t magic;
-
- if (client->dev.platform_data) {
- chip = *(struct at24_platform_data *)client->dev.platform_data;
- } else {
- if (!id->driver_data) {
- err = -ENODEV;
- goto err_out;
- }
- magic = id->driver_data;
- chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
- magic >>= AT24_SIZE_BYTELEN;
- chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
- /*
- * This is slow, but we can't know all eeproms, so we better
- * play safe. Specifying custom eeprom-types via platform_data
- * is recommended anyhow.
- */
- chip.page_size = 1;
- }
-
- if (!is_power_of_2(chip.byte_len))
- dev_warn(&client->dev,
- "byte_len looks suspicious (no power of 2)!\n");
- if (!is_power_of_2(chip.page_size))
- dev_warn(&client->dev,
- "page_size looks suspicious (no power of 2)!\n");
-
- /* Use I2C operations unless we're stuck with SMBus extensions. */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- if (chip.flags & AT24_FLAG_ADDR16) {
- err = -EPFNOSUPPORT;
- goto err_out;
- }
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- err = -EPFNOSUPPORT;
- goto err_out;
- }
- use_smbus = true;
- }
-
- if (chip.flags & AT24_FLAG_TAKE8ADDR)
- num_addresses = 8;
- else
- num_addresses = DIV_ROUND_UP(chip.byte_len,
- (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
-
- at24 = kzalloc(sizeof(struct at24_data) +
- num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
- if (!at24) {
- err = -ENOMEM;
- goto err_out;
- }
-
- mutex_init(&at24->lock);
- at24->use_smbus = use_smbus;
- at24->chip = chip;
- at24->num_addresses = num_addresses;
-
- /*
- * Export the EEPROM bytes through sysfs, since that's convenient.
- * By default, only root should see the data (maybe passwords etc)
- */
- at24->bin.attr.name = "eeprom";
- at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
- at24->bin.read = at24_bin_read;
- at24->bin.size = chip.byte_len;
-
- writable = !(chip.flags & AT24_FLAG_READONLY);
- if (writable) {
- if (!use_smbus || i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
-
- unsigned write_max = chip.page_size;
-
- at24->bin.write = at24_bin_write;
- at24->bin.attr.mode |= S_IWUSR;
-
- if (write_max > io_limit)
- write_max = io_limit;
- if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
- write_max = I2C_SMBUS_BLOCK_MAX;
- at24->write_max = write_max;
-
- /* buffer (data + address at the beginning) */
- at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL);
- if (!at24->writebuf) {
- err = -ENOMEM;
- goto err_struct;
- }
- } else {
- dev_warn(&client->dev,
- "cannot write due to controller restrictions.");
- }
- }
-
- at24->client[0] = client;
-
- /* use dummy devices for multiple-address chips */
- for (i = 1; i < num_addresses; i++) {
- at24->client[i] = i2c_new_dummy(client->adapter,
- client->addr + i);
- if (!at24->client[i]) {
- dev_err(&client->dev, "address 0x%02x unavailable\n",
- client->addr + i);
- err = -EADDRINUSE;
- goto err_clients;
- }
- }
-
- err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
- if (err)
- goto err_clients;
-
- i2c_set_clientdata(client, at24);
-
- dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
- at24->bin.size, client->name,
- writable ? "(writable)" : "(read-only)");
- dev_dbg(&client->dev,
- "page_size %d, num_addresses %d, write_max %d%s\n",
- chip.page_size, num_addresses,
- at24->write_max,
- use_smbus ? ", use_smbus" : "");
-
- return 0;
-
-err_clients:
- for (i = 1; i < num_addresses; i++)
- if (at24->client[i])
- i2c_unregister_device(at24->client[i]);
-
- kfree(at24->writebuf);
-err_struct:
- kfree(at24);
-err_out:
- dev_dbg(&client->dev, "probe error %d\n", err);
- return err;
-}
-
-static int __devexit at24_remove(struct i2c_client *client)
-{
- struct at24_data *at24;
- int i;
-
- at24 = i2c_get_clientdata(client);
- sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
-
- for (i = 1; i < at24->num_addresses; i++)
- i2c_unregister_device(at24->client[i]);
-
- kfree(at24->writebuf);
- kfree(at24);
- i2c_set_clientdata(client, NULL);
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct i2c_driver at24_driver = {
- .driver = {
- .name = "at24",
- .owner = THIS_MODULE,
- },
- .probe = at24_probe,
- .remove = __devexit_p(at24_remove),
- .id_table = at24_ids,
-};
-
-static int __init at24_init(void)
-{
- io_limit = rounddown_pow_of_two(io_limit);
- return i2c_add_driver(&at24_driver);
-}
-module_init(at24_init);
-
-static void __exit at24_exit(void)
-{
- i2c_del_driver(&at24_driver);
-}
-module_exit(at24_exit);
-
-MODULE_DESCRIPTION("Driver for most I2C EEPROMs");
-MODULE_AUTHOR("David Brownell and Wolfram Sang");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
deleted file mode 100644
index 2c27193aeaa..00000000000
--- a/drivers/i2c/chips/eeprom.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
- Philip Edelbrock <phil@netroedge.com>
- Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
- Copyright (C) 2003 IBM Corp.
- Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
- 0x55, 0x56, 0x57, I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_1(eeprom);
-
-
-/* Size of EEPROM in bytes */
-#define EEPROM_SIZE 256
-
-/* possible types of eeprom devices */
-enum eeprom_nature {
- UNKNOWN,
- VAIO,
-};
-
-/* Each client has this additional data */
-struct eeprom_data {
- struct mutex update_lock;
- u8 valid; /* bitfield, bit!=0 if slice is valid */
- unsigned long last_updated[8]; /* In jiffies, 8 slices */
- u8 data[EEPROM_SIZE]; /* Register values */
- enum eeprom_nature nature;
-};
-
-
-static void eeprom_update_client(struct i2c_client *client, u8 slice)
-{
- struct eeprom_data *data = i2c_get_clientdata(client);
- int i;
-
- mutex_lock(&data->update_lock);
-
- if (!(data->valid & (1 << slice)) ||
- time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
- dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
-
- if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- for (i = slice << 5; i < (slice + 1) << 5; i += 32)
- if (i2c_smbus_read_i2c_block_data(client, i,
- 32, data->data + i)
- != 32)
- goto exit;
- } else {
- for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
- int word = i2c_smbus_read_word_data(client, i);
- if (word < 0)
- goto exit;
- data->data[i] = word & 0xff;
- data->data[i + 1] = word >> 8;
- }
- }
- data->last_updated[slice] = jiffies;
- data->valid |= (1 << slice);
- }
-exit:
- mutex_unlock(&data->update_lock);
-}
-
-static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
-{
- struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
- struct eeprom_data *data = i2c_get_clientdata(client);
- u8 slice;
-
- if (off > EEPROM_SIZE)
- return 0;
- if (off + count > EEPROM_SIZE)
- count = EEPROM_SIZE - off;
-
- /* Only refresh slices which contain requested bytes */
- for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
- eeprom_update_client(client, slice);
-
- /* Hide Vaio private settings to regular users:
- - BIOS passwords: bytes 0x00 to 0x0f
- - UUID: bytes 0x10 to 0x1f
- - Serial number: 0xc0 to 0xdf */
- if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
- int i;
-
- for (i = 0; i < count; i++) {
- if ((off + i <= 0x1f) ||
- (off + i >= 0xc0 && off + i <= 0xdf))
- buf[i] = 0;
- else
- buf[i] = data->data[off + i];
- }
- } else {
- memcpy(buf, &data->data[off], count);
- }
-
- return count;
-}
-
-static struct bin_attribute eeprom_attr = {
- .attr = {
- .name = "eeprom",
- .mode = S_IRUGO,
- },
- .size = EEPROM_SIZE,
- .read = eeprom_read,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int eeprom_detect(struct i2c_client *client, int kind,
- struct i2c_board_info *info)
-{
- struct i2c_adapter *adapter = client->adapter;
-
- /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
- addresses 0x50-0x57, but we only care about 0x50. So decline
- attaching to addresses >= 0x51 on DDC buses */
- if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51)
- return -ENODEV;
-
- /* There are four ways we can read the EEPROM data:
- (1) I2C block reads (faster, but unsupported by most adapters)
- (2) Word reads (128% overhead)
- (3) Consecutive byte reads (88% overhead, unsafe)
- (4) Regular byte data reads (265% overhead)
- The third and fourth methods are not implemented by this driver
- because all known adapters support one of the first two. */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
- && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
- return -ENODEV;
-
- strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int eeprom_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct i2c_adapter *adapter = client->adapter;
- struct eeprom_data *data;
- int err;
-
- if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- memset(data->data, 0xff, EEPROM_SIZE);
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
- data->nature = UNKNOWN;
-
- /* Detect the Vaio nature of EEPROMs.
- We use the "PCG-" or "VGN-" prefix as the signature. */
- if (client->addr == 0x57
- && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
- char name[4];
-
- name[0] = i2c_smbus_read_byte_data(client, 0x80);
- name[1] = i2c_smbus_read_byte_data(client, 0x81);
- name[2] = i2c_smbus_read_byte_data(client, 0x82);
- name[3] = i2c_smbus_read_byte_data(client, 0x83);
-
- if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
- dev_info(&client->dev, "Vaio EEPROM detected, "
- "enabling privacy protection\n");
- data->nature = VAIO;
- }
- }
-
- /* create the sysfs eeprom file */
- err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
- if (err)
- goto exit_kfree;
-
- return 0;
-
-exit_kfree:
- kfree(data);
-exit:
- return err;
-}
-
-static int eeprom_remove(struct i2c_client *client)
-{
- sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
- kfree(i2c_get_clientdata(client));
-
- return 0;
-}
-
-static const struct i2c_device_id eeprom_id[] = {
- { "eeprom", 0 },
- { }
-};
-
-static struct i2c_driver eeprom_driver = {
- .driver = {
- .name = "eeprom",
- },
- .probe = eeprom_probe,
- .remove = eeprom_remove,
- .id_table = eeprom_id,
-
- .class = I2C_CLASS_DDC | I2C_CLASS_SPD,
- .detect = eeprom_detect,
- .address_data = &addr_data,
-};
-
-static int __init eeprom_init(void)
-{
- return i2c_add_driver(&eeprom_driver);
-}
-
-static void __exit eeprom_exit(void)
-{
- i2c_del_driver(&eeprom_driver);
-}
-
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
- "Philip Edelbrock <phil@netroedge.com> and "
- "Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("I2C EEPROM driver");
-MODULE_LICENSE("GPL");
-
-module_init(eeprom_init);
-module_exit(eeprom_exit);
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
deleted file mode 100644
index 28902ebd553..00000000000
--- a/drivers/i2c/chips/isp1301_omap.c
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004 Texas Instruments
- * Copyright (C) 2004 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-
-#include <asm/irq.h>
-#include <mach/usb.h>
-
-
-#ifndef DEBUG
-#undef VERBOSE
-#endif
-
-
-#define DRIVER_VERSION "24 August 2004"
-#define DRIVER_NAME (isp1301_driver.driver.name)
-
-MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
-MODULE_LICENSE("GPL");
-
-struct isp1301 {
- struct otg_transceiver otg;
- struct i2c_client *client;
- void (*i2c_release)(struct device *dev);
-
- int irq_type;
-
- u32 last_otg_ctrl;
- unsigned working:1;
-
- struct timer_list timer;
-
- /* use keventd context to change the state for us */
- struct work_struct work;
-
- unsigned long todo;
-# define WORK_UPDATE_ISP 0 /* update ISP from OTG */
-# define WORK_UPDATE_OTG 1 /* update OTG from ISP */
-# define WORK_HOST_RESUME 4 /* resume host */
-# define WORK_TIMER 6 /* timer fired */
-# define WORK_STOP 7 /* don't resubmit */
-};
-
-
-/* bits in OTG_CTRL */
-
-#define OTG_XCEIV_OUTPUTS \
- (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
-#define OTG_XCEIV_INPUTS \
- (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
-#define OTG_CTRL_BITS \
- (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
- /* and OTG_PULLUP is sometimes written */
-
-#define OTG_CTRL_MASK (OTG_DRIVER_SEL| \
- OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
- OTG_CTRL_BITS)
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_MACH_OMAP_H2
-
-/* board-specific PM hooks */
-
-#include <asm/gpio.h>
-#include <mach/mux.h>
-#include <asm/mach-types.h>
-
-
-#if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
-
-#include <linux/i2c/tps65010.h>
-
-#else
-
-static inline int tps65010_set_vbus_draw(unsigned mA)
-{
- pr_debug("tps65010: draw %d mA (STUB)\n", mA);
- return 0;
-}
-
-#endif
-
-static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
-{
- int status = tps65010_set_vbus_draw(mA);
- if (status < 0)
- pr_debug(" VBUS %d mA error %d\n", mA, status);
-}
-
-static void enable_vbus_source(struct isp1301 *isp)
-{
- /* this board won't supply more than 8mA vbus power.
- * some boards can switch a 100ma "unit load" (or more).
- */
-}
-
-
-/* products will deliver OTG messages with LEDs, GUI, etc */
-static inline void notresponding(struct isp1301 *isp)
-{
- printk(KERN_NOTICE "OTG device not responding.\n");
-}
-
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static struct i2c_driver isp1301_driver;
-
-/* smbus apis are used for portability */
-
-static inline u8
-isp1301_get_u8(struct isp1301 *isp, u8 reg)
-{
- return i2c_smbus_read_byte_data(isp->client, reg + 0);
-}
-
-static inline int
-isp1301_get_u16(struct isp1301 *isp, u8 reg)
-{
- return i2c_smbus_read_word_data(isp->client, reg);
-}
-
-static inline int
-isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
-{
- return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
-}
-
-static inline int
-isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
-{
- return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* identification */
-#define ISP1301_VENDOR_ID 0x00 /* u16 read */
-#define ISP1301_PRODUCT_ID 0x02 /* u16 read */
-#define ISP1301_BCD_DEVICE 0x14 /* u16 read */
-
-#define I2C_VENDOR_ID_PHILIPS 0x04cc
-#define I2C_PRODUCT_ID_PHILIPS_1301 0x1301
-
-/* operational registers */
-#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */
-# define MC1_SPEED (1 << 0)
-# define MC1_SUSPEND (1 << 1)
-# define MC1_DAT_SE0 (1 << 2)
-# define MC1_TRANSPARENT (1 << 3)
-# define MC1_BDIS_ACON_EN (1 << 4)
-# define MC1_OE_INT_EN (1 << 5)
-# define MC1_UART_EN (1 << 6)
-# define MC1_MASK 0x7f
-#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */
-# define MC2_GLOBAL_PWR_DN (1 << 0)
-# define MC2_SPD_SUSP_CTRL (1 << 1)
-# define MC2_BI_DI (1 << 2)
-# define MC2_TRANSP_BDIR0 (1 << 3)
-# define MC2_TRANSP_BDIR1 (1 << 4)
-# define MC2_AUDIO_EN (1 << 5)
-# define MC2_PSW_EN (1 << 6)
-# define MC2_EN2V7 (1 << 7)
-#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */
-# define OTG1_DP_PULLUP (1 << 0)
-# define OTG1_DM_PULLUP (1 << 1)
-# define OTG1_DP_PULLDOWN (1 << 2)
-# define OTG1_DM_PULLDOWN (1 << 3)
-# define OTG1_ID_PULLDOWN (1 << 4)
-# define OTG1_VBUS_DRV (1 << 5)
-# define OTG1_VBUS_DISCHRG (1 << 6)
-# define OTG1_VBUS_CHRG (1 << 7)
-#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */
-# define OTG_B_SESS_END (1 << 6)
-# define OTG_B_SESS_VLD (1 << 7)
-
-#define ISP1301_INTERRUPT_SOURCE 0x08 /* u8 read */
-#define ISP1301_INTERRUPT_LATCH 0x0A /* u8 read, set, +1 clear */
-
-#define ISP1301_INTERRUPT_FALLING 0x0C /* u8 read, set, +1 clear */
-#define ISP1301_INTERRUPT_RISING 0x0E /* u8 read, set, +1 clear */
-
-/* same bitfields in all interrupt registers */
-# define INTR_VBUS_VLD (1 << 0)
-# define INTR_SESS_VLD (1 << 1)
-# define INTR_DP_HI (1 << 2)
-# define INTR_ID_GND (1 << 3)
-# define INTR_DM_HI (1 << 4)
-# define INTR_ID_FLOAT (1 << 5)
-# define INTR_BDIS_ACON (1 << 6)
-# define INTR_CR_INT (1 << 7)
-
-/*-------------------------------------------------------------------------*/
-
-static const char *state_string(enum usb_otg_state state)
-{
- switch (state) {
- case OTG_STATE_A_IDLE: return "a_idle";
- case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise";
- case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon";
- case OTG_STATE_A_HOST: return "a_host";
- case OTG_STATE_A_SUSPEND: return "a_suspend";
- case OTG_STATE_A_PERIPHERAL: return "a_peripheral";
- case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall";
- case OTG_STATE_A_VBUS_ERR: return "a_vbus_err";
- case OTG_STATE_B_IDLE: return "b_idle";
- case OTG_STATE_B_SRP_INIT: return "b_srp_init";
- case OTG_STATE_B_PERIPHERAL: return "b_peripheral";
- case OTG_STATE_B_WAIT_ACON: return "b_wait_acon";
- case OTG_STATE_B_HOST: return "b_host";
- default: return "UNDEFINED";
- }
-}
-
-static inline const char *state_name(struct isp1301 *isp)
-{
- return state_string(isp->otg.state);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NOTE: some of this ISP1301 setup is specific to H2 boards;
- * not everything is guarded by board-specific checks, or even using
- * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
- *
- * ALSO: this currently doesn't use ISP1301 low-power modes
- * while OTG is running.
- */
-
-static void power_down(struct isp1301 *isp)
-{
- isp->otg.state = OTG_STATE_UNDEFINED;
-
- // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
-
- isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
- isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-}
-
-static void power_up(struct isp1301 *isp)
-{
- // isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
- isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
-
- /* do this only when cpu is driving transceiver,
- * so host won't see a low speed device...
- */
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-}
-
-#define NO_HOST_SUSPEND
-
-static int host_suspend(struct isp1301 *isp)
-{
-#ifdef NO_HOST_SUSPEND
- return 0;
-#else
- struct device *dev;
-
- if (!isp->otg.host)
- return -ENODEV;
-
- /* Currently ASSUMES only the OTG port matters;
- * other ports could be active...
- */
- dev = isp->otg.host->controller;
- return dev->driver->suspend(dev, 3, 0);
-#endif
-}
-
-static int host_resume(struct isp1301 *isp)
-{
-#ifdef NO_HOST_SUSPEND
- return 0;
-#else
- struct device *dev;
-
- if (!isp->otg.host)
- return -ENODEV;
-
- dev = isp->otg.host->controller;
- return dev->driver->resume(dev, 0);
-#endif
-}
-
-static int gadget_suspend(struct isp1301 *isp)
-{
- isp->otg.gadget->b_hnp_enable = 0;
- isp->otg.gadget->a_hnp_support = 0;
- isp->otg.gadget->a_alt_hnp_support = 0;
- return usb_gadget_vbus_disconnect(isp->otg.gadget);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define TIMER_MINUTES 10
-#define TIMER_JIFFIES (TIMER_MINUTES * 60 * HZ)
-
-/* Almost all our I2C messaging comes from a work queue's task context.
- * NOTE: guaranteeing certain response times might mean we shouldn't
- * share keventd's work queue; a realtime task might be safest.
- */
-void
-isp1301_defer_work(struct isp1301 *isp, int work)
-{
- int status;
-
- if (isp && !test_and_set_bit(work, &isp->todo)) {
- (void) get_device(&isp->client->dev);
- status = schedule_work(&isp->work);
- if (!status && !isp->working)
- dev_vdbg(&isp->client->dev,
- "work item %d may be lost\n", work);
- }
-}
-
-/* called from irq handlers */
-static void a_idle(struct isp1301 *isp, const char *tag)
-{
- u32 l;
-
- if (isp->otg.state == OTG_STATE_A_IDLE)
- return;
-
- isp->otg.default_a = 1;
- if (isp->otg.host) {
- isp->otg.host->is_b_host = 0;
- host_suspend(isp);
- }
- if (isp->otg.gadget) {
- isp->otg.gadget->is_a_peripheral = 1;
- gadget_suspend(isp);
- }
- isp->otg.state = OTG_STATE_A_IDLE;
- l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
- omap_writel(l, OTG_CTRL);
- isp->last_otg_ctrl = l;
- pr_debug(" --> %s/%s\n", state_name(isp), tag);
-}
-
-/* called from irq handlers */
-static void b_idle(struct isp1301 *isp, const char *tag)
-{
- u32 l;
-
- if (isp->otg.state == OTG_STATE_B_IDLE)
- return;
-
- isp->otg.default_a = 0;
- if (isp->otg.host) {
- isp->otg.host->is_b_host = 1;
- host_suspend(isp);
- }
- if (isp->otg.gadget) {
- isp->otg.gadget->is_a_peripheral = 0;
- gadget_suspend(isp);
- }
- isp->otg.state = OTG_STATE_B_IDLE;
- l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
- omap_writel(l, OTG_CTRL);
- isp->last_otg_ctrl = l;
- pr_debug(" --> %s/%s\n", state_name(isp), tag);
-}
-
-static void
-dump_regs(struct isp1301 *isp, const char *label)
-{
-#ifdef DEBUG
- u8 ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
- u8 status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
- u8 src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
-
- pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n",
- omap_readl(OTG_CTRL), label, state_name(isp),
- ctrl, status, src);
- /* mode control and irq enables don't change much */
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_OTG
-
-/*
- * The OMAP OTG controller handles most of the OTG state transitions.
- *
- * We translate isp1301 outputs (mostly voltage comparator status) into
- * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state
- * flags into isp1301 inputs ... and infer state transitions.
- */
-
-#ifdef VERBOSE
-
-static void check_state(struct isp1301 *isp, const char *tag)
-{
- enum usb_otg_state state = OTG_STATE_UNDEFINED;
- u8 fsm = omap_readw(OTG_TEST) & 0x0ff;
- unsigned extra = 0;
-
- switch (fsm) {
-
- /* default-b */
- case 0x0:
- state = OTG_STATE_B_IDLE;
- break;
- case 0x3:
- case 0x7:
- extra = 1;
- case 0x1:
- state = OTG_STATE_B_PERIPHERAL;
- break;
- case 0x11:
- state = OTG_STATE_B_SRP_INIT;
- break;
-
- /* extra dual-role default-b states */
- case 0x12:
- case 0x13:
- case 0x16:
- extra = 1;
- case 0x17:
- state = OTG_STATE_B_WAIT_ACON;
- break;
- case 0x34:
- state = OTG_STATE_B_HOST;
- break;
-
- /* default-a */
- case 0x36:
- state = OTG_STATE_A_IDLE;
- break;
- case 0x3c:
- state = OTG_STATE_A_WAIT_VFALL;
- break;
- case 0x7d:
- state = OTG_STATE_A_VBUS_ERR;
- break;
- case 0x9e:
- case 0x9f:
- extra = 1;
- case 0x89:
- state = OTG_STATE_A_PERIPHERAL;
- break;
- case 0xb7:
- state = OTG_STATE_A_WAIT_VRISE;
- break;
- case 0xb8:
- state = OTG_STATE_A_WAIT_BCON;
- break;
- case 0xb9:
- state = OTG_STATE_A_HOST;
- break;
- case 0xba:
- state = OTG_STATE_A_SUSPEND;
- break;
- default:
- break;
- }
- if (isp->otg.state == state && !extra)
- return;
- pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
- state_string(state), fsm, state_name(isp),
- omap_readl(OTG_CTRL));
-}
-
-#else
-
-static inline void check_state(struct isp1301 *isp, const char *tag) { }
-
-#endif
-
-/* outputs from ISP1301_INTERRUPT_SOURCE */
-static void update_otg1(struct isp1301 *isp, u8 int_src)
-{
- u32 otg_ctrl;
-
- otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- otg_ctrl &= ~OTG_XCEIV_INPUTS;
- otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
-
-
- if (int_src & INTR_SESS_VLD)
- otg_ctrl |= OTG_ASESSVLD;
- else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
- a_idle(isp, "vfall");
- otg_ctrl &= ~OTG_CTRL_BITS;
- }
- if (int_src & INTR_VBUS_VLD)
- otg_ctrl |= OTG_VBUSVLD;
- if (int_src & INTR_ID_GND) { /* default-A */
- if (isp->otg.state == OTG_STATE_B_IDLE
- || isp->otg.state == OTG_STATE_UNDEFINED) {
- a_idle(isp, "init");
- return;
- }
- } else { /* default-B */
- otg_ctrl |= OTG_ID;
- if (isp->otg.state == OTG_STATE_A_IDLE
- || isp->otg.state == OTG_STATE_UNDEFINED) {
- b_idle(isp, "init");
- return;
- }
- }
- omap_writel(otg_ctrl, OTG_CTRL);
-}
-
-/* outputs from ISP1301_OTG_STATUS */
-static void update_otg2(struct isp1301 *isp, u8 otg_status)
-{
- u32 otg_ctrl;
-
- otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- otg_ctrl &= ~OTG_XCEIV_INPUTS;
- otg_ctrl &= ~(OTG_BSESSVLD | OTG_BSESSEND);
- if (otg_status & OTG_B_SESS_VLD)
- otg_ctrl |= OTG_BSESSVLD;
- else if (otg_status & OTG_B_SESS_END)
- otg_ctrl |= OTG_BSESSEND;
- omap_writel(otg_ctrl, OTG_CTRL);
-}
-
-/* inputs going to ISP1301 */
-static void otg_update_isp(struct isp1301 *isp)
-{
- u32 otg_ctrl, otg_change;
- u8 set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;
-
- otg_ctrl = omap_readl(OTG_CTRL);
- otg_change = otg_ctrl ^ isp->last_otg_ctrl;
- isp->last_otg_ctrl = otg_ctrl;
- otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
-
- switch (isp->otg.state) {
- case OTG_STATE_B_IDLE:
- case OTG_STATE_B_PERIPHERAL:
- case OTG_STATE_B_SRP_INIT:
- if (!(otg_ctrl & OTG_PULLUP)) {
- // if (otg_ctrl & OTG_B_HNPEN) {
- if (isp->otg.gadget->b_hnp_enable) {
- isp->otg.state = OTG_STATE_B_WAIT_ACON;
- pr_debug(" --> b_wait_acon\n");
- }
- goto pulldown;
- }
-pullup:
- set |= OTG1_DP_PULLUP;
- clr |= OTG1_DP_PULLDOWN;
- break;
- case OTG_STATE_A_SUSPEND:
- case OTG_STATE_A_PERIPHERAL:
- if (otg_ctrl & OTG_PULLUP)
- goto pullup;
- /* FALLTHROUGH */
- // case OTG_STATE_B_WAIT_ACON:
- default:
-pulldown:
- set |= OTG1_DP_PULLDOWN;
- clr |= OTG1_DP_PULLUP;
- break;
- }
-
-# define toggle(OTG,ISP) do { \
- if (otg_ctrl & OTG) set |= ISP; \
- else clr |= ISP; \
- } while (0)
-
- if (!(isp->otg.host))
- otg_ctrl &= ~OTG_DRV_VBUS;
-
- switch (isp->otg.state) {
- case OTG_STATE_A_SUSPEND:
- if (otg_ctrl & OTG_DRV_VBUS) {
- set |= OTG1_VBUS_DRV;
- break;
- }
- /* HNP failed for some reason (A_AIDL_BDIS timeout) */
- notresponding(isp);
-
- /* FALLTHROUGH */
- case OTG_STATE_A_VBUS_ERR:
- isp->otg.state = OTG_STATE_A_WAIT_VFALL;
- pr_debug(" --> a_wait_vfall\n");
- /* FALLTHROUGH */
- case OTG_STATE_A_WAIT_VFALL:
- /* FIXME usbcore thinks port power is still on ... */
- clr |= OTG1_VBUS_DRV;
- break;
- case OTG_STATE_A_IDLE:
- if (otg_ctrl & OTG_DRV_VBUS) {
- isp->otg.state = OTG_STATE_A_WAIT_VRISE;
- pr_debug(" --> a_wait_vrise\n");
- }
- /* FALLTHROUGH */
- default:
- toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
- }
-
- toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
- toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);
-
-# undef toggle
-
- isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
- isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);
-
- /* HNP switch to host or peripheral; and SRP */
- if (otg_change & OTG_PULLUP) {
- u32 l;
-
- switch (isp->otg.state) {
- case OTG_STATE_B_IDLE:
- if (clr & OTG1_DP_PULLUP)
- break;
- isp->otg.state = OTG_STATE_B_PERIPHERAL;
- pr_debug(" --> b_peripheral\n");
- break;
- case OTG_STATE_A_SUSPEND:
- if (clr & OTG1_DP_PULLUP)
- break;
- isp->otg.state = OTG_STATE_A_PERIPHERAL;
- pr_debug(" --> a_peripheral\n");
- break;
- default:
- break;
- }
- l = omap_readl(OTG_CTRL);
- l |= OTG_PULLUP;
- omap_writel(l, OTG_CTRL);
- }
-
- check_state(isp, __func__);
- dump_regs(isp, "otg->isp1301");
-}
-
-static irqreturn_t omap_otg_irq(int irq, void *_isp)
-{
- u16 otg_irq = omap_readw(OTG_IRQ_SRC);
- u32 otg_ctrl;
- int ret = IRQ_NONE;
- struct isp1301 *isp = _isp;
-
- /* update ISP1301 transciever from OTG controller */
- if (otg_irq & OPRT_CHG) {
- omap_writew(OPRT_CHG, OTG_IRQ_SRC);
- isp1301_defer_work(isp, WORK_UPDATE_ISP);
- ret = IRQ_HANDLED;
-
- /* SRP to become b_peripheral failed */
- } else if (otg_irq & B_SRP_TMROUT) {
- pr_debug("otg: B_SRP_TIMEOUT, %06x\n", omap_readl(OTG_CTRL));
- notresponding(isp);
-
- /* gadget drivers that care should monitor all kinds of
- * remote wakeup (SRP, normal) using their own timer
- * to give "check cable and A-device" messages.
- */
- if (isp->otg.state == OTG_STATE_B_SRP_INIT)
- b_idle(isp, "srp_timeout");
-
- omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- /* HNP to become b_host failed */
- } else if (otg_irq & B_HNP_FAIL) {
- pr_debug("otg: %s B_HNP_FAIL, %06x\n",
- state_name(isp), omap_readl(OTG_CTRL));
- notresponding(isp);
-
- otg_ctrl = omap_readl(OTG_CTRL);
- otg_ctrl |= OTG_BUSDROP;
- otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
- omap_writel(otg_ctrl, OTG_CTRL);
-
- /* subset of b_peripheral()... */
- isp->otg.state = OTG_STATE_B_PERIPHERAL;
- pr_debug(" --> b_peripheral\n");
-
- omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- /* detect SRP from B-device ... */
- } else if (otg_irq & A_SRP_DETECT) {
- pr_debug("otg: %s SRP_DETECT, %06x\n",
- state_name(isp), omap_readl(OTG_CTRL));
-
- isp1301_defer_work(isp, WORK_UPDATE_OTG);
- switch (isp->otg.state) {
- case OTG_STATE_A_IDLE:
- if (!isp->otg.host)
- break;
- isp1301_defer_work(isp, WORK_HOST_RESUME);
- otg_ctrl = omap_readl(OTG_CTRL);
- otg_ctrl |= OTG_A_BUSREQ;
- otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
- & ~OTG_XCEIV_INPUTS
- & OTG_CTRL_MASK;
- omap_writel(otg_ctrl, OTG_CTRL);
- break;
- default:
- break;
- }
-
- omap_writew(A_SRP_DETECT, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- /* timer expired: T(a_wait_bcon) and maybe T(a_wait_vrise)
- * we don't track them separately
- */
- } else if (otg_irq & A_REQ_TMROUT) {
- otg_ctrl = omap_readl(OTG_CTRL);
- pr_info("otg: BCON_TMOUT from %s, %06x\n",
- state_name(isp), otg_ctrl);
- notresponding(isp);
-
- otg_ctrl |= OTG_BUSDROP;
- otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
- omap_writel(otg_ctrl, OTG_CTRL);
- isp->otg.state = OTG_STATE_A_WAIT_VFALL;
-
- omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- /* A-supplied voltage fell too low; overcurrent */
- } else if (otg_irq & A_VBUS_ERR) {
- otg_ctrl = omap_readl(OTG_CTRL);
- printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n",
- state_name(isp), otg_irq, otg_ctrl);
-
- otg_ctrl |= OTG_BUSDROP;
- otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
- omap_writel(otg_ctrl, OTG_CTRL);
- isp->otg.state = OTG_STATE_A_VBUS_ERR;
-
- omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- /* switch driver; the transciever code activates it,
- * ungating the udc clock or resuming OHCI.
- */
- } else if (otg_irq & DRIVER_SWITCH) {
- int kick = 0;
-
- otg_ctrl = omap_readl(OTG_CTRL);
- printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n",
- state_name(isp),
- (otg_ctrl & OTG_DRIVER_SEL)
- ? "gadget" : "host",
- otg_ctrl);
- isp1301_defer_work(isp, WORK_UPDATE_ISP);
-
- /* role is peripheral */
- if (otg_ctrl & OTG_DRIVER_SEL) {
- switch (isp->otg.state) {
- case OTG_STATE_A_IDLE:
- b_idle(isp, __func__);
- break;
- default:
- break;
- }
- isp1301_defer_work(isp, WORK_UPDATE_ISP);
-
- /* role is host */
- } else {
- if (!(otg_ctrl & OTG_ID)) {
- otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
- omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL);
- }
-
- if (isp->otg.host) {
- switch (isp->otg.state) {
- case OTG_STATE_B_WAIT_ACON:
- isp->otg.state = OTG_STATE_B_HOST;
- pr_debug(" --> b_host\n");
- kick = 1;
- break;
- case OTG_STATE_A_WAIT_BCON:
- isp->otg.state = OTG_STATE_A_HOST;
- pr_debug(" --> a_host\n");
- break;
- case OTG_STATE_A_PERIPHERAL:
- isp->otg.state = OTG_STATE_A_WAIT_BCON;
- pr_debug(" --> a_wait_bcon\n");
- break;
- default:
- break;
- }
- isp1301_defer_work(isp, WORK_HOST_RESUME);
- }
- }
-
- omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC);
- ret = IRQ_HANDLED;
-
- if (kick)
- usb_bus_start_enum(isp->otg.host,
- isp->otg.host->otg_port);
- }
-
- check_state(isp, __func__);
- return ret;
-}
-
-static struct platform_device *otg_dev;
-
-static int otg_init(struct isp1301 *isp)
-{
- u32 l;
-
- if (!otg_dev)
- return -ENODEV;
-
- dump_regs(isp, __func__);
- /* some of these values are board-specific... */
- l = omap_readl(OTG_SYSCON_2);
- l |= OTG_EN
- /* for B-device: */
- | SRP_GPDATA /* 9msec Bdev D+ pulse */
- | SRP_GPDVBUS /* discharge after VBUS pulse */
- // | (3 << 24) /* 2msec VBUS pulse */
- /* for A-device: */
- | (0 << 20) /* 200ms nominal A_WAIT_VRISE timer */
- | SRP_DPW /* detect 167+ns SRP pulses */
- | SRP_DATA | SRP_VBUS /* accept both kinds of SRP pulse */
- ;
- omap_writel(l, OTG_SYSCON_2);
-
- update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
- update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
-
- check_state(isp, __func__);
- pr_debug("otg: %s, %s %06x\n",
- state_name(isp), __func__, omap_readl(OTG_CTRL));
-
- omap_writew(DRIVER_SWITCH | OPRT_CHG
- | B_SRP_TMROUT | B_HNP_FAIL
- | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT, OTG_IRQ_EN);
-
- l = omap_readl(OTG_SYSCON_2);
- l |= OTG_EN;
- omap_writel(l, OTG_SYSCON_2);
-
- return 0;
-}
-
-static int otg_probe(struct platform_device *dev)
-{
- // struct omap_usb_config *config = dev->platform_data;
-
- otg_dev = dev;
- return 0;
-}
-
-static int otg_remove(struct platform_device *dev)
-{
- otg_dev = 0;
- return 0;
-}
-
-struct platform_driver omap_otg_driver = {
- .probe = otg_probe,
- .remove = otg_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "omap_otg",
- },
-};
-
-static int otg_bind(struct isp1301 *isp)
-{
- int status;
-
- if (otg_dev)
- return -EBUSY;
-
- status = platform_driver_register(&omap_otg_driver);
- if (status < 0)
- return status;
-
- if (otg_dev)
- status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
- IRQF_DISABLED, DRIVER_NAME, isp);
- else
- status = -ENODEV;
-
- if (status < 0)
- platform_driver_unregister(&omap_otg_driver);
- return status;
-}
-
-static void otg_unbind(struct isp1301 *isp)
-{
- if (!otg_dev)
- return;
- free_irq(otg_dev->resource[1].start, isp);
-}
-
-#else
-
-/* OTG controller isn't clocked */
-
-#endif /* CONFIG_USB_OTG */
-
-/*-------------------------------------------------------------------------*/
-
-static void b_peripheral(struct isp1301 *isp)
-{
- u32 l;
-
- l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
- omap_writel(l, OTG_CTRL);
-
- usb_gadget_vbus_connect(isp->otg.gadget);
-
-#ifdef CONFIG_USB_OTG
- enable_vbus_draw(isp, 8);
- otg_update_isp(isp);
-#else
- enable_vbus_draw(isp, 100);
- /* UDC driver just set OTG_BSESSVLD */
- isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
- isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
- isp->otg.state = OTG_STATE_B_PERIPHERAL;
- pr_debug(" --> b_peripheral\n");
- dump_regs(isp, "2periph");
-#endif
-}
-
-static void isp_update_otg(struct isp1301 *isp, u8 stat)
-{
- u8 isp_stat, isp_bstat;
- enum usb_otg_state state = isp->otg.state;
-
- if (stat & INTR_BDIS_ACON)
- pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp));
-
- /* start certain state transitions right away */
- isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
- if (isp_stat & INTR_ID_GND) {
- if (isp->otg.default_a) {
- switch (state) {
- case OTG_STATE_B_IDLE:
- a_idle(isp, "idle");
- /* FALLTHROUGH */
- case OTG_STATE_A_IDLE:
- enable_vbus_source(isp);
- /* FALLTHROUGH */
- case OTG_STATE_A_WAIT_VRISE:
- /* we skip over OTG_STATE_A_WAIT_BCON, since
- * the HC will transition to A_HOST (or
- * A_SUSPEND!) without our noticing except
- * when HNP is used.
- */
- if (isp_stat & INTR_VBUS_VLD)
- isp->otg.state = OTG_STATE_A_HOST;
- break;
- case OTG_STATE_A_WAIT_VFALL:
- if (!(isp_stat & INTR_SESS_VLD))
- a_idle(isp, "vfell");
- break;
- default:
- if (!(isp_stat & INTR_VBUS_VLD))
- isp->otg.state = OTG_STATE_A_VBUS_ERR;
- break;
- }
- isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
- } else {
- switch (state) {
- case OTG_STATE_B_PERIPHERAL:
- case OTG_STATE_B_HOST:
- case OTG_STATE_B_WAIT_ACON:
- usb_gadget_vbus_disconnect(isp->otg.gadget);
- break;
- default:
- break;
- }
- if (state != OTG_STATE_A_IDLE)
- a_idle(isp, "id");
- if (isp->otg.host && state == OTG_STATE_A_IDLE)
- isp1301_defer_work(isp, WORK_HOST_RESUME);
- isp_bstat = 0;
- }
- } else {
- u32 l;
-
- /* if user unplugged mini-A end of cable,
- * don't bypass A_WAIT_VFALL.
- */
- if (isp->otg.default_a) {
- switch (state) {
- default:
- isp->otg.state = OTG_STATE_A_WAIT_VFALL;
- break;
- case OTG_STATE_A_WAIT_VFALL:
- state = OTG_STATE_A_IDLE;
- /* khubd may take a while to notice and
- * handle this disconnect, so don't go
- * to B_IDLE quite yet.
- */
- break;
- case OTG_STATE_A_IDLE:
- host_suspend(isp);
- isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
- MC1_BDIS_ACON_EN);
- isp->otg.state = OTG_STATE_B_IDLE;
- l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- l &= ~OTG_CTRL_BITS;
- omap_writel(l, OTG_CTRL);
- break;
- case OTG_STATE_B_IDLE:
- break;
- }
- }
- isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
-
- switch (isp->otg.state) {
- case OTG_STATE_B_PERIPHERAL:
- case OTG_STATE_B_WAIT_ACON:
- case OTG_STATE_B_HOST:
- if (likely(isp_bstat & OTG_B_SESS_VLD))
- break;
- enable_vbus_draw(isp, 0);
-#ifndef CONFIG_USB_OTG
- /* UDC driver will clear OTG_BSESSVLD */
- isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
- OTG1_DP_PULLDOWN);
- isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
- OTG1_DP_PULLUP);
- dump_regs(isp, __func__);
-#endif
- /* FALLTHROUGH */
- case OTG_STATE_B_SRP_INIT:
- b_idle(isp, __func__);
- l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
- omap_writel(l, OTG_CTRL);
- /* FALLTHROUGH */
- case OTG_STATE_B_IDLE:
- if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) {
-#ifdef CONFIG_USB_OTG
- update_otg1(isp, isp_stat);
- update_otg2(isp, isp_bstat);
-#endif
- b_peripheral(isp);
- } else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
- isp_bstat |= OTG_B_SESS_END;
- break;
- case OTG_STATE_A_WAIT_VFALL:
- break;
- default:
- pr_debug("otg: unsupported b-device %s\n",
- state_name(isp));
- break;
- }
- }
-
- if (state != isp->otg.state)
- pr_debug(" isp, %s -> %s\n",
- state_string(state), state_name(isp));
-
-#ifdef CONFIG_USB_OTG
- /* update the OTG controller state to match the isp1301; may
- * trigger OPRT_CHG irqs for changes going to the isp1301.
- */
- update_otg1(isp, isp_stat);
- update_otg2(isp, isp_bstat);
- check_state(isp, __func__);
-#endif
-
- dump_regs(isp, "isp1301->otg");
-}
-
-/*-------------------------------------------------------------------------*/
-
-static u8 isp1301_clear_latch(struct isp1301 *isp)
-{
- u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH);
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch);
- return latch;
-}
-
-static void
-isp1301_work(struct work_struct *work)
-{
- struct isp1301 *isp = container_of(work, struct isp1301, work);
- int stop;
-
- /* implicit lock: we're the only task using this device */
- isp->working = 1;
- do {
- stop = test_bit(WORK_STOP, &isp->todo);
-
-#ifdef CONFIG_USB_OTG
- /* transfer state from otg engine to isp1301 */
- if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
- otg_update_isp(isp);
- put_device(&isp->client->dev);
- }
-#endif
- /* transfer state from isp1301 to otg engine */
- if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) {
- u8 stat = isp1301_clear_latch(isp);
-
- isp_update_otg(isp, stat);
- put_device(&isp->client->dev);
- }
-
- if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
- u32 otg_ctrl;
-
- /*
- * skip A_WAIT_VRISE; hc transitions invisibly
- * skip A_WAIT_BCON; same.
- */
- switch (isp->otg.state) {
- case OTG_STATE_A_WAIT_BCON:
- case OTG_STATE_A_WAIT_VRISE:
- isp->otg.state = OTG_STATE_A_HOST;
- pr_debug(" --> a_host\n");
- otg_ctrl = omap_readl(OTG_CTRL);
- otg_ctrl |= OTG_A_BUSREQ;
- otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
- & OTG_CTRL_MASK;
- omap_writel(otg_ctrl, OTG_CTRL);
- break;
- case OTG_STATE_B_WAIT_ACON:
- isp->otg.state = OTG_STATE_B_HOST;
- pr_debug(" --> b_host (acon)\n");
- break;
- case OTG_STATE_B_HOST:
- case OTG_STATE_B_IDLE:
- case OTG_STATE_A_IDLE:
- break;
- default:
- pr_debug(" host resume in %s\n",
- state_name(isp));
- }
- host_resume(isp);
- // mdelay(10);
- put_device(&isp->client->dev);
- }
-
- if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
-#ifdef VERBOSE
- dump_regs(isp, "timer");
- if (!stop)
- mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
-#endif
- put_device(&isp->client->dev);
- }
-
- if (isp->todo)
- dev_vdbg(&isp->client->dev,
- "work done, todo = 0x%lx\n",
- isp->todo);
- if (stop) {
- dev_dbg(&isp->client->dev, "stop\n");
- break;
- }
- } while (isp->todo);
- isp->working = 0;
-}
-
-static irqreturn_t isp1301_irq(int irq, void *isp)
-{
- isp1301_defer_work(isp, WORK_UPDATE_OTG);
- return IRQ_HANDLED;
-}
-
-static void isp1301_timer(unsigned long _isp)
-{
- isp1301_defer_work((void *)_isp, WORK_TIMER);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void isp1301_release(struct device *dev)
-{
- struct isp1301 *isp;
-
- isp = dev_get_drvdata(dev);
-
- /* ugly -- i2c hijacks our memory hook to wait_for_completion() */
- if (isp->i2c_release)
- isp->i2c_release(dev);
- kfree (isp);
-}
-
-static struct isp1301 *the_transceiver;
-
-static int __exit isp1301_remove(struct i2c_client *i2c)
-{
- struct isp1301 *isp;
-
- isp = i2c_get_clientdata(i2c);
-
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
- free_irq(i2c->irq, isp);
-#ifdef CONFIG_USB_OTG
- otg_unbind(isp);
-#endif
- if (machine_is_omap_h2())
- omap_free_gpio(2);
-
- isp->timer.data = 0;
- set_bit(WORK_STOP, &isp->todo);
- del_timer_sync(&isp->timer);
- flush_scheduled_work();
-
- put_device(&i2c->dev);
- the_transceiver = 0;
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NOTE: three modes are possible here, only one of which
- * will be standards-conformant on any given system:
- *
- * - OTG mode (dual-role), required if there's a Mini-AB connector
- * - HOST mode, for when there's one or more A (host) connectors
- * - DEVICE mode, for when there's a B/Mini-B (device) connector
- *
- * As a rule, you won't have an isp1301 chip unless it's there to
- * support the OTG mode. Other modes help testing USB controllers
- * in isolation from (full) OTG support, or maybe so later board
- * revisions can help to support those feature.
- */
-
-#ifdef CONFIG_USB_OTG
-
-static int isp1301_otg_enable(struct isp1301 *isp)
-{
- power_up(isp);
- otg_init(isp);
-
- /* NOTE: since we don't change this, this provides
- * a few more interrupts than are strictly needed.
- */
- isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
- INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
- isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
- INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
-
- dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
-
- return 0;
-}
-
-#endif
-
-/* add or disable the host device+driver */
-static int
-isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
-{
- struct isp1301 *isp = container_of(otg, struct isp1301, otg);
-
- if (!otg || isp != the_transceiver)
- return -ENODEV;
-
- if (!host) {
- omap_writew(0, OTG_IRQ_EN);
- power_down(isp);
- isp->otg.host = 0;
- return 0;
- }
-
-#ifdef CONFIG_USB_OTG
- isp->otg.host = host;
- dev_dbg(&isp->client->dev, "registered host\n");
- host_suspend(isp);
- if (isp->otg.gadget)
- return isp1301_otg_enable(isp);
- return 0;
-
-#elif !defined(CONFIG_USB_GADGET_OMAP)
- // FIXME update its refcount
- isp->otg.host = host;
-
- power_up(isp);
-
- if (machine_is_omap_h2())
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-
- dev_info(&isp->client->dev, "A-Host sessions ok\n");
- isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
- INTR_ID_GND);
- isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
- INTR_ID_GND);
-
- /* If this has a Mini-AB connector, this mode is highly
- * nonstandard ... but can be handy for testing, especially with
- * the Mini-A end of an OTG cable. (Or something nonstandard
- * like MiniB-to-StandardB, maybe built with a gender mender.)
- */
- isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
-
- dump_regs(isp, __func__);
-
- return 0;
-
-#else
- dev_dbg(&isp->client->dev, "host sessions not allowed\n");
- return -EINVAL;
-#endif
-
-}
-
-static int
-isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
-{
- struct isp1301 *isp = container_of(otg, struct isp1301, otg);
- u32 l;
-
- if (!otg || isp != the_transceiver)
- return -ENODEV;
-
- if (!gadget) {
- omap_writew(0, OTG_IRQ_EN);
- if (!isp->otg.default_a)
- enable_vbus_draw(isp, 0);
- usb_gadget_vbus_disconnect(isp->otg.gadget);
- isp->otg.gadget = 0;
- power_down(isp);
- return 0;
- }
-
-#ifdef CONFIG_USB_OTG
- isp->otg.gadget = gadget;
- dev_dbg(&isp->client->dev, "registered gadget\n");
- /* gadget driver may be suspended until vbus_connect () */
- if (isp->otg.host)
- return isp1301_otg_enable(isp);
- return 0;
-
-#elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
- isp->otg.gadget = gadget;
- // FIXME update its refcount
-
- l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
- l |= OTG_ID;
- omap_writel(l, OTG_CTRL);
-
- power_up(isp);
- isp->otg.state = OTG_STATE_B_IDLE;
-
- if (machine_is_omap_h2())
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-
- isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
- INTR_SESS_VLD);
- isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
- INTR_VBUS_VLD);
- dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
- dump_regs(isp, __func__);
-
- /* If this has a Mini-AB connector, this mode is highly
- * nonstandard ... but can be handy for testing, so long
- * as you don't plug a Mini-A cable into the jack.
- */
- if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
- b_peripheral(isp);
-
- return 0;
-
-#else
- dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
- return -EINVAL;
-#endif
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int
-isp1301_set_power(struct otg_transceiver *dev, unsigned mA)
-{
- if (!the_transceiver)
- return -ENODEV;
- if (dev->state == OTG_STATE_B_PERIPHERAL)
- enable_vbus_draw(the_transceiver, mA);
- return 0;
-}
-
-static int
-isp1301_start_srp(struct otg_transceiver *dev)
-{
- struct isp1301 *isp = container_of(dev, struct isp1301, otg);
- u32 otg_ctrl;
-
- if (!dev || isp != the_transceiver
- || isp->otg.state != OTG_STATE_B_IDLE)
- return -ENODEV;
-
- otg_ctrl = omap_readl(OTG_CTRL);
- if (!(otg_ctrl & OTG_BSESSEND))
- return -EINVAL;
-
- otg_ctrl |= OTG_B_BUSREQ;
- otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
- omap_writel(otg_ctrl, OTG_CTRL);
- isp->otg.state = OTG_STATE_B_SRP_INIT;
-
- pr_debug("otg: SRP, %s ... %06x\n", state_name(isp),
- omap_readl(OTG_CTRL));
-#ifdef CONFIG_USB_OTG
- check_state(isp, __func__);
-#endif
- return 0;
-}
-
-static int
-isp1301_start_hnp(struct otg_transceiver *dev)
-{
-#ifdef CONFIG_USB_OTG
- struct isp1301 *isp = container_of(dev, struct isp1301, otg);
- u32 l;
-
- if (!dev || isp != the_transceiver)
- return -ENODEV;
- if (isp->otg.default_a && (isp->otg.host == NULL
- || !isp->otg.host->b_hnp_enable))
- return -ENOTCONN;
- if (!isp->otg.default_a && (isp->otg.gadget == NULL
- || !isp->otg.gadget->b_hnp_enable))
- return -ENOTCONN;
-
- /* We want hardware to manage most HNP protocol timings.
- * So do this part as early as possible...
- */
- switch (isp->otg.state) {
- case OTG_STATE_B_HOST:
- isp->otg.state = OTG_STATE_B_PERIPHERAL;
- /* caller will suspend next */
- break;
- case OTG_STATE_A_HOST:
-#if 0
- /* autoconnect mode avoids irq latency bugs */
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
- MC1_BDIS_ACON_EN);
-#endif
- /* caller must suspend then clear A_BUSREQ */
- usb_gadget_vbus_connect(isp->otg.gadget);
- l = omap_readl(OTG_CTRL);
- l |= OTG_A_SETB_HNPEN;
- omap_writel(l, OTG_CTRL);
-
- break;
- case OTG_STATE_A_PERIPHERAL:
- /* initiated by B-Host suspend */
- break;
- default:
- return -EILSEQ;
- }
- pr_debug("otg: HNP %s, %06x ...\n",
- state_name(isp), omap_readl(OTG_CTRL));
- check_state(isp, __func__);
- return 0;
-#else
- /* srp-only */
- return -EINVAL;
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __init isp1301_probe(struct i2c_client *i2c)
-{
- int status;
- struct isp1301 *isp;
-
- if (the_transceiver)
- return 0;
-
- isp = kzalloc(sizeof *isp, GFP_KERNEL);
- if (!isp)
- return 0;
-
- INIT_WORK(&isp->work, isp1301_work);
- init_timer(&isp->timer);
- isp->timer.function = isp1301_timer;
- isp->timer.data = (unsigned long) isp;
-
- i2c_set_clientdata(i2c, isp);
- isp->client = i2c;
-
- /* verify the chip (shouldn't be necesary) */
- status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
- if (status != I2C_VENDOR_ID_PHILIPS) {
- dev_dbg(&i2c->dev, "not philips id: %d\n", status);
- goto fail;
- }
- status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
- if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
- dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
- goto fail;
- }
- isp->i2c_release = i2c->dev.release;
- i2c->dev.release = isp1301_release;
-
- /* initial development used chiprev 2.00 */
- status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
- dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
- status >> 8, status & 0xff);
-
- /* make like power-on reset */
- isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);
-
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
- isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);
-
- isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
- OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
- isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
- ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
-
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
- isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
-
-#ifdef CONFIG_USB_OTG
- status = otg_bind(isp);
- if (status < 0) {
- dev_dbg(&i2c->dev, "can't bind OTG\n");
- goto fail;
- }
-#endif
-
- if (machine_is_omap_h2()) {
- /* full speed signaling by default */
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
- MC1_SPEED);
- isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
- MC2_SPD_SUSP_CTRL);
-
- /* IRQ wired at M14 */
- omap_cfg_reg(M14_1510_GPIO2);
- if (gpio_request(2, "isp1301") == 0)
- gpio_direction_input(2);
- isp->irq_type = IRQF_TRIGGER_FALLING;
- }
-
- isp->irq_type |= IRQF_SAMPLE_RANDOM;
- status = request_irq(i2c->irq, isp1301_irq,
- isp->irq_type, DRIVER_NAME, isp);
- if (status < 0) {
- dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
- i2c->irq, status);
- goto fail;
- }
-
- isp->otg.dev = &i2c->dev;
- isp->otg.label = DRIVER_NAME;
-
- isp->otg.set_host = isp1301_set_host,
- isp->otg.set_peripheral = isp1301_set_peripheral,
- isp->otg.set_power = isp1301_set_power,
- isp->otg.start_srp = isp1301_start_srp,
- isp->otg.start_hnp = isp1301_start_hnp,
-
- enable_vbus_draw(isp, 0);
- power_down(isp);
- the_transceiver = isp;
-
-#ifdef CONFIG_USB_OTG
- update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
- update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
-#endif
-
- dump_regs(isp, __func__);
-
-#ifdef VERBOSE
- mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
- dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
-#endif
-
- status = otg_set_transceiver(&isp->otg);
- if (status < 0)
- dev_err(&i2c->dev, "can't register transceiver, %d\n",
- status);
-
- return 0;
-
-fail:
- kfree(isp);
- return -ENODEV;
-}
-
-static const struct i2c_device_id isp1301_id[] = {
- { "isp1301_omap", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, isp1301_id);
-
-static struct i2c_driver isp1301_driver = {
- .driver = {
- .name = "isp1301_omap",
- },
- .probe = isp1301_probe,
- .remove = __exit_p(isp1301_remove),
- .id_table = isp1301_id,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init isp_init(void)
-{
- return i2c_add_driver(&isp1301_driver);
-}
-module_init(isp_init);
-
-static void __exit isp_exit(void)
-{
- if (the_transceiver)
- otg_set_transceiver(0);
- i2c_del_driver(&isp1301_driver);
-}
-module_exit(isp_exit);
-
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c
deleted file mode 100644
index 82a9bcb858b..00000000000
--- a/drivers/i2c/chips/mcu_mpc8349emitx.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
- *
- * Copyright (c) 2008 MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-
-/*
- * I don't have specifications for the MCU firmware, I found this register
- * and bits positions by the trial&error method.
- */
-#define MCU_REG_CTRL 0x20
-#define MCU_CTRL_POFF 0x40
-
-#define MCU_NUM_GPIO 2
-
-struct mcu {
- struct mutex lock;
- struct device_node *np;
- struct i2c_client *client;
- struct of_gpio_chip of_gc;
- u8 reg_ctrl;
-};
-
-static struct mcu *glob_mcu;
-
-static void mcu_power_off(void)
-{
- struct mcu *mcu = glob_mcu;
-
- pr_info("Sending power-off request to the MCU...\n");
- mutex_lock(&mcu->lock);
- i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
- mcu->reg_ctrl | MCU_CTRL_POFF);
- mutex_unlock(&mcu->lock);
-}
-
-static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
- struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
- u8 bit = 1 << (4 + gpio);
-
- mutex_lock(&mcu->lock);
- if (val)
- mcu->reg_ctrl &= ~bit;
- else
- mcu->reg_ctrl |= bit;
-
- i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
- mutex_unlock(&mcu->lock);
-}
-
-static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- mcu_gpio_set(gc, gpio, val);
- return 0;
-}
-
-static int mcu_gpiochip_add(struct mcu *mcu)
-{
- struct device_node *np;
- struct of_gpio_chip *of_gc = &mcu->of_gc;
- struct gpio_chip *gc = &of_gc->gc;
- int ret;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
- if (!np)
- return -ENODEV;
-
- gc->owner = THIS_MODULE;
- gc->label = np->full_name;
- gc->can_sleep = 1;
- gc->ngpio = MCU_NUM_GPIO;
- gc->base = -1;
- gc->set = mcu_gpio_set;
- gc->direction_output = mcu_gpio_dir_out;
- of_gc->gpio_cells = 2;
- of_gc->xlate = of_gpio_simple_xlate;
-
- np->data = of_gc;
- mcu->np = np;
-
- /*
- * We don't want to lose the node, its ->data and ->full_name...
- * So, if succeeded, we don't put the node here.
- */
- ret = gpiochip_add(gc);
- if (ret)
- of_node_put(np);
- return ret;
-}
-
-static int mcu_gpiochip_remove(struct mcu *mcu)
-{
- int ret;
-
- ret = gpiochip_remove(&mcu->of_gc.gc);
- if (ret)
- return ret;
- of_node_put(mcu->np);
-
- return 0;
-}
-
-static int __devinit mcu_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct mcu *mcu;
- int ret;
-
- mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
- if (!mcu)
- return -ENOMEM;
-
- mutex_init(&mcu->lock);
- mcu->client = client;
- i2c_set_clientdata(client, mcu);
-
- ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
- if (ret < 0)
- goto err;
- mcu->reg_ctrl = ret;
-
- ret = mcu_gpiochip_add(mcu);
- if (ret)
- goto err;
-
- /* XXX: this is potentially racy, but there is no lock for ppc_md */
- if (!ppc_md.power_off) {
- glob_mcu = mcu;
- ppc_md.power_off = mcu_power_off;
- dev_info(&client->dev, "will provide power-off service\n");
- }
-
- return 0;
-err:
- kfree(mcu);
- return ret;
-}
-
-static int __devexit mcu_remove(struct i2c_client *client)
-{
- struct mcu *mcu = i2c_get_clientdata(client);
- int ret;
-
- if (glob_mcu == mcu) {
- ppc_md.power_off = NULL;
- glob_mcu = NULL;
- }
-
- ret = mcu_gpiochip_remove(mcu);
- if (ret)
- return ret;
- i2c_set_clientdata(client, NULL);
- kfree(mcu);
- return 0;
-}
-
-static const struct i2c_device_id mcu_ids[] = {
- { "mcu-mpc8349emitx", },
- {},
-};
-MODULE_DEVICE_TABLE(i2c, mcu_ids);
-
-static struct i2c_driver mcu_driver = {
- .driver = {
- .name = "mcu-mpc8349emitx",
- .owner = THIS_MODULE,
- },
- .probe = mcu_probe,
- .remove = __devexit_p(mcu_remove),
- .id_table = mcu_ids,
-};
-
-static int __init mcu_init(void)
-{
- return i2c_add_driver(&mcu_driver);
-}
-module_init(mcu_init);
-
-static void __exit mcu_exit(void)
-{
- i2c_del_driver(&mcu_driver);
-}
-module_exit(mcu_exit);
-
-MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
- "MPC8349E-mITX-compatible MCU");
-MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
deleted file mode 100644
index 4b364bae6b3..00000000000
--- a/drivers/i2c/chips/menelaus.c
+++ /dev/null
@@ -1,1285 +0,0 @@
-/*
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * Some parts based tps65010.c:
- * Copyright (C) 2004 Texas Instruments and
- * Copyright (C) 2004-2005 David Brownell
- *
- * Some parts based on tlv320aic24.c:
- * Copyright (C) by Kai Svahn <kai.svahn@nokia.com>
- *
- * Changes for interrupt handling and clean-up by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
- * Cleanup and generalized support for voltage setting by
- * Juha Yrjola
- * Added support for controlling VCORE and regulator sleep states,
- * Amit Kucheria <amit.kucheria@nokia.com>
- * Copyright (C) 2005, 2006 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/gpio.h>
-#include <mach/menelaus.h>
-
-#define DRIVER_NAME "menelaus"
-
-#define MENELAUS_I2C_ADDRESS 0x72
-
-#define MENELAUS_REV 0x01
-#define MENELAUS_VCORE_CTRL1 0x02
-#define MENELAUS_VCORE_CTRL2 0x03
-#define MENELAUS_VCORE_CTRL3 0x04
-#define MENELAUS_VCORE_CTRL4 0x05
-#define MENELAUS_VCORE_CTRL5 0x06
-#define MENELAUS_DCDC_CTRL1 0x07
-#define MENELAUS_DCDC_CTRL2 0x08
-#define MENELAUS_DCDC_CTRL3 0x09
-#define MENELAUS_LDO_CTRL1 0x0A
-#define MENELAUS_LDO_CTRL2 0x0B
-#define MENELAUS_LDO_CTRL3 0x0C
-#define MENELAUS_LDO_CTRL4 0x0D
-#define MENELAUS_LDO_CTRL5 0x0E
-#define MENELAUS_LDO_CTRL6 0x0F
-#define MENELAUS_LDO_CTRL7 0x10
-#define MENELAUS_LDO_CTRL8 0x11
-#define MENELAUS_SLEEP_CTRL1 0x12
-#define MENELAUS_SLEEP_CTRL2 0x13
-#define MENELAUS_DEVICE_OFF 0x14
-#define MENELAUS_OSC_CTRL 0x15
-#define MENELAUS_DETECT_CTRL 0x16
-#define MENELAUS_INT_MASK1 0x17
-#define MENELAUS_INT_MASK2 0x18
-#define MENELAUS_INT_STATUS1 0x19
-#define MENELAUS_INT_STATUS2 0x1A
-#define MENELAUS_INT_ACK1 0x1B
-#define MENELAUS_INT_ACK2 0x1C
-#define MENELAUS_GPIO_CTRL 0x1D
-#define MENELAUS_GPIO_IN 0x1E
-#define MENELAUS_GPIO_OUT 0x1F
-#define MENELAUS_BBSMS 0x20
-#define MENELAUS_RTC_CTRL 0x21
-#define MENELAUS_RTC_UPDATE 0x22
-#define MENELAUS_RTC_SEC 0x23
-#define MENELAUS_RTC_MIN 0x24
-#define MENELAUS_RTC_HR 0x25
-#define MENELAUS_RTC_DAY 0x26
-#define MENELAUS_RTC_MON 0x27
-#define MENELAUS_RTC_YR 0x28
-#define MENELAUS_RTC_WKDAY 0x29
-#define MENELAUS_RTC_AL_SEC 0x2A
-#define MENELAUS_RTC_AL_MIN 0x2B
-#define MENELAUS_RTC_AL_HR 0x2C
-#define MENELAUS_RTC_AL_DAY 0x2D
-#define MENELAUS_RTC_AL_MON 0x2E
-#define MENELAUS_RTC_AL_YR 0x2F
-#define MENELAUS_RTC_COMP_MSB 0x30
-#define MENELAUS_RTC_COMP_LSB 0x31
-#define MENELAUS_S1_PULL_EN 0x32
-#define MENELAUS_S1_PULL_DIR 0x33
-#define MENELAUS_S2_PULL_EN 0x34
-#define MENELAUS_S2_PULL_DIR 0x35
-#define MENELAUS_MCT_CTRL1 0x36
-#define MENELAUS_MCT_CTRL2 0x37
-#define MENELAUS_MCT_CTRL3 0x38
-#define MENELAUS_MCT_PIN_ST 0x39
-#define MENELAUS_DEBOUNCE1 0x3A
-
-#define IH_MENELAUS_IRQS 12
-#define MENELAUS_MMC_S1CD_IRQ 0 /* MMC slot 1 card change */
-#define MENELAUS_MMC_S2CD_IRQ 1 /* MMC slot 2 card change */
-#define MENELAUS_MMC_S1D1_IRQ 2 /* MMC DAT1 low in slot 1 */
-#define MENELAUS_MMC_S2D1_IRQ 3 /* MMC DAT1 low in slot 2 */
-#define MENELAUS_LOWBAT_IRQ 4 /* Low battery */
-#define MENELAUS_HOTDIE_IRQ 5 /* Hot die detect */
-#define MENELAUS_UVLO_IRQ 6 /* UVLO detect */
-#define MENELAUS_TSHUT_IRQ 7 /* Thermal shutdown */
-#define MENELAUS_RTCTMR_IRQ 8 /* RTC timer */
-#define MENELAUS_RTCALM_IRQ 9 /* RTC alarm */
-#define MENELAUS_RTCERR_IRQ 10 /* RTC error */
-#define MENELAUS_PSHBTN_IRQ 11 /* Push button */
-#define MENELAUS_RESERVED12_IRQ 12 /* Reserved */
-#define MENELAUS_RESERVED13_IRQ 13 /* Reserved */
-#define MENELAUS_RESERVED14_IRQ 14 /* Reserved */
-#define MENELAUS_RESERVED15_IRQ 15 /* Reserved */
-
-static void menelaus_work(struct work_struct *_menelaus);
-
-struct menelaus_chip {
- struct mutex lock;
- struct i2c_client *client;
- struct work_struct work;
-#ifdef CONFIG_RTC_DRV_TWL92330
- struct rtc_device *rtc;
- u8 rtc_control;
- unsigned uie:1;
-#endif
- unsigned vcore_hw_mode:1;
- u8 mask1, mask2;
- void (*handlers[16])(struct menelaus_chip *);
- void (*mmc_callback)(void *data, u8 mask);
- void *mmc_callback_data;
-};
-
-static struct menelaus_chip *the_menelaus;
-
-static int menelaus_write_reg(int reg, u8 value)
-{
- int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);
-
- if (val < 0) {
- pr_err(DRIVER_NAME ": write error");
- return val;
- }
-
- return 0;
-}
-
-static int menelaus_read_reg(int reg)
-{
- int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);
-
- if (val < 0)
- pr_err(DRIVER_NAME ": read error");
-
- return val;
-}
-
-static int menelaus_enable_irq(int irq)
-{
- if (irq > 7) {
- irq -= 8;
- the_menelaus->mask2 &= ~(1 << irq);
- return menelaus_write_reg(MENELAUS_INT_MASK2,
- the_menelaus->mask2);
- } else {
- the_menelaus->mask1 &= ~(1 << irq);
- return menelaus_write_reg(MENELAUS_INT_MASK1,
- the_menelaus->mask1);
- }
-}
-
-static int menelaus_disable_irq(int irq)
-{
- if (irq > 7) {
- irq -= 8;
- the_menelaus->mask2 |= (1 << irq);
- return menelaus_write_reg(MENELAUS_INT_MASK2,
- the_menelaus->mask2);
- } else {
- the_menelaus->mask1 |= (1 << irq);
- return menelaus_write_reg(MENELAUS_INT_MASK1,
- the_menelaus->mask1);
- }
-}
-
-static int menelaus_ack_irq(int irq)
-{
- if (irq > 7)
- return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8));
- else
- return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq);
-}
-
-/* Adds a handler for an interrupt. Does not run in interrupt context */
-static int menelaus_add_irq_work(int irq,
- void (*handler)(struct menelaus_chip *))
-{
- int ret = 0;
-
- mutex_lock(&the_menelaus->lock);
- the_menelaus->handlers[irq] = handler;
- ret = menelaus_enable_irq(irq);
- mutex_unlock(&the_menelaus->lock);
-
- return ret;
-}
-
-/* Removes handler for an interrupt */
-static int menelaus_remove_irq_work(int irq)
-{
- int ret = 0;
-
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_disable_irq(irq);
- the_menelaus->handlers[irq] = NULL;
- mutex_unlock(&the_menelaus->lock);
-
- return ret;
-}
-
-/*
- * Gets scheduled when a card detect interrupt happens. Note that in some cases
- * this line is wired to card cover switch rather than the card detect switch
- * in each slot. In this case the cards are not seen by menelaus.
- * FIXME: Add handling for D1 too
- */
-static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw)
-{
- int reg;
- unsigned char card_mask = 0;
-
- reg = menelaus_read_reg(MENELAUS_MCT_PIN_ST);
- if (reg < 0)
- return;
-
- if (!(reg & 0x1))
- card_mask |= (1 << 0);
-
- if (!(reg & 0x2))
- card_mask |= (1 << 1);
-
- if (menelaus_hw->mmc_callback)
- menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data,
- card_mask);
-}
-
-/*
- * Toggles the MMC slots between open-drain and push-pull mode.
- */
-int menelaus_set_mmc_opendrain(int slot, int enable)
-{
- int ret, val;
-
- if (slot != 1 && slot != 2)
- return -EINVAL;
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_read_reg(MENELAUS_MCT_CTRL1);
- if (ret < 0) {
- mutex_unlock(&the_menelaus->lock);
- return ret;
- }
- val = ret;
- if (slot == 1) {
- if (enable)
- val |= 1 << 2;
- else
- val &= ~(1 << 2);
- } else {
- if (enable)
- val |= 1 << 3;
- else
- val &= ~(1 << 3);
- }
- ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val);
- mutex_unlock(&the_menelaus->lock);
-
- return ret;
-}
-EXPORT_SYMBOL(menelaus_set_mmc_opendrain);
-
-int menelaus_set_slot_sel(int enable)
-{
- int ret;
-
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
- if (ret < 0)
- goto out;
- ret |= 0x02;
- if (enable)
- ret |= 1 << 5;
- else
- ret &= ~(1 << 5);
- ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
-out:
- mutex_unlock(&the_menelaus->lock);
- return ret;
-}
-EXPORT_SYMBOL(menelaus_set_slot_sel);
-
-int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en)
-{
- int ret, val;
-
- if (slot != 1 && slot != 2)
- return -EINVAL;
- if (power >= 3)
- return -EINVAL;
-
- mutex_lock(&the_menelaus->lock);
-
- ret = menelaus_read_reg(MENELAUS_MCT_CTRL2);
- if (ret < 0)
- goto out;
- val = ret;
- if (slot == 1) {
- if (cd_en)
- val |= (1 << 4) | (1 << 6);
- else
- val &= ~((1 << 4) | (1 << 6));
- } else {
- if (cd_en)
- val |= (1 << 5) | (1 << 7);
- else
- val &= ~((1 << 5) | (1 << 7));
- }
- ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val);
- if (ret < 0)
- goto out;
-
- ret = menelaus_read_reg(MENELAUS_MCT_CTRL3);
- if (ret < 0)
- goto out;
- val = ret;
- if (slot == 1) {
- if (enable)
- val |= 1 << 0;
- else
- val &= ~(1 << 0);
- } else {
- int b;
-
- if (enable)
- ret |= 1 << 1;
- else
- ret &= ~(1 << 1);
- b = menelaus_read_reg(MENELAUS_MCT_CTRL2);
- b &= ~0x03;
- b |= power;
- ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b);
- if (ret < 0)
- goto out;
- }
- /* Disable autonomous shutdown */
- val &= ~(0x03 << 2);
- ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val);
-out:
- mutex_unlock(&the_menelaus->lock);
- return ret;
-}
-EXPORT_SYMBOL(menelaus_set_mmc_slot);
-
-int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
- void *data)
-{
- int ret = 0;
-
- the_menelaus->mmc_callback_data = data;
- the_menelaus->mmc_callback = callback;
- ret = menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ,
- menelaus_mmc_cd_work);
- if (ret < 0)
- return ret;
- ret = menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ,
- menelaus_mmc_cd_work);
- if (ret < 0)
- return ret;
- ret = menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ,
- menelaus_mmc_cd_work);
- if (ret < 0)
- return ret;
- ret = menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ,
- menelaus_mmc_cd_work);
-
- return ret;
-}
-EXPORT_SYMBOL(menelaus_register_mmc_callback);
-
-void menelaus_unregister_mmc_callback(void)
-{
- menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ);
- menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ);
- menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ);
- menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
-
- the_menelaus->mmc_callback = NULL;
- the_menelaus->mmc_callback_data = 0;
-}
-EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
-
-struct menelaus_vtg {
- const char *name;
- u8 vtg_reg;
- u8 vtg_shift;
- u8 vtg_bits;
- u8 mode_reg;
-};
-
-struct menelaus_vtg_value {
- u16 vtg;
- u16 val;
-};
-
-static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
- int vtg_val, int mode)
-{
- int val, ret;
- struct i2c_client *c = the_menelaus->client;
-
- mutex_lock(&the_menelaus->lock);
- if (vtg == 0)
- goto set_voltage;
-
- ret = menelaus_read_reg(vtg->vtg_reg);
- if (ret < 0)
- goto out;
- val = ret & ~(((1 << vtg->vtg_bits) - 1) << vtg->vtg_shift);
- val |= vtg_val << vtg->vtg_shift;
-
- dev_dbg(&c->dev, "Setting voltage '%s'"
- "to %d mV (reg 0x%02x, val 0x%02x)\n",
- vtg->name, mV, vtg->vtg_reg, val);
-
- ret = menelaus_write_reg(vtg->vtg_reg, val);
- if (ret < 0)
- goto out;
-set_voltage:
- ret = menelaus_write_reg(vtg->mode_reg, mode);
-out:
- mutex_unlock(&the_menelaus->lock);
- if (ret == 0) {
- /* Wait for voltage to stabilize */
- msleep(1);
- }
- return ret;
-}
-
-static int menelaus_get_vtg_value(int vtg, const struct menelaus_vtg_value *tbl,
- int n)
-{
- int i;
-
- for (i = 0; i < n; i++, tbl++)
- if (tbl->vtg == vtg)
- return tbl->val;
- return -EINVAL;
-}
-
-/*
- * Vcore can be programmed in two ways:
- * SW-controlled: Required voltage is programmed into VCORE_CTRL1
- * HW-controlled: Required range (roof-floor) is programmed into VCORE_CTRL3
- * and VCORE_CTRL4
- *
- * Call correct 'set' function accordingly
- */
-
-static const struct menelaus_vtg_value vcore_values[] = {
- { 1000, 0 },
- { 1025, 1 },
- { 1050, 2 },
- { 1075, 3 },
- { 1100, 4 },
- { 1125, 5 },
- { 1150, 6 },
- { 1175, 7 },
- { 1200, 8 },
- { 1225, 9 },
- { 1250, 10 },
- { 1275, 11 },
- { 1300, 12 },
- { 1325, 13 },
- { 1350, 14 },
- { 1375, 15 },
- { 1400, 16 },
- { 1425, 17 },
- { 1450, 18 },
-};
-
-int menelaus_set_vcore_sw(unsigned int mV)
-{
- int val, ret;
- struct i2c_client *c = the_menelaus->client;
-
- val = menelaus_get_vtg_value(mV, vcore_values,
- ARRAY_SIZE(vcore_values));
- if (val < 0)
- return -EINVAL;
-
- dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
-
- /* Set SW mode and the voltage in one go. */
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
- if (ret == 0)
- the_menelaus->vcore_hw_mode = 0;
- mutex_unlock(&the_menelaus->lock);
- msleep(1);
-
- return ret;
-}
-
-int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
-{
- int fval, rval, val, ret;
- struct i2c_client *c = the_menelaus->client;
-
- rval = menelaus_get_vtg_value(roof_mV, vcore_values,
- ARRAY_SIZE(vcore_values));
- if (rval < 0)
- return -EINVAL;
- fval = menelaus_get_vtg_value(floor_mV, vcore_values,
- ARRAY_SIZE(vcore_values));
- if (fval < 0)
- return -EINVAL;
-
- dev_dbg(&c->dev, "Setting VCORE FLOOR to %d mV and ROOF to %d mV\n",
- floor_mV, roof_mV);
-
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_write_reg(MENELAUS_VCORE_CTRL3, fval);
- if (ret < 0)
- goto out;
- ret = menelaus_write_reg(MENELAUS_VCORE_CTRL4, rval);
- if (ret < 0)
- goto out;
- if (!the_menelaus->vcore_hw_mode) {
- val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
- /* HW mode, turn OFF byte comparator */
- val |= ((1 << 7) | (1 << 5));
- ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
- the_menelaus->vcore_hw_mode = 1;
- }
- msleep(1);
-out:
- mutex_unlock(&the_menelaus->lock);
- return ret;
-}
-
-static const struct menelaus_vtg vmem_vtg = {
- .name = "VMEM",
- .vtg_reg = MENELAUS_LDO_CTRL1,
- .vtg_shift = 0,
- .vtg_bits = 2,
- .mode_reg = MENELAUS_LDO_CTRL3,
-};
-
-static const struct menelaus_vtg_value vmem_values[] = {
- { 1500, 0 },
- { 1800, 1 },
- { 1900, 2 },
- { 2500, 3 },
-};
-
-int menelaus_set_vmem(unsigned int mV)
-{
- int val;
-
- if (mV == 0)
- return menelaus_set_voltage(&vmem_vtg, 0, 0, 0);
-
- val = menelaus_get_vtg_value(mV, vmem_values, ARRAY_SIZE(vmem_values));
- if (val < 0)
- return -EINVAL;
- return menelaus_set_voltage(&vmem_vtg, mV, val, 0x02);
-}
-EXPORT_SYMBOL(menelaus_set_vmem);
-
-static const struct menelaus_vtg vio_vtg = {
- .name = "VIO",
- .vtg_reg = MENELAUS_LDO_CTRL1,
- .vtg_shift = 2,
- .vtg_bits = 2,
- .mode_reg = MENELAUS_LDO_CTRL4,
-};
-
-static const struct menelaus_vtg_value vio_values[] = {
- { 1500, 0 },
- { 1800, 1 },
- { 2500, 2 },
- { 2800, 3 },
-};
-
-int menelaus_set_vio(unsigned int mV)
-{
- int val;
-
- if (mV == 0)
- return menelaus_set_voltage(&vio_vtg, 0, 0, 0);
-
- val = menelaus_get_vtg_value(mV, vio_values, ARRAY_SIZE(vio_values));
- if (val < 0)
- return -EINVAL;
- return menelaus_set_voltage(&vio_vtg, mV, val, 0x02);
-}
-EXPORT_SYMBOL(menelaus_set_vio);
-
-static const struct menelaus_vtg_value vdcdc_values[] = {
- { 1500, 0 },
- { 1800, 1 },
- { 2000, 2 },
- { 2200, 3 },
- { 2400, 4 },
- { 2800, 5 },
- { 3000, 6 },
- { 3300, 7 },
-};
-
-static const struct menelaus_vtg vdcdc2_vtg = {
- .name = "VDCDC2",
- .vtg_reg = MENELAUS_DCDC_CTRL1,
- .vtg_shift = 0,
- .vtg_bits = 3,
- .mode_reg = MENELAUS_DCDC_CTRL2,
-};
-
-static const struct menelaus_vtg vdcdc3_vtg = {
- .name = "VDCDC3",
- .vtg_reg = MENELAUS_DCDC_CTRL1,
- .vtg_shift = 3,
- .vtg_bits = 3,
- .mode_reg = MENELAUS_DCDC_CTRL3,
-};
-
-int menelaus_set_vdcdc(int dcdc, unsigned int mV)
-{
- const struct menelaus_vtg *vtg;
- int val;
-
- if (dcdc != 2 && dcdc != 3)
- return -EINVAL;
- if (dcdc == 2)
- vtg = &vdcdc2_vtg;
- else
- vtg = &vdcdc3_vtg;
-
- if (mV == 0)
- return menelaus_set_voltage(vtg, 0, 0, 0);
-
- val = menelaus_get_vtg_value(mV, vdcdc_values,
- ARRAY_SIZE(vdcdc_values));
- if (val < 0)
- return -EINVAL;
- return menelaus_set_voltage(vtg, mV, val, 0x03);
-}
-
-static const struct menelaus_vtg_value vmmc_values[] = {
- { 1850, 0 },
- { 2800, 1 },
- { 3000, 2 },
- { 3100, 3 },
-};
-
-static const struct menelaus_vtg vmmc_vtg = {
- .name = "VMMC",
- .vtg_reg = MENELAUS_LDO_CTRL1,
- .vtg_shift = 6,
- .vtg_bits = 2,
- .mode_reg = MENELAUS_LDO_CTRL7,
-};
-
-int menelaus_set_vmmc(unsigned int mV)
-{
- int val;
-
- if (mV == 0)
- return menelaus_set_voltage(&vmmc_vtg, 0, 0, 0);
-
- val = menelaus_get_vtg_value(mV, vmmc_values, ARRAY_SIZE(vmmc_values));
- if (val < 0)
- return -EINVAL;
- return menelaus_set_voltage(&vmmc_vtg, mV, val, 0x02);
-}
-EXPORT_SYMBOL(menelaus_set_vmmc);
-
-
-static const struct menelaus_vtg_value vaux_values[] = {
- { 1500, 0 },
- { 1800, 1 },
- { 2500, 2 },
- { 2800, 3 },
-};
-
-static const struct menelaus_vtg vaux_vtg = {
- .name = "VAUX",
- .vtg_reg = MENELAUS_LDO_CTRL1,
- .vtg_shift = 4,
- .vtg_bits = 2,
- .mode_reg = MENELAUS_LDO_CTRL6,
-};
-
-int menelaus_set_vaux(unsigned int mV)
-{
- int val;
-
- if (mV == 0)
- return menelaus_set_voltage(&vaux_vtg, 0, 0, 0);
-
- val = menelaus_get_vtg_value(mV, vaux_values, ARRAY_SIZE(vaux_values));
- if (val < 0)
- return -EINVAL;
- return menelaus_set_voltage(&vaux_vtg, mV, val, 0x02);
-}
-EXPORT_SYMBOL(menelaus_set_vaux);
-
-int menelaus_get_slot_pin_states(void)
-{
- return menelaus_read_reg(MENELAUS_MCT_PIN_ST);
-}
-EXPORT_SYMBOL(menelaus_get_slot_pin_states);
-
-int menelaus_set_regulator_sleep(int enable, u32 val)
-{
- int t, ret;
- struct i2c_client *c = the_menelaus->client;
-
- mutex_lock(&the_menelaus->lock);
- ret = menelaus_write_reg(MENELAUS_SLEEP_CTRL2, val);
- if (ret < 0)
- goto out;
-
- dev_dbg(&c->dev, "regulator sleep configuration: %02x\n", val);
-
- ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
- if (ret < 0)
- goto out;
- t = ((1 << 6) | 0x04);
- if (enable)
- ret |= t;
- else
- ret &= ~t;
- ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
-out:
- mutex_unlock(&the_menelaus->lock);
- return ret;
-}
-
-/*-----------------------------------------------------------------------*/
-
-/* Handles Menelaus interrupts. Does not run in interrupt context */
-static void menelaus_work(struct work_struct *_menelaus)
-{
- struct menelaus_chip *menelaus =
- container_of(_menelaus, struct menelaus_chip, work);
- void (*handler)(struct menelaus_chip *menelaus);
-
- while (1) {
- unsigned isr;
-
- isr = (menelaus_read_reg(MENELAUS_INT_STATUS2)
- & ~menelaus->mask2) << 8;
- isr |= menelaus_read_reg(MENELAUS_INT_STATUS1)
- & ~menelaus->mask1;
- if (!isr)
- break;
-
- while (isr) {
- int irq = fls(isr) - 1;
- isr &= ~(1 << irq);
-
- mutex_lock(&menelaus->lock);
- menelaus_disable_irq(irq);
- menelaus_ack_irq(irq);
- handler = menelaus->handlers[irq];
- if (handler)
- handler(menelaus);
- menelaus_enable_irq(irq);
- mutex_unlock(&menelaus->lock);
- }
- }
- enable_irq(menelaus->client->irq);
-}
-
-/*
- * We cannot use I2C in interrupt context, so we just schedule work.
- */
-static irqreturn_t menelaus_irq(int irq, void *_menelaus)
-{
- struct menelaus_chip *menelaus = _menelaus;
-
- disable_irq_nosync(irq);
- (void)schedule_work(&menelaus->work);
-
- return IRQ_HANDLED;
-}
-
-/*-----------------------------------------------------------------------*/
-
-/*
- * The RTC needs to be set once, then it runs on backup battery power.
- * It supports alarms, including system wake alarms (from some modes);
- * and 1/second IRQs if requested.
- */
-#ifdef CONFIG_RTC_DRV_TWL92330
-
-#define RTC_CTRL_RTC_EN (1 << 0)
-#define RTC_CTRL_AL_EN (1 << 1)
-#define RTC_CTRL_MODE12 (1 << 2)
-#define RTC_CTRL_EVERY_MASK (3 << 3)
-#define RTC_CTRL_EVERY_SEC (0 << 3)
-#define RTC_CTRL_EVERY_MIN (1 << 3)
-#define RTC_CTRL_EVERY_HR (2 << 3)
-#define RTC_CTRL_EVERY_DAY (3 << 3)
-
-#define RTC_UPDATE_EVERY 0x08
-
-#define RTC_HR_PM (1 << 7)
-
-static void menelaus_to_time(char *regs, struct rtc_time *t)
-{
- t->tm_sec = bcd2bin(regs[0]);
- t->tm_min = bcd2bin(regs[1]);
- if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
- t->tm_hour = bcd2bin(regs[2] & 0x1f) - 1;
- if (regs[2] & RTC_HR_PM)
- t->tm_hour += 12;
- } else
- t->tm_hour = bcd2bin(regs[2] & 0x3f);
- t->tm_mday = bcd2bin(regs[3]);
- t->tm_mon = bcd2bin(regs[4]) - 1;
- t->tm_year = bcd2bin(regs[5]) + 100;
-}
-
-static int time_to_menelaus(struct rtc_time *t, int regnum)
-{
- int hour, status;
-
- status = menelaus_write_reg(regnum++, bin2bcd(t->tm_sec));
- if (status < 0)
- goto fail;
-
- status = menelaus_write_reg(regnum++, bin2bcd(t->tm_min));
- if (status < 0)
- goto fail;
-
- if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
- hour = t->tm_hour + 1;
- if (hour > 12)
- hour = RTC_HR_PM | bin2bcd(hour - 12);
- else
- hour = bin2bcd(hour);
- } else
- hour = bin2bcd(t->tm_hour);
- status = menelaus_write_reg(regnum++, hour);
- if (status < 0)
- goto fail;
-
- status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mday));
- if (status < 0)
- goto fail;
-
- status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mon + 1));
- if (status < 0)
- goto fail;
-
- status = menelaus_write_reg(regnum++, bin2bcd(t->tm_year - 100));
- if (status < 0)
- goto fail;
-
- return 0;
-fail:
- dev_err(&the_menelaus->client->dev, "rtc write reg %02x, err %d\n",
- --regnum, status);
- return status;
-}
-
-static int menelaus_read_time(struct device *dev, struct rtc_time *t)
-{
- struct i2c_msg msg[2];
- char regs[7];
- int status;
-
- /* block read date and time registers */
- regs[0] = MENELAUS_RTC_SEC;
-
- msg[0].addr = MENELAUS_I2C_ADDRESS;
- msg[0].flags = 0;
- msg[0].len = 1;
- msg[0].buf = regs;
-
- msg[1].addr = MENELAUS_I2C_ADDRESS;
- msg[1].flags = I2C_M_RD;
- msg[1].len = sizeof(regs);
- msg[1].buf = regs;
-
- status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
- if (status != 2) {
- dev_err(dev, "%s error %d\n", "read", status);
- return -EIO;
- }
-
- menelaus_to_time(regs, t);
- t->tm_wday = bcd2bin(regs[6]);
-
- return 0;
-}
-
-static int menelaus_set_time(struct device *dev, struct rtc_time *t)
-{
- int status;
-
- /* write date and time registers */
- status = time_to_menelaus(t, MENELAUS_RTC_SEC);
- if (status < 0)
- return status;
- status = menelaus_write_reg(MENELAUS_RTC_WKDAY, bin2bcd(t->tm_wday));
- if (status < 0) {
- dev_err(&the_menelaus->client->dev, "rtc write reg %02x "
- "err %d\n", MENELAUS_RTC_WKDAY, status);
- return status;
- }
-
- /* now commit the write */
- status = menelaus_write_reg(MENELAUS_RTC_UPDATE, RTC_UPDATE_EVERY);
- if (status < 0)
- dev_err(&the_menelaus->client->dev, "rtc commit time, err %d\n",
- status);
-
- return 0;
-}
-
-static int menelaus_read_alarm(struct device *dev, struct rtc_wkalrm *w)
-{
- struct i2c_msg msg[2];
- char regs[6];
- int status;
-
- /* block read alarm registers */
- regs[0] = MENELAUS_RTC_AL_SEC;
-
- msg[0].addr = MENELAUS_I2C_ADDRESS;
- msg[0].flags = 0;
- msg[0].len = 1;
- msg[0].buf = regs;
-
- msg[1].addr = MENELAUS_I2C_ADDRESS;
- msg[1].flags = I2C_M_RD;
- msg[1].len = sizeof(regs);
- msg[1].buf = regs;
-
- status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
- if (status != 2) {
- dev_err(dev, "%s error %d\n", "alarm read", status);
- return -EIO;
- }
-
- menelaus_to_time(regs, &w->time);
-
- w->enabled = !!(the_menelaus->rtc_control & RTC_CTRL_AL_EN);
-
- /* NOTE we *could* check if actually pending... */
- w->pending = 0;
-
- return 0;
-}
-
-static int menelaus_set_alarm(struct device *dev, struct rtc_wkalrm *w)
-{
- int status;
-
- if (the_menelaus->client->irq <= 0 && w->enabled)
- return -ENODEV;
-
- /* clear previous alarm enable */
- if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) {
- the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
- status = menelaus_write_reg(MENELAUS_RTC_CTRL,
- the_menelaus->rtc_control);
- if (status < 0)
- return status;
- }
-
- /* write alarm registers */
- status = time_to_menelaus(&w->time, MENELAUS_RTC_AL_SEC);
- if (status < 0)
- return status;
-
- /* enable alarm if requested */
- if (w->enabled) {
- the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
- status = menelaus_write_reg(MENELAUS_RTC_CTRL,
- the_menelaus->rtc_control);
- }
-
- return status;
-}
-
-#ifdef CONFIG_RTC_INTF_DEV
-
-static void menelaus_rtc_update_work(struct menelaus_chip *m)
-{
- /* report 1/sec update */
- local_irq_disable();
- rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_UF);
- local_irq_enable();
-}
-
-static int menelaus_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
-{
- int status;
-
- if (the_menelaus->client->irq <= 0)
- return -ENOIOCTLCMD;
-
- switch (cmd) {
- /* alarm IRQ */
- case RTC_AIE_ON:
- if (the_menelaus->rtc_control & RTC_CTRL_AL_EN)
- return 0;
- the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
- break;
- case RTC_AIE_OFF:
- if (!(the_menelaus->rtc_control & RTC_CTRL_AL_EN))
- return 0;
- the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
- break;
- /* 1/second "update" IRQ */
- case RTC_UIE_ON:
- if (the_menelaus->uie)
- return 0;
- status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
- status = menelaus_add_irq_work(MENELAUS_RTCTMR_IRQ,
- menelaus_rtc_update_work);
- if (status == 0)
- the_menelaus->uie = 1;
- return status;
- case RTC_UIE_OFF:
- if (!the_menelaus->uie)
- return 0;
- status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
- if (status == 0)
- the_menelaus->uie = 0;
- return status;
- default:
- return -ENOIOCTLCMD;
- }
- return menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
-}
-
-#else
-#define menelaus_ioctl NULL
-#endif
-
-/* REVISIT no compensation register support ... */
-
-static const struct rtc_class_ops menelaus_rtc_ops = {
- .ioctl = menelaus_ioctl,
- .read_time = menelaus_read_time,
- .set_time = menelaus_set_time,
- .read_alarm = menelaus_read_alarm,
- .set_alarm = menelaus_set_alarm,
-};
-
-static void menelaus_rtc_alarm_work(struct menelaus_chip *m)
-{
- /* report alarm */
- local_irq_disable();
- rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_AF);
- local_irq_enable();
-
- /* then disable it; alarms are oneshot */
- the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
- menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
-}
-
-static inline void menelaus_rtc_init(struct menelaus_chip *m)
-{
- int alarm = (m->client->irq > 0);
-
- /* assume 32KDETEN pin is pulled high */
- if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) {
- dev_dbg(&m->client->dev, "no 32k oscillator\n");
- return;
- }
-
- /* support RTC alarm; it can issue wakeups */
- if (alarm) {
- if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ,
- menelaus_rtc_alarm_work) < 0) {
- dev_err(&m->client->dev, "can't handle RTC alarm\n");
- return;
- }
- device_init_wakeup(&m->client->dev, 1);
- }
-
- /* be sure RTC is enabled; allow 1/sec irqs; leave 12hr mode alone */
- m->rtc_control = menelaus_read_reg(MENELAUS_RTC_CTRL);
- if (!(m->rtc_control & RTC_CTRL_RTC_EN)
- || (m->rtc_control & RTC_CTRL_AL_EN)
- || (m->rtc_control & RTC_CTRL_EVERY_MASK)) {
- if (!(m->rtc_control & RTC_CTRL_RTC_EN)) {
- dev_warn(&m->client->dev, "rtc clock needs setting\n");
- m->rtc_control |= RTC_CTRL_RTC_EN;
- }
- m->rtc_control &= ~RTC_CTRL_EVERY_MASK;
- m->rtc_control &= ~RTC_CTRL_AL_EN;
- menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
- }
-
- m->rtc = rtc_device_register(DRIVER_NAME,
- &m->client->dev,
- &menelaus_rtc_ops, THIS_MODULE);
- if (IS_ERR(m->rtc)) {
- if (alarm) {
- menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
- device_init_wakeup(&m->client->dev, 0);
- }
- dev_err(&m->client->dev, "can't register RTC: %d\n",
- (int) PTR_ERR(m->rtc));
- the_menelaus->rtc = NULL;
- }
-}
-
-#else
-
-static inline void menelaus_rtc_init(struct menelaus_chip *m)
-{
- /* nothing */
-}
-
-#endif
-
-/*-----------------------------------------------------------------------*/
-
-static struct i2c_driver menelaus_i2c_driver;
-
-static int menelaus_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct menelaus_chip *menelaus;
- int rev = 0, val;
- int err = 0;
- struct menelaus_platform_data *menelaus_pdata =
- client->dev.platform_data;
-
- if (the_menelaus) {
- dev_dbg(&client->dev, "only one %s for now\n",
- DRIVER_NAME);
- return -ENODEV;
- }
-
- menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL);
- if (!menelaus)
- return -ENOMEM;
-
- i2c_set_clientdata(client, menelaus);
-
- the_menelaus = menelaus;
- menelaus->client = client;
-
- /* If a true probe check the device */
- rev = menelaus_read_reg(MENELAUS_REV);
- if (rev < 0) {
- pr_err(DRIVER_NAME ": device not found");
- err = -ENODEV;
- goto fail1;
- }
-
- /* Ack and disable all Menelaus interrupts */
- menelaus_write_reg(MENELAUS_INT_ACK1, 0xff);
- menelaus_write_reg(MENELAUS_INT_ACK2, 0xff);
- menelaus_write_reg(MENELAUS_INT_MASK1, 0xff);
- menelaus_write_reg(MENELAUS_INT_MASK2, 0xff);
- menelaus->mask1 = 0xff;
- menelaus->mask2 = 0xff;
-
- /* Set output buffer strengths */
- menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
-
- if (client->irq > 0) {
- err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
- DRIVER_NAME, menelaus);
- if (err) {
- dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
- client->irq, err);
- goto fail1;
- }
- }
-
- mutex_init(&menelaus->lock);
- INIT_WORK(&menelaus->work, menelaus_work);
-
- pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f);
-
- val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
- if (val < 0)
- goto fail2;
- if (val & (1 << 7))
- menelaus->vcore_hw_mode = 1;
- else
- menelaus->vcore_hw_mode = 0;
-
- if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) {
- err = menelaus_pdata->late_init(&client->dev);
- if (err < 0)
- goto fail2;
- }
-
- menelaus_rtc_init(menelaus);
-
- return 0;
-fail2:
- free_irq(client->irq, menelaus);
- flush_scheduled_work();
-fail1:
- kfree(menelaus);
- return err;
-}
-
-static int __exit menelaus_remove(struct i2c_client *client)
-{
- struct menelaus_chip *menelaus = i2c_get_clientdata(client);
-
- free_irq(client->irq, menelaus);
- kfree(menelaus);
- i2c_set_clientdata(client, NULL);
- the_menelaus = NULL;
- return 0;
-}
-
-static const struct i2c_device_id menelaus_id[] = {
- { "menelaus", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, menelaus_id);
-
-static struct i2c_driver menelaus_i2c_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .probe = menelaus_probe,
- .remove = __exit_p(menelaus_remove),
- .id_table = menelaus_id,
-};
-
-static int __init menelaus_init(void)
-{
- int res;
-
- res = i2c_add_driver(&menelaus_i2c_driver);
- if (res < 0) {
- pr_err(DRIVER_NAME ": driver registration failed\n");
- return res;
- }
-
- return 0;
-}
-
-static void __exit menelaus_exit(void)
-{
- i2c_del_driver(&menelaus_i2c_driver);
-
- /* FIXME: Shutdown menelaus parts that can be shut down */
-}
-
-MODULE_AUTHOR("Texas Instruments, Inc. (and others)");
-MODULE_DESCRIPTION("I2C interface for Menelaus.");
-MODULE_LICENSE("GPL");
-
-module_init(menelaus_init);
-module_exit(menelaus_exit);
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
deleted file mode 100644
index acf8b9d5f57..00000000000
--- a/drivers/i2c/chips/tps65010.c
+++ /dev/null
@@ -1,1072 +0,0 @@
-/*
- * tps65010 - driver for tps6501x power management chips
- *
- * Copyright (C) 2004 Texas Instruments
- * Copyright (C) 2004-2005 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-
-#include <linux/i2c/tps65010.h>
-
-#include <asm/gpio.h>
-
-
-/*-------------------------------------------------------------------------*/
-
-#define DRIVER_VERSION "2 May 2005"
-#define DRIVER_NAME (tps65010_driver.driver.name)
-
-MODULE_DESCRIPTION("TPS6501x Power Management Driver");
-MODULE_LICENSE("GPL");
-
-static struct i2c_driver tps65010_driver;
-
-/*-------------------------------------------------------------------------*/
-
-/* This driver handles a family of multipurpose chips, which incorporate
- * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs,
- * and other features often needed in portable devices like cell phones
- * or digital cameras.
- *
- * The tps65011 and tps65013 have different voltage settings compared
- * to tps65010 and tps65012. The tps65013 has a NO_CHG status/irq.
- * All except tps65010 have "wait" mode, possibly defaulted so that
- * battery-insert != device-on.
- *
- * We could distinguish between some models by checking VDCDC1.UVLO or
- * other registers, unless they've been changed already after powerup
- * as part of board setup by a bootloader.
- */
-enum tps_model {
- TPS65010,
- TPS65011,
- TPS65012,
- TPS65013,
-};
-
-struct tps65010 {
- struct i2c_client *client;
- struct mutex lock;
- struct delayed_work work;
- struct dentry *file;
- unsigned charging:1;
- unsigned por:1;
- unsigned model:8;
- u16 vbus;
- unsigned long flags;
-#define FLAG_VBUS_CHANGED 0
-#define FLAG_IRQ_ENABLE 1
-
- /* copies of last register state */
- u8 chgstatus, regstatus, chgconf;
- u8 nmask1, nmask2;
-
- u8 outmask;
- struct gpio_chip chip;
- struct platform_device *leds;
-};
-
-#define POWER_POLL_DELAY msecs_to_jiffies(5000)
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
-
-static void dbg_chgstat(char *buf, size_t len, u8 chgstatus)
-{
- snprintf(buf, len, "%02x%s%s%s%s%s%s%s%s\n",
- chgstatus,
- (chgstatus & TPS_CHG_USB) ? " USB" : "",
- (chgstatus & TPS_CHG_AC) ? " AC" : "",
- (chgstatus & TPS_CHG_THERM) ? " therm" : "",
- (chgstatus & TPS_CHG_TERM) ? " done" :
- ((chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
- ? " (charging)" : ""),
- (chgstatus & TPS_CHG_TAPER_TMO) ? " taper_tmo" : "",
- (chgstatus & TPS_CHG_CHG_TMO) ? " charge_tmo" : "",
- (chgstatus & TPS_CHG_PRECHG_TMO) ? " prechg_tmo" : "",
- (chgstatus & TPS_CHG_TEMP_ERR) ? " temp_err" : "");
-}
-
-static void dbg_regstat(char *buf, size_t len, u8 regstatus)
-{
- snprintf(buf, len, "%02x %s%s%s%s%s%s%s%s\n",
- regstatus,
- (regstatus & TPS_REG_ONOFF) ? "off" : "(on)",
- (regstatus & TPS_REG_COVER) ? " uncover" : "",
- (regstatus & TPS_REG_UVLO) ? " UVLO" : "",
- (regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "",
- (regstatus & TPS_REG_PG_LD02) ? " ld02_bad" : "",
- (regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "",
- (regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "",
- (regstatus & TPS_REG_PG_CORE) ? " core_bad" : "");
-}
-
-static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig)
-{
- const char *hibit;
-
- if (por)
- hibit = (chgconfig & TPS_CHARGE_POR)
- ? "POR=69ms" : "POR=1sec";
- else
- hibit = (chgconfig & TPS65013_AUA) ? "AUA" : "";
-
- snprintf(buf, len, "%02x %s%s%s AC=%d%% USB=%dmA %sCharge\n",
- chgconfig, hibit,
- (chgconfig & TPS_CHARGE_RESET) ? " reset" : "",
- (chgconfig & TPS_CHARGE_FAST) ? " fast" : "",
- ({int p; switch ((chgconfig >> 3) & 3) {
- case 3: p = 100; break;
- case 2: p = 75; break;
- case 1: p = 50; break;
- default: p = 25; break;
- }; p; }),
- (chgconfig & TPS_VBUS_CHARGING)
- ? ((chgconfig & TPS_VBUS_500MA) ? 500 : 100)
- : 0,
- (chgconfig & TPS_CHARGE_ENABLE) ? "" : "No");
-}
-
-#endif
-
-#ifdef DEBUG
-
-static void show_chgstatus(const char *label, u8 chgstatus)
-{
- char buf [100];
-
- dbg_chgstat(buf, sizeof buf, chgstatus);
- pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
-}
-
-static void show_regstatus(const char *label, u8 regstatus)
-{
- char buf [100];
-
- dbg_regstat(buf, sizeof buf, regstatus);
- pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
-}
-
-static void show_chgconfig(int por, const char *label, u8 chgconfig)
-{
- char buf [100];
-
- dbg_chgconf(por, buf, sizeof buf, chgconfig);
- pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
-}
-
-#else
-
-static inline void show_chgstatus(const char *label, u8 chgstatus) { }
-static inline void show_regstatus(const char *label, u8 chgstatus) { }
-static inline void show_chgconfig(int por, const char *label, u8 chgconfig) { }
-
-#endif
-
-#ifdef CONFIG_DEBUG_FS
-
-static int dbg_show(struct seq_file *s, void *_)
-{
- struct tps65010 *tps = s->private;
- u8 value, v2;
- unsigned i;
- char buf[100];
- const char *chip;
-
- switch (tps->model) {
- case TPS65010: chip = "tps65010"; break;
- case TPS65011: chip = "tps65011"; break;
- case TPS65012: chip = "tps65012"; break;
- case TPS65013: chip = "tps65013"; break;
- default: chip = NULL; break;
- }
- seq_printf(s, "driver %s\nversion %s\nchip %s\n\n",
- DRIVER_NAME, DRIVER_VERSION, chip);
-
- mutex_lock(&tps->lock);
-
- /* FIXME how can we tell whether a battery is present?
- * likely involves a charge gauging chip (like BQ26501).
- */
-
- seq_printf(s, "%scharging\n\n", tps->charging ? "" : "(not) ");
-
-
- /* registers for monitoring battery charging and status; note
- * that reading chgstat and regstat may ack IRQs...
- */
- value = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG);
- dbg_chgconf(tps->por, buf, sizeof buf, value);
- seq_printf(s, "chgconfig %s", buf);
-
- value = i2c_smbus_read_byte_data(tps->client, TPS_CHGSTATUS);
- dbg_chgstat(buf, sizeof buf, value);
- seq_printf(s, "chgstat %s", buf);
- value = i2c_smbus_read_byte_data(tps->client, TPS_MASK1);
- dbg_chgstat(buf, sizeof buf, value);
- seq_printf(s, "mask1 %s", buf);
- /* ignore ackint1 */
-
- value = i2c_smbus_read_byte_data(tps->client, TPS_REGSTATUS);
- dbg_regstat(buf, sizeof buf, value);
- seq_printf(s, "regstat %s", buf);
- value = i2c_smbus_read_byte_data(tps->client, TPS_MASK2);
- dbg_regstat(buf, sizeof buf, value);
- seq_printf(s, "mask2 %s\n", buf);
- /* ignore ackint2 */
-
- (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
-
-
- /* VMAIN voltage, enable lowpower, etc */
- value = i2c_smbus_read_byte_data(tps->client, TPS_VDCDC1);
- seq_printf(s, "vdcdc1 %02x\n", value);
-
- /* VCORE voltage, vibrator on/off */
- value = i2c_smbus_read_byte_data(tps->client, TPS_VDCDC2);
- seq_printf(s, "vdcdc2 %02x\n", value);
-
- /* both LD0s, and their lowpower behavior */
- value = i2c_smbus_read_byte_data(tps->client, TPS_VREGS1);
- seq_printf(s, "vregs1 %02x\n\n", value);
-
-
- /* LEDs and GPIOs */
- value = i2c_smbus_read_byte_data(tps->client, TPS_LED1_ON);
- v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED1_PER);
- seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n",
- (value & 0x80)
- ? ((v2 & 0x80) ? "on" : "off")
- : ((v2 & 0x80) ? "blink" : "(nPG)"),
- value, v2,
- (value & 0x7f) * 10, (v2 & 0x7f) * 100);
-
- value = i2c_smbus_read_byte_data(tps->client, TPS_LED2_ON);
- v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED2_PER);
- seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n",
- (value & 0x80)
- ? ((v2 & 0x80) ? "on" : "off")
- : ((v2 & 0x80) ? "blink" : "off"),
- value, v2,
- (value & 0x7f) * 10, (v2 & 0x7f) * 100);
-
- value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
- v2 = i2c_smbus_read_byte_data(tps->client, TPS_MASK3);
- seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2);
-
- for (i = 0; i < 4; i++) {
- if (value & (1 << (4 + i)))
- seq_printf(s, " gpio%d-out %s\n", i + 1,
- (value & (1 << i)) ? "low" : "hi ");
- else
- seq_printf(s, " gpio%d-in %s %s %s\n", i + 1,
- (value & (1 << i)) ? "hi " : "low",
- (v2 & (1 << i)) ? "no-irq" : "irq",
- (v2 & (1 << (4 + i))) ? "rising" : "falling");
- }
-
- mutex_unlock(&tps->lock);
- return 0;
-}
-
-static int dbg_tps_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dbg_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = dbg_tps_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-#define DEBUG_FOPS &debug_fops
-
-#else
-#define DEBUG_FOPS NULL
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* handle IRQS in a task context, so we can use I2C calls */
-static void tps65010_interrupt(struct tps65010 *tps)
-{
- u8 tmp = 0, mask, poll;
-
- /* IRQs won't trigger for certain events, but we can get
- * others by polling (normally, with external power applied).
- */
- poll = 0;
-
- /* regstatus irqs */
- if (tps->nmask2) {
- tmp = i2c_smbus_read_byte_data(tps->client, TPS_REGSTATUS);
- mask = tmp ^ tps->regstatus;
- tps->regstatus = tmp;
- mask &= tps->nmask2;
- } else
- mask = 0;
- if (mask) {
- tps->regstatus = tmp;
- /* may need to shut something down ... */
-
- /* "off" usually means deep sleep */
- if (tmp & TPS_REG_ONOFF) {
- pr_info("%s: power off button\n", DRIVER_NAME);
-#if 0
- /* REVISIT: this might need its own workqueue
- * plus tweaks including deadlock avoidance ...
- * also needs to get error handling and probably
- * an #ifdef CONFIG_HIBERNATION
- */
- hibernate();
-#endif
- poll = 1;
- }
- }
-
- /* chgstatus irqs */
- if (tps->nmask1) {
- tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGSTATUS);
- mask = tmp ^ tps->chgstatus;
- tps->chgstatus = tmp;
- mask &= tps->nmask1;
- } else
- mask = 0;
- if (mask) {
- unsigned charging = 0;
-
- show_chgstatus("chg/irq", tmp);
- if (tmp & (TPS_CHG_USB|TPS_CHG_AC))
- show_chgconfig(tps->por, "conf", tps->chgconf);
-
- /* Unless it was turned off or disabled, we charge any
- * battery whenever there's power available for it
- * and the charger hasn't been disabled.
- */
- if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC))
- && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
- && (tps->chgconf & TPS_CHARGE_ENABLE)
- ) {
- if (tps->chgstatus & TPS_CHG_USB) {
- /* VBUS options are readonly until reconnect */
- if (mask & TPS_CHG_USB)
- set_bit(FLAG_VBUS_CHANGED, &tps->flags);
- charging = 1;
- } else if (tps->chgstatus & TPS_CHG_AC)
- charging = 1;
- }
- if (charging != tps->charging) {
- tps->charging = charging;
- pr_info("%s: battery %scharging\n",
- DRIVER_NAME, charging ? "" :
- ((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
- ? "NOT " : "dis"));
- }
- }
-
- /* always poll to detect (a) power removal, without tps65013
- * NO_CHG IRQ; or (b) restart of charging after stop.
- */
- if ((tps->model != TPS65013 || !tps->charging)
- && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
- poll = 1;
- if (poll)
- (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
-
- /* also potentially gpio-in rise or fall */
-}
-
-/* handle IRQs and polling using keventd for now */
-static void tps65010_work(struct work_struct *work)
-{
- struct tps65010 *tps;
-
- tps = container_of(work, struct tps65010, work.work);
- mutex_lock(&tps->lock);
-
- tps65010_interrupt(tps);
-
- if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) {
- int status;
- u8 chgconfig, tmp;
-
- chgconfig = i2c_smbus_read_byte_data(tps->client,
- TPS_CHGCONFIG);
- chgconfig &= ~(TPS_VBUS_500MA | TPS_VBUS_CHARGING);
- if (tps->vbus == 500)
- chgconfig |= TPS_VBUS_500MA | TPS_VBUS_CHARGING;
- else if (tps->vbus >= 100)
- chgconfig |= TPS_VBUS_CHARGING;
-
- status = i2c_smbus_write_byte_data(tps->client,
- TPS_CHGCONFIG, chgconfig);
-
- /* vbus update fails unless VBUS is connected! */
- tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG);
- tps->chgconf = tmp;
- show_chgconfig(tps->por, "update vbus", tmp);
- }
-
- if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
- enable_irq(tps->client->irq);
-
- mutex_unlock(&tps->lock);
-}
-
-static irqreturn_t tps65010_irq(int irq, void *_tps)
-{
- struct tps65010 *tps = _tps;
-
- disable_irq_nosync(irq);
- set_bit(FLAG_IRQ_ENABLE, &tps->flags);
- (void) schedule_work(&tps->work.work);
- return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* offsets 0..3 == GPIO1..GPIO4
- * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
- * offset 6 == vibrator motor driver
- */
-static void
-tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- if (offset < 4)
- tps65010_set_gpio_out_value(offset + 1, value);
- else if (offset < 6)
- tps65010_set_led(offset - 3, value ? ON : OFF);
- else
- tps65010_set_vib(value);
-}
-
-static int
-tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
-{
- /* GPIOs may be input-only */
- if (offset < 4) {
- struct tps65010 *tps;
-
- tps = container_of(chip, struct tps65010, chip);
- if (!(tps->outmask & (1 << offset)))
- return -EINVAL;
- tps65010_set_gpio_out_value(offset + 1, value);
- } else if (offset < 6)
- tps65010_set_led(offset - 3, value ? ON : OFF);
- else
- tps65010_set_vib(value);
-
- return 0;
-}
-
-static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- int value;
- struct tps65010 *tps;
-
- tps = container_of(chip, struct tps65010, chip);
-
- if (offset < 4) {
- value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
- if (value < 0)
- return 0;
- if (value & (1 << (offset + 4))) /* output */
- return !(value & (1 << offset));
- else /* input */
- return (value & (1 << offset));
- }
-
- /* REVISIT we *could* report LED1/nPG and LED2 state ... */
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct tps65010 *the_tps;
-
-static int __exit tps65010_remove(struct i2c_client *client)
-{
- struct tps65010 *tps = i2c_get_clientdata(client);
- struct tps65010_board *board = client->dev.platform_data;
-
- if (board && board->teardown) {
- int status = board->teardown(client, board->context);
- if (status < 0)
- dev_dbg(&client->dev, "board %s %s err %d\n",
- "teardown", client->name, status);
- }
- if (client->irq > 0)
- free_irq(client->irq, tps);
- cancel_delayed_work(&tps->work);
- flush_scheduled_work();
- debugfs_remove(tps->file);
- kfree(tps);
- i2c_set_clientdata(client, NULL);
- the_tps = NULL;
- return 0;
-}
-
-static int tps65010_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tps65010 *tps;
- int status;
- struct tps65010_board *board = client->dev.platform_data;
-
- if (the_tps) {
- dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
- return -ENODEV;
- }
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EINVAL;
-
- tps = kzalloc(sizeof *tps, GFP_KERNEL);
- if (!tps)
- return -ENOMEM;
-
- mutex_init(&tps->lock);
- INIT_DELAYED_WORK(&tps->work, tps65010_work);
- tps->client = client;
- tps->model = id->driver_data;
-
- /* the IRQ is active low, but many gpio lines can't support that
- * so this driver uses falling-edge triggers instead.
- */
- if (client->irq > 0) {
- status = request_irq(client->irq, tps65010_irq,
- IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING,
- DRIVER_NAME, tps);
- if (status < 0) {
- dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
- client->irq, status);
- goto fail1;
- }
- /* annoying race here, ideally we'd have an option
- * to claim the irq now and enable it later.
- * FIXME genirq IRQF_NOAUTOEN now solves that ...
- */
- disable_irq(client->irq);
- set_bit(FLAG_IRQ_ENABLE, &tps->flags);
- } else
- dev_warn(&client->dev, "IRQ not configured!\n");
-
-
- switch (tps->model) {
- case TPS65010:
- case TPS65012:
- tps->por = 1;
- break;
- /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
- }
- tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
- show_chgconfig(tps->por, "conf/init", tps->chgconf);
-
- show_chgstatus("chg/init",
- i2c_smbus_read_byte_data(client, TPS_CHGSTATUS));
- show_regstatus("reg/init",
- i2c_smbus_read_byte_data(client, TPS_REGSTATUS));
-
- pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(client, TPS_VDCDC1),
- i2c_smbus_read_byte_data(client, TPS_VDCDC2),
- i2c_smbus_read_byte_data(client, TPS_VREGS1));
- pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
- i2c_smbus_read_byte_data(client, TPS_MASK3));
-
- i2c_set_clientdata(client, tps);
- the_tps = tps;
-
-#if defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
- /* USB hosts can't draw VBUS. OTG devices could, later
- * when OTG infrastructure enables it. USB peripherals
- * could be relying on VBUS while booting, though.
- */
- tps->vbus = 100;
-#endif
-
- /* unmask the "interesting" irqs, then poll once to
- * kickstart monitoring, initialize shadowed status
- * registers, and maybe disable VBUS draw.
- */
- tps->nmask1 = ~0;
- (void) i2c_smbus_write_byte_data(client, TPS_MASK1, ~tps->nmask1);
-
- tps->nmask2 = TPS_REG_ONOFF;
- if (tps->model == TPS65013)
- tps->nmask2 |= TPS_REG_NO_CHG;
- (void) i2c_smbus_write_byte_data(client, TPS_MASK2, ~tps->nmask2);
-
- (void) i2c_smbus_write_byte_data(client, TPS_MASK3, 0x0f
- | i2c_smbus_read_byte_data(client, TPS_MASK3));
-
- tps65010_work(&tps->work.work);
-
- tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
- tps, DEBUG_FOPS);
-
- /* optionally register GPIOs */
- if (board && board->base > 0) {
- tps->outmask = board->outmask;
-
- tps->chip.label = client->name;
- tps->chip.dev = &client->dev;
- tps->chip.owner = THIS_MODULE;
-
- tps->chip.set = tps65010_gpio_set;
- tps->chip.direction_output = tps65010_output;
-
- /* NOTE: only partial support for inputs; nyet IRQs */
- tps->chip.get = tps65010_gpio_get;
-
- tps->chip.base = board->base;
- tps->chip.ngpio = 7;
- tps->chip.can_sleep = 1;
-
- status = gpiochip_add(&tps->chip);
- if (status < 0)
- dev_err(&client->dev, "can't add gpiochip, err %d\n",
- status);
- else if (board->setup) {
- status = board->setup(client, board->context);
- if (status < 0) {
- dev_dbg(&client->dev,
- "board %s %s err %d\n",
- "setup", client->name, status);
- status = 0;
- }
- }
- }
-
- return 0;
-fail1:
- kfree(tps);
- return status;
-}
-
-static const struct i2c_device_id tps65010_id[] = {
- { "tps65010", TPS65010 },
- { "tps65011", TPS65011 },
- { "tps65012", TPS65012 },
- { "tps65013", TPS65013 },
- { "tps65014", TPS65011 }, /* tps65011 charging at 6.5V max */
- { }
-};
-MODULE_DEVICE_TABLE(i2c, tps65010_id);
-
-static struct i2c_driver tps65010_driver = {
- .driver = {
- .name = "tps65010",
- },
- .probe = tps65010_probe,
- .remove = __exit_p(tps65010_remove),
- .id_table = tps65010_id,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Draw from VBUS:
- * 0 mA -- DON'T DRAW (might supply power instead)
- * 100 mA -- usb unit load (slowest charge rate)
- * 500 mA -- usb high power (fast battery charge)
- */
-int tps65010_set_vbus_draw(unsigned mA)
-{
- unsigned long flags;
-
- if (!the_tps)
- return -ENODEV;
-
- /* assumes non-SMP */
- local_irq_save(flags);
- if (mA >= 500)
- mA = 500;
- else if (mA >= 100)
- mA = 100;
- else
- mA = 0;
- the_tps->vbus = mA;
- if ((the_tps->chgstatus & TPS_CHG_USB)
- && test_and_set_bit(
- FLAG_VBUS_CHANGED, &the_tps->flags)) {
- /* gadget drivers call this in_irq() */
- (void) schedule_work(&the_tps->work.work);
- }
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(tps65010_set_vbus_draw);
-
-/*-------------------------------------------------------------------------*/
-/* tps65010_set_gpio_out_value parameter:
- * gpio: GPIO1, GPIO2, GPIO3 or GPIO4
- * value: LOW or HIGH
- */
-int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
-{
- int status;
- unsigned defgpio;
-
- if (!the_tps)
- return -ENODEV;
- if ((gpio < GPIO1) || (gpio > GPIO4))
- return -EINVAL;
-
- mutex_lock(&the_tps->lock);
-
- defgpio = i2c_smbus_read_byte_data(the_tps->client, TPS_DEFGPIO);
-
- /* Configure GPIO for output */
- defgpio |= 1 << (gpio + 3);
-
- /* Writing 1 forces a logic 0 on that GPIO and vice versa */
- switch (value) {
- case LOW:
- defgpio |= 1 << (gpio - 1); /* set GPIO low by writing 1 */
- break;
- /* case HIGH: */
- default:
- defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */
- break;
- }
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_DEFGPIO, defgpio);
-
- pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
- gpio, value ? "high" : "low",
- i2c_smbus_read_byte_data(the_tps->client, TPS_DEFGPIO));
-
- mutex_unlock(&the_tps->lock);
- return status;
-}
-EXPORT_SYMBOL(tps65010_set_gpio_out_value);
-
-/*-------------------------------------------------------------------------*/
-/* tps65010_set_led parameter:
- * led: LED1 or LED2
- * mode: ON, OFF or BLINK
- */
-int tps65010_set_led(unsigned led, unsigned mode)
-{
- int status;
- unsigned led_on, led_per, offs;
-
- if (!the_tps)
- return -ENODEV;
-
- if (led == LED1)
- offs = 0;
- else {
- offs = 2;
- led = LED2;
- }
-
- mutex_lock(&the_tps->lock);
-
- pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led,
- i2c_smbus_read_byte_data(the_tps->client,
- TPS_LED1_ON + offs));
-
- pr_debug("%s: led%i_per 0x%02x\n", DRIVER_NAME, led,
- i2c_smbus_read_byte_data(the_tps->client,
- TPS_LED1_PER + offs));
-
- switch (mode) {
- case OFF:
- led_on = 1 << 7;
- led_per = 0 << 7;
- break;
- case ON:
- led_on = 1 << 7;
- led_per = 1 << 7;
- break;
- case BLINK:
- led_on = 0x30 | (0 << 7);
- led_per = 0x08 | (1 << 7);
- break;
- default:
- printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n",
- DRIVER_NAME);
- mutex_unlock(&the_tps->lock);
- return -EINVAL;
- }
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_LED1_ON + offs, led_on);
-
- if (status != 0) {
- printk(KERN_ERR "%s: Failed to write led%i_on register\n",
- DRIVER_NAME, led);
- mutex_unlock(&the_tps->lock);
- return status;
- }
-
- pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led,
- i2c_smbus_read_byte_data(the_tps->client, TPS_LED1_ON + offs));
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_LED1_PER + offs, led_per);
-
- if (status != 0) {
- printk(KERN_ERR "%s: Failed to write led%i_per register\n",
- DRIVER_NAME, led);
- mutex_unlock(&the_tps->lock);
- return status;
- }
-
- pr_debug("%s: led%i_per 0x%02x\n", DRIVER_NAME, led,
- i2c_smbus_read_byte_data(the_tps->client,
- TPS_LED1_PER + offs));
-
- mutex_unlock(&the_tps->lock);
-
- return status;
-}
-EXPORT_SYMBOL(tps65010_set_led);
-
-/*-------------------------------------------------------------------------*/
-/* tps65010_set_vib parameter:
- * value: ON or OFF
- */
-int tps65010_set_vib(unsigned value)
-{
- int status;
- unsigned vdcdc2;
-
- if (!the_tps)
- return -ENODEV;
-
- mutex_lock(&the_tps->lock);
-
- vdcdc2 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC2);
- vdcdc2 &= ~(1 << 1);
- if (value)
- vdcdc2 |= (1 << 1);
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_VDCDC2, vdcdc2);
-
- pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
-
- mutex_unlock(&the_tps->lock);
- return status;
-}
-EXPORT_SYMBOL(tps65010_set_vib);
-
-/*-------------------------------------------------------------------------*/
-/* tps65010_set_low_pwr parameter:
- * mode: ON or OFF
- */
-int tps65010_set_low_pwr(unsigned mode)
-{
- int status;
- unsigned vdcdc1;
-
- if (!the_tps)
- return -ENODEV;
-
- mutex_lock(&the_tps->lock);
-
- pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
- mode ? "enable" : "disable",
- i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));
-
- vdcdc1 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1);
-
- switch (mode) {
- case OFF:
- vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
- break;
- /* case ON: */
- default:
- vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */
- break;
- }
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_VDCDC1, vdcdc1);
-
- if (status != 0)
- printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
- DRIVER_NAME);
- else
- pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));
-
- mutex_unlock(&the_tps->lock);
-
- return status;
-}
-EXPORT_SYMBOL(tps65010_set_low_pwr);
-
-/*-------------------------------------------------------------------------*/
-/* tps65010_config_vregs1 parameter:
- * value to be written to VREGS1 register
- * Note: The complete register is written, set all bits you need
- */
-int tps65010_config_vregs1(unsigned value)
-{
- int status;
-
- if (!the_tps)
- return -ENODEV;
-
- mutex_lock(&the_tps->lock);
-
- pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(the_tps->client, TPS_VREGS1));
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_VREGS1, value);
-
- if (status != 0)
- printk(KERN_ERR "%s: Failed to write vregs1 register\n",
- DRIVER_NAME);
- else
- pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(the_tps->client, TPS_VREGS1));
-
- mutex_unlock(&the_tps->lock);
-
- return status;
-}
-EXPORT_SYMBOL(tps65010_config_vregs1);
-
-/*-------------------------------------------------------------------------*/
-/* tps65013_set_low_pwr parameter:
- * mode: ON or OFF
- */
-
-/* FIXME: Assumes AC or USB power is present. Setting AUA bit is not
- required if power supply is through a battery */
-
-int tps65013_set_low_pwr(unsigned mode)
-{
- int status;
- unsigned vdcdc1, chgconfig;
-
- if (!the_tps || the_tps->por)
- return -ENODEV;
-
- mutex_lock(&the_tps->lock);
-
- pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
- DRIVER_NAME,
- mode ? "enable" : "disable",
- i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG),
- i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));
-
- chgconfig = i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG);
- vdcdc1 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1);
-
- switch (mode) {
- case OFF:
- chgconfig &= ~TPS65013_AUA; /* disable AUA bit */
- vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
- break;
- /* case ON: */
- default:
- chgconfig |= TPS65013_AUA; /* enable AUA bit */
- vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */
- break;
- }
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_CHGCONFIG, chgconfig);
- if (status != 0) {
- printk(KERN_ERR "%s: Failed to write chconfig register\n",
- DRIVER_NAME);
- mutex_unlock(&the_tps->lock);
- return status;
- }
-
- chgconfig = i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG);
- the_tps->chgconf = chgconfig;
- show_chgconfig(0, "chgconf", chgconfig);
-
- status = i2c_smbus_write_byte_data(the_tps->client,
- TPS_VDCDC1, vdcdc1);
-
- if (status != 0)
- printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
- DRIVER_NAME);
- else
- pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
- i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));
-
- mutex_unlock(&the_tps->lock);
-
- return status;
-}
-EXPORT_SYMBOL(tps65013_set_low_pwr);
-
-/*-------------------------------------------------------------------------*/
-
-static int __init tps_init(void)
-{
- u32 tries = 3;
- int status = -ENODEV;
-
- printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION);
-
- /* some boards have startup glitches */
- while (tries--) {
- status = i2c_add_driver(&tps65010_driver);
- if (the_tps)
- break;
- i2c_del_driver(&tps65010_driver);
- if (!tries) {
- printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME);
- return -ENODEV;
- }
- pr_debug("%s: re-probe ...\n", DRIVER_NAME);
- msleep(10);
- }
-
- return status;
-}
-/* NOTE: this MUST be initialized before the other parts of the system
- * that rely on it ... but after the i2c bus on which this relies.
- * That is, much earlier than on PC-type systems, which don't often use
- * I2C as a core system bus.
- */
-subsys_initcall(tps_init);
-
-static void __exit tps_exit(void)
-{
- i2c_del_driver(&tps65010_driver);
-}
-module_exit(tps_exit);
-
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5a485c22660..b1c9abe24c7 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -459,7 +459,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
pr_debug("I2C adapter driver [%s] forgot to specify "
"physical device\n", adap->name);
}
- sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
+ dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.release = &i2c_adapter_dev_release;
adap->dev.class = &i2c_adapter_class;
res = device_register(&adap->dev);
@@ -631,7 +631,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because
* it can fail; in which case we give up. */
- list_for_each_entry_safe(client, _n, &adap->clients, list) {
+ list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
struct i2c_driver *driver;
driver = client->driver;
@@ -845,8 +845,8 @@ int i2c_attach_client(struct i2c_client *client)
} else
client->dev.release = i2c_client_dev_release;
- snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
- "%d-%04x", i2c_adapter_id(adapter), client->addr);
+ dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter),
+ client->addr);
res = device_register(&client->dev);
if (res)
goto out_err;
@@ -856,7 +856,7 @@ int i2c_attach_client(struct i2c_client *client)
mutex_unlock(&adapter->clist_lock);
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
- client->name, client->dev.bus_id);
+ client->name, dev_name(&client->dev));
if (adapter->client_register) {
if (adapter->client_register(client)) {