i2c/tps65010: New-style driver updates, part 2
authorDavid Brownell <david-b@pacbell.net>
Sat, 13 Oct 2007 21:56:30 +0000 (23:56 +0200)
committerJean Delvare <khali@hyperion.delvare>
Sat, 13 Oct 2007 21:56:30 +0000 (23:56 +0200)
Switch the tps65010 driver into a "new-style" I2C driver, and convert all
of its in-tree users (board support for OSK, H2, H3) accordingly.

That accounts for most of the board-specific code in this driver; the
rest of that code is now moved into board-specific initcalls.

Also remove some of the many now-superfluous #includes.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-osk.c
drivers/i2c/chips/tps65010.c

index 48c8c9195dc3ed339ac26f403f48c59a86fc7733..2f8f6ecf111f3ccbac765c6644e8bc274ee7e0d1 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/input.h>
-#include <linux/workqueue.h>
 
 #include <asm/hardware.h>
+#include <asm/gpio.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/irda.h>
@@ -277,6 +278,20 @@ static struct platform_device *h2_devices[] __initdata = {
        &h2_mcbsp1_device,
 };
 
+static struct i2c_board_info __initdata h2_i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("tps65010", 0x48),
+               .type           = "tps65010",
+               .irq            = OMAP_GPIO_IRQ(58),
+       },
+       /* TODO when driver support is ready:
+        *  - isp1301 OTG transceiver
+        *  - optional ov9640 camera sensor at 0x30
+        *  - pcf9754 for aGPS control
+        *  - ... etc
+        */
+};
+
 static void __init h2_init_smc91x(void)
 {
        if ((omap_request_gpio(0)) < 0) {
@@ -367,6 +382,14 @@ static void __init h2_init(void)
        omap_board_config = h2_config;
        omap_board_config_size = ARRAY_SIZE(h2_config);
        omap_serial_init();
+
+       /* irq for tps65010 chip */
+       omap_cfg_reg(W4_GPIO58);
+       if (gpio_request(58, "tps65010") == 0)
+               gpio_direction_input(58);
+
+       i2c_register_board_info(1, h2_i2c_board_info,
+                       ARRAY_SIZE(h2_i2c_board_info));
 }
 
 static void __init h2_map_io(void)
@@ -374,6 +397,22 @@ static void __init h2_map_io(void)
        omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init h2_tps_init(void)
+{
+       if (!machine_is_omap_h2())
+               return 0;
+
+       /* gpio3 for SD, gpio4 for VDD_DSP */
+       /* FIXME send power to DSP iff it's configured */
+
+       /* Enable LOW_PWR */
+       tps65010_set_low_pwr(ON);
+       return 0;
+}
+fs_initcall(h2_tps_init);
+#endif
+
 MACHINE_START(OMAP_H2, "TI-H2")
        /* Maintainer: Imre Deak <imre.deak@nokia.com> */
        .phys_io        = 0xfff00000,
index 79d4ef4c54d4818918b216db9da312d24e14b0bf..add2f703204fae66cefbe2e8261bed4b63348f93 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/workqueue.h>
+#include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/hardware.h>
+#include <asm/gpio.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/gpioexpander.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/mux.h>
@@ -413,6 +416,19 @@ static struct omap_board_config_kernel h3_config[] = {
        { OMAP_TAG_LCD,         &h3_lcd_config },
 };
 
+static struct i2c_board_info __initdata h3_i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("tps65010", 0x48),
+               .type           = "tps65013",
+               /* .irq         = OMAP_GPIO_IRQ(??), */
+       },
+       /* TODO when driver support is ready:
+        *  - isp1301 OTG transceiver
+        *  - optional ov9640 camera sensor at 0x30
+        *  - ...
+        */
+};
+
 #define H3_NAND_RB_GPIO_PIN    10
 
 static int nand_dev_ready(struct nand_platform_data *data)
@@ -446,6 +462,10 @@ static void __init h3_init(void)
        omap_board_config = h3_config;
        omap_board_config_size = ARRAY_SIZE(h3_config);
        omap_serial_init();
