Fix issues around twl4030-gpio used as a module
Subsystems (5)
cover Fix issues around twl4030-gpio used as a module
Hi Tony,
This series is based on top of 'hsmmc' branch in linux-omap on top of commit '0e91c8ddf0e0932da59ec1d116e34049791b0e73' as requested by you.
This mainly splits omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and omap_hsmmc_deferred_del() and adds .teardown hooks in all omap3 boards to handle issues around multiple twl4030-gpio module insmod/unbind/bind as reported by Russell.
In the process this series adds an api to unregister an omap_device, makes mmc driver work with hotpluggable devices and also removes 'deferred' flag for a few mmc devices on some boards which are not really dependent on twl4030-gpio for card detect as reported by Igor.
I have tested this series on omap3 beagle, with twl4030-gpio built in, as well as twl4030-gpio built as a module and by doing multiple insmod/unbind/bind sequence. I have tested card-detect to work fine on beagle too.
regards,
Rajendra
Rajendra Nayak (6):
ARM: OMAP: omap_device: Add omap_device_unregister()
mmc: omap_hsmmc: Make the driver support hotpluggable devices
mmc: omap_hsmmc: If probe fails, give our error messages
ARM: OMAP3: Make only mmc devices using gpio_cd as deferred
ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc
devices
ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests
arch/arm/mach-omap2/board-3430sdp.c | 15 ++++- arch/arm/mach-omap2/board-cm-t35.c | 15 ++++- arch/arm/mach-omap2/board-devkit8000.c | 15 ++++- arch/arm/mach-omap2/board-igep0020.c | 18 ++++- arch/arm/mach-omap2/board-ldp.c | 13 ++++ arch/arm/mach-omap2/board-omap3beagle.c | 17 ++++- arch/arm/mach-omap2/board-omap3evm.c | 16 ++++- arch/arm/mach-omap2/board-omap3pandora.c | 14 +++- arch/arm/mach-omap2/board-omap3stalker.c | 16 ++++- arch/arm/mach-omap2/board-omap3touchbook.c | 15 ++++- arch/arm/mach-omap2/board-overo.c | 11 +++- arch/arm/mach-omap2/board-rx51-peripherals.c | 11 +++ arch/arm/mach-omap2/board-zoom-peripherals.c | 14 +++- arch/arm/mach-omap2/hsmmc.c | 93 ++++++++++++------------- arch/arm/mach-omap2/hsmmc.h | 9 ++- arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/omap_device.c | 20 +++++- drivers/mmc/host/omap_hsmmc.c | 11 ++-- 18 files changed, 249 insertions(+), 75 deletions(-)
PATCH 1/6 ARM: OMAP: omap_device: Add omap_device_unregister()
Add support to unregister an omap_device usingomap_device_unregister api.
While here, also fix the kerneldoc comments foromap_device_register.
--- arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/omap_device.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-)
arch/arm/plat-omap/include/plat/omap_device.h +1 -0
@@ -106,6 +106,7 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, int pm_lats_cnt);void omap_device_delete (struct omap_device *od);int omap_device_register (struct platform_device *pdev); +void omap_device_unregister (struct platform_device *pdev);void __iomem *omap_device_get_rt_va (struct omap_device *od);struct device *omap_device_get_by_hwmod_name (const char *oh_name);
arch/arm/plat-omap/omap_device.c +18 -2
@@ -808,8 +808,8 @@ static struct dev_pm_domain omap_device_pm_domain = {* @od: struct omap_device * to register * * Register the omap_device structure. This currently just calls -* platform_device_register() on the underlying platform_device. -* Returns the return value of platform_device_register(). +* platform_device_add() on the underlying platform_device. +* Returns the return value of platform_device_add(). */ int omap_device_register (struct platform_device *pdev) {
@@ -820,6 +820,22 @@ int omap_device_register(struct platform_device *pdev)return platform_device_add (pdev); } +/** +* omap_device_unregister - unregister an omap_device with one omap_hwmod +* @od: struct omap_device * to unregister +* +* Unregister the omap_device structure. This currently just calls +* platform_device_del() on the underlying platform_device. +* No return value. +*/ +void omap_device_unregister (struct platform_device *pdev) +{ +pr_debug ("omap_device: %s: unregistering\n" , pdev->name); + + pdev->dev.parent = &omap_device_parent; + pdev->dev.pm_domain = &omap_device_pm_domain; +platform_device_del (pdev); +}/* Public functions for use by device drivers through struct platform_data */
Signature · 1 line
1.7.1
PATCH 2/6 mmc: omap_hsmmc: Make the driver support hotpluggable devices
In reply to Rajendra NayakMake the hsmmc driver register the driver using platform_driver_register() so it can support hotpluggable devices.
This is needed, for instance, in case of OMAP3, wherein some of the mmc devices might get added and removed dynamically based on dependent modules like twl4030-gpio.
--- drivers/mmc/host/omap_hsmmc.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/mmc/host/omap_hsmmc.c +3 -2
@@ -1847,7 +1847,7 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)#endif -static int __init omap_hsmmc_probe (struct platform_device *pdev) +static int omap_hsmmc_probe (struct platform_device *pdev) {struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;struct mmc_host *mmc;
@@ -2264,6 +2264,7 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { };static struct platform_driver omap_hsmmc_driver = { + .probe = omap_hsmmc_probe, .remove = omap_hsmmc_remove, .driver = { .name =DRIVER_NAME ,
@@ -2275,7 +2276,7 @@ static struct platform_driver omap_hsmmc_driver = {static int __init omap_hsmmc_init (void ) {/* Register the MMC driver */ -return platform_driver_probe (&omap_hsmmc_driver, omap_hsmmc_probe); +return platform_driver_register (&omap_hsmmc_driver); } static void __exit omap_hsmmc_cleanup(void)
Signature · 1 line
1.7.1
PATCH 3/6 mmc: omap_hsmmc: If probe fails, give out error messages
In reply to Rajendra NayakGiving out debug messages even in case of probe failure seems not very useful. Make them error messages instead.
--- drivers/mmc/host/omap_hsmmc.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/mmc/host/omap_hsmmc.c +3 -3
@@ -2008,13 +2008,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ret =request_irq (host->irq, omap_hsmmc_irq,0 ,mmc_hostname (mmc), host);if (ret) { -dev_dbg (mmc_dev (host->mmc),"Unable to grab HSMMC IRQ\n" ); +dev_err (mmc_dev (host->mmc),"Unable to grab HSMMC IRQ\n" ); goto err_irq; }if (pdata->init !=NULL ) {if (pdata->init (&pdev->dev) !=0 ) { -dev_dbg (mmc_dev (host->mmc), +dev_err (mmc_dev (host->mmc),"Unable to configure MMC IRQs\n" ); goto err_irq_cd_init; }
@@ -2037,7 +2037,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING , mmc_hostname(mmc), host);if (ret) { -dev_dbg (mmc_dev (host->mmc), +dev_err (mmc_dev (host->mmc),"Unable to grab MMC CD IRQ\n" ); goto err_irq_cd; }
Signature · 1 line
1.7.1
PATCH 4/6 ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
In reply to Rajendra Nayakmmc devices which actually do not depend on twl4030-gpio for gpio_cd should not be maked as deferred.
Also on overo, since none of the mmc devices need to be deferred, get rid of omap_hsmmc_late_init() altogether.
--- arch/arm/mach-omap2/board-cm-t35.c | 1 - arch/arm/mach-omap2/board-igep0020.c | 1 - arch/arm/mach-omap2/board-omap3evm.c | 1 - arch/arm/mach-omap2/board-omap3pandora.c | 1 - arch/arm/mach-omap2/board-overo.c | 4 ---- arch/arm/mach-omap2/board-zoom-peripherals.c | 2 -- 6 files changed, 0 insertions(+), 10 deletions(-)
arch/arm/mach-omap2/board-cm-t35.c +0 -1
@@ -422,7 +422,6 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, .ocr_mask = 0x00100000, /* 3.3V */ - .deferred = true, }, {}/* Terminator */ };
arch/arm/mach-omap2/board-igep0020.c +0 -1
@@ -303,7 +303,6 @@ static struct omap2_hsmmc_info mmc[] = { .caps = MMC_CAP_4_BIT_DATA, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, - .deferred = true, },#endif {}/* Terminator */
arch/arm/mach-omap2/board-omap3evm.c +0 -1
@@ -327,7 +327,6 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, .nonremovable = true, - .deferred = true, },#endif {}/* Terminator */
arch/arm/mach-omap2/board-omap3pandora.c +0 -1
@@ -290,7 +290,6 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = { .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, .init_card = pandora_wl1251_init_card, - .deferred = true, }, {}/* Terminator */ };
arch/arm/mach-omap2/board-overo.c +0 -4
@@ -301,7 +301,6 @@ static struct omap2_hsmmc_info mmc[] = { .caps = MMC_CAP_4_BIT_DATA, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, - .deferred = true, }, { .mmc = 2,
@@ -310,7 +309,6 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .transceiver = true, .ocr_mask = 0x00100000, /* 3.3V */ - .deferred = true, }, {}/* Terminator */ };
@@ -409,8 +407,6 @@ static inline void __init overo_init_keys(void) { return; }static int overo_twl_gpio_setup (struct device *dev,unsigned gpio,unsigned ngpio) { -omap_hsmmc_late_init (mmc); -#if defined(CONFIG_LEDS_GPIO ) || defined(CONFIG_LEDS_GPIO_MODULE )/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2 ].gpio = gpio +TWL4030_GPIO_MAX +1 ;
arch/arm/mach-omap2/board-zoom-peripherals.c +0 -2
@@ -215,7 +215,6 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .nonremovable = true, .power_saving = true, - .deferred = true, }, { .name = "wl1271",
@@ -224,7 +223,6 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, .nonremovable = true, - .deferred = true, }, {}/* Terminator */ };
Signature · 1 line
1.7.1
Tony Lindgren
maintainerPATCH 4/6 ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
Quoted 8 lines · Rajendra Nayak
mmc devices which actually do not depend on twl4030-gpio for
gpio_cdshould not be maked as deferred.Also on overo, since none of the mmc devices need to be deferred, get rid of
omap_hsmmc_late_init()altogether.Reported-by Igor Grinberg <[email protected]>Signed-off-by Rajendra Nayak <[email protected]>
Thanks, I'll fold this into the original patch with your SOB so we avoid the extra churn.
Regards,
Tony
PATCH 4/6 ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
Quoted 4 lines · Tony Lindgren
Quoted 3 lines · Rajendra Nayak
mmc devices which actually do not depend on twl4030-gpio for
gpio_cdshould not be maked as deferred.
Quoted 8 lines
Quoted 5 lines
Also on overo, since none of the mmc devices need to be deferred, get rid of
omap_hsmmc_late_init()altogether.Reported-by Igor Grinberg<[email protected]>Signed-off-by Rajendra Nayak<[email protected]>Thanks, I'll fold this into the original patch with your SOB so we avoid the extra churn.
okay, thanks.
Quoted 4 lines
Regards,
Tony
PATCH 5/6 ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
In reply to Rajendra Nayakomap_hsmmc_late_init() adds deferred (if any) mmc devices which are dependent on twl4030-gpio device to be available.
If twl4030-gpio is built as a module and inserted and deleted multiple times, the mmc devices also should be added and deleted accordingly. Split omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and omap_hsmmc_deferred_del() to handle this.
The .setup board hook for twl4030-gpio handles the runtime adding on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio should handle the runtime deletion by calling omap_hsmmc_deferred_del(). This is done for all existing omap3 boards in subsequent patches.
--- arch/arm/mach-omap2/board-3430sdp.c | 2 +- arch/arm/mach-omap2/board-cm-t35.c | 2 +- arch/arm/mach-omap2/board-devkit8000.c | 2 +- arch/arm/mach-omap2/board-igep0020.c | 2 +- arch/arm/mach-omap2/board-omap3beagle.c | 2 +- arch/arm/mach-omap2/board-omap3evm.c | 2 +- arch/arm/mach-omap2/board-omap3pandora.c | 2 +- arch/arm/mach-omap2/board-omap3stalker.c | 2 +- arch/arm/mach-omap2/board-omap3touchbook.c | 2 +- arch/arm/mach-omap2/board-zoom-peripherals.c | 2 +- arch/arm/mach-omap2/hsmmc.c | 93 ++++++++++++-------------- arch/arm/mach-omap2/hsmmc.h | 9 ++- 12 files changed, 61 insertions(+), 61 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +1 -1
@@ -251,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,*/ mmc[0 ].gpio_cd = gpio +0 ; mmc[1 ].gpio_cd = gpio +1 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ gpio_request_one (gpio +7 ,GPIOF_OUT_INIT_LOW ,"sub_lcd_en_bkl" );
arch/arm/mach-omap2/board-cm-t35.c +1 -1
@@ -471,7 +471,7 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);return 0 ; }
arch/arm/mach-omap2/board-devkit8000.c +1 -1
@@ -229,7 +229,7 @@ static int devkit8000_twl_gpio_setup(struct device *dev,/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2 ].gpio = gpio +TWL4030_GPIO_MAX +1 ;
arch/arm/mach-omap2/board-igep0020.c +1 -1
@@ -403,7 +403,7 @@ static int igep_twl_gpio_setup(struct device *dev,/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ #if !defined(CONFIG_LEDS_GPIO ) && !defined(CONFIG_LEDS_GPIO_MODULE )
arch/arm/mach-omap2/board-omap3beagle.c +1 -1
@@ -276,7 +276,7 @@ static int beagle_twl_gpio_setup(struct device *dev, mmc[0 ].gpio_wp = beagle_config.mmc1_gpio_wp;/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
arch/arm/mach-omap2/board-omap3evm.c +1 -1
@@ -363,7 +363,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* * Most GPIOs are for USB OTG. Some are mostly sent to
arch/arm/mach-omap2/board-omap3pandora.c +1 -1
@@ -302,7 +302,7 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,/* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */ omap3pandora_mmc[0 ].gpio_cd = gpio +0 ; omap3pandora_mmc[1 ].gpio_cd = gpio +1 ; -omap_hsmmc_late_init (omap3pandora_mmc); +omap_hsmmc_deferred_add (omap3pandora_mmc);/* gpio + 13 drives 32kHz buffer for wifi module */ gpio_32khz = gpio +13 ;
arch/arm/mach-omap2/board-omap3stalker.c +1 -1
@@ -284,7 +284,7 @@ omap3stalker_twl_gpio_setup(struct device *dev, {/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* * Most GPIOs are for USB OTG. Some are mostly sent to
arch/arm/mach-omap2/board-omap3touchbook.c +1 -1
@@ -120,7 +120,7 @@ static int touchbook_twl_gpio_setup(struct device *dev, {/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc);/* REVISIT: need ehci-omap hooks for external VBUS * power switch and overcurrent detect
arch/arm/mach-omap2/board-zoom-peripherals.c +1 -1
@@ -234,7 +234,7 @@ static int zoom_twl_gpio_setup(struct device *dev,/* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0 ].gpio_cd = gpio +0 ; -omap_hsmmc_late_init (mmc); +omap_hsmmc_deferred_add (mmc); ret =gpio_request_one (LCD_PANEL_ENABLE_GPIO ,GPIOF_OUT_INIT_LOW ,"lcd enable" );
arch/arm/mach-omap2/hsmmc.c +44 -49
140 lines not on this page · raw message
arch/arm/mach-omap2/hsmmc.h +7 -2
@@ -31,12 +31,14 @@ struct omap2_hsmmc_info {void (*remux)(struct device *dev,int slot,int power_on);/* init some special card */ void (*init_card)(struct mmc_card *card); +struct omap_mmc_platform_data *mmc_data; };#if defined(CONFIG_MMC_OMAP_HS ) || defined(CONFIG_MMC_OMAP_HS_MODULE )void omap_hsmmc_init (struct omap2_hsmmc_info *); -void omap_hsmmc_late_init (struct omap2_hsmmc_info *); +void omap_hsmmc_deferred_add (struct omap2_hsmmc_info *); +void omap_hsmmc_deferred_del (struct omap2_hsmmc_info *);#else
@@ -44,8 +46,11 @@ static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info) { } -static inline void omap_hsmmc_late_init (struct omap2_hsmmc_info *info) +static inline void omap_hsmmc_deferred_add (struct omap2_hsmmc_info *info) { } +static inline void omap_hsmmc_deferred_del (struct omap2_hsmmc_info *info) +{ +}#endif
Signature · 1 line
1.7.1
Tony Lindgren
maintainerPATCH 5/6 ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
Hi,
Quoted 10 lines · Rajendra Nayak
omap_hsmmc_late_init()adds deferred (if any) mmc devices which are dependent on twl4030-gpio device to be available.
If twl4030-gpio is built as a module and inserted and deleted multiple times, the mmc devices also should be added and deleted accordingly. Splitomap_hsmmc_late_init()intoomap_hsmmc_deferred_add()andomap_hsmmc_deferred_del()to handle this.
The .setup board hook for twl4030-gpio handles the runtime adding on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio should handle the runtime deletion by callingomap_hsmmc_deferred_del(). This is done for all existing omap3 boards in subsequent patches.
This gets complex.. But I think I've found a simpler way where we can use the twl gpio offsets and let the drivers take care of the rest. I'll post some patches hopefully on Monday.
Regards,
Tony
PATCH 5/6 ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
Quoted 14 lines · Tony Lindgren
Hi,
Quoted 10 lines · Rajendra Nayak
omap_hsmmc_late_init()adds deferred (if any) mmc devices which are dependent on twl4030-gpio device to be available.
If twl4030-gpio is built as a module and inserted and deleted multiple times, the mmc devices also should be added and deleted accordingly. Splitomap_hsmmc_late_init()intoomap_hsmmc_deferred_add()andomap_hsmmc_deferred_del()to handle this.
The .setup board hook for twl4030-gpio handles the runtime adding on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio should handle the runtime deletion by callingomap_hsmmc_deferred_del(). This is done for all existing omap3 boards in subsequent patches.
Quoted 3 lines
This gets complex.. But I think I've found a simpler way where we can use the twl gpio offsets and let the drivers take care of the rest. I'll post some patches hopefully on Monday.
I agree it gets complex. If you have a simpler way to handle this, that would be great.
regards,
Rajendra
Quoted 4 lines
Regards,
Tony
Tony Lindgren
maintainerPATCH 5/6 ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
Quoted 15 lines · Rajendra Nayak
Quoted 14 lines · Tony Lindgren
Hi,
Quoted 10 lines · Rajendra Nayak
omap_hsmmc_late_init()adds deferred (if any) mmc devices which are dependent on twl4030-gpio device to be available.
If twl4030-gpio is built as a module and inserted and deleted multiple times, the mmc devices also should be added and deleted accordingly. Splitomap_hsmmc_late_init()intoomap_hsmmc_deferred_add()andomap_hsmmc_deferred_del()to handle this.
The .setup board hook for twl4030-gpio handles the runtime adding on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio should handle the runtime deletion by callingomap_hsmmc_deferred_del(). This is done for all existing omap3 boards in subsequent patches.
Quoted 6 lines
Quoted 3 lines
This gets complex.. But I think I've found a simpler way where we can use the twl gpio offsets and let the drivers take care of the rest. I'll post some patches hopefully on Monday.
I agree it gets complex. If you have a simpler way to handle this, that would be great.
Posted now, sorry it too a bit longer, I got distracted with other stuff. The thread is "[PATCH 0/4] Start getting rid of pdata callbacks with gpio_find_by_chip_name()". Some further testing would be appreciated.
Regards,
Tony
PATCH 6/6 ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests
In reply to Rajendra NayakAll OMAP3 boards which register a .setup function with twl4030 gpio driver do not seem to have a .teardown hook implemented. .setup mainly requests a few gpios and also in most cases does a omap_hsmmc_deferred_add(). Have a .teardown do a gpio_free() and of the requested gpios and also do a omap_hsmmc_deferred_del(). This helps in case the twl4030 gpio driver is built as a module and added and removed multiple times. Without the .teardown a multiple insmod/rmmod can result in gpio request failues and also WARN messages stating addition of already registered mmc devices.
--- arch/arm/mach-omap2/board-3430sdp.c | 13 +++++++++++++ arch/arm/mach-omap2/board-cm-t35.c | 12 ++++++++++++ arch/arm/mach-omap2/board-devkit8000.c | 13 +++++++++++++ arch/arm/mach-omap2/board-igep0020.c | 15 +++++++++++++++ arch/arm/mach-omap2/board-ldp.c | 13 +++++++++++++ arch/arm/mach-omap2/board-omap3beagle.c | 15 +++++++++++++++ arch/arm/mach-omap2/board-omap3evm.c | 13 +++++++++++++ arch/arm/mach-omap2/board-omap3pandora.c | 11 +++++++++++ arch/arm/mach-omap2/board-omap3stalker.c | 14 ++++++++++++++ arch/arm/mach-omap2/board-omap3touchbook.c | 13 +++++++++++++ arch/arm/mach-omap2/board-rx51-peripherals.c | 11 +++++++++++ arch/arm/mach-omap2/board-zoom-peripherals.c | 10 ++++++++++ 12 files changed, 153 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +13 -0
@@ -262,6 +262,18 @@ static int sdp3430_twl_gpio_setup(struct device *dev,return 0 ; } +static int sdp3430_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ +gpio_free (gpio +7 ); +/* gpio + 15 is "sub_lcd_nRST" (output) */ +gpio_free (gpio +15 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data sdp3430_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE ,
@@ -269,6 +281,7 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = { .pulldowns = BIT(2) | BIT(6) | BIT(8) | BIT(13) | BIT(16) | BIT(17), .setup = sdp3430_twl_gpio_setup, + .teardown = sdp3430_twl_gpio_teardown, };/* regulator consumer mappings */
arch/arm/mach-omap2/board-cm-t35.c +12 -0
@@ -476,11 +476,23 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,return 0 ; } +static int cm_t35_twl_gpio_teardown (struct device *dev,unsigned gpio, +unsigned ngpio) +{ +int wlan_rst = gpio +2 ; + +omap_hsmmc_deferred_del (mmc); +gpio_free (wlan_rst); + +return 0 ; +} +static struct twl4030_gpio_platform_data cm_t35_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .setup = cm_t35_twl_gpio_setup, + .teardown = cm_t35_twl_gpio_teardown, };static struct twl4030_platform_data cm_t35_twldata = {
arch/arm/mach-omap2/board-devkit8000.c +13 -0
@@ -255,6 +255,18 @@ static int devkit8000_twl_gpio_setup(struct device *dev,return 0 ; } +static int devkit8000_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ +gpio_free (gpio +TWL4030_GPIO_MAX +0 ); +/* gpio + 7 is "DVI_PD" (out, active low) */ +gpio_free (gpio +7 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data devkit8000_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE ,
@@ -263,6 +275,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { .pulldowns = BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13) | BIT(15) | BIT(16) | BIT(17), .setup = devkit8000_twl_gpio_setup, + .teardown = devkit8000_twl_gpio_teardown, };static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
arch/arm/mach-omap2/board-igep0020.c +15 -0
@@ -436,12 +436,27 @@ static int igep_twl_gpio_setup(struct device *dev,return 0 ; }; +static int igep_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ +gpio_free (gpio +TWL4030_GPIO_MAX +1 ); +if (machine_is_igep0030 ()) +return 0 ; + +gpio_free_array (igep2_twl_gpios,ARRAY_SIZE (igep2_twl_gpios)); + +return 0 ; +} +static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .use_leds = true, .setup = igep_twl_gpio_setup, + .teardown = igep_twl_gpio_teardown, };static int igep2_enable_dvi (struct omap_dss_device *dssdev)
arch/arm/mach-omap2/board-ldp.c +13 -0
@@ -274,11 +274,24 @@ static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)return 0 ; } +static int ldp_twl_gpio_teardown (struct device *dev,unsigned gpio, +unsigned ngpio) +{ +struct gpio gpios[] = { + {gpio +7 ,GPIOF_OUT_INIT_LOW ,"LCD ENABLE" }, + {gpio +15 ,GPIOF_OUT_INIT_LOW ,"LCD BACKLIGHT" }, + }; +gpio_free_array (gpios,ARRAY_SIZE (gpios)); + +return 0 ; +} +static struct twl4030_gpio_platform_data ldp_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .setup = ldp_twl_gpio_setup, + .teardown = ldp_twl_gpio_teardown, };static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
arch/arm/mach-omap2/board-omap3beagle.c +15 -0
@@ -320,6 +320,20 @@ static int beagle_twl_gpio_setup(struct device *dev,return 0 ; } +static int beagle_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* gpio + 1 is used for differently on beagle and beagle-Xm boards */ +gpio_free (gpio +1 ); +if (cpu_is_omap3630 ()) +/* gpio + 2 is used only on Xm */ +gpio_free (gpio +2 ); +gpio_free (gpio +TWL4030_GPIO_MAX ); + +return 0 ; +} +static struct twl4030_gpio_platform_data beagle_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE ,
@@ -329,6 +343,7 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = { .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) | BIT(15) | BIT(16) | BIT(17), .setup = beagle_twl_gpio_setup, + .teardown = beagle_twl_gpio_teardown, };/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
arch/arm/mach-omap2/board-omap3evm.c +13 -0
@@ -388,12 +388,25 @@ static int omap3evm_twl_gpio_setup(struct device *dev,return 0 ; } +static int omap3evm_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* gpio + TWL4030_GPIO_MAX used for ledA, LCD Backlight control */ +gpio_free (gpio +TWL4030_GPIO_MAX ); +/* gpio + 7 used for DVI Enable */ +gpio_free (gpio +7 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data omap3evm_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .use_leds = true, .setup = omap3evm_twl_gpio_setup, + .teardown = omap3evm_twl_gpio_teardown, };static uint32_t board_keymap[] = {
arch/arm/mach-omap2/board-omap3pandora.c +11 -0
@@ -315,11 +315,22 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,return 0 ; } +static int omap3pandora_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (omap3pandora_mmc); +/* gpio + 13 drives 32kHz buffer for wifi module */ +gpio_free (gpio +13 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .setup = omap3pandora_twl_gpio_setup, + .teardown = omap3pandora_twl_gpio_teardown, };static struct regulator_consumer_supply pandora_vmmc1_supply[] = {
arch/arm/mach-omap2/board-omap3stalker.c +14 -0
@@ -307,12 +307,26 @@ omap3stalker_twl_gpio_setup(struct device *dev,return 0 ; } +static int +omap3stalker_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* gpio + TWL4030_GPIO_MAX used for ledA, LCD Backlight control */ +gpio_free (gpio +TWL4030_GPIO_MAX ); +/* gpio + 7 used for DVI Enable */ +gpio_free (gpio +7 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data omap3stalker_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE , .irq_end =TWL4030_GPIO_IRQ_END , .use_leds = true, .setup = omap3stalker_twl_gpio_setup, + .teardown = omap3stalker_twl_gpio_teardown, };static uint32_t board_keymap[] = {
arch/arm/mach-omap2/board-omap3touchbook.c +13 -0
@@ -137,6 +137,18 @@ static int touchbook_twl_gpio_setup(struct device *dev,return 0 ; } +static int touchbook_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +/* gpio + 1 used for EHCI_nOC */ +gpio_free (gpio +1 ); +/* gpio + TWL4030_GPIO_MAX used for ledA, EHCI nEN_USB_PWR */ +gpio_free (gpio +TWL4030_GPIO_MAX ); + +return 0 ; +} +static struct twl4030_gpio_platform_data touchbook_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE ,
@@ -146,6 +158,7 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = { .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) | BIT(15) | BIT(16) | BIT(17), .setup = touchbook_twl_gpio_setup, + .teardown = touchbook_twl_gpio_teardown, };static struct regulator_consumer_supply touchbook_vdac_supply[] = {
arch/arm/mach-omap2/board-rx51-peripherals.c +11 -0
@@ -702,6 +702,16 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)return 0 ; } +static int rx51_twlgpio_teardown (struct device *dev,unsigned gpio,unsigned n) +{ +/* gpio + 6 used for backlight_pwm */ +gpio_free (gpio +6 ); +/* gpio + 7 used for speaker_en */ +gpio_free (gpio +7 ); + +return 0 ; +} +static struct twl4030_gpio_platform_data rx51_gpio_data = { .gpio_base =OMAP_MAX_GPIO_LINES , .irq_base =TWL4030_GPIO_IRQ_BASE ,
@@ -712,6 +722,7 @@ static struct twl4030_gpio_platform_data rx51_gpio_data = { | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) , .setup = rx51_twlgpio_setup, + .teardown = rx51_twlgpio_teardown, };static struct twl4030_ins sleep_on_seq[]__initdata = {
arch/arm/mach-omap2/board-zoom-peripherals.c +10 -0
@@ -245,6 +245,15 @@ static int zoom_twl_gpio_setup(struct device *dev,return ret; } +static int zoom_twl_gpio_teardown (struct device *dev, +unsigned gpio,unsigned ngpio) +{ +omap_hsmmc_deferred_del (mmc); +gpio_free (LCD_PANEL_ENABLE_GPIO ); + +return 0 ; +} +/* EXTMUTE callback function */ static void zoom2_set_hs_extmute (int mute) {
@@ -256,6 +265,7 @@ static struct twl4030_gpio_platform_data zoom_gpio_data = { .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, .setup = zoom_twl_gpio_setup, + .teardown = zoom_twl_gpio_teardown, };static struct twl4030_platform_data zoom_twldata = {
Signature · 1 line
1.7.1