Dne St 22. července 2009 00:33:34 Russell King - ARM Linux napsal(a): > On Wed, Jul 22, 2009 at 12:13:12AM +0200, Marek Vasut wrote: > > + ret = set_irq_type(gpio_to_irq(pdata->charge_gpio), > > + IRQ_TYPE_EDGE_BOTH); > > + if (ret) > > + goto err2; > > + ret = request_irq(gpio_to_irq(pdata->charge_gpio), > > + wm97xx_chrg_irq, IRQF_DISABLED, > > + "AC Detect", 0); > > This should be done as one call to request_irq(). > > Why? > > If the IRQ is already in use by something else, calling set_irq_type() > will stamp on that other user, enforcing the change of configuration. > request_irq() will then fail, leaving the IRQ configuration buggered. > > Combining the two allows request_irq() to fail if the IRQ line is busy. > If it isn't busy, it will configure the IRQ line prior to enabling the > IRQ. If the IRQ is shared and sharing is permitted, it will fail if > the configuration is not compatible with the existing IRQ configuration. > > set_irq_type() should only be used very sparingly and when there's no > other option. Sorry, I removed that, this patch should be OK.
From 54febe82847aeef3fcc02a074fd9d21def97f174 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marek.vasut@xxxxxxxxx> Date: Tue, 21 Jul 2009 18:52:28 +0200 Subject: [PATCH 3/4] Convert WM97xx driver to use platform_data This patch converts the wm97xx driver to use platform_data supplied by ac97 bus. Also, this fixes the related wm97xx-battery driver to use it's platform_data and prepares a structure for touchscreen driver. Signed-off-by: Marek Vasut <marek.vasut@xxxxxxxxx> --- drivers/input/touchscreen/wm97xx-core.c | 3 ++ drivers/power/wm97xx_battery.c | 55 ++++++++++++++++++++++-------- include/linux/wm97xx.h | 18 ++++++++++ include/linux/wm97xx_batt.h | 26 -------------- 4 files changed, 61 insertions(+), 41 deletions(-) delete mode 100644 include/linux/wm97xx_batt.h diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 252eb11..f944918 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -561,6 +561,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev) static int wm97xx_probe(struct device *dev) { struct wm97xx *wm; + struct wm97xx_pdata *pdata = dev->platform_data; int ret = 0, id = 0; wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL); @@ -658,6 +659,7 @@ static int wm97xx_probe(struct device *dev) } platform_set_drvdata(wm->battery_dev, wm); wm->battery_dev->dev.parent = dev; + wm->battery_dev->dev.platform_data = pdata; ret = platform_device_add(wm->battery_dev); if (ret < 0) goto batt_reg_err; @@ -671,6 +673,7 @@ static int wm97xx_probe(struct device *dev) } platform_set_drvdata(wm->touch_dev, wm); wm->touch_dev->dev.parent = dev; + wm->touch_dev->dev.platform_data = pdata; ret = platform_device_add(wm->touch_dev); if (ret < 0) goto touch_reg_err; diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index 8bde921..f31cad9 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c @@ -22,17 +22,19 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/gpio.h> -#include <linux/wm97xx_batt.h> +#include <linux/irq.h> static DEFINE_MUTEX(bat_lock); static struct work_struct bat_work; struct mutex work_lock; static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; -static struct wm97xx_batt_info *pdata; static enum power_supply_property *prop; static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, pdata->batt_aux) * pdata->batt_mult / pdata->batt_div; @@ -40,6 +42,9 @@ static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, pdata->temp_aux) * pdata->temp_mult / pdata->temp_div; @@ -49,6 +54,9 @@ static int wm97xx_bat_get_property(struct power_supply *bat_ps, enum power_supply_property psp, union power_supply_propval *val) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = bat_status; @@ -97,6 +105,7 @@ static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps) static void wm97xx_bat_update(struct power_supply *bat_ps) { int old_status = bat_status; + struct wm97xx_batt_pdata *pdata = dev_get_drvdata(bat_ps->dev->parent); mutex_lock(&work_lock); @@ -127,6 +136,12 @@ static void wm97xx_bat_work(struct work_struct *work) wm97xx_bat_update(&bat_ps); } +static irqreturn_t wm97xx_chrg_irq(int irq, void *data) +{ + schedule_work(&bat_work); + return IRQ_HANDLED; +} + #ifdef CONFIG_PM static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state) { @@ -149,6 +164,8 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) int ret = 0; int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ int i = 0; + struct wm97xx_pdata *wmdata = dev->dev.platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; if (dev->id != -1) return -EINVAL; @@ -156,17 +173,22 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) mutex_init(&work_lock); if (!pdata) { - dev_err(&dev->dev, "Please use wm97xx_bat_set_pdata\n"); + dev_err(&dev->dev, "No platform_data supplied\n"); return -EINVAL; } - if (pdata->charge_gpio >= 0 && gpio_is_valid(pdata->charge_gpio)) { + if (gpio_is_valid(pdata->charge_gpio)) { ret = gpio_request(pdata->charge_gpio, "BATT CHRG"); if (ret) goto err; ret = gpio_direction_input(pdata->charge_gpio); if (ret) goto err2; + ret = request_irq(gpio_to_irq(pdata->charge_gpio), + wm97xx_chrg_irq, IRQF_DISABLED, + "AC Detect", 0); + if (ret) + goto err3; props++; /* POWER_SUPPLY_PROP_STATUS */ } @@ -183,7 +205,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); if (!prop) - goto err2; + goto err3; prop[i++] = POWER_SUPPLY_PROP_PRESENT; if (pdata->charge_gpio >= 0) @@ -216,21 +238,30 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) if (!ret) schedule_work(&bat_work); else - goto err3; + goto err4; return 0; -err3: +err4: kfree(prop); +err3: + if (gpio_is_valid(pdata->charge_gpio)) + free_irq(gpio_to_irq(pdata->charge_gpio), dev); err2: - gpio_free(pdata->charge_gpio); + if (gpio_is_valid(pdata->charge_gpio)) + gpio_free(pdata->charge_gpio); err: return ret; } static int __devexit wm97xx_bat_remove(struct platform_device *dev) { - if (pdata && pdata->charge_gpio && pdata->charge_gpio >= 0) + struct wm97xx_pdata *wmdata = dev->dev.platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + + if (pdata && gpio_is_valid(pdata->charge_gpio)) { + free_irq(gpio_to_irq(pdata->charge_gpio), dev); gpio_free(pdata->charge_gpio); + } flush_scheduled_work(); power_supply_unregister(&bat_ps); kfree(prop); @@ -258,12 +289,6 @@ static void __exit wm97xx_bat_exit(void) platform_driver_unregister(&wm97xx_bat_driver); } -void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) -{ - pdata = data; -} -EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); - module_init(wm97xx_bat_init); module_exit(wm97xx_bat_exit); diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h index 0c98781..38e8c4d 100644 --- a/include/linux/wm97xx.h +++ b/include/linux/wm97xx.h @@ -293,6 +293,24 @@ struct wm97xx { u16 suspend_mode; /* PRP in suspend mode */ }; +struct wm97xx_batt_pdata { + int batt_aux; + int temp_aux; + int charge_gpio; + int min_voltage; + int max_voltage; + int batt_div; + int batt_mult; + int temp_div; + int temp_mult; + int batt_tech; + char *batt_name; +}; + +struct wm97xx_pdata { + struct wm97xx_batt_pdata *batt_pdata; /* battery data */ +}; + /* * Codec GPIO access (not supported on WM9705) * This can be used to set/get codec GPIO and Virtual GPIO status. diff --git a/include/linux/wm97xx_batt.h b/include/linux/wm97xx_batt.h deleted file mode 100644 index 9681d1a..0000000 --- a/include/linux/wm97xx_batt.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LINUX_WM97XX_BAT_H -#define _LINUX_WM97XX_BAT_H - -#include <linux/wm97xx.h> - -struct wm97xx_batt_info { - int batt_aux; - int temp_aux; - int charge_gpio; - int min_voltage; - int max_voltage; - int batt_div; - int batt_mult; - int temp_div; - int temp_mult; - int batt_tech; - char *batt_name; -}; - -#ifdef CONFIG_BATTERY_WM97XX -void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data); -#else -static inline void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) {} -#endif - -#endif -- 1.6.3.3
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel