* [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 15:53 ` Kumar Gala
2007-12-18 2:39 ` [PATCH 2/7] Implement module aliasing for i2c to translate from device tree names Jon Smirl
` (5 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Temporarily copy the mpc-i2c driver to continue support for the ppc architecture until it is removed in mid-2008. This file should be deleted as part of ppc's final removal.
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
arch/ppc/configs/TQM8540_defconfig | 2
arch/ppc/configs/TQM8541_defconfig | 2
arch/ppc/configs/TQM8555_defconfig | 2
arch/ppc/configs/TQM8560_defconfig | 2
arch/ppc/configs/mpc834x_sys_defconfig | 2
arch/ppc/configs/mpc8540_ads_defconfig | 2
arch/ppc/configs/mpc8548_cds_defconfig | 2
arch/ppc/configs/mpc8555_cds_defconfig | 2
arch/ppc/configs/mpc8560_ads_defconfig | 2
drivers/i2c/busses/Kconfig | 16 +
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-mpc-ppc.c | 418 ++++++++++++++++++++++++++++++++
12 files changed, 443 insertions(+), 10 deletions(-)
create mode 100644 drivers/i2c/busses/i2c-mpc-ppc.c
diff --git a/arch/ppc/configs/TQM8540_defconfig b/arch/ppc/configs/TQM8540_defconfig
index f33f0e7..7098ed0 100644
--- a/arch/ppc/configs/TQM8540_defconfig
+++ b/arch/ppc/configs/TQM8540_defconfig
@@ -684,7 +684,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
diff --git a/arch/ppc/configs/TQM8541_defconfig b/arch/ppc/configs/TQM8541_defconfig
index e00cd62..2137d01 100644
--- a/arch/ppc/configs/TQM8541_defconfig
+++ b/arch/ppc/configs/TQM8541_defconfig
@@ -687,7 +687,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_MPC8260 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
diff --git a/arch/ppc/configs/TQM8555_defconfig b/arch/ppc/configs/TQM8555_defconfig
index 43a0d9d..f2317b6 100644
--- a/arch/ppc/configs/TQM8555_defconfig
+++ b/arch/ppc/configs/TQM8555_defconfig
@@ -687,7 +687,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
diff --git a/arch/ppc/configs/TQM8560_defconfig b/arch/ppc/configs/TQM8560_defconfig
index a814d17..6c19121 100644
--- a/arch/ppc/configs/TQM8560_defconfig
+++ b/arch/ppc/configs/TQM8560_defconfig
@@ -694,7 +694,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_MPC8260 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
index d90c8a7..cd568d2 100644
--- a/arch/ppc/configs/mpc834x_sys_defconfig
+++ b/arch/ppc/configs/mpc834x_sys_defconfig
@@ -562,7 +562,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
diff --git a/arch/ppc/configs/mpc8540_ads_defconfig b/arch/ppc/configs/mpc8540_ads_defconfig
index bf676eb..5819835 100644
--- a/arch/ppc/configs/mpc8540_ads_defconfig
+++ b/arch/ppc/configs/mpc8540_ads_defconfig
@@ -452,7 +452,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PIIX4 is not set
diff --git a/arch/ppc/configs/mpc8548_cds_defconfig b/arch/ppc/configs/mpc8548_cds_defconfig
index f36fc5d..e5b5071 100644
--- a/arch/ppc/configs/mpc8548_cds_defconfig
+++ b/arch/ppc/configs/mpc8548_cds_defconfig
@@ -413,7 +413,7 @@ CONFIG_I2C_CHARDEV=y
#
# I2C Hardware Bus support
#
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PCA_ISA is not set
diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig
index 4f1e320..08dbab0 100644
--- a/arch/ppc/configs/mpc8555_cds_defconfig
+++ b/arch/ppc/configs/mpc8555_cds_defconfig
@@ -518,7 +518,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
diff --git a/arch/ppc/configs/mpc8560_ads_defconfig b/arch/ppc/configs/mpc8560_ads_defconfig
index f12d48f..0e0080b 100644
--- a/arch/ppc/configs/mpc8560_ads_defconfig
+++ b/arch/ppc/configs/mpc8560_ads_defconfig
@@ -489,7 +489,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index c466c6c..c5ad557 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -301,7 +301,7 @@ config I2C_POWERMAC
config I2C_MPC
tristate "MPC107/824x/85xx/52xx/86xx"
- depends on PPC32
+ depends on PPC32 && PPC_MERGE
help
If you say yes to this option, support will be included for the
built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
@@ -311,6 +311,20 @@ config I2C_MPC
This driver can also be built as a module. If so, the module
will be called i2c-mpc.
+config I2C_MPC_PPC
+ tristate "MPC107/824x/85xx/52xx/86xx"
+ depends on PPC32 && !PPC_MERGE
+ help
+ If you say yes to this option, support will be included for the
+ built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+ MPC85xx/MPC8641 family processors. The driver may also work on 52xx
+ family processors, though interrupts are known not to work.
+
+ This version of the driver is scheduled for deletion with the PPC architecture.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-mpc.
+
config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 81d43c2..b7fe095 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
+obj-$(CONFIG_I2C_MPC_PPC) += i2c-mpc-ppc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
diff --git a/drivers/i2c/busses/i2c-mpc-ppc.c b/drivers/i2c/busses/i2c-mpc-ppc.c
new file mode 100644
index 0000000..d8de4ac
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mpc-ppc.c
@@ -0,0 +1,418 @@
+/*
+ * (C) Copyright 2003-2004
+ * Humboldt Solutions Ltd, adrian@humboldt.co.uk.
+
+ * This is a combined i2c adapter and algorithm driver for the
+ * MPC107/Tsi107 PowerPC northbridge and processors that include
+ * the same I2C unit (8240, 8245, 85xx).
+ *
+ * Release 0.8
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#define MPC_I2C_ADDR 0x00
+#define MPC_I2C_FDR 0x04
+#define MPC_I2C_CR 0x08
+#define MPC_I2C_SR 0x0c
+#define MPC_I2C_DR 0x10
+#define MPC_I2C_DFSRR 0x14
+#define MPC_I2C_REGION 0x20
+
+#define CCR_MEN 0x80
+#define CCR_MIEN 0x40
+#define CCR_MSTA 0x20
+#define CCR_MTX 0x10
+#define CCR_TXAK 0x08
+#define CCR_RSTA 0x04
+
+#define CSR_MCF 0x80
+#define CSR_MAAS 0x40
+#define CSR_MBB 0x20
+#define CSR_MAL 0x10
+#define CSR_SRW 0x04
+#define CSR_MIF 0x02
+#define CSR_RXAK 0x01
+
+struct mpc_i2c {
+ void __iomem *base;
+ u32 interrupt;
+ wait_queue_head_t queue;
+ struct i2c_adapter adap;
+ int irq;
+ u32 flags;
+};
+
+static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
+{
+ writeb(x, i2c->base + MPC_I2C_CR);
+}
+
+static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
+{
+ struct mpc_i2c *i2c = dev_id;
+ if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
+ /* Read again to allow register to stabilise */
+ i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
+ writeb(0, i2c->base + MPC_I2C_SR);
+ wake_up_interruptible(&i2c->queue);
+ }
+ return IRQ_HANDLED;
+}
+
+/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+ * the bus, because it wants to send ACK.
+ * Following sequence of enabling/disabling and sending start/stop generates
+ * the pulse, so it's all OK.
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+ writeccr(i2c, 0);
+ udelay(30);
+ writeccr(i2c, CCR_MEN);
+ udelay(30);
+ writeccr(i2c, CCR_MSTA | CCR_MTX);
+ udelay(30);
+ writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+ udelay(30);
+ writeccr(i2c, CCR_MEN);
+ udelay(30);
+}
+
+static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
+{
+ unsigned long orig_jiffies = jiffies;
+ u32 x;
+ int result = 0;
+
+ if (i2c->irq == 0)
+ {
+ while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
+ schedule();
+ if (time_after(jiffies, orig_jiffies + timeout)) {
+ pr_debug("I2C: timeout\n");
+ writeccr(i2c, 0);
+ result = -EIO;
+ break;
+ }
+ }
+ x = readb(i2c->base + MPC_I2C_SR);
+ writeb(0, i2c->base + MPC_I2C_SR);
+ } else {
+ /* Interrupt mode */
+ result = wait_event_interruptible_timeout(i2c->queue,
+ (i2c->interrupt & CSR_MIF), timeout * HZ);
+
+ if (unlikely(result < 0)) {
+ pr_debug("I2C: wait interrupted\n");
+ writeccr(i2c, 0);
+ } else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
+ pr_debug("I2C: wait timeout\n");
+ writeccr(i2c, 0);
+ result = -ETIMEDOUT;
+ }
+
+ x = i2c->interrupt;
+ i2c->interrupt = 0;
+ }
+
+ if (result < 0)
+ return result;
+
+ if (!(x & CSR_MCF)) {
+ pr_debug("I2C: unfinished\n");
+ return -EIO;
+ }
+
+ if (x & CSR_MAL) {
+ pr_debug("I2C: MAL\n");
+ return -EIO;
+ }
+
+ if (writing && (x & CSR_RXAK)) {
+ pr_debug("I2C: No RXAK\n");
+ /* generate stop */
+ writeccr(i2c, CCR_MEN);
+ return -EIO;
+ }
+ return 0;
+}
+
+static void mpc_i2c_setclock(struct mpc_i2c *i2c)
+{
+ /* Set clock and filters */
+ if (i2c->flags & FSL_I2C_DEV_SEPARATE_DFSRR) {
+ writeb(0x31, i2c->base + MPC_I2C_FDR);
+ writeb(0x10, i2c->base + MPC_I2C_DFSRR);
+ } else if (i2c->flags & FSL_I2C_DEV_CLOCK_5200)
+ writeb(0x3f, i2c->base + MPC_I2C_FDR);
+ else
+ writel(0x1031, i2c->base + MPC_I2C_FDR);
+}
+
+static void mpc_i2c_start(struct mpc_i2c *i2c)
+{
+ /* Clear arbitration */
+ writeb(0, i2c->base + MPC_I2C_SR);
+ /* Start with MEN */
+ writeccr(i2c, CCR_MEN);
+}
+
+static void mpc_i2c_stop(struct mpc_i2c *i2c)
+{
+ writeccr(i2c, CCR_MEN);
+}
+
+static int mpc_write(struct mpc_i2c *i2c, int target,
+ const u8 * data, int length, int restart)
+{
+ int i;
+ unsigned timeout = i2c->adap.timeout;
+ u32 flags = restart ? CCR_RSTA : 0;
+
+ /* Start with MEN */
+ if (!restart)
+ writeccr(i2c, CCR_MEN);
+ /* Start as master */
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+ /* Write target byte */
+ writeb((target << 1), i2c->base + MPC_I2C_DR);
+
+ if (i2c_wait(i2c, timeout, 1) < 0)
+ return -1;
+
+ for (i = 0; i < length; i++) {
+ /* Write data byte */
+ writeb(data[i], i2c->base + MPC_I2C_DR);
+
+ if (i2c_wait(i2c, timeout, 1) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mpc_read(struct mpc_i2c *i2c, int target,
+ u8 * data, int length, int restart)
+{
+ unsigned timeout = i2c->adap.timeout;
+ int i;
+ u32 flags = restart ? CCR_RSTA : 0;
+
+ /* Start with MEN */
+ if (!restart)
+ writeccr(i2c, CCR_MEN);
+ /* Switch to read - restart */
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+ /* Write target address byte - this time with the read flag set */
+ writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+
+ if (i2c_wait(i2c, timeout, 1) < 0)
+ return -1;
+
+ if (length) {
+ if (length == 1)
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+ else
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
+ /* Dummy read */
+ readb(i2c->base + MPC_I2C_DR);
+ }
+
+ for (i = 0; i < length; i++) {
+ if (i2c_wait(i2c, timeout, 0) < 0)
+ return -1;
+
+ /* Generate txack on next to last byte */
+ if (i == length - 2)
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+ /* Generate stop on last byte */
+ if (i == length - 1)
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+ data[i] = readb(i2c->base + MPC_I2C_DR);
+ }
+
+ return length;
+}
+
+static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct i2c_msg *pmsg;
+ int i;
+ int ret = 0;
+ unsigned long orig_jiffies = jiffies;
+ struct mpc_i2c *i2c = i2c_get_adapdata(adap);
+
+ mpc_i2c_start(i2c);
+
+ /* Allow bus up to 1s to become not busy */
+ while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
+ if (signal_pending(current)) {
+ pr_debug("I2C: Interrupted\n");
+ writeccr(i2c, 0);
+ return -EINTR;
+ }
+ if (time_after(jiffies, orig_jiffies + HZ)) {
+ pr_debug("I2C: timeout\n");
+ if (readb(i2c->base + MPC_I2C_SR) ==
+ (CSR_MCF | CSR_MBB | CSR_RXAK))
+ mpc_i2c_fixup(i2c);
+ return -EIO;
+ }
+ schedule();
+ }
+
+ for (i = 0; ret >= 0 && i < num; i++) {
+ pmsg = &msgs[i];
+ pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+ pmsg->flags & I2C_M_RD ? "read" : "write",
+ pmsg->len, pmsg->addr, i + 1, num);
+ if (pmsg->flags & I2C_M_RD)
+ ret =
+ mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+ else
+ ret =
+ mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+ }
+ mpc_i2c_stop(i2c);
+ return (ret < 0) ? ret : num;
+}
+
+static u32 mpc_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mpc_algo = {
+ .master_xfer = mpc_xfer,
+ .functionality = mpc_functionality,
+};
+
+static struct i2c_adapter mpc_ops = {
+ .owner = THIS_MODULE,
+ .name = "MPC adapter",
+ .id = I2C_HW_MPC107,
+ .algo = &mpc_algo,
+ .class = I2C_CLASS_HWMON,
+ .timeout = 1,
+ .retries = 1
+};
+
+static int fsl_i2c_probe(struct platform_device *pdev)
+{
+ int result = 0;
+ struct mpc_i2c *i2c;
+ struct fsl_i2c_platform_data *pdata;
+ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
+
+ if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
+ return -ENOMEM;
+ }
+
+ i2c->irq = platform_get_irq(pdev, 0);
+ if (i2c->irq < 0) {
+ result = -ENXIO;
+ goto fail_get_irq;
+ }
+ i2c->flags = pdata->device_flags;
+ init_waitqueue_head(&i2c->queue);
+
+ i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
+
+ if (!i2c->base) {
+ printk(KERN_ERR "i2c-mpc - failed to map controller\n");
+ result = -ENOMEM;
+ goto fail_map;
+ }
+
+ if (i2c->irq != 0)
+ if ((result = request_irq(i2c->irq, mpc_i2c_isr,
+ IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
+ printk(KERN_ERR
+ "i2c-mpc - failed to attach interrupt\n");
+ goto fail_irq;
+ }
+
+ mpc_i2c_setclock(i2c);
+ platform_set_drvdata(pdev, i2c);
+
+ i2c->adap = mpc_ops;
+ i2c->adap.nr = pdev->id;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &pdev->dev;
+ if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
+ printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
+ goto fail_add;
+ }
+
+ return result;
+
+ fail_add:
+ if (i2c->irq != 0)
+ free_irq(i2c->irq, i2c);
+ fail_irq:
+ iounmap(i2c->base);
+ fail_map:
+ fail_get_irq:
+ kfree(i2c);
+ return result;
+};
+
+static int fsl_i2c_remove(struct platform_device *pdev)
+{
+ struct mpc_i2c *i2c = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&i2c->adap);
+ platform_set_drvdata(pdev, NULL);
+
+ if (i2c->irq != 0)
+ free_irq(i2c->irq, i2c);
+
+ iounmap(i2c->base);
+ kfree(i2c);
+ return 0;
+};
+
+/* Structure for a device driver */
+static struct platform_driver fsl_i2c_driver = {
+ .probe = fsl_i2c_probe,
+ .remove = fsl_i2c_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "fsl-i2c",
+ },
+};
+
+static int __init fsl_i2c_init(void)
+{
+ return platform_driver_register(&fsl_i2c_driver);
+}
+
+static void __exit fsl_i2c_exit(void)
+{
+ platform_driver_unregister(&fsl_i2c_driver);
+}
+
+module_init(fsl_i2c_init);
+module_exit(fsl_i2c_exit);
+
+MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
+MODULE_DESCRIPTION
+ ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
+MODULE_LICENSE("GPL");
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc
2007-12-18 2:39 ` [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc Jon Smirl
@ 2007-12-18 15:53 ` Kumar Gala
0 siblings, 0 replies; 10+ messages in thread
From: Kumar Gala @ 2007-12-18 15:53 UTC (permalink / raw)
To: Jon Smirl; +Cc: linuxppc-dev, i2c, linux-kernel
On Dec 17, 2007, at 8:39 PM, Jon Smirl wrote:
> Temporarily copy the mpc-i2c driver to continue support for the ppc
> architecture until it is removed in mid-2008. This file should be
> deleted as part of ppc's final removal.
>
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
>
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
>
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
> ---
>
> arch/ppc/configs/TQM8540_defconfig | 2
> arch/ppc/configs/TQM8541_defconfig | 2
> arch/ppc/configs/TQM8555_defconfig | 2
> arch/ppc/configs/TQM8560_defconfig | 2
> arch/ppc/configs/mpc834x_sys_defconfig | 2
> arch/ppc/configs/mpc8540_ads_defconfig | 2
> arch/ppc/configs/mpc8548_cds_defconfig | 2
> arch/ppc/configs/mpc8555_cds_defconfig | 2
> arch/ppc/configs/mpc8560_ads_defconfig | 2
> drivers/i2c/busses/Kconfig | 16 +
> drivers/i2c/busses/Makefile | 1
> drivers/i2c/busses/i2c-mpc-ppc.c | 418 +++++++++++++++++++++++
> +++++++++
> 12 files changed, 443 insertions(+), 10 deletions(-)
> create mode 100644 drivers/i2c/busses/i2c-mpc-ppc.c
Nak.
Just ifdef the probe functionality in i2c-mpc.c based on
CONFIG_PPC_MERGE. Your patch set shows the reason you should do
this. You provide fixes to the error path handling, but only for i2c-
mpc.c and not i2c-mpc-ppc.c.
- k
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/7] Implement module aliasing for i2c to translate from device tree names
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
2007-12-18 2:39 ` [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:39 ` [PATCH 3/7] Modify several rtc drivers to use the alias names list property of i2c Jon Smirl
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
This patch allows new style i2c chip drivers to have alias names using
the official kernel aliasing system and MODULE_DEVICE_TABLE(). I've
tested it on PowerPC and x86. This change is required for PowerPC
device tree support.
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
drivers/i2c/i2c-core.c | 32 ++++++++++++++++++++++++++------
include/linux/i2c.h | 9 ++++-----
include/linux/mod_devicetable.h | 20 ++++++++++++++++++++
scripts/mod/file2alias.c | 19 +++++++++++++++++++
4 files changed, 69 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b5e13e4..fce06fd 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -47,10 +47,25 @@ static DEFINE_IDR(i2c_adapter_idr);
/* ------------------------------------------------------------------------- */
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
+static const struct i2c_device_id *i2c_device_match(const struct i2c_device_id *id, struct i2c_client *client)
+{
+ /* only powerpc drivers implement the id_table,
+ * it is empty on other platforms */
+ if (id) {
+ while (id->name[0]) {
+ if (strcmp(client->driver_name, id->name) == 0)
+ return id;
+ id++;
+ }
+ }
+ return NULL;
+}
+
+static int i2c_bus_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(drv);
+ const struct i2c_device_id *found_id;
/* make legacy i2c drivers bypass driver model probing entirely;
* such drivers scan each i2c adapter/bus themselves.
@@ -58,9 +73,11 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
if (!is_newstyle_driver(driver))
return 0;
- /* new style drivers use the same kind of driver matching policy
- * as platform devices or SPI: compare device and driver IDs.
- */
+ /* match on an id table if there is one */
+ found_id = i2c_device_match(driver->id_table, client);
+ if (found_id)
+ return 1;
+
return strcmp(client->driver_name, drv->name) == 0;
}
@@ -89,12 +106,15 @@ static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(dev->driver);
+ const struct i2c_device_id *id;
if (!driver->probe)
return -ENODEV;
client->driver = driver;
dev_dbg(dev, "probe\n");
- return driver->probe(client);
+
+ id = i2c_device_match(driver->id_table, client);
+ return driver->probe(client, id);
}
static int i2c_device_remove(struct device *dev)
@@ -189,7 +209,7 @@ static struct device_attribute i2c_dev_attrs[] = {
static struct bus_type i2c_bus_type = {
.name = "i2c",
.dev_attrs = i2c_dev_attrs,
- .match = i2c_device_match,
+ .match = i2c_bus_match,
.uevent = i2c_device_uevent,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index a100c9f..49fc682 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -126,7 +126,7 @@ struct i2c_driver {
* With the driver model, device enumeration is NEVER done by drivers;
* it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
*/
- int (*probe)(struct i2c_client *);
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */
@@ -141,11 +141,10 @@ struct i2c_driver {
struct device_driver driver;
struct list_head list;
+ struct i2c_device_id *id_table;
};
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
-#define I2C_NAME_SIZE 20
-
/**
* struct i2c_client - represent an I2C slave device
* @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
@@ -179,7 +178,7 @@ struct i2c_client {
/* to the client */
struct device dev; /* the device structure */
int irq; /* irq issued by device (or -1) */
- char driver_name[KOBJ_NAME_LEN];
+ char driver_name[I2C_NAME_SIZE];
struct list_head list;
struct completion released;
};
@@ -223,7 +222,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
* with the adapter already known.
*/
struct i2c_board_info {
- char driver_name[KOBJ_NAME_LEN];
+ char driver_name[I2C_NAME_SIZE];
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index e9fddb4..d66038a 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -367,4 +367,24 @@ struct virtio_device_id {
};
#define VIRTIO_DEV_ANY_ID 0xffffffff
+/* i2c */
+
+/* These defines are used to separate PowerPC open firmware
+ * drivers into their own namespace */
+#define I2C_NAME_SIZE (16*3)
+#define I2C_MODULE_PREFIX "i2c:N"
+#ifdef CONFIG_OF
+#define OF_I2C_PREFIX "OF,"
+#define I2C_OF_MODULE_PREFIX I2C_MODULE_PREFIX OF_I2C_PREFIX
+#define OF_I2C_ID(s,d) {OF_I2C_PREFIX s, (d) },
+#else
+#define OF_I2C_ID(s,d)
+#endif
+
+struct i2c_device_id {
+ char name[I2C_NAME_SIZE];
+ kernel_ulong_t driver_data; /* Data private to the driver */
+};
+
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index d802b5a..da43742 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -539,6 +539,21 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
return 1;
}
+/* Looks like: i2c:Ns */
+static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+ char *alias)
+{
+ char *tmp;
+ sprintf (alias, I2C_MODULE_PREFIX "%s", id->name);
+
+ /* Replace all whitespace with underscores */
+ for (tmp = alias; tmp && *tmp; tmp++)
+ if (isspace (*tmp))
+ *tmp = '_';
+
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -669,6 +684,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct virtio_device_id), "virtio",
do_virtio_entry, mod);
+ else if (sym_is(symname, "__mod_i2c_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct i2c_device_id), "i2c",
+ do_i2c_entry, mod);
free(zeros);
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/7] Modify several rtc drivers to use the alias names list property of i2c
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
2007-12-18 2:39 ` [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc Jon Smirl
2007-12-18 2:39 ` [PATCH 2/7] Implement module aliasing for i2c to translate from device tree names Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:39 ` [PATCH 4/7] Clean up error returns Jon Smirl
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
This patch modifies the ds1307, ds1374, and rs5c372 i2c drivers to support
device tree names using the new i2c mod alias support
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
arch/powerpc/sysdev/fsl_soc.c | 44 ++++----------------------------
drivers/rtc/rtc-ds1307.c | 20 +++++++++++++-
drivers/rtc/rtc-ds1374.c | 9 ++++++
drivers/rtc/rtc-m41t80.c | 57 ++++++++++++++++++++++++++++-------------
drivers/rtc/rtc-rs5c372.c | 16 ++++++++++--
5 files changed, 85 insertions(+), 61 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3ace747..268638a 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -320,48 +320,12 @@ arch_initcall(gfar_of_init);
#ifdef CONFIG_I2C_BOARDINFO
#include <linux/i2c.h>
-struct i2c_driver_device {
- char *of_device;
- char *i2c_driver;
- char *i2c_type;
-};
-
-static struct i2c_driver_device i2c_devices[] __initdata = {
- {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
- {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
- {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",},
- {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
- {"dallas,ds1307", "rtc-ds1307", "ds1307",},
- {"dallas,ds1337", "rtc-ds1307", "ds1337",},
- {"dallas,ds1338", "rtc-ds1307", "ds1338",},
- {"dallas,ds1339", "rtc-ds1307", "ds1339",},
- {"dallas,ds1340", "rtc-ds1307", "ds1340",},
- {"stm,m41t00", "rtc-ds1307", "m41t00"},
- {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",},
-};
-
-static int __init of_find_i2c_driver(struct device_node *node,
- struct i2c_board_info *info)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
- if (!of_device_is_compatible(node, i2c_devices[i].of_device))
- continue;
- if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
- KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
- strlcpy(info->type, i2c_devices[i].i2c_type,
- I2C_NAME_SIZE) >= I2C_NAME_SIZE)
- return -ENOMEM;
- return 0;
- }
- return -ENODEV;
-}
static void __init of_register_i2c_devices(struct device_node *adap_node,
int bus_num)
{
struct device_node *node = NULL;
+ const char *compatible;
while ((node = of_get_next_child(adap_node, node))) {
struct i2c_board_info info = {};
@@ -378,8 +342,12 @@ static void __init of_register_i2c_devices(struct device_node *adap_node,
if (info.irq == NO_IRQ)
info.irq = -1;
- if (of_find_i2c_driver(node, &info) < 0)
+ compatible = of_get_property(node, "compatible", &len);
+ if (!compatible) {
+ printk(KERN_WARNING "i2c-mpc.c: invalid entry, missing compatible attribute\n");
continue;
+ }
+ strncpy(info.driver_name, compatible, sizeof(info.driver_name));
info.addr = *addr;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index bc1c7fe..d4874ff 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -139,6 +139,17 @@ static inline const struct chip_desc *find_chip(const char *s)
return NULL;
}
+static struct i2c_device_id ds1307_id[] = {
+ OF_I2C_ID("dallas,ds1307", ds_1307)
+ OF_I2C_ID("dallas,ds1337", ds_1337)
+ OF_I2C_ID("dallas,ds1338", ds_1338)
+ OF_I2C_ID("dallas,ds1339", ds_1339)
+ OF_I2C_ID("dallas,ds1340", ds_1340)
+ OF_I2C_ID("stm,m41t00", m41t00)
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
+
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
@@ -326,7 +337,7 @@ static struct bin_attribute nvram = {
static struct i2c_driver ds1307_driver;
-static int __devinit ds1307_probe(struct i2c_client *client)
+static int __devinit ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct ds1307 *ds1307;
int err = -ENODEV;
@@ -334,7 +345,11 @@ static int __devinit ds1307_probe(struct i2c_client *client)
const struct chip_desc *chip;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- chip = find_chip(client->name);
+ if (id)
+ chip = &chips[id->driver_data];
+ else
+ chip = find_chip(client->name);
+
if (!chip) {
dev_err(&client->dev, "unknown chip type '%s'\n",
client->name);
@@ -537,6 +552,7 @@ static struct i2c_driver ds1307_driver = {
},
.probe = ds1307_probe,
.remove = __devexit_p(ds1307_remove),
+ .id_table = ds1307_id,
};
static int __init ds1307_init(void)
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 45bda18..6dc05c4 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -41,6 +41,12 @@
#define DS1374_REG_SR_AF 0x01 /* Alarm Flag */
#define DS1374_REG_TCR 0x09 /* Trickle Charge */
+static struct i2c_device_id ds1374_id[] = {
+ OF_I2C_ID("dallas,ds1374", 0)
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, ds1374_id);
+
struct ds1374 {
struct i2c_client *client;
struct rtc_device *rtc;
@@ -355,7 +361,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
.ioctl = ds1374_ioctl,
};
-static int ds1374_probe(struct i2c_client *client)
+static int ds1374_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct ds1374 *ds1374;
int ret;
@@ -429,6 +435,7 @@ static struct i2c_driver ds1374_driver = {
},
.probe = ds1374_probe,
.remove = __devexit_p(ds1374_remove),
+ .id_table = ds1374_id,
};
static int __init ds1374_init(void)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 1cb33ca..fc33f77 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -100,8 +100,21 @@ static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
},
};
+static struct i2c_device_id m41t80_id[] = {
+ OF_I2C_ID("stm,m41t80", 0)
+ OF_I2C_ID("stm,m41t81", M41T80_FEATURE_HT)
+ OF_I2C_ID("stm,m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ OF_I2C_ID("stm,m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ OF_I2C_ID("stm,m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ OF_I2C_ID("stm,m41t84", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ OF_I2C_ID("stm,m41t85", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ OF_I2C_ID("stm,m41t87", M41T80_FEATURE_HT | M41T80_FEATURE_BL)
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, m41t80_id);
+
struct m41t80_data {
- const struct m41t80_chip_info *chip;
+ u8 features;
struct rtc_device *rtc;
};
@@ -208,7 +221,7 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
struct m41t80_data *clientdata = i2c_get_clientdata(client);
u8 reg;
- if (clientdata->chip->features & M41T80_FEATURE_BL) {
+ if (clientdata->features & M41T80_FEATURE_BL) {
reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
seq_printf(seq, "battery\t\t: %s\n",
(reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
@@ -756,12 +769,12 @@ static struct notifier_block wdt_notifier = {
*
*****************************************************************************
*/
-static int m41t80_probe(struct i2c_client *client)
+static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int i, rc = 0;
struct rtc_device *rtc = NULL;
struct rtc_time tm;
- const struct m41t80_chip_info *chip;
+ u8 features;
struct m41t80_data *clientdata = NULL;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
@@ -773,17 +786,24 @@ static int m41t80_probe(struct i2c_client *client)
dev_info(&client->dev,
"chip found, driver version " DRV_VERSION "\n");
- chip = NULL;
- for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
- if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
- chip = &m41t80_chip_info_tbl[i];
- break;
+ if (id)
+ features = id->driver_data;
+ else {
+ const struct m41t80_chip_info *chip;
+
+ chip = NULL;
+ for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
+ if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
+ chip = &m41t80_chip_info_tbl[i];
+ break;
+ }
}
- }
- if (!chip) {
- dev_err(&client->dev, "%s is not supported\n", client->name);
- rc = -ENODEV;
- goto exit;
+ if (!chip) {
+ dev_err(&client->dev, "%s is not supported\n", client->name);
+ rc = -ENODEV;
+ goto exit;
+ }
+ features = chip->features;
}
clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
@@ -801,7 +821,7 @@ static int m41t80_probe(struct i2c_client *client)
}
clientdata->rtc = rtc;
- clientdata->chip = chip;
+ clientdata->features = features;
i2c_set_clientdata(client, clientdata);
/* Make sure HT (Halt Update) bit is cleared */
@@ -810,7 +830,7 @@ static int m41t80_probe(struct i2c_client *client)
goto ht_err;
if (rc & M41T80_ALHOUR_HT) {
- if (chip->features & M41T80_FEATURE_HT) {
+ if (features & M41T80_FEATURE_HT) {
m41t80_get_datetime(client, &tm);
dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev,
@@ -842,7 +862,7 @@ static int m41t80_probe(struct i2c_client *client)
goto exit;
#ifdef CONFIG_RTC_DRV_M41T80_WDT
- if (chip->features & M41T80_FEATURE_HT) {
+ if (features & M41T80_FEATURE_HT) {
rc = misc_register(&wdt_dev);
if (rc)
goto exit;
@@ -878,7 +898,7 @@ static int m41t80_remove(struct i2c_client *client)
struct rtc_device *rtc = clientdata->rtc;
#ifdef CONFIG_RTC_DRV_M41T80_WDT
- if (clientdata->chip->features & M41T80_FEATURE_HT) {
+ if (clientdata->features & M41T80_FEATURE_HT) {
misc_deregister(&wdt_dev);
unregister_reboot_notifier(&wdt_notifier);
}
@@ -896,6 +916,7 @@ static struct i2c_driver m41t80_driver = {
},
.probe = m41t80_probe,
.remove = m41t80_remove,
+ .id_table = m41t80_id,
};
static int __init m41t80_rtc_init(void)
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 6b67b50..e2022c0 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -69,6 +69,15 @@ enum rtc_type {
rtc_rv5c387a,
};
+static struct i2c_device_id rs5c372_id[] = {
+ OF_I2C_ID("ricoh,rs5c372a", rtc_rs5c372a)
+ OF_I2C_ID("ricoh,rs5c372b", rtc_rs5c372b)
+ OF_I2C_ID("ricoh,rv5c386", rtc_rv5c386)
+ OF_I2C_ID("ricoh,rv5c387a", rtc_rv5c387a)
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
/* REVISIT: this assumes that:
* - we're in the 21st century, so it's safe to ignore the century
* bit for rv5c38[67] (REG_MONTH bit 7);
@@ -494,7 +503,7 @@ static void rs5c_sysfs_unregister(struct device *dev)
static struct i2c_driver rs5c372_driver;
-static int rs5c372_probe(struct i2c_client *client)
+static int rs5c372_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int err = 0;
struct rs5c372 *rs5c372;
@@ -522,7 +531,9 @@ static int rs5c372_probe(struct i2c_client *client)
if (err < 0)
goto exit_kfree;
- if (strcmp(client->name, "rs5c372a") == 0)
+ if (id)
+ rs5c372->type = id->driver_data;
+ else if (strcmp(client->name, "rs5c372a") == 0)
rs5c372->type = rtc_rs5c372a;
else if (strcmp(client->name, "rs5c372b") == 0)
rs5c372->type = rtc_rs5c372b;
@@ -651,6 +662,7 @@ static struct i2c_driver rs5c372_driver = {
},
.probe = rs5c372_probe,
.remove = rs5c372_remove,
+ .id_table = rs5c372_id,
};
static __init int rs5c372_init(void)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/7] Clean up error returns
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
` (2 preceding siblings ...)
2007-12-18 2:39 ` [PATCH 3/7] Modify several rtc drivers to use the alias names list property of i2c Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:39 ` [PATCH 5/7] Convert PowerPC MPC i2c to of_platform_driver from platform_driver Jon Smirl
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Return errors that were being ignored in the mpc-i2c driver
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
drivers/i2c/busses/i2c-mpc.c | 30 +++++++++++++++++-------------
1 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index d8de4ac..7c35a8f 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
static int mpc_write(struct mpc_i2c *i2c, int target,
const u8 * data, int length, int restart)
{
- int i;
+ int i, result;
unsigned timeout = i2c->adap.timeout;
u32 flags = restart ? CCR_RSTA : 0;
@@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
/* Write target byte */
writeb((target << 1), i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
for (i = 0; i < length; i++) {
/* Write data byte */
writeb(data[i], i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
}
return 0;
@@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
u8 * data, int length, int restart)
{
unsigned timeout = i2c->adap.timeout;
- int i;
+ int i, result;
u32 flags = restart ? CCR_RSTA : 0;
/* Start with MEN */
@@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
/* Write target address byte - this time with the read flag set */
writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
if (length) {
if (length == 1)
@@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
}
for (i = 0; i < length; i++) {
- if (i2c_wait(i2c, timeout, 0) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 0);
+ if (result < 0)
+ return result;
/* Generate txack on next to last byte */
if (i == length - 2)
@@ -321,9 +325,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
- if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
return -ENOMEM;
- }
i2c->irq = platform_get_irq(pdev, 0);
if (i2c->irq < 0) {
@@ -381,7 +385,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c->adap);
platform_set_drvdata(pdev, NULL);
- if (i2c->irq != 0)
+ if (i2c->irq != NO_IRQ)
free_irq(i2c->irq, i2c);
iounmap(i2c->base);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/7] Convert PowerPC MPC i2c to of_platform_driver from platform_driver
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
` (3 preceding siblings ...)
2007-12-18 2:39 ` [PATCH 4/7] Clean up error returns Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:39 ` [PATCH 6/7] Convert pfc8563 i2c driver from old style to new style Jon Smirl
2007-12-18 2:39 ` [PATCH 7/7] Makefile Jon Smirl
6 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Convert MPC i2c driver from being a platform_driver to an open firmware version. Error returns were improved. Routine names were changed from fsl_ to mpc_ to make them match the file name.
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
arch/powerpc/sysdev/fsl_soc.c | 96 ------------------------
drivers/i2c/busses/i2c-mpc.c | 167 +++++++++++++++++++++++++++++------------
2 files changed, 119 insertions(+), 144 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 268638a..d6ef264 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -318,102 +318,6 @@ err:
arch_initcall(gfar_of_init);
-#ifdef CONFIG_I2C_BOARDINFO
-#include <linux/i2c.h>
-
-static void __init of_register_i2c_devices(struct device_node *adap_node,
- int bus_num)
-{
- struct device_node *node = NULL;
- const char *compatible;
-
- while ((node = of_get_next_child(adap_node, node))) {
- struct i2c_board_info info = {};
- const u32 *addr;
- int len;
-
- addr = of_get_property(node, "reg", &len);
- if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
- printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");
- continue;
- }
-
- info.irq = irq_of_parse_and_map(node, 0);
- if (info.irq == NO_IRQ)
- info.irq = -1;
-
- compatible = of_get_property(node, "compatible", &len);
- if (!compatible) {
- printk(KERN_WARNING "i2c-mpc.c: invalid entry, missing compatible attribute\n");
- continue;
- }
- strncpy(info.driver_name, compatible, sizeof(info.driver_name));
-
- info.addr = *addr;
-
- i2c_register_board_info(bus_num, &info, 1);
- }
-}
-
-static int __init fsl_i2c_of_init(void)
-{
- struct device_node *np;
- unsigned int i;
- struct platform_device *i2c_dev;
- int ret;
-
- for (np = NULL, i = 0;
- (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
- i++) {
- struct resource r[2];
- struct fsl_i2c_platform_data i2c_data;
- const unsigned char *flags = NULL;
-
- memset(&r, 0, sizeof(r));
- memset(&i2c_data, 0, sizeof(i2c_data));
-
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- goto err;
-
- of_irq_to_resource(np, 0, &r[1]);
-
- i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
- if (IS_ERR(i2c_dev)) {
- ret = PTR_ERR(i2c_dev);
- goto err;
- }
-
- i2c_data.device_flags = 0;
- flags = of_get_property(np, "dfsrr", NULL);
- if (flags)
- i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
-
- flags = of_get_property(np, "fsl5200-clocking", NULL);
- if (flags)
- i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
-
- ret =
- platform_device_add_data(i2c_dev, &i2c_data,
- sizeof(struct
- fsl_i2c_platform_data));
- if (ret)
- goto unreg;
-
- of_register_i2c_devices(np, i);
- }
-
- return 0;
-
-unreg:
- platform_device_unregister(i2c_dev);
-err:
- return ret;
-}
-
-arch_initcall(fsl_i2c_of_init);
-#endif
-
#ifdef CONFIG_PPC_83xx
static int __init mpc83xx_wdt_init(void)
{
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7c35a8f..fc46207 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -17,7 +17,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/init.h>
-#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/io.h>
#include <linux/fsl_devices.h>
@@ -25,13 +25,13 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
-#define MPC_I2C_ADDR 0x00
+#define DRV_NAME "mpc-i2c"
+
#define MPC_I2C_FDR 0x04
#define MPC_I2C_CR 0x08
#define MPC_I2C_SR 0x0c
#define MPC_I2C_DR 0x10
#define MPC_I2C_DFSRR 0x14
-#define MPC_I2C_REGION 0x20
#define CCR_MEN 0x80
#define CCR_MIEN 0x40
@@ -316,105 +316,176 @@ static struct i2c_adapter mpc_ops = {
.retries = 1
};
-static int fsl_i2c_probe(struct platform_device *pdev)
+struct i2c_driver_device {
+ char *of_device;
+ char *i2c_driver;
+ char *i2c_type;
+};
+
+static void of_register_i2c_devices(struct i2c_adapter *adap, struct device_node *adap_node)
+{
+ struct device_node *node = NULL;
+
+ while ((node = of_get_next_child(adap_node, node))) {
+ struct i2c_board_info info;
+ const u32 *addr;
+ const char *compatible;
+ int len;
+
+ addr = of_get_property(node, "reg", &len);
+ if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
+ printk(KERN_ERR "i2c-mpc.c: invalid entry, missing reg attribute\n");
+ continue;
+ }
+
+ info.irq = irq_of_parse_and_map(node, 0);
+ if (info.irq == NO_IRQ)
+ info.irq = -1;
+
+ compatible = of_get_property(node, "compatible", &len);
+ if (!compatible) {
+ printk(KERN_ERR "i2c-mpc.c: invalid entry, missing compatible attribute\n");
+ continue;
+ }
+
+ /* need full alias i2c:NOF,vendor,device */
+ strcpy(info.driver_name, I2C_OF_MODULE_PREFIX);
+ strncat(info.driver_name, compatible, sizeof(info.driver_name));
+ request_module(info.driver_name);
+
+ /* need module alias OF,vendor,device */
+ strcpy(info.driver_name, OF_I2C_PREFIX);
+ strncat(info.driver_name, compatible, sizeof(info.driver_name));
+
+ info.type[0] = '\0';
+ info.platform_data = NULL;
+ info.addr = *addr;
+
+ if (!i2c_new_device(adap, &info)) {
+ printk(KERN_ERR "i2c-mpc.c: Failed to load driver for %s\n", info.driver_name);
+ continue;
+ }
+ }
+}
+
+static int mpc_i2c_probe(struct of_device *op, const struct of_device_id *match)
{
int result = 0;
struct mpc_i2c *i2c;
- struct fsl_i2c_platform_data *pdata;
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- i2c->irq = platform_get_irq(pdev, 0);
- if (i2c->irq < 0) {
- result = -ENXIO;
- goto fail_get_irq;
- }
- i2c->flags = pdata->device_flags;
- init_waitqueue_head(&i2c->queue);
+ if (of_get_property(op->node, "dfsrr", NULL))
+ i2c->flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
- i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
+ if (of_device_is_compatible(op->node, "mpc5200-i2c"))
+ i2c->flags |= FSL_I2C_DEV_CLOCK_5200;
+ init_waitqueue_head(&i2c->queue);
+
+ i2c->base = of_iomap(op->node, 0);
if (!i2c->base) {
printk(KERN_ERR "i2c-mpc - failed to map controller\n");
result = -ENOMEM;
goto fail_map;
}
- if (i2c->irq != 0)
- if ((result = request_irq(i2c->irq, mpc_i2c_isr,
- IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
- printk(KERN_ERR
- "i2c-mpc - failed to attach interrupt\n");
- goto fail_irq;
- }
+ i2c->irq = irq_of_parse_and_map(op->node, 0);
+ if (i2c->irq == NO_IRQ) {
+ result = -ENXIO;
+ goto fail_irq;
+ }
+
+ result = request_irq(i2c->irq, mpc_i2c_isr, IRQF_SHARED, "i2c-mpc", i2c);
+ if (result < 0) {
+ printk(KERN_ERR "i2c-mpc - failed to attach interrupt\n");
+ goto fail_request;
+ }
mpc_i2c_setclock(i2c);
- platform_set_drvdata(pdev, i2c);
+
+ dev_set_drvdata(&op->dev, i2c);
i2c->adap = mpc_ops;
- i2c->adap.nr = pdev->id;
i2c_set_adapdata(&i2c->adap, i2c);
- i2c->adap.dev.parent = &pdev->dev;
- if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
+ i2c->adap.dev.parent = &op->dev;
+
+ result = i2c_add_adapter(&i2c->adap);
+ if (result < 0) {
printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
goto fail_add;
}
+ of_register_i2c_devices(&i2c->adap, op->node);
+
return result;
- fail_add:
- if (i2c->irq != 0)
- free_irq(i2c->irq, i2c);
- fail_irq:
+fail_add:
+ free_irq(i2c->irq, i2c);
+fail_request:
+ irq_dispose_mapping(i2c->irq);
+fail_irq:
iounmap(i2c->base);
- fail_map:
- fail_get_irq:
+fail_map:
kfree(i2c);
return result;
};
-static int fsl_i2c_remove(struct platform_device *pdev)
+static int mpc_i2c_remove(struct of_device *op)
{
- struct mpc_i2c *i2c = platform_get_drvdata(pdev);
+ struct mpc_i2c *i2c = dev_get_drvdata(&op->dev);
i2c_del_adapter(&i2c->adap);
- platform_set_drvdata(pdev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
if (i2c->irq != NO_IRQ)
free_irq(i2c->irq, i2c);
+ irq_dispose_mapping(i2c->irq);
iounmap(i2c->base);
kfree(i2c);
return 0;
};
+static struct of_device_id mpc_i2c_of_match[] = {
+ {
+ .compatible = "fsl-i2c",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
+
+
/* Structure for a device driver */
-static struct platform_driver fsl_i2c_driver = {
- .probe = fsl_i2c_probe,
- .remove = fsl_i2c_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "fsl-i2c",
+static struct of_platform_driver mpc_i2c_driver = {
+ .match_table = mpc_i2c_of_match,
+ .probe = mpc_i2c_probe,
+ .remove = __devexit_p(mpc_i2c_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
},
};
-static int __init fsl_i2c_init(void)
+static int __init mpc_i2c_init(void)
{
- return platform_driver_register(&fsl_i2c_driver);
+ int rv;
+
+ rv = of_register_platform_driver(&mpc_i2c_driver);
+ if (rv)
+ printk(KERN_ERR DRV_NAME " of_register_platform_driver failed (%i)\n", rv);
+ return rv;
}
-static void __exit fsl_i2c_exit(void)
+static void __exit mpc_i2c_exit(void)
{
- platform_driver_unregister(&fsl_i2c_driver);
+ of_unregister_platform_driver(&mpc_i2c_driver);
}
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
+module_init(mpc_i2c_init);
+module_exit(mpc_i2c_exit);
MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
MODULE_DESCRIPTION
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/7] Convert pfc8563 i2c driver from old style to new style
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
` (4 preceding siblings ...)
2007-12-18 2:39 ` [PATCH 5/7] Convert PowerPC MPC i2c to of_platform_driver from platform_driver Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:39 ` [PATCH 7/7] Makefile Jon Smirl
6 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Convert pfc8563 i2c driver from old style to new style. The
driver is also modified to support device tree names via the
i2c mod alias mechanism.
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
drivers/rtc/rtc-pcf8563.c | 107 +++++++++++----------------------------------
1 files changed, 27 insertions(+), 80 deletions(-)
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 0242d80..e1ea2a0 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -25,10 +25,6 @@
* located at 0x51 will pass the validation routine due to
* the way the registers are implemented.
*/
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Module parameters */
-I2C_CLIENT_INSMOD;
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
@@ -72,9 +68,6 @@ struct pcf8563 {
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
};
-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
-static int pcf8563_detach(struct i2c_client *client);
-
/*
* In the routines that deal directly with the pcf8563 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
@@ -257,98 +250,52 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
.set_time = pcf8563_rtc_set_time,
};
-static int pcf8563_attach(struct i2c_adapter *adapter)
+static int pcf8563_remove(struct i2c_client *client)
{
- return i2c_probe(adapter, &addr_data, pcf8563_probe);
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ return 0;
}
+static struct i2c_device_id pcf8563_id[] = {
+ OF_I2C_ID("philips,pcf8563", 0)
+ OF_I2C_ID("epson,rtc8564", 0)
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+
+static int pcf8563_probe(struct i2c_client *client, const struct i2c_device_id *id);
+
static struct i2c_driver pcf8563_driver = {
.driver = {
- .name = "pcf8563",
+ .name = "rtc-pcf8563",
},
.id = I2C_DRIVERID_PCF8563,
- .attach_adapter = &pcf8563_attach,
- .detach_client = &pcf8563_detach,
+ .probe = &pcf8563_probe,
+ .remove = &pcf8563_remove,
+ .id_table = pcf8563_id,
};
-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8563_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- struct pcf8563 *pcf8563;
- struct i2c_client *client;
+ int result;
struct rtc_device *rtc;
- int err = 0;
-
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!(pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- client = &pcf8563->client;
- client->addr = address;
- client->driver = &pcf8563_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE);
-
- /* Verify the chip is really an PCF8563 */
- if (kind < 0) {
- if (pcf8563_validate_client(client) < 0) {
- err = -ENODEV;
- goto exit_kfree;
- }
- }
-
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
-
- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+ result = pcf8563_validate_client(client);
+ if (result)
+ return result;
rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
&pcf8563_rtc_ops, THIS_MODULE);
-
- if (IS_ERR(rtc)) {
- err = PTR_ERR(rtc);
- goto exit_detach;
- }
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
i2c_set_clientdata(client, rtc);
return 0;
-
-exit_detach:
- i2c_detach_client(client);
-
-exit_kfree:
- kfree(pcf8563);
-
-exit:
- return err;
-}
-
-static int pcf8563_detach(struct i2c_client *client)
-{
- struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
- int err;
- struct rtc_device *rtc = i2c_get_clientdata(client);
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(pcf8563);
-
- return 0;
}
static int __init pcf8563_init(void)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/7] Makefile
2007-12-18 2:39 [PATCH 0/7] Series to add device tree naming to i2c Jon Smirl
` (5 preceding siblings ...)
2007-12-18 2:39 ` [PATCH 6/7] Convert pfc8563 i2c driver from old style to new style Jon Smirl
@ 2007-12-18 2:39 ` Jon Smirl
2007-12-18 2:43 ` Jon Smirl
6 siblings, 1 reply; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:39 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
Makefile | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
index c1825aa..15ada3f 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,9 @@ MAKEFLAGS += -rR --no-print-directory
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands
+ARCH=powerpc
+CROSS_COMPILE=powerpc-603e-linux-gnu-
+
ifdef V
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 7/7] Makefile
2007-12-18 2:39 ` [PATCH 7/7] Makefile Jon Smirl
@ 2007-12-18 2:43 ` Jon Smirl
0 siblings, 0 replies; 10+ messages in thread
From: Jon Smirl @ 2007-12-18 2:43 UTC (permalink / raw)
To: i2c, linuxppc-dev, linux-kernel
Ignore this patch, I forgot to remove it before mailing the series.
On 12/17/07, Jon Smirl <jonsmirl@gmail.com> wrote:
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
>
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
> ---
>
> Makefile | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
>
> diff --git a/Makefile b/Makefile
> index c1825aa..15ada3f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -35,6 +35,9 @@ MAKEFLAGS += -rR --no-print-directory
> # To put more focus on warnings, be less verbose as default
> # Use 'make V=1' to see the full commands
>
> +ARCH=powerpc
> +CROSS_COMPILE=powerpc-603e-linux-gnu-
> +
> ifdef V
> ifeq ("$(origin V)", "command line")
> KBUILD_VERBOSE = $(V)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply [flat|nested] 10+ messages in thread