From: David Brownell Date: Sat, 13 Oct 2007 21:56:30 +0000 (+0200) Subject: i2c/tps65010: New-style driver updates, part 2 X-Git-Tag: v2.6.24-rc1~1354 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8056c6cb2bb1632aa9221dce0e43a61db37b420f;p=linux-2.6 i2c/tps65010: New-style driver updates, part 2 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 Signed-off-by: Jean Delvare --- diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 48c8c9195d..2f8f6ecf11 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -20,22 +20,23 @@ */ #include -#include #include #include +#include #include #include #include #include -#include #include +#include + #include #include #include #include -#include +#include #include #include #include @@ -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 */ .phys_io = 0xfff00000, diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 79d4ef4c54..add2f70320 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,12 +30,14 @@ #include #include #include +#include + #include #include #include #include -#include +#include #include #include #include @@ -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, diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index e7130293a0..a61bf455ee 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -31,18 +31,21 @@ #include #include #include +#include #include #include #include +#include + #include #include #include #include -#include #include +#include #include #include #include @@ -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 */ .phys_io = 0xfff00000, diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 402d911a9e..e320994b98 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -24,20 +24,13 @@ #include #include #include -#include #include #include #include -#include #include #include #include -#include -#include - -#include -#include #include /*-------------------------------------------------------------------------*/ @@ -48,10 +41,6 @@ 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