+
+       /* FIXME setup irq for tps65013 chip */
+       i2c_register_board_info(1, h3_i2c_board_info,
+                       ARRAY_SIZE(h3_i2c_board_info));
 }
 
 static void __init h3_init_smc91x(void)
@@ -470,6 +490,23 @@ static void __init h3_map_io(void)
        omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init h3_tps_init(void)
+{
+       if (!machine_is_omap_h3())
+               return 0;
+
+       /* gpio4 for SD, gpio3 for VDD_DSP */
+       /* FIXME send power to DSP iff it's configured */
+
+       /* Enable LOW_PWR */
+       tps65013_set_low_pwr(ON);
+
+       return 0;
+}
+fs_initcall(h3_tps_init);
+#endif
+
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
        /* Maintainer: Texas Instruments, Inc. */
        .phys_io        = 0xfff00000,
index e7130293a03fbc2e96346aeb5d22aa6b7e20ee1a..a61bf455ee02ac3552aebaf2f54e68692456c73e 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/i2c.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/hardware.h>
+#include <asm/gpio.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
-#include <asm/arch/gpio.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/common.h>
@@ -179,6 +182,19 @@ static struct platform_device *osk5912_devices[] __initdata = {
        &osk5912_mcbsp1_device,
 };
 
+static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("tps65010", 0x48),
+               .type           = "tps65010",
+               .irq            = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
+       },
+       /* TODO when driver support is ready:
+        *  - aic23 audio chip at 0x1a
+        *  - on Mistral, 24c04 eeprom at 0x50
+        *  - optionally on Mistral, ov9640 camera sensor at 0x30
+        */
+};
+
 static void __init osk_init_smc91x(void)
 {
        if ((omap_request_gpio(0)) < 0) {
@@ -397,6 +413,14 @@ static void __init osk_init(void)
        omap_board_config_size = ARRAY_SIZE(osk_config);
        USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
 
+       /* irq for tps65010 chip */
+       /* bootloader effectively does:  omap_cfg_reg(U19_1610_MPUIO1); */
+       if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0)
+               gpio_direction_input(OMAP_MPUIO(1));
+
+       i2c_register_board_info(1, osk_i2c_board_info,
+                       ARRAY_SIZE(osk_i2c_board_info));
+
        omap_serial_init();
        osk_mistral_init();
 }
@@ -406,6 +430,44 @@ static void __init osk_map_io(void)
        omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init osk_tps_init(void)
+{
+       if (!machine_is_omap_osk())
+               return 0;
+
+       /* Let LED1 (D9) blink */
+       tps65010_set_led(LED1, BLINK);
+
+       /* Disable LED 2 (D2) */
+       tps65010_set_led(LED2, OFF);
+
+       /* Set GPIO 1 HIGH to disable VBUS power supply;
+        * OHCI driver powers it up/down as needed.
+        */
+       tps65010_set_gpio_out_value(GPIO1, HIGH);
+
+       /* Set GPIO 2 low to turn on LED D3 */
+       tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+       /* Set GPIO 3 low to take ethernet out of reset */
+       tps65010_set_gpio_out_value(GPIO3, LOW);
+
+       /* gpio4 for VDD_DSP */
+       /* FIXME send power to DSP iff it's configured */
+
+       /* Enable LOW_PWR */
+       tps65010_set_low_pwr(ON);
+
+       /* Switch VLDO2 to 3.0V for AIC23 */
+       tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
+                       | TPS_LDO1_ENABLE);
+
+       return 0;
+}
+fs_initcall(osk_tps_init);
+#endif
+
 MACHINE_START(OMAP_OSK, "TI-OSK")
        /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
        .phys_io        = 0xfff00000,
index 402d911a9e7ba04f8f21022c2991532162a18505..e320994b981cdd1b7f08f52f79ca5208298c9e0b 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
-#include <linux/suspend.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
 #include <asm/arch/tps65010.h>
 
 /*-------------------------------------------------------------------------*/
 MODULE_DESCRIPTION("TPS6501x Power Management Driver");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static struct i2c_driver tps65010_driver;
 
 /*-------------------------------------------------------------------------*/
