From 6e7fee4b8ed7a8669d5e4eaa492e8c6cb6105de6 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 5 Jun 2009 11:11:04 +0400 Subject: GTA02: gps power management bugfix After suspending with GPS powered on power_on sysfs node reports 0 and GPS is actually unpowered but "echo 1 > power_on" has no effect. This patch fixes it. Reported and analised by Timo Juhani Lindfors , ticket #2293. Signed-off-by: Paul Fertser --- arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c index 93b491137e7..b59d4959257 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c @@ -305,7 +305,8 @@ static void gps_pwron_set(int on) /* remove pulldown now it won't be floating any more */ s3c2410_gpio_pullup(S3C2410_GPH5, 0); - if (!neo1973_gps.power_was_on) + if (!regulator_is_enabled(neo1973_gps.regulator[ + GTA02_GPS_REG_RF_3V])) regulator_enable(neo1973_gps.regulator[ GTA02_GPS_REG_RF_3V]); return; -- cgit v1.2.3 From 6fbbacd00b2e6e09583b0f88aed39a7a6cfb6c81 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 8 Jun 2009 23:46:53 +0400 Subject: GTA0[12]: make headset button report PLAY pressed on press As discussed on the ML, currently headset button reports "KEY_PAUSE released" on press and "pressed" on release. For "pause" semantics it makes sense but if someone thinks of that as of just another button, it'd be good to have "pressed/released" events consistent with button press/release. Luca Capello suggested to change the button event to KEY_PLAY and to invert the state to make it more consistent. This trivial patch inverts button events for GTA03 KEY_PLUS and KEY_MINUS, i'm not sure how undesirable that is. I can prepare an alternative that preserves current behaviour on GTA03 per request. Signed-off-by: Paul Fertser --- drivers/input/keyboard/neo1973kbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/keyboard/neo1973kbd.c b/drivers/input/keyboard/neo1973kbd.c index a95dd5806d2..8756ae60910 100644 --- a/drivers/input/keyboard/neo1973kbd.c +++ b/drivers/input/keyboard/neo1973kbd.c @@ -75,7 +75,7 @@ static struct neo1973kbd_key keys[] = { [NEO1973_KEY_HOLD] = { .name = "Neo1973 HOLD button", .isr = neo1973kbd_default_key_irq, - .input_key = KEY_PAUSE, + .input_key = KEY_PLAY, }, [NEO1973_KEY_JACK] = { .name = "Neo1973 Headphone jack", @@ -161,7 +161,7 @@ static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id) continue; input_report_key(kbd->input, keys[n].input_key, - gpio_get_value(kbd->pdev->resource[n].start)); + !gpio_get_value(kbd->pdev->resource[n].start)); input_sync(kbd->input); } @@ -346,7 +346,7 @@ static int neo1973kbd_probe(struct platform_device *pdev) input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_SW); set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); set_bit(KEY_PHONE, input_dev->keybit); - set_bit(KEY_PAUSE, input_dev->keybit); + set_bit(KEY_PLAY, input_dev->keybit); rc = input_register_device(neo1973kbd->input); if (rc) -- cgit v1.2.3 From e6c028cdcc8c3baf5bcd053f4c37fa49bad6cf60 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 10 Jun 2009 15:39:38 +0400 Subject: gta01: asoc: fix lm4857 control Commit 4eaa9819dc08d7bfd1065ce530e31b18a119dcaf changed semantics of private_value member of kcontrol. This resulted in inability to control amplifier and subsequently in very low output volume. Tested-by: Johannes Schauer Signed-off-by: Paul Fertser --- sound/soc/s3c24xx/neo1973_wm8753.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 2970305990f..3f170cb53d3 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c @@ -353,9 +353,11 @@ static void lm4857_write_regs(void) static int lm4857_get_reg(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int reg = kcontrol->private_value & 0xFF; - int shift = (kcontrol->private_value >> 8) & 0x0F; - int mask = (kcontrol->private_value >> 16) & 0xFF; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + int shift = mc->shift; + int mask = mc->max; DBG("Entered %s\n", __func__); @@ -366,9 +368,11 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol, static int lm4857_set_reg(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int reg = kcontrol->private_value & 0xFF; - int shift = (kcontrol->private_value >> 8) & 0x0F; - int mask = (kcontrol->private_value >> 16) & 0xFF; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + int shift = mc->shift; + int mask = mc->max; if (((lm4857_regs[reg] >> shift) & mask) == ucontrol->value.integer.value[0]) -- cgit v1.2.3 From d7ac922b016626921887e5a1ee42cefce1d0d607 Mon Sep 17 00:00:00 2001 From: Luca Capello Date: Wed, 10 Jun 2009 01:23:59 +0200 Subject: CONFIG_BATTERY_BQ27000_HDQ selects CONFIG_HDQ_GPIO_BITBANG This is because of commit 1f06c28eaa6e77384a366c3d2ab1ccdbb8a807e0 The BQ27000 Battery requires HDQ. Otherwise the battery is not available at all. Signed-off-by: Luca Capello --- drivers/power/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index b5332f714cd..f88c5aab640 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -90,6 +90,7 @@ config CHARGER_PCF50633 config BATTERY_BQ27000_HDQ tristate "BQ27000 HDQ battery monitor driver" + select HDQ_GPIO_BITBANG help Say Y to enable support for the battery on the Neo Freerunner -- cgit v1.2.3 From 5a6ed99264c704e517ac312283c58204ee38fee5 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sat, 13 Jun 2009 02:04:18 +0400 Subject: gta02: move debugging messages to the appropriate levels Clean up debugging messages so that we don't see any output with loglevel=4 (default for Qi). This avoids slowing down suspend/resume by slow fb output. Checkpatch barks on this patch but i guess most of that debugging would have to be changed prior to upstream submission anyway. Signed-off-by: Paul Fertser --- drivers/mfd/glamo/glamo-fb.c | 4 ++-- drivers/mfd/glamo/glamo-mci.c | 4 ++-- include/linux/resume-dependency.h | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c index 1ebb87d1276..44ab9a39787 100644 --- a/drivers/mfd/glamo/glamo-fb.c +++ b/drivers/mfd/glamo/glamo-fb.c @@ -1061,7 +1061,7 @@ static int __init glamofb_probe(struct platform_device *pdev) glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD); glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD); - dev_info(&pdev->dev, "spin_lock_init\n"); + dev_dbg(&pdev->dev, "spin_lock_init\n"); spin_lock_init(&glamofb->lock_cmd); glamofb_init_regs(glamofb); #ifdef CONFIG_MFD_GLAMO_HWACCEL @@ -1148,7 +1148,7 @@ static int glamofb_resume(struct platform_device *pdev) glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD); glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD); - printk(KERN_ERR"spin_lock_init\n"); + dev_dbg(&pdev->dev, "spin_lock_init\n"); spin_lock_init(&gfb->lock_cmd); glamofb_init_regs(gfb); #ifdef CONFIG_MFD_GLAMO_HWACCEL diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c index bc3ed66d43c..acf16360cfd 100644 --- a/drivers/mfd/glamo/glamo-mci.c +++ b/drivers/mfd/glamo/glamo-mci.c @@ -616,7 +616,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc) int insanity_timeout = 1000000; if (host->suspending) { - dev_err(&host->pdev->dev, "IGNORING glamo_mci_send_request while " + dev_dbg(&host->pdev->dev, "REFUSING glamo_mci_send_request while " "suspended\n"); cmd->error = -EIO; if (cmd->data) @@ -774,7 +774,7 @@ static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void glamo_mci_reset(struct glamo_mci_host *host) { if (host->suspending) { - dev_err(&host->pdev->dev, "IGNORING glamo_mci_reset while " + dev_info(&host->pdev->dev, "IGNORING glamo_mci_reset while " "suspended\n"); return; } diff --git a/include/linux/resume-dependency.h b/include/linux/resume-dependency.h index 46cc1d1c6da..f84bf618205 100644 --- a/include/linux/resume-dependency.h +++ b/include/linux/resume-dependency.h @@ -38,7 +38,7 @@ struct resume_dependency { */ #define init_resume_dependency_list(_head) \ - printk(KERN_INFO "##### init_resume_dependency_list(head=%p)\n", (_head)); \ + printk(KERN_DEBUG "##### init_resume_dependency_list(head=%p)\n", (_head)); \ INIT_LIST_HEAD(&(_head)->list); @@ -52,13 +52,13 @@ struct resume_dependency { struct list_head *_pos, *_q; \ struct resume_dependency *_d; \ \ - printk(KERN_ERR "##### register_resume_dependency(head=%p, dep=%p)\n", (_head), (_dep)); \ + printk(KERN_DEBUG "##### register_resume_dependency(head=%p, dep=%p)\n", (_head), (_dep)); \ (_dep)->called_flag = 1; \ list_for_each_safe(_pos, _q, &((_head)->list)) { \ _d = list_entry(_pos, struct resume_dependency, list); \ if (_d == (_dep)) { \ list_del(_pos); \ - printk(KERN_ERR "##### duplicate dependency removed first\n"); \ + printk(KERN_DEBUG "##### duplicate dependency removed first\n"); \ } \ } \ list_add(&(_dep)->list, &(_head)->list); \ @@ -73,12 +73,12 @@ struct resume_dependency { struct list_head *_pos, *_q; \ struct resume_dependency *_dep; \ \ - printk(KERN_ERR "##### callback_all_resume_dependencies(head=%p)\n", (_head)); \ + printk(KERN_DEBUG "##### callback_all_resume_dependencies(head=%p)\n", (_head)); \ list_for_each_safe(_pos, _q, &((_head)->list)) { \ _dep = list_entry(_pos, struct resume_dependency, list); \ - printk(KERN_ERR "##### callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \ + printk(KERN_DEBUG "##### callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \ _dep->called_flag = 1; \ - printk(KERN_ERR "##### callback=%p(context=%p))\n", (_dep->callback),(_dep->context)); \ + printk(KERN_DEBUG "##### callback=%p(context=%p))\n", (_dep->callback),(_dep->context)); \ (_dep->callback)(_dep->context); \ list_del(_pos); \ } \ @@ -97,10 +97,10 @@ struct resume_dependency { struct list_head *_pos, *_q; \ struct resume_dependency *_dep; \ \ - printk(KERN_ERR "##### activate_all_resume_dependencies(head=%p)\n", (_head)); \ + printk(KERN_DEBUG "##### activate_all_resume_dependencies(head=%p)\n", (_head)); \ list_for_each_safe(_pos, _q, &((_head)->list)) { \ _dep = list_entry(_pos, struct resume_dependency, list); \ - printk(KERN_ERR "##### activating callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \ + printk(KERN_DEBUG "##### activating callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \ _dep->called_flag = 0; \ } \ } -- cgit v1.2.3 From 4e418ad2a6bae9681a7863ab8f376ce47da3e33a Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 11 Jun 2009 10:16:14 +0400 Subject: RNDIS: crude hack to fix oops on connecting to WXP SP2 F4t discovered that his freerunner panics on connect to his windows box. This crude hack workarounds the problem. Signed-off-by: Paul Fertser --- drivers/usb/gadget/rndis.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 8c26f5ea2b8..c719b1efcbc 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -294,9 +294,22 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - length = strlen (rndis_per_dev_params [configNr].vendorDescr); - memcpy (outbuf, - rndis_per_dev_params [configNr].vendorDescr, length); + + if (rndis_per_dev_params[configNr].vendorDescr) { + length = strlen( + rndis_per_dev_params[configNr].vendorDescr); + memcpy(outbuf, + rndis_per_dev_params[configNr].vendorDescr, + length); + } else { + /* + * FIXME: Openmoko hack by Paul Fertser to avoid + * panic with Win XP SP2 when vendorDescr is NULL + * (always ATM). + */ + length = 5; + memcpy(outbuf, "dummy", length); + } retval = 0; break; -- cgit v1.2.3 From e03b339e05fbf46836c83d5595d4db77112b429d Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 24 Jun 2009 12:29:37 +0400 Subject: GTA0[12]: add nls 866, 1251 to defconfigs These codepages are still widely used by inferior operating systems to represent cyrillic letters in filenames, both in fat filesystem and by some samba-servers. Signed-off-by: Paul Fertser --- arch/arm/configs/gta01_moredrivers_defconfig | 4 ++-- arch/arm/configs/gta02_packaging_defconfig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/gta01_moredrivers_defconfig b/arch/arm/configs/gta01_moredrivers_defconfig index 1f5883729dc..36d2b170b52 100644 --- a/arch/arm/configs/gta01_moredrivers_defconfig +++ b/arch/arm/configs/gta01_moredrivers_defconfig @@ -1839,7 +1839,7 @@ CONFIG_NLS_CODEPAGE_850=m # CONFIG_NLS_CODEPAGE_863 is not set # CONFIG_NLS_CODEPAGE_864 is not set # CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set +CONFIG_NLS_CODEPAGE_866=m # CONFIG_NLS_CODEPAGE_869 is not set CONFIG_NLS_CODEPAGE_936=m CONFIG_NLS_CODEPAGE_950=m @@ -1848,7 +1848,7 @@ CONFIG_NLS_CODEPAGE_950=m # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_CODEPAGE_1251=m # CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set diff --git a/arch/arm/configs/gta02_packaging_defconfig b/arch/arm/configs/gta02_packaging_defconfig index dfdfb19a2f1..755e416b100 100644 --- a/arch/arm/configs/gta02_packaging_defconfig +++ b/arch/arm/configs/gta02_packaging_defconfig @@ -1953,7 +1953,7 @@ CONFIG_NLS_CODEPAGE_850=m # CONFIG_NLS_CODEPAGE_863 is not set # CONFIG_NLS_CODEPAGE_864 is not set # CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set +CONFIG_NLS_CODEPAGE_866=m # CONFIG_NLS_CODEPAGE_869 is not set CONFIG_NLS_CODEPAGE_936=m CONFIG_NLS_CODEPAGE_950=m @@ -1962,7 +1962,7 @@ CONFIG_NLS_CODEPAGE_950=m # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_CODEPAGE_1251=m # CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set -- cgit v1.2.3 From 68a6151ff2e9e18ee9fc6a5c3b8fd65f1eb2a23b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jul 2009 09:33:39 +0100 Subject: ASoC: Fix register cache initialisation for WM8753 The wrong register cache variable was being used to provide the size for the memcpy(), resulting in a copy of only a void * of data. Reported-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8753.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index e8f0da02677..a808c7a3d55 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1669,7 +1669,7 @@ static int wm8753_register(struct wm8753_priv *wm8753) codec->reg_cache = &wm8753->reg_cache; codec->private_data = wm8753; - memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); + memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); ret = wm8753_reset(codec); -- cgit v1.2.3 From d1c828aa7073b356207b967e394defb26ab4da82 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 2 Jul 2009 23:04:16 +0200 Subject: ASoC: Fix wm8753 register cache size and initialization Register cache space was not being allocated for the final register, causing bugs when it was used. Allocate space for it. Also ensure that the final register is displayed in sysfs. [Commit message rewritten to document actual issue. -- broonie] Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8753.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a808c7a3d55..f753bc16da2 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = { 0x0097, 0x0097, 0x0000, 0x0004, 0x0000, 0x0083, 0x0024, 0x01ba, 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0000 + 0x0000, 0x0000, 0x0000 }; /* codec private data */ @@ -1665,7 +1665,7 @@ static int wm8753_register(struct wm8753_priv *wm8753) codec->set_bias_level = wm8753_set_bias_level; codec->dai = wm8753_dai; codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); + codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; codec->reg_cache = &wm8753->reg_cache; codec->private_data = wm8753; -- cgit v1.2.3 From 991a4b782728554b7274339e763a01b0905c1fe4 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 5 Jul 2009 22:53:25 +0400 Subject: GTA01: fix current and voltage reporting units According to power_supply class specification all voltages and currents must be reported in uV and uA correspondingly. Signed-off-by: Paul Fertser --- arch/arm/mach-s3c2410/mach-gta01.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c index 1fe3eef2257..1021ff5f2d5 100644 --- a/arch/arm/mach-s3c2410/mach-gta01.c +++ b/arch/arm/mach-s3c2410/mach-gta01.c @@ -237,7 +237,7 @@ static int gta01_bat_get_voltage(void) adc = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_BATVOLT_RES); mv = (adc * 6000) / 1024; - return mv; + return mv * 1000; } static int gta01_bat_get_current(void) @@ -251,7 +251,7 @@ static int gta01_bat_get_current(void) res = (adc_adcin1 - adc_battvolt) * 2400; /*rsense is 220 milli */ - return (res * 1000) / (220 * 1024); + return (res * 1000) / (220 * 1024) * 1000; } static struct gta01_bat_platform_data gta01_bat_pdata = { -- cgit v1.2.3 From d5095005f091b71d4ad68d152465b52c91957eb8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Jul 2009 21:02:57 +0200 Subject: bq27000: Return -ENODEV in bq27000_battery_get_property if the battery is not If the battery is not present hdq_read will always return an error. If the drivers knows that the battery is not present the correct thing to do is to return -ENODEV instead of passing the error on. Do this for all properties except POWER_SUPPLY_PROP_PRESENT. The power supply sysfs expects us to do so, else it won't generate a proper uevent file. Signed-off-by: Lars-Peter Clausen --- drivers/power/bq27000_battery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c index 593cbe6f752..f1dcda3297d 100644 --- a/drivers/power/bq27000_battery.c +++ b/drivers/power/bq27000_battery.c @@ -186,6 +186,9 @@ static int bq27000_battery_get_property(struct power_supply *psy, int n; struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat); + if (di->regs.rsoc < 0 && psp != POWER_SUPPLY_PROP_PRESENT) + return -ENODEV; + switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = POWER_SUPPLY_STATUS_UNKNOWN; -- cgit v1.2.3 From dcd90798cdab0ab1e7c1fb56af8841bb225b5fdc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 26 Jul 2009 20:51:48 +0200 Subject: gta02: fix compile without CHARGER_PCF50633 gta02_pmu_force_shutdown is only defined when CONFIG_CHARGER_PCF50633 is set, but it's used unconditionally. Signed-off-by: Lars-Peter Clausen --- arch/arm/mach-s3c2442/mach-gta02.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index cb821cedcd0..82b7de85ac9 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -490,6 +490,7 @@ static int gta02_udc_vbus_status(void) #define gta02_get_charger_online_status NULL #define gta02_get_charger_active_status NULL #define gta02_pmu_event_callback NULL +#define gta02_pmu_force_shutdown NULL #define gta02_udc_vbus_draw NULL #define gta02_udc_vbus_status NULL #endif -- cgit v1.2.3 From 5af71f726c58adeef22afafacc2242fd920f9882 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 26 Jul 2009 17:56:54 +0400 Subject: gta01_battery: fix unloading bug Driver data must be properly registered after allocation Signed-off-by: Paul Fertser --- drivers/power/gta01_battery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c index 81a0fe7387e..5b1a6c9b966 100644 --- a/drivers/power/gta01_battery.c +++ b/drivers/power/gta01_battery.c @@ -76,6 +76,7 @@ static int gta01_battery_probe(struct platform_device *pdev) gta01_bat->psy.external_power_changed = gta01_bat_ext_changed; gta01_bat->pdata = pdev->dev.platform_data; + platform_set_drvdata(pdev, gta01_bat); power_supply_register(&pdev->dev, >a01_bat->psy); return 0; -- cgit v1.2.3 From ec22388dfefaf8eda07d12284b8f946d3c6eb148 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 26 Jul 2009 18:00:29 +0400 Subject: gta01_battery: generalise the driver, add capacity estimation Check if machine-specific hooks exist before calling, this allows to use this driver with gta02 or any other device that is able to provide battery voltage readings. Report an estimate of capacity percentage left, based on discharge curves. Strictly speaking, this is a violation of power_supply class specs but since this is the only driver for dumb batteries and userspace lacks any library to do the estimation itself, we have to stuff it here. Please keep in mind that this estimation is by no means accurate, usually cell phones have only 5 bars to represent charge status. Credit goes to Joerg Reisenweber and SpeedEvil for helping with gathering and analysing the data. Signed-off-by: Paul Fertser --- drivers/power/gta01_battery.c | 54 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c index 5b1a6c9b966..3c7c49777b0 100644 --- a/drivers/power/gta01_battery.c +++ b/drivers/power/gta01_battery.c @@ -23,8 +23,35 @@ static enum power_supply_property gta01_bat_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CAPACITY, }; +static int gta01_bat_voltscale(int volt) +{ + /* This table is suggested by SpeedEvil based on analysis of + * experimental data */ + static const int lut[][2] = { + { 4120, 100 }, + { 3900, 60 }, + { 3740, 25 }, + { 3600, 5 }, + { 3000, 0 } }; + int i, res = 0; + + if (volt > lut[0][0]) + res = lut[0][1]; + else + for (i = 0; lut[i][1]; i++) { + if (volt <= lut[i][0] && volt >= lut[i+1][0]) { + res = lut[i][1] - (lut[i][0]-volt)* + (lut[i][1]-lut[i+1][1])/ + (lut[i][0]-lut[i+1][0]); + break; + } + } + return res; +} + static int gta01_bat_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -33,20 +60,37 @@ static int gta01_bat_get_property(struct power_supply *psy, switch(psp) { case POWER_SUPPLY_PROP_STATUS: - if (bat->pdata->get_charging_status()) - val->intval = POWER_SUPPLY_STATUS_CHARGING; + if (bat->pdata->get_charging_status) + if (bat->pdata->get_charging_status()) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = bat->pdata->get_voltage(); + if (bat->pdata->get_voltage) + val->intval = bat->pdata->get_voltage(); + else + val->intval = 0; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = bat->pdata->get_current(); + if (bat->pdata->get_current) + val->intval = bat->pdata->get_current(); + else + val->intval = 0; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = 1; /* You must never run GTA01 without battery. */ break; + case POWER_SUPPLY_PROP_CAPACITY: + if (bat->pdata->get_voltage) + val->intval = gta01_bat_voltscale( + bat->pdata->get_voltage()/1000); + else + val->intval = 0; + break; + default: return -EINVAL; } -- cgit v1.2.3 From 85c8727000a44c7932e534d63a28724bea4ab724 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 31 Jul 2009 00:47:41 +0400 Subject: gta01_battery: add charge_{now,full} properties Some userspace (notably Enlightment's batget) ignores "capacity" completely if there're no other properties. Expose a fake value (850mAh, typical for BL-5C) to make them happy. Signed-off-by: Paul Fertser --- drivers/power/gta01_battery.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c index 3c7c49777b0..2078b071b06 100644 --- a/drivers/power/gta01_battery.c +++ b/drivers/power/gta01_battery.c @@ -24,8 +24,13 @@ static enum power_supply_property gta01_bat_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, }; +/* Capacity of typical BL-5C dumb battery */ +#define GTA01_BAT_CHARGE_FULL 850000 + static int gta01_bat_voltscale(int volt) { /* This table is suggested by SpeedEvil based on analysis of @@ -83,6 +88,14 @@ static int gta01_bat_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: val->intval = 1; /* You must never run GTA01 without battery. */ break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + if (bat->pdata->get_voltage) { + int perc = gta01_bat_voltscale( + bat->pdata->get_voltage()/1000); + val->intval = perc * GTA01_BAT_CHARGE_FULL / 100; + } else + val->intval = 0; + break; case POWER_SUPPLY_PROP_CAPACITY: if (bat->pdata->get_voltage) val->intval = gta01_bat_voltscale( @@ -90,6 +103,9 @@ static int gta01_bat_get_property(struct power_supply *psy, else val->intval = 0; break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = GTA01_BAT_CHARGE_FULL; + break; default: return -EINVAL; -- cgit v1.2.3 From bcdf6f7109ea494ca84a3baea3a3c563dca9f68b Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 29 Jul 2009 18:32:52 +0400 Subject: gta02: charging_restart_interval should no longer be used, count on MBC auto-restart Signed-off-by: Paul Fertser --- arch/arm/mach-s3c2442/mach-gta02.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index 82b7de85ac9..d70c3e62500 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -570,7 +570,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .batteries = gta02_batteries, .num_batteries = ARRAY_SIZE(gta02_batteries), - .charging_restart_interval = (900 * HZ), .chg_ref_current_ma = 1000, .reg_init_data = { -- cgit v1.2.3 From 21658522b00d047212d7a78cb749648ff3bfeb04 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 28 Jul 2009 00:41:15 +0400 Subject: pcf50633: use a dedicated workqueue for irq processing Using the default kernel "events" workqueue causes problems with synchronous adc readings if initiated from some task on the same workqueue. I had a deadlock trying to use pcf50633_adc_sync_read from a power_supply class driver because the reading was initiated from the workqueue and it waited for the irq processing to complete (to get the result) and that was put on the same workqueue. Signed-off-by: Paul Fertser --- drivers/mfd/pcf50633-core.c | 5 ++++- include/linux/mfd/pcf50633/core.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 29c9395d65f..5006746ff5c 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -448,7 +448,7 @@ static irqreturn_t pcf50633_irq(int irq, void *data) get_device(pcf->dev); disable_irq(pcf->irq); - schedule_work(&pcf->irq_work); + queue_work(pcf->work_queue, &pcf->irq_work); return IRQ_HANDLED; } @@ -579,6 +579,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client, pcf->dev = &client->dev; pcf->i2c_client = client; pcf->irq = client->irq; + pcf->work_queue = create_singlethread_workqueue("pcf50633"); INIT_WORK(&pcf->irq_work, pcf50633_irq_worker); @@ -656,6 +657,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client, return 0; err: + destroy_workqueue(pcf->work_queue); kfree(pcf); return ret; } @@ -666,6 +668,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client) int i; free_irq(pcf->irq, pcf); + destroy_workqueue(pcf->work_queue); platform_device_unregister(pcf->input_pdev); platform_device_unregister(pcf->rtc_pdev); diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index af67b4e3ec6..aed1fabb068 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h @@ -138,6 +138,7 @@ struct pcf50633 { int irq; struct pcf50633_irq irq_handler[PCF50633_NUM_IRQ]; struct work_struct irq_work; + struct workqueue_struct *work_queue; struct mutex lock; u8 mask_regs[5]; -- cgit v1.2.3 From 1f0f8418cdbacc41ddf3adcce0b8552f075b26d7 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 28 Jul 2009 00:58:48 +0400 Subject: pcf50633: revise locking for ADC Current implementation is prone to races, this patch attempts to remove all but one (in pcf50633_adc_sync_read). The idea is that we need to guard the queue access only on inserting and removing items. If we insert and there're no more items in the queue it means that the last irq already happened and we need to trigger ADC manually. If not, then the next conversion will be triggered by the irq handler upon completion of the previous. Signed-off-by: Paul Fertser --- drivers/mfd/pcf50633-adc.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c index c2d05becfa9..3d31e97d6a4 100644 --- a/drivers/mfd/pcf50633-adc.c +++ b/drivers/mfd/pcf50633-adc.c @@ -73,15 +73,10 @@ static void trigger_next_adc_job_if_any(struct pcf50633 *pcf) struct pcf50633_adc *adc = __to_adc(pcf); int head; - mutex_lock(&adc->queue_mutex); - head = adc->queue_head; - if (!adc->queue[head]) { - mutex_unlock(&adc->queue_mutex); + if (!adc->queue[head]) return; - } - mutex_unlock(&adc->queue_mutex); adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg); } @@ -99,16 +94,17 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req) if (adc->queue[tail]) { mutex_unlock(&adc->queue_mutex); + dev_err(pcf->dev, "ADC queue is full, dropping request\n"); return -EBUSY; } adc->queue[tail] = req; + if (head == tail) + trigger_next_adc_job_if_any(pcf); adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1); mutex_unlock(&adc->queue_mutex); - trigger_next_adc_job_if_any(pcf); - return 0; } @@ -124,6 +120,7 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) { struct pcf50633_adc_request *req; + int err; /* req is freed when the result is ready, in interrupt handler */ req = kzalloc(sizeof(*req), GFP_KERNEL); @@ -136,9 +133,13 @@ int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) req->callback_param = req; init_completion(&req->completion); - adc_enqueue_request(pcf, req); + err = adc_enqueue_request(pcf, req); + if (err) + return err; + wait_for_completion(&req->completion); + /* FIXME by this time req might be already freed */ return req->result; } EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); @@ -159,9 +160,7 @@ int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg, req->callback = callback; req->callback_param = callback_param; - adc_enqueue_request(pcf, req); - - return 0; + return adc_enqueue_request(pcf, req); } EXPORT_SYMBOL_GPL(pcf50633_adc_async_read); @@ -184,7 +183,7 @@ static void pcf50633_adc_irq(int irq, void *data) struct pcf50633_adc *adc = data; struct pcf50633 *pcf = adc->pcf; struct pcf50633_adc_request *req; - int head; + int head, res; mutex_lock(&adc->queue_mutex); head = adc->queue_head; @@ -199,12 +198,13 @@ static void pcf50633_adc_irq(int irq, void *data) adc->queue_head = (head + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1); + res = adc_result(pcf); + trigger_next_adc_job_if_any(pcf); + mutex_unlock(&adc->queue_mutex); - req->callback(pcf, req->callback_param, adc_result(pcf)); + req->callback(pcf, req->callback_param, res); kfree(req); - - trigger_next_adc_job_if_any(pcf); } static int __devinit pcf50633_adc_probe(struct platform_device *pdev) -- cgit v1.2.3 From 1ff8185e1564c020b69eff3f222b5393f3b6c35b Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 28 Jul 2009 01:09:04 +0400 Subject: pcf50633: fix wrong define for 10bit ADC mode Signed-off-by: Paul Fertser --- include/linux/mfd/pcf50633/adc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/mfd/pcf50633/adc.h b/include/linux/mfd/pcf50633/adc.h index 56669b4183a..b35e62801ff 100644 --- a/include/linux/mfd/pcf50633/adc.h +++ b/include/linux/mfd/pcf50633/adc.h @@ -25,7 +25,8 @@ #define PCF50633_REG_ADCS3 0x57 #define PCF50633_ADCC1_ADCSTART 0x01 -#define PCF50633_ADCC1_RES_10BIT 0x02 +#define PCF50633_ADCC1_RES_8BIT 0x02 +#define PCF50633_ADCC1_RES_10BIT 0x00 #define PCF50633_ADCC1_AVERAGE_NO 0x00 #define PCF50633_ADCC1_AVERAGE_4 0x04 #define PCF50633_ADCC1_AVERAGE_8 0x08 -- cgit v1.2.3 From c31a0fec70c7ab1f9d0a5846abb31b80274e6914 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 29 Jul 2009 17:39:52 +0400 Subject: pcf50633: get rid of charging restart software auto-triggering After reaching Battery Full condition MBC state machine switches back into charging mode when the battery voltage falls below 96% of a battery float voltage. The voltage drop in Li-Ion batteries is marginal (1-2%) till about 80% of its capacity - which means, after a BATFULL, charging won't be restarted until 75-80%. That is a desired behaviour recommended by battery manufacturers, don't mess with it. Signed-off-by: Paul Fertser --- drivers/power/pcf50633-charger.c | 46 --------------------------------------- include/linux/mfd/pcf50633/core.h | 2 -- 2 files changed, 48 deletions(-) diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 1bdb9906201..cda0c6792dd 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c @@ -37,8 +37,6 @@ struct pcf50633_mbc { struct power_supply usb; struct power_supply adapter; struct power_supply ac; - - struct delayed_work charging_restart_work; }; int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) @@ -226,44 +224,10 @@ static struct attribute_group mbc_attr_group = { .attrs = pcf50633_mbc_sysfs_entries, }; -/* MBC state machine switches into charging mode when the battery voltage - * falls below 96% of a battery float voltage. But the voltage drop in Li-ion - * batteries is marginal(1~2 %) till about 80% of its capacity - which means, - * after a BATFULL, charging won't be restarted until 80%. - * - * This work_struct function restarts charging every few seconds and makes - * sure we don't discharge too much - */ - -static void pcf50633_mbc_charging_restart(struct work_struct *work) -{ - struct pcf50633_mbc *mbc; - u8 mbcs2, chgmod; - - mbc = container_of(work, struct pcf50633_mbc, - charging_restart_work.work); - - mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); - chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); - - if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) - return; - - /* Restart charging */ - pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1, - PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); - mbc->usb_active = 1; - power_supply_changed(&mbc->usb); - - dev_info(mbc->pcf->dev, "Charging restarted\n"); -} - static void pcf50633_mbc_irq_handler(int irq, void *data) { struct pcf50633_mbc *mbc = data; - int chg_restart_interval = - mbc->pcf->pdata->charging_restart_interval; /* USB */ if (irq == PCF50633_IRQ_USBINS) { @@ -272,7 +236,6 @@ pcf50633_mbc_irq_handler(int irq, void *data) mbc->usb_online = 0; mbc->usb_active = 0; pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); - cancel_delayed_work_sync(&mbc->charging_restart_work); } /* Adapter */ @@ -287,10 +250,6 @@ pcf50633_mbc_irq_handler(int irq, void *data) if (irq == PCF50633_IRQ_BATFULL) { mbc->usb_active = 0; mbc->adapter_active = 0; - - if (chg_restart_interval > 0) - schedule_delayed_work(&mbc->charging_restart_work, - chg_restart_interval); } else if (irq == PCF50633_IRQ_USBLIMON) mbc->usb_active = 0; else if (irq == PCF50633_IRQ_USBLIMOFF) @@ -428,9 +387,6 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) mbc->ac.supplied_to = mbc->pcf->pdata->batteries; mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries; - INIT_DELAYED_WORK(&mbc->charging_restart_work, - pcf50633_mbc_charging_restart); - ret = power_supply_register(&pdev->dev, &mbc->adapter); if (ret) { dev_err(mbc->pcf->dev, "failed to register adapter\n"); @@ -480,8 +436,6 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev) power_supply_unregister(&mbc->usb); power_supply_unregister(&mbc->adapter); - cancel_delayed_work_sync(&mbc->charging_restart_work); - kfree(mbc); return 0; diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index aed1fabb068..c8125f2e99e 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h @@ -29,8 +29,6 @@ struct pcf50633_platform_data { char **batteries; int num_batteries; - int charging_restart_interval; - int chg_ref_current_ma; /* Callbacks */ -- cgit v1.2.3 From 37deadd5c1aca22e1be6793cbe09532485c1d43b Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 29 Jul 2009 18:09:20 +0400 Subject: pcf50633: properly reenable charging when the supply conditions change If chgmod == BATFULL, setting chgena has no effect. Datasheet says we need to set resume instead but when autoresume is used resume doesn't work. Clear and set chgena instead. This enables a user to force charging by re-plugging USB even when the charger entered Battery Full mode, might be handy before a long trip. Signed-off-by: Paul Fertser --- drivers/power/pcf50633-charger.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index cda0c6792dd..5b5fe805fd9 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c @@ -90,14 +90,18 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); /* If chgmod == BATFULL, setting chgena has no effect. - * We need to set resume instead. + * Datasheet says we need to set resume instead but when autoresume is + * used resume doesn't work. Clear and set chgena instead. */ if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); - else + else { + pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1, + PCF50633_MBCC1_CHGENA); pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, - PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); + PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); + } mbc->usb_active = charging_start; -- cgit v1.2.3 From 53bbb82febf74555ee737998d761b7d8e6b1317e Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 29 Jul 2009 18:24:39 +0400 Subject: pcf50633: query charger status directly Current scheme is fragile and is likely to go off sync, especially on batfull->adapter charging automatic MBC transition. Query the status bit every time we need it instead. We need to export another function to query for USB presence because we can't read anything from PCF50633 (via I2C) inside irq context and that is needed by usb gadgets. Signed-off-by: Paul Fertser --- drivers/power/pcf50633-charger.c | 45 ++++++++++++++++++++++------------------ include/linux/mfd/pcf50633/mbc.h | 1 + 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 5b5fe805fd9..6fbe26eb756 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c @@ -29,9 +29,7 @@ struct pcf50633_mbc { struct pcf50633 *pcf; - int adapter_active; int adapter_online; - int usb_active; int usb_online; struct power_supply usb; @@ -103,8 +101,6 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); } - mbc->usb_active = charging_start; - power_supply_changed(&mbc->usb); return ret; @@ -115,23 +111,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf) { struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); int status = 0; + u8 chgmod; if (!mbc) return 0; + chgmod = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2) + & PCF50633_MBCS2_MBC_MASK; + if (mbc->usb_online) status |= PCF50633_MBC_USB_ONLINE; - if (mbc->usb_active) + if (chgmod == PCF50633_MBCS2_MBC_USB_PRE || + chgmod == PCF50633_MBCS2_MBC_USB_PRE_WAIT || + chgmod == PCF50633_MBCS2_MBC_USB_FAST || + chgmod == PCF50633_MBCS2_MBC_USB_FAST_WAIT) status |= PCF50633_MBC_USB_ACTIVE; if (mbc->adapter_online) status |= PCF50633_MBC_ADAPTER_ONLINE; - if (mbc->adapter_active) + if (chgmod == PCF50633_MBCS2_MBC_ADP_PRE || + chgmod == PCF50633_MBCS2_MBC_ADP_PRE_WAIT || + chgmod == PCF50633_MBCS2_MBC_ADP_FAST || + chgmod == PCF50633_MBCS2_MBC_ADP_FAST_WAIT) status |= PCF50633_MBC_ADAPTER_ACTIVE; return status; } EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); +int pcf50633_mbc_get_usb_online_status(struct pcf50633 *pcf) +{ + struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); + + if (!mbc) + return 0; + + return mbc->usb_online; +} +EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status); + static ssize_t show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) { @@ -238,26 +255,14 @@ pcf50633_mbc_irq_handler(int irq, void *data) mbc->usb_online = 1; } else if (irq == PCF50633_IRQ_USBREM) { mbc->usb_online = 0; - mbc->usb_active = 0; pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); } /* Adapter */ - if (irq == PCF50633_IRQ_ADPINS) { + if (irq == PCF50633_IRQ_ADPINS) mbc->adapter_online = 1; - mbc->adapter_active = 1; - } else if (irq == PCF50633_IRQ_ADPREM) { + else if (irq == PCF50633_IRQ_ADPREM) mbc->adapter_online = 0; - mbc->adapter_active = 0; - } - - if (irq == PCF50633_IRQ_BATFULL) { - mbc->usb_active = 0; - mbc->adapter_active = 0; - } else if (irq == PCF50633_IRQ_USBLIMON) - mbc->usb_active = 0; - else if (irq == PCF50633_IRQ_USBLIMOFF) - mbc->usb_active = 1; power_supply_changed(&mbc->usb); power_supply_changed(&mbc->adapter); diff --git a/include/linux/mfd/pcf50633/mbc.h b/include/linux/mfd/pcf50633/mbc.h index 747725b0cd0..e6328a664b3 100644 --- a/include/linux/mfd/pcf50633/mbc.h +++ b/include/linux/mfd/pcf50633/mbc.h @@ -128,5 +128,6 @@ enum pcf50633_reg_mbcs3 { int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma); int pcf50633_mbc_get_status(struct pcf50633 *); +int pcf50633_mbc_get_usb_online_status(struct pcf50633 *); #endif -- cgit v1.2.3 From 9190ad6503355a829b20154286dcb8a3ad482d8d Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 29 Jul 2009 23:56:48 +0400 Subject: gta02: use a dedicated function to query usb online status We need to use a dedicated function because we can't get charger status from an irq context and that is required by usb gadgets. Signed-off-by: Paul Fertser --- arch/arm/mach-s3c2442/mach-gta02.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index d70c3e62500..cb272fd49ac 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -391,7 +391,7 @@ static int gta02_get_charger_online_status(void) { struct pcf50633 *pcf = gta02_pcf; - return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE; + return pcf50633_mbc_get_usb_online_status(pcf); } static int gta02_get_charger_active_status(void) @@ -484,7 +484,7 @@ static int gta02_udc_vbus_status(void) if (!gta02_pcf) return -ENODEV; - return !!(pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE); + return pcf50633_mbc_get_usb_online_status(pcf); } #else /* !CONFIG_CHARGER_PCF50633 */ #define gta02_get_charger_online_status NULL -- cgit v1.2.3 From 2d158aae9d8d36f575504f59884ed8e80802efe2 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 26 Jul 2009 18:09:13 +0400 Subject: GTA02: add support for dumb battery driver This allows to use gta01 battery driver on gta02. echo bq27000-battery.0 > /sys/bus/platform/drivers/bq27000-battery/unbind modprobe gta01_battery Signed-off-by: Paul Fertser --- arch/arm/configs/gta02_moredrivers_defconfig | 2 +- arch/arm/configs/gta02_packaging_defconfig | 2 +- arch/arm/mach-s3c2442/mach-gta02.c | 30 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/gta02_moredrivers_defconfig b/arch/arm/configs/gta02_moredrivers_defconfig index 8d06cd6c70b..bd66869f74a 100644 --- a/arch/arm/configs/gta02_moredrivers_defconfig +++ b/arch/arm/configs/gta02_moredrivers_defconfig @@ -1177,7 +1177,7 @@ CONFIG_APM_POWER=y CONFIG_CHARGER_PCF50633=y CONFIG_BATTERY_BQ27000_HDQ=y CONFIG_HDQ_GPIO_BITBANG=y -# CONFIG_BATTERY_GTA01 is not set +CONFIG_BATTERY_GTA01=m CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_AD7414 is not set diff --git a/arch/arm/configs/gta02_packaging_defconfig b/arch/arm/configs/gta02_packaging_defconfig index 755e416b100..15defd28841 100644 --- a/arch/arm/configs/gta02_packaging_defconfig +++ b/arch/arm/configs/gta02_packaging_defconfig @@ -1180,7 +1180,7 @@ CONFIG_APM_POWER=y CONFIG_CHARGER_PCF50633=y CONFIG_BATTERY_BQ27000_HDQ=y CONFIG_HDQ_GPIO_BITBANG=y -# CONFIG_BATTERY_GTA01 is not set +CONFIG_BATTERY_GTA01=m CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_AD7414 is not set diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index cb272fd49ac..5de85c01893 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -100,6 +100,7 @@ #include #include +#include #include "../plat-s3c24xx/neo1973_pm_gps.h" @@ -747,6 +748,34 @@ static void mangle_pmu_pdata_by_system_rev(void) } } +static int gta02_bat_get_voltage(void) +{ + struct pcf50633 *pcf = gta02_pcf; + u16 adc, mv = 0; + adc = pcf50633_adc_sync_read(pcf, + PCF50633_ADCC1_MUX_BATSNS_RES, + PCF50633_ADCC1_AVERAGE_16); + /* The formula from DS is for divide-by-two mode, current driver uses + divide-by-three */ + mv = (adc * 6000) / 1023; + return mv * 1000; +} + +static struct gta01_bat_platform_data gta01_bat_pdata = { +#ifdef CONFIG_CHARGER_PCF50633 + .get_charging_status = gta02_get_charger_active_status, +#endif + .get_voltage = gta02_bat_get_voltage, +}; + +struct platform_device gta01_bat = { + .name = "gta01_battery", + .id = -1, + .dev = { + .platform_data = >a01_bat_pdata, + } +}; + #ifdef CONFIG_HDQ_GPIO_BITBANG /* BQ27000 Battery */ @@ -1550,6 +1579,7 @@ static struct platform_device *gta02_devices_pmu_children[] = { >a02_spi_gpio_dev, /* input 2 and 3 */ >a02_button_dev, /* input 4 */ >a02_resume_reason_device, + >a01_bat, }; static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id) -- cgit v1.2.3 From 197d20a357d6a8840b26577c6ed2764493f96b8b Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Sun, 23 Aug 2009 17:17:23 +0200 Subject: Fix max voltage of LDO1 This patch fixes a typo in the voltage setting of LDO1. In the function mangle_pmu_pdata_by_system_rev() the value of min_uV is set twice, while the value of max_uV stays at the initialized value. This leaves us with .constraints.min_uV = 3300000 and .constraints.max_uV = 1300000, which is probably not what we want. This patch is only required on andy-tracking. Signed-off-by: Sven Rebhan --- arch/arm/mach-s3c2442/mach-gta02.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index 5de85c01893..e4f052595bd 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -727,7 +727,7 @@ static void mangle_pmu_pdata_by_system_rev(void) reg_init_data[PCF50633_REGULATOR_LDO1] .constraints.min_uV = 3300000; reg_init_data[PCF50633_REGULATOR_LDO1] - .constraints.min_uV = 3300000; + .constraints.max_uV = 3300000; reg_init_data[PCF50633_REGULATOR_LDO1] .constraints.state_mem.enabled = 0; -- cgit v1.2.3 From 8851834038aec76c07454f3620fa9fb1506e7217 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 30 Aug 2009 11:55:48 +0400 Subject: Revert "AR6000: move low-level cleanup from ar6000_destroy to ar6000_close" This reverts commit 9c4451ff31b937a478f3d3eabef30b71cbe12b12. This commit made wifi unusable after ifconfig down and sometimes after unbinding. --- drivers/ar6000/ar6000/ar6000_drv.c | 150 ++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 76 deletions(-) diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c index b790670ece8..21504f221dd 100644 --- a/drivers/ar6000/ar6000/ar6000_drv.c +++ b/drivers/ar6000/ar6000/ar6000_drv.c @@ -974,17 +974,86 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister) return; } + /* Stop the transmit queues */ + netif_stop_queue(dev); + + /* Disable the target and the interrupts associated with it */ + if (ar->arWmiReady == TRUE) + { + if (!bypasswmi) + { + if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) + { + AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__); + AR6000_SPIN_LOCK(&ar->arLock, 0); + ar6000_init_profile_info(ar); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + wmi_disconnect_cmd(ar->arWmi); + } + + ar6000_dbglog_get_debug_logs(ar); + ar->arWmiReady = FALSE; + ar->arConnected = FALSE; + ar->arConnectPending = FALSE; + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = FALSE; + ar->arWmi = NULL; + ar->arWlanState = WLAN_ENABLED; +#ifdef USER_KEYS + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; +#endif + } + + AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__); + } + else + { + AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n", + __func__, (unsigned int) ar, (unsigned int) ar->arWmi); + + /* Shut down WMI if we have started it */ + if(ar->arWmiEnabled == TRUE) + { + AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__); + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = FALSE; + ar->arWmi = NULL; + } + } + + /* stop HTC */ + HTCStop(ar->arHtcTarget); + + /* set the instance to NULL so we do not get called back on remove incase we + * we're explicity destroyed by module unload */ + HTCSetInstance(ar->arHtcTarget, NULL); + + if (resetok) { + /* try to reset the device if we can + * The driver may have been configure NOT to reset the target during + * a debug session */ + AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n"); + ar6000_reset_device(ar->arHifDevice, ar->arTargetType); + } else { + AR_DEBUG_PRINTF(" Host does not want target reset. \n"); + } + + /* Done with cookies */ + ar6000_cookie_cleanup(ar); + + /* Cleanup BMI */ + BMIInit(); + /* Clear the tx counters */ memset(tx_attempt, 0, sizeof(tx_attempt)); memset(tx_post, 0, sizeof(tx_post)); memset(tx_complete, 0, sizeof(tx_complete)); + /* Free up the device data structure */ - if (unregister) { - unregister_netdev(dev); - } else { - ar6000_close(dev); - } + if (unregister) + unregister_netdev(dev); free_raw_buffers(ar); @@ -1090,79 +1159,8 @@ ar6000_open(struct net_device *dev) static int ar6000_close(struct net_device *dev) { - AR_SOFTC_T *ar = netdev_priv(dev); - - /* Stop the transmit queues */ netif_stop_queue(dev); - /* Disable the target and the interrupts associated with it */ - if (ar->arWmiReady == TRUE) - { - if (!bypasswmi) - { - if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) - { - AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__); - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar6000_init_profile_info(ar); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - wmi_disconnect_cmd(ar->arWmi); - } - - ar6000_dbglog_get_debug_logs(ar); - ar->arWmiReady = FALSE; - ar->arConnected = FALSE; - ar->arConnectPending = FALSE; - wmi_shutdown(ar->arWmi); - ar->arWmiEnabled = FALSE; - ar->arWmi = NULL; - ar->arWlanState = WLAN_ENABLED; -#ifdef USER_KEYS - ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; - ar->user_key_ctrl = 0; -#endif - } - - AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__); - } - else - { - AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n", - __func__, (unsigned int) ar, (unsigned int) ar->arWmi); - - /* Shut down WMI if we have started it */ - if(ar->arWmiEnabled == TRUE) - { - AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__); - wmi_shutdown(ar->arWmi); - ar->arWmiEnabled = FALSE; - ar->arWmi = NULL; - } - } - - /* stop HTC */ - HTCStop(ar->arHtcTarget); - - /* set the instance to NULL so we do not get called back on remove incase we - * we're explicity destroyed by module unload */ - HTCSetInstance(ar->arHtcTarget, NULL); - - if (resetok) { - /* try to reset the device if we can - * The driver may have been configure NOT to reset the target during - * a debug session */ - AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n"); - ar6000_reset_device(ar->arHifDevice, ar->arTargetType); - } else { - AR_DEBUG_PRINTF(" Host does not want target reset. \n"); - } - - /* Done with cookies */ - ar6000_cookie_cleanup(ar); - - /* Cleanup BMI */ - BMIInit(); - return 0; } -- cgit v1.2.3 From 05d6078079f605ea8740b9e7d87e421d1662222e Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 27 Aug 2009 11:37:49 +0400 Subject: pcf50606: move messages to appropriate log levels Signed-off-by: Arnaud Patard Signed-off-by: Paul Fertser --- drivers/mfd/pcf50606-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/pcf50606-core.c b/drivers/mfd/pcf50606-core.c index 7c4fb42b460..09ce70b9b79 100644 --- a/drivers/mfd/pcf50606-core.c +++ b/drivers/mfd/pcf50606-core.c @@ -282,7 +282,7 @@ out: int pcf50606_irq_mask(struct pcf50606 *pcf, int irq) { - dev_info(pcf->dev, "Masking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); return __pcf50606_irq_mask_set(pcf, irq, 1); } @@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(pcf50606_irq_mask); int pcf50606_irq_unmask(struct pcf50606 *pcf, int irq) { - dev_info(pcf->dev, "Unmasking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); return __pcf50606_irq_mask_set(pcf, irq, 0); } @@ -330,7 +330,7 @@ static void pcf50606_irq_worker(struct work_struct *work) ret = pcf50606_read_block(pcf, PCF50606_REG_INT1, ARRAY_SIZE(pcf_int), pcf_int); if (ret != ARRAY_SIZE(pcf_int)) { - dev_info(pcf->dev, "Error reading INT registers\n"); + dev_err(pcf->dev, "Error reading INT registers\n"); /* * If this doesn't ACK the interrupt to the chip, we'll be -- cgit v1.2.3 From 4616eea5f3b3a603a03f31721de3eeb42dbd7711 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 27 Aug 2009 11:39:33 +0400 Subject: pcf50633: move messages to appropriate log levels Signed-off-by: Arnaud Patard Signed-off-by: Paul Fertser --- drivers/mfd/pcf50633-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 5006746ff5c..b3c96015600 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -291,7 +291,7 @@ out: int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) { - dev_info(pcf->dev, "Masking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); return __pcf50633_irq_mask_set(pcf, irq, 1); } @@ -299,7 +299,7 @@ EXPORT_SYMBOL_GPL(pcf50633_irq_mask); int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) { - dev_info(pcf->dev, "Unmasking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); return __pcf50633_irq_mask_set(pcf, irq, 0); } -- cgit v1.2.3 From 65329e6e3de2b2fd07e524a3c10958f2acb7bcb0 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 27 Aug 2009 11:46:41 +0400 Subject: pcf50606: fix RTC alarm This makes wake up on RTC alarm work properly, ported from rtc-pcf50633 commits 4caf79de95c26495e7cdc8204023d97598f887d2 and c3e4e22fb0c3e1d82f66e67f6592949e48f3995a. Signed-off-by: Arnaud Patard Signed-off-by: Paul Fertser --- drivers/rtc/rtc-pcf50606.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf50606.c b/drivers/rtc/rtc-pcf50606.c index 434cfc1dca4..6bd93b0b672 100644 --- a/drivers/rtc/rtc-pcf50606.c +++ b/drivers/rtc/rtc-pcf50606.c @@ -58,6 +58,7 @@ struct pcf50606_time { struct pcf50606_rtc { int alarm_enabled; int second_enabled; + int alarm_pending; struct pcf50606 *pcf; struct rtc_device *rtc_dev; @@ -198,6 +199,7 @@ static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) rtc = dev_get_drvdata(dev); alrm->enabled = rtc->alarm_enabled; + alrm->pending = rtc->alarm_pending; ret = pcf50606_read_block(rtc->pcf, PCF50606_REG_RTCSCA, PCF50606_TI_EXTENT, &pcf_tm.time[0]); @@ -234,8 +236,12 @@ static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSCA, PCF50606_TI_EXTENT, &pcf_tm.time[0]); - if (!alarm_masked) + if (!alrm->enabled) + rtc->alarm_pending = 0; + + if (!alarm_masked || alrm->enabled) pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM); + rtc->alarm_enabled = alrm->enabled; return ret; } @@ -255,6 +261,7 @@ static void pcf50606_rtc_irq(int irq, void *data) switch (irq) { case PCF50606_IRQ_ALARM: rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + rtc->alarm_pending = 1; break; case PCF50606_IRQ_SECOND: rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); -- cgit v1.2.3 From a3587e4ed77974adfb057af261aaeea4022018e8 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 27 Aug 2009 12:19:12 +0400 Subject: gta01: when charging the current reported should be negative Reported-by: Arnaud Patard Signed-off-by: Paul Fertser --- arch/arm/mach-s3c2410/mach-gta01.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c index 1021ff5f2d5..8a13a4adcfd 100644 --- a/arch/arm/mach-s3c2410/mach-gta01.c +++ b/arch/arm/mach-s3c2410/mach-gta01.c @@ -248,7 +248,7 @@ static int gta01_bat_get_current(void) adc_battvolt = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_BATVOLT_SUBTR); adc_adcin1 = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_ADCIN1_SUBTR); - res = (adc_adcin1 - adc_battvolt) * 2400; + res = (adc_battvolt - adc_adcin1) * 2400; /*rsense is 220 milli */ return (res * 1000) / (220 * 1024) * 1000; -- cgit v1.2.3