@@ -79,10 +68,8 @@ enum tps_model {
 };
 
 struct tps65010 {
-       struct i2c_client       c;
        struct i2c_client       *client;
        struct mutex            lock;
-       int                     irq;
        struct delayed_work     work;
        struct dentry           *file;
        unsigned                charging:1;
@@ -445,7 +432,7 @@ static void tps65010_work(struct work_struct *work)
        }
 
        if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
-               enable_irq(tps->irq);
+               enable_irq(tps->client->irq);
 
        mutex_unlock(&tps->lock);
 }
@@ -464,116 +451,75 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
 
 static struct tps65010 *the_tps;
 
-static int __exit tps65010_detach_client(struct i2c_client *client)
+static int __exit tps65010_remove(struct i2c_client *client)
 {
-       struct tps65010         *tps;
+       struct tps65010         *tps = i2c_get_clientdata(client);
 
-       tps = container_of(client, struct tps65010, c);
-       free_irq(tps->irq, tps);
-#ifdef CONFIG_ARM
-       if (machine_is_omap_h2())
-               omap_free_gpio(58);
-       if (machine_is_omap_osk())
-               omap_free_gpio(OMAP_MPUIO(1));
-#endif
+       if (client->irq > 0)
+               free_irq(client->irq, tps);
        cancel_delayed_work(&tps->work);
        flush_scheduled_work();
        debugfs_remove(tps->file);
-       if (i2c_detach_client(client) == 0)
-               kfree(tps);
+       kfree(tps);
        the_tps = NULL;
        return 0;
 }
 
-static int tps65010_noscan(struct i2c_adapter *bus)
-{
-       /* pure paranoia, in case someone adds another i2c bus
-        * after our init section's gone...
-        */
-       return -ENODEV;
-}
-
-/* no error returns, they'd just make bus scanning stop */
-static int __init
-tps65010_probe(struct i2c_adapter *bus, int address, int kind)
+static int tps65010_probe(struct i2c_client *client)
 {
        struct tps65010         *tps;
        int                     status;
-       unsigned long           irqflags;
-       struct i2c_client       *client;
 
        if (the_tps) {
-               dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
-               return 0;
+               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 0;
+               return -ENOMEM;
 
        mutex_init(&tps->lock);
        INIT_DELAYED_WORK(&tps->work, tps65010_work);
-       tps->irq = -1;
-       tps->c.addr = address;
-       tps->c.adapter = bus;
-       tps->c.driver = &tps65010_driver;
-       strlcpy(tps->c.name, DRIVER_NAME, I2C_NAME_SIZE);
-       tps->client = client = &tps->c;
-
-       status = i2c_attach_client(client);
-       if (status < 0) {
-               dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
-                               DRIVER_NAME, address, status);
-               goto fail1;
-       }
+       tps->client = client;
 
-       /* the IRQ is active low, but many gpio lines can't support that
-        * so this driver can use falling-edge triggers instead.
-        */
-       irqflags = IRQF_SAMPLE_RANDOM;
-#ifdef CONFIG_ARM
-       if (machine_is_omap_h2()) {
-               tps->model = TPS65010;
-               omap_cfg_reg(W4_GPIO58);
-               tps->irq = OMAP_GPIO_IRQ(58);
-               omap_request_gpio(58);
-               omap_set_gpio_direction(58, 1);
-               irqflags |= IRQF_TRIGGER_FALLING;
-       }
-       if (machine_is_omap_osk()) {
+       if (strcmp(client->name, "tps65010") == 0)
                tps->model = TPS65010;
-               // omap_cfg_reg(U19_1610_MPUIO1);
-               tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
-               omap_request_gpio(OMAP_MPUIO(1));
-               omap_set_gpio_direction(OMAP_MPUIO(1), 1);
-               irqflags |= IRQF_TRIGGER_FALLING;
-       }
-       if (machine_is_omap_h3()) {
+       else if (strcmp(client->name, "tps65011") == 0)
+               tps->model = TPS65011;
+       else if (strcmp(client->name, "tps65012") == 0)
+               tps->model = TPS65012;
+       else if (strcmp(client->name, "tps65013") == 0)
                tps->model = TPS65013;
-
-               // FIXME set up this board's IRQ ...
+       else {
+               dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
+               status = -ENODEV;
+               goto fail1;
        }
-#endif
 
-       if (tps->irq > 0) {
-               status = request_irq(tps->irq, tps65010_irq,
-                       irqflags, DRIVER_NAME, tps);
+       /* 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",
-                                       tps->irq, status);
-                       i2c_detach_client(client);
+                                       client->irq, status);
                        goto fail1;
                }
-#ifdef CONFIG_ARM
                /* 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(tps->irq);
+               disable_irq(client->irq);
                set_bit(FLAG_IRQ_ENABLE, &tps->flags);
-#endif
        } else
-               printk(KERN_WARNING "%s: IRQ not configured!\n",
-                               DRIVER_NAME);
+               dev_warn(&client->dev, "IRQ not configured!\n");
 
 
        switch (tps->model) {
@@ -602,7 +548,6 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
                i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
                i2c_smbus_read_byte_data(client, TPS_MASK3));
 
-       tps65010_driver.attach_adapter = tps65010_noscan;
        the_tps = tps;
 
 #if    defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
@@ -635,22 +580,15 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
        return 0;
 fail1:
        kfree(tps);
-       return 0;
-}
-
-static int __init tps65010_scan_bus(struct i2c_adapter *bus)
-{
-       if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA))
-               return -EINVAL;
-       return i2c_probe(bus, &addr_data, tps65010_probe);
+       return status;
 }
 
 static struct i2c_driver tps65010_driver = {
        .driver = {
                .name   = "tps65010",
        },
-       .attach_adapter = tps65010_scan_bus,
-       .detach_client  = __exit_p(tps65010_detach_client),
+       .probe  = tps65010_probe,
+       .remove = __exit_p(tps65010_remove),
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1014,52 +952,6 @@ static int __init tps_init(void)
                msleep(10);
        }
 
-#ifdef CONFIG_ARM
-       if (machine_is_omap_osk()) {
-
-               // FIXME: More should be placed in the initialization code
-               //        of the submodules (DSP, ethernet, power management,
-               //        board-osk.c). Careful: I2C is initialized "late".
-
-               /* Let LED1 (D9) blink */
-               tps65010_set_led(LED1, BLINK);
-
-               /* Disable LED 2 (D2) */
-               tps65010_set_led(LED2, OFF);
-
-               /* Set GPIO 1 HIGH to disable VBUS power supply;
-                * OHCI driver powers it up/down as needed.
-                */
-               tps65010_set_gpio_out_value(GPIO1, HIGH);
-
-               /* Set GPIO 2 low to turn on LED D3 */
-               tps65010_set_gpio_out_value(GPIO2, HIGH);
-
-               /* Set GPIO 3 low to take ethernet out of reset */
-               tps65010_set_gpio_out_value(GPIO3, LOW);
-
-               /* gpio4 for VDD_DSP */
-
-               /* Enable LOW_PWR */
-               tps65010_set_low_pwr(ON);
-
-               /* Switch VLDO2 to 3.0V for AIC23 */
-               tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | TPS_LDO1_ENABLE);
-
-       } else if (machine_is_omap_h2()) {
-               /* gpio3 for SD, gpio4 for VDD_DSP */
-
-               /* Enable LOW_PWR */
-               tps65010_set_low_pwr(ON);
-       } else if (machine_is_omap_h3()) {
-               /* gpio4 for SD, gpio3 for VDD_DSP */
-#ifdef CONFIG_PM
-               /* Enable LOW_PWR */
-               tps65013_set_low_pwr(ON);
-#endif
-       }
-#endif
-
        return status;
 }
 /* NOTE:  this MUST be initialized before the other parts of the system