From 2e64ac0ca64482f78d32a955dd8e49eb87582a4e Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 22 Sep 2011 15:42:25 +0200 Subject: ARM: kernel: smp_twd: Add save/restore functions Add simple save and restore functions which needs to be called before/after the core(s) are powered off. Change-Id: I95b7e5205d067e3c4949ba09370ea099633ca54e Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32133 --- arch/arm/include/asm/smp_twd.h | 8 ++++++++ arch/arm/kernel/smp_twd.c | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index 0f01f4677bd..e0faaeb30ea 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h @@ -42,4 +42,12 @@ static inline void twd_local_timer_of_register(void) } #endif +#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPU_IDLE) +void twd_save(void); +void twd_restore(void); +#else +static inline void twd_save(void) { } +static inline void twd_restore(void) { } +#endif + #endif diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cec..33e4a0456c3 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -33,6 +33,9 @@ static void __iomem *twd_base; static struct clk *twd_clk; static unsigned long twd_timer_rate; +static DEFINE_PER_CPU(u32, twd_ctrl); +static DEFINE_PER_CPU(u32, twd_load); + static struct clock_event_device __percpu **twd_evt; static int twd_ppi; @@ -345,3 +348,24 @@ out: WARN(err, "twd_local_timer_of_register failed (%d)\n", err); } #endif + +#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPU_IDLE) +void twd_save(void) +{ + int this_cpu = smp_processor_id(); + + per_cpu(twd_ctrl, this_cpu) = __raw_readl(twd_base + TWD_TIMER_CONTROL); + per_cpu(twd_load, this_cpu) = __raw_readl(twd_base + TWD_TIMER_LOAD); + +} + +void twd_restore(void) +{ + int this_cpu = smp_processor_id(); + + __raw_writel(per_cpu(twd_ctrl, this_cpu), + twd_base + TWD_TIMER_CONTROL); + __raw_writel(per_cpu(twd_load, this_cpu), + twd_base + TWD_TIMER_LOAD); +} +#endif -- cgit v1.2.3 From f056e01dcf46e1eaa261d60a604b35c6f023b6ff Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 22 Jun 2010 11:37:20 +0200 Subject: fix build errors with CPU_IDLE enabled Current PM for Montblanc enables both LOCAL_TIMERS and GENERIC_CLOCKEVENTS_BROADCAST. This causes build error with v2.6.34. This patch fixes this error. The PM scheme should be reviewed for v2.6.34. Signed-off-by: Mian Yousaf Kaukab Change-Id: Icdafd6f60cec858fc1311614be2e053bba168ef3 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2257 Reviewed-by: Jonas ABERG Signed-off-by: Lee Jones --- arch/arm/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8f464465977..805c7fc57ce 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -423,7 +423,7 @@ static void ipi_timer(void) } #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -static void smp_timer_broadcast(const struct cpumask *mask) +void smp_timer_broadcast(const struct cpumask *mask) { smp_cross_call(mask, IPI_TIMER); } -- cgit v1.2.3 From b129a2e44ae6e78b1d4bbc42394f4b1ded6855cc Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 24 Mar 2011 11:42:48 +0000 Subject: ARM: smp: don't recalculate loops_per_jiffy Manually applied patch based on Jonas Aaberg's commit in aid of the 2.6.35 -> 2.6.38 GLK upgrade loops_per_jiffy is calculated at boot, so no need to recalculate loops_per_jiffy each time a secondary cpu goes online. ST-Ericsson Linux next: Yes, 2011-01-12 ST-Ericsson ID: ER282335 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I359b3d2bcc03f1bdb0da641c6975478568778acd Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/11290 Reviewed-by: QATOOLS Reviewed-by: Mattias WALLIN Signed-off-by: Lee Jones --- arch/arm/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 805c7fc57ce..d0029d1ef7e 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -275,8 +275,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) notify_cpu_starting(cpu); - calibrate_delay(); - smp_store_cpu_info(cpu); /* -- cgit v1.2.3 From cbfcee037b964c37941e92ec31c0ba87d1ff9b15 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Mon, 21 Mar 2011 16:53:46 +0100 Subject: misc/bh1780gli: add PM features misc/bh1780gli: change unsigned long to long Change-Id: Ia1fc1425bf77e5af042980e0fbdf4f964dbcc03a Signed-off-by: Robert Marklund --- drivers/misc/bh1780gli.c | 66 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 54f6f39f990..b3f6e54596a 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -18,11 +18,13 @@ * this program. If not, see . */ #include +#include #include #include #include #include #include +#include #define BH1780_REG_CONTROL 0x80 #define BH1780_REG_PARTID 0x8A @@ -40,6 +42,7 @@ struct bh1780_data { struct i2c_client *client; + struct regulator *regulator; int power_state; /* lock for sysfs operations */ struct mutex lock; @@ -72,6 +75,9 @@ static ssize_t bh1780_show_lux(struct device *dev, struct bh1780_data *ddata = platform_get_drvdata(pdev); int lsb, msb; + if (ddata->power_state == BH1780_POFF) + return -EINVAL; + lsb = bh1780_read(ddata, BH1780_REG_DLOW, "DLOW"); if (lsb < 0) return lsb; @@ -89,13 +95,9 @@ static ssize_t bh1780_show_power_state(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct bh1780_data *ddata = platform_get_drvdata(pdev); - int state; - - state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL"); - if (state < 0) - return state; - return sprintf(buf, "%d\n", state & BH1780_POWMASK); + /* we already maintain a sw state */ + return sprintf(buf, "%d\n", ddata->power_state); } static ssize_t bh1780_store_power_state(struct device *dev, @@ -104,7 +106,7 @@ static ssize_t bh1780_store_power_state(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct bh1780_data *ddata = platform_get_drvdata(pdev); - unsigned long val; + long val; int error; error = strict_strtoul(buf, 0, &val); @@ -116,12 +118,22 @@ static ssize_t bh1780_store_power_state(struct device *dev, mutex_lock(&ddata->lock); + if (ddata->power_state == val) + return count; + + if (ddata->power_state == BH1780_POFF) + regulator_enable(ddata->regulator); + error = bh1780_write(ddata, BH1780_REG_CONTROL, val, "CONTROL"); if (error < 0) { mutex_unlock(&ddata->lock); + regulator_disable(ddata->regulator); return error; } + if (val == BH1780_POFF) + regulator_disable(ddata->regulator); + msleep(BH1780_PON_DELAY); ddata->power_state = val; mutex_unlock(&ddata->lock); @@ -131,7 +143,7 @@ static ssize_t bh1780_store_power_state(struct device *dev, static DEVICE_ATTR(lux, S_IRUGO, bh1780_show_lux, NULL); -static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, +static DEVICE_ATTR(power_state, S_IWUGO | S_IRUGO, bh1780_show_power_state, bh1780_store_power_state); static struct attribute *bh1780_attributes[] = { @@ -153,21 +165,37 @@ static int __devinit bh1780_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { ret = -EIO; - goto err_op_failed; + return ret; } ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL); if (ddata == NULL) { + dev_err(&client->dev, "failed to alloc ddata\n"); ret = -ENOMEM; - goto err_op_failed; + return ret; } ddata->client = client; i2c_set_clientdata(client, ddata); + dev_set_name(&client->dev, "bh1780"); + + ddata->regulator = regulator_get(&client->dev, "v-als"); + if (IS_ERR(ddata->regulator)) { + dev_err(&client->dev, "failed to get regulator\n"); + ret = PTR_ERR(ddata->regulator); + goto free_ddata; + } + + regulator_enable(ddata->regulator); ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); - if (ret < 0) - goto err_op_failed; + if (ret < 0) { + dev_err(&client->dev, "failed to read part ID\n"); + goto put_regulator; + } + + regulator_disable(ddata->regulator); + ddata->power_state = BH1780_POFF; dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n", (ret & BH1780_REVMASK)); @@ -176,11 +204,14 @@ static int __devinit bh1780_probe(struct i2c_client *client, ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); if (ret) - goto err_op_failed; + goto put_regulator; return 0; -err_op_failed: +put_regulator: + regulator_disable(ddata->regulator); + regulator_put(ddata->regulator); +free_ddata: kfree(ddata); return ret; } @@ -216,6 +247,8 @@ static int bh1780_suspend(struct device *dev) if (ret < 0) return ret; + regulator_disable(ddata->regulator); + return 0; } @@ -230,11 +263,16 @@ static int bh1780_resume(struct device *dev) ret = bh1780_write(ddata, BH1780_REG_CONTROL, state, "CONTROL"); + regulator_enable(ddata->regulator); + + ret = bh1780_write(ddata, BH1780_REG_CONTROL, ddata->power_state, + "CONTROL"); if (ret < 0) return ret; return 0; } + static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume); #define BH1780_PMOPS (&bh1780_pm) #else -- cgit v1.2.3 From af9e55de8c6e4ab825ec9ad4fbd943a86cb6981c Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Mon, 21 Mar 2011 16:58:25 +0100 Subject: mpcore_wdt: Set correct watchdog rate mpcore_wdt: Use notifiers to modify WD rate mpcore_wdt: Stop watchdog of non-crashing cores mpcore_wdt: don't sleep in atomic context Signed-off-by: Robert Marklund --- drivers/watchdog/mpcore_wdt.c | 96 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 7c741dc987b..8d814e0470d 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include @@ -50,6 +52,8 @@ struct mpcore_wdt { static struct platform_device *mpcore_wdt_pdev; static DEFINE_SPINLOCK(wdt_lock); +static DEFINE_PER_CPU(unsigned long, mpcore_wdt_rate); + #define TIMER_MARGIN 60 static int mpcore_margin = TIMER_MARGIN; module_param(mpcore_margin, int, 0); @@ -70,6 +74,8 @@ MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, " "set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")"); +#define MPCORE_WDT_PERIPHCLK_PRESCALER 2 + /* * This is the interrupt handler. Note that we only use this * in testing mode, so don't actually do a reboot here. @@ -102,9 +108,8 @@ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) spin_lock(&wdt_lock); /* Assume prescale is set to 256 */ - count = __raw_readl(wdt->base + TWD_WDOG_COUNTER); - count = (0xFFFFFFFFU - count) * (HZ / 5); - count = (count / 256) * mpcore_margin; + count = per_cpu(mpcore_wdt_rate, smp_processor_id()) / 256; + count = count*mpcore_margin; /* Reload the counter */ writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); @@ -112,6 +117,56 @@ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) spin_unlock(&wdt_lock); } +static void mpcore_wdt_set_rate(unsigned long new_rate) +{ + unsigned long count; + unsigned long long rate_tmp; + unsigned long old_rate; + + spin_lock(&wdt_lock); + old_rate = per_cpu(mpcore_wdt_rate, smp_processor_id()); + per_cpu(mpcore_wdt_rate, smp_processor_id()) = new_rate; + + if (mpcore_wdt_dev) { + struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev); + count = readl(wdt->base + TWD_WDOG_COUNTER); + /* The goal: count = count * (new_rate/old_rate); */ + rate_tmp = (unsigned long long)count * new_rate; + do_div(rate_tmp, old_rate); + count = rate_tmp; + writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); + wdt->perturb = wdt->perturb ? 0 : 1; + } + spin_unlock(&wdt_lock); +} + +static void mpcore_wdt_update_cpu_frequency_on_cpu(void *data) +{ + struct cpufreq_freqs *freq = data; + mpcore_wdt_set_rate((freq->new * 1000) / + MPCORE_WDT_PERIPHCLK_PRESCALER); +} + +static int mpcore_wdt_cpufreq_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (event == CPUFREQ_RESUMECHANGE || + (event == CPUFREQ_PRECHANGE && freq->new > freq->old) || + (event == CPUFREQ_POSTCHANGE && freq->new < freq->old)) + smp_call_function_single(freq->cpu, + mpcore_wdt_update_cpu_frequency_on_cpu, + freq, 1); + + return 0; +} + +static struct notifier_block mpcore_wdt_cpufreq_notifier_block = { + .notifier_call = mpcore_wdt_cpufreq_notifier, +}; + + static void mpcore_wdt_stop(struct mpcore_wdt *wdt) { spin_lock(&wdt_lock); @@ -146,6 +201,20 @@ static int mpcore_wdt_set_heartbeat(int t) return 0; } +static int mpcore_wdt_stop_notifier(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev); + printk(KERN_INFO "Stopping watchdog on non-crashing core %u\n", + smp_processor_id()); + mpcore_wdt_stop(wdt); + return NOTIFY_STOP; +} + +static struct notifier_block mpcore_wdt_stop_block = { + .notifier_call = mpcore_wdt_stop_notifier, +}; + /* * /dev/watchdog handling */ @@ -153,7 +222,7 @@ static int mpcore_wdt_open(struct inode *inode, struct file *file) { struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_pdev); - if (test_and_set_bit(0, &wdt->timer_alive)) + if (cpumask_test_and_set_cpu(smp_processor_id(), &wdt->timer_alive)) return -EBUSY; if (nowayout) @@ -161,6 +230,9 @@ static int mpcore_wdt_open(struct inode *inode, struct file *file) file->private_data = wdt; + atomic_notifier_chain_register(&crash_percpu_notifier_list, + &mpcore_wdt_stop_block); + /* * Activate timer */ @@ -184,7 +256,7 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) "unexpected close, not stopping watchdog!\n"); mpcore_wdt_keepalive(wdt); } - clear_bit(0, &wdt->timer_alive); + cpumask_clear_cpu(smp_processor_id(), &wdt->timer_alive); wdt->expect_close = 0; return 0; } @@ -427,6 +499,8 @@ static struct platform_driver mpcore_wdt_driver = { static int __init mpcore_wdt_init(void) { + int i; + /* * Check that the margin value is within it's range; * if not reset to the default @@ -437,6 +511,18 @@ static int __init mpcore_wdt_init(void) TIMER_MARGIN); } + cpufreq_register_notifier(&mpcore_wdt_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + for_each_online_cpu(i) + per_cpu(mpcore_wdt_rate, i) = + (cpufreq_get(i) * 1000) / MPCORE_WDT_PERIPHCLK_PRESCALER; + + for_each_online_cpu(i) + pr_info("mpcore_wdt: rate for core %d is %lu.%02luMHz.\n", i, + per_cpu(mpcore_wdt_rate, i) / 1000000, + (per_cpu(mpcore_wdt_rate, i) / 10000) % 100); + pr_info("MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n", mpcore_noboot, mpcore_margin, nowayout); -- cgit v1.2.3 From f1c1d5e930b06881b7307fccffd6144180b3bcd7 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Tue, 22 Mar 2011 10:14:24 +0100 Subject: amba-pl022: Initialize burstsize from FIFO trigger level amba-pl022: support runtime PM Signed-off-by: Robert Marklund --- drivers/spi/spi-pl022.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 400ae2121a2..7a137e9bde6 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -895,6 +895,12 @@ static int configure_dma(struct pl022 *pl022) struct dma_async_tx_descriptor *rxdesc; struct dma_async_tx_descriptor *txdesc; + /* DMA burstsize should be same as the FIFO trigger level */ + rx_conf.src_maxburst = pl022->rx_lev_trig ? 1 << + (pl022->rx_lev_trig + 1) : pl022->rx_lev_trig; + tx_conf.dst_maxburst = pl022->tx_lev_trig ? 1 << + (pl022->tx_lev_trig + 1) : pl022->tx_lev_trig; + /* Check that the channels are available */ if (!rxchan || !txchan) return -ENODEV; @@ -2048,6 +2054,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); + pm_runtime_enable(dev); + pm_runtime_resume(dev); + pl022->clk = clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { status = PTR_ERR(pl022->clk); @@ -2158,6 +2167,7 @@ pl022_remove(struct amba_device *adev) clk_disable(pl022->clk); clk_unprepare(pl022->clk); clk_put(pl022->clk); + pm_runtime_disable(&adev->dev); iounmap(pl022->virtbase); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); @@ -2260,6 +2270,14 @@ static struct vendor_data vendor_db5500_pl023 = { .loopback = true, }; +static struct vendor_data vendor_db5500_pl023 = { + .fifodepth = 32, + .max_bpw = 32, + .unidir = false, + .extended_cr = true, + .pl023 = true, +}; + static struct amba_id pl022_ids[] = { { /* -- cgit v1.2.3 From e41e399ab5554c467fcef0e603033eab426536e8 Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Fri, 9 Jul 2010 12:14:56 +0200 Subject: arm: allow passing an ELF64 header to elf_check_arch() Signed-off-by: Per Fransson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2732 Tested-by: Per FRANSSON Reviewed-by: Jonas ABERG Change-Id: I616a21ea86221d179fff1e87174aafa0eeee7f98 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/3181 Tested-by: Mian Yousaf KAUKAB Reviewed-by: Srinidhi KASAGAR Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Lee Jones --- arch/arm/include/asm/elf.h | 4 ++-- arch/arm/kernel/elf.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index 38050b1c480..cd644aade4c 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -96,8 +96,8 @@ struct elf32_hdr; /* * This is used to ensure we don't load something for the wrong architecture. */ -extern int elf_check_arch(const struct elf32_hdr *); -#define elf_check_arch elf_check_arch +extern int arm_elf_check_arch(const struct elf32_hdr *); +#define elf_check_arch(x) arm_elf_check_arch((const struct elf32_hdr *)(x)) #define vmcore_elf64_check_arch(x) (0) diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index d0d1e83150c..6602eae1527 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -5,11 +5,13 @@ #include #include -int elf_check_arch(const struct elf32_hdr *x) +int arm_elf_check_arch(const struct elf32_hdr *x) { unsigned int eflags; /* Make sure it's an ARM executable */ + if (x->e_ident[EI_CLASS] != ELF_CLASS) + return 0; if (x->e_machine != EM_ARM) return 0; @@ -36,7 +38,7 @@ int elf_check_arch(const struct elf32_hdr *x) } return 1; } -EXPORT_SYMBOL(elf_check_arch); +EXPORT_SYMBOL(arm_elf_check_arch); void elf_set_personality(const struct elf32_hdr *x) { -- cgit v1.2.3 From 72c8ed036da99fd4586227f0b4123ea81ab17fa4 Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Thu, 27 Jan 2011 14:08:16 +0100 Subject: mpcore_wdt: Stop watchdog of non-crashing cores When kexec'ing to u-boot only the crashing core is used (and will have to be kicked by u-boot). The watchdog of other core has to be stopped before leaving linux. ST-Ericsson ID: - Change-Id: I329630fd8040f8af3e54fc51aa7187217938f0b8 Signed-off-by: Per Fransson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/13678 Reviewed-by: QATOOLS Reviewed-by: Srinidhi KASAGAR Reviewed-by: Jonas ABERG Signed-off-by: Lee Jones --- arch/arm/kernel/machine_kexec.c | 1 + include/linux/kexec.h | 1 + kernel/kexec.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index dfcdb9f7c12..29b7f3c27b7 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -47,6 +47,7 @@ void machine_crash_nonpanic_core(void *unused) printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", smp_processor_id()); crash_save_cpu(®s, smp_processor_id()); + atomic_notifier_call_chain(&crash_percpu_notifier_list, 0, NULL); flush_cache_all(); atomic_dec(&waiting_for_crash_ipi); diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 0d7d6a1b172..ddeb2a9debe 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -170,6 +170,7 @@ unsigned long paddr_vmcoreinfo_note(void); extern struct kimage *kexec_image; extern struct kimage *kexec_crash_image; +extern struct atomic_notifier_head crash_percpu_notifier_list; #ifndef kexec_flush_icache_page #define kexec_flush_icache_page(page) diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6ae..6146beeeecc 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -48,6 +48,8 @@ u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; size_t vmcoreinfo_size; size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data); +ATOMIC_NOTIFIER_HEAD(crash_percpu_notifier_list); + /* Location of the reserved area for the crash kernel */ struct resource crashk_res = { .name = "Crash kernel", -- cgit v1.2.3 From c64437840cebe0078494bc84056b5e561752e746 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 10 Oct 2011 16:29:13 +0200 Subject: mfd: stmpe: Recheck the status to avoid failure stmpe: add stmpe documentation to DocBook Signed-off-by: Robert Marklund --- Documentation/DocBook/Makefile | 3 +- Documentation/DocBook/stmpe.tmpl | 119 +++++++++++++++++++++++++++++++++++++++ drivers/mfd/stmpe.c | 18 +++++- 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 Documentation/DocBook/stmpe.tmpl diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 66725a3d30d..3f118e4defb 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -14,7 +14,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ - tracepoint.xml drm.xml media_api.xml + tracepoint.xml drm.xml media_api.xml \ + stmpe.xml include $(srctree)/Documentation/DocBook/media/Makefile diff --git a/Documentation/DocBook/stmpe.tmpl b/Documentation/DocBook/stmpe.tmpl new file mode 100644 index 00000000000..6759149d6ce --- /dev/null +++ b/Documentation/DocBook/stmpe.tmpl @@ -0,0 +1,119 @@ + + + + + + STMPE IO-Port Expander guide + + + + Rabin + Vincent + +
+ rabin.vincent@stericsson.com +
+
+
+
+ + + 2010 + ST-Ericsson + + + + + Linux standard functions + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + + +
+ + + + + Introduction + + This documentation describes the driver for STMicroelectronics + STMPExxxx port expander devices. + + + + + Known Bugs And Assumptions + + + + None. + + + None. + + + + + + + + + Public Functions Provided + + List of public interfaces in stmpe driver + +!Edrivers/mfd/stmpe.c + + + + Private Functions + + STMPE Keypad driver + STMPE GPIO driver + +
+ stmpe-keypad.c +!Idrivers/input/keyboard/stmpe-keypad.c +
+
+ stmpe-gpio.c +!Idrivers/gpio/stmpe-gpio.c +
+
+ + + Other Data Structures + + This Section lists some of the Data structure used by the stmpe driver and client drivers. + +!Iinclude/linux/mfd/stmpe.h +!Idrivers/mfd/stmpe.h + +
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 2dd8d49cb30..6b8f9417c00 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -772,7 +772,7 @@ static irqreturn_t stmpe_irq(int irq, void *data) ret = stmpe_block_read(stmpe, israddr, num, isr); if (ret < 0) return IRQ_NONE; - +back: for (i = 0; i < num; i++) { int bank = num - i - 1; u8 status = isr[i]; @@ -794,6 +794,22 @@ static irqreturn_t stmpe_irq(int irq, void *data) stmpe_reg_write(stmpe, israddr + i, clear); } + /* + It may happen that on the first status read interrupt + sources may not showup, so read one more time. + */ + ret = stmpe_block_read(stmpe, israddr, num, isr); + if (ret >= 0) { + for (i = 0; i < num; i++) { + int bank = num - i - 1; + u8 status = isr[i]; + + status &= stmpe->ier[bank]; + if (status) + goto back; + } + } + return IRQ_HANDLED; } -- cgit v1.2.3 From 83f9cd3abfe1c8689453e2f8e5c39de91c3794d7 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Mar 2011 10:36:12 +0100 Subject: i2c: nomadic-i2c driver updates for clock and power, busy management Moreover driver documentation is added in DocBook Signed-off-by: Jonas Aaberg Signed-off-by: Mian Yousaf Kaukab --- Documentation/DocBook/i2c.tmpl | 116 +++++++++++++++++++++++++++++++++++++++ drivers/i2c/busses/i2c-nomadik.c | 6 ++ 2 files changed, 122 insertions(+) create mode 100644 Documentation/DocBook/i2c.tmpl diff --git a/Documentation/DocBook/i2c.tmpl b/Documentation/DocBook/i2c.tmpl new file mode 100644 index 00000000000..8a4cb49204e --- /dev/null +++ b/Documentation/DocBook/i2c.tmpl @@ -0,0 +1,116 @@ + + + + + + I2C + + + + Srinidhi + Kasagar + +
+ srinidhi.kasagar@stericsson.com +
+
+
+ + Sachin + Verma + +
+ sachin.verma@st.com +
+
+
+
+ + + 2009-2010 + ST-Ericsson + + + + + Linux standard functions + + + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + Introduction + + This Documentation describes the API's provided by the I2C controller Driver. + Since this driver registers the transferfunction with kernel framework, there + are only private functions in this I2C bus driver. This driver currently + works only in master mode and does 7 bit adderssing only. There is no support + for 10 bit addressing. The driver currently supports standard mode (100KHz) + and Fast mode (400KHz) operation. + + + + Known Bugs And Assumptions + + + + None + + + None. + + + + + + + + + Public Functions Provided + + Not Applicable + + + + + Private Functions + + This Section lists the functions used internally by the I2C controller driver. + +!Idrivers/i2c/busses/i2c-nomadik.c + + +
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5267ab93d55..486f392825f 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -267,6 +267,9 @@ static int init_hw(struct nmk_i2c_dev *dev) dev->cli.operation = I2C_NO_OPERATION; exit: + clk_disable(dev->clk); + + udelay(I2C_DELAY); return stat; } @@ -634,6 +637,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, clk_enable(dev->clk); + dev->busy = true; + status = init_hw(dev); if (status) goto out; @@ -1047,6 +1052,7 @@ static struct platform_driver nmk_i2c_driver = { }, .probe = nmk_i2c_probe, .remove = __devexit_p(nmk_i2c_remove), + .suspend = nmk_i2c_suspend, }; static int __init nmk_i2c_init(void) -- cgit v1.2.3 From 5f4a658578f924afbdfaf63a5c954f2e849892d9 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Mar 2011 10:39:49 +0100 Subject: nmk-i2c: use pm_runtime API Use the pm_runtime API for pins control. ST-Ericsson Linux next: - ST-Ericsson ID: ER323382 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib847143b96950c25221c6aa25dae541017840677 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16045 Tested-by: Rabin VINCENT Reviewed-by: Srinidhi KASAGAR Reviewed-by: Jonas ABERG --- drivers/i2c/busses/i2c-nomadik.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 486f392825f..482176eb647 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -253,6 +253,8 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; + clk_enable(dev->clk); + stat = flush_i2c_fifo(dev); if (stat) goto exit; @@ -433,9 +435,10 @@ static int read_i2c(struct nmk_i2c_dev *dev) } if (timeout == 0) { - /* Controller timed out */ - dev_err(&dev->pdev->dev, "read from slave 0x%x timed out\n", + /* controller has timedout, re-init the h/w */ + dev_err(&dev->pdev->dev, "Read from Slave 0x%x timed out\n", dev->cli.slave_adr); + (void) init_hw(dev); status = -ETIMEDOUT; } return status; @@ -520,9 +523,10 @@ static int write_i2c(struct nmk_i2c_dev *dev) } if (timeout == 0) { - /* Controller timed out */ - dev_err(&dev->pdev->dev, "write to slave 0x%x timed out\n", + /* controller has timedout, re-init the h/w */ + dev_err(&dev->pdev->dev, "Write to slave 0x%x timed out\n", dev->cli.slave_adr); + (void) init_hw(dev); status = -ETIMEDOUT; } -- cgit v1.2.3 From bad7ddf6881888194989b625dcafbcf8ed4651ea Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Mar 2011 11:31:20 +0100 Subject: i2c-nomadik: Add code to retry on timeout failure and set i2c clock to 400KHz It is seen that i2c-nomadik controller randomly stops generating the interrupts leading to a i2c timeout. As a workaround to this problem add retries, to the on going transfer on failure. Since this behaviour does not get changed with a wait for longer duration, the timeout can be reduced to a lower value, leading to a quicker retry attempt. ST-Ericsson ID: ER 325661 Signed-off-by: Virupax Sadashivpetimath Change-Id: Ic9db2b15ff5ce7e656cbbdfeb19270da9e32f9d1 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16972 Tested-by: Virupax SADASHIVPETIMATH Reviewed-by: Jonas ABERG --- drivers/i2c/busses/i2c-nomadik.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 482176eb647..f108c77d50d 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -253,8 +253,6 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; - clk_enable(dev->clk); - stat = flush_i2c_fifo(dev); if (stat) goto exit; @@ -269,8 +267,6 @@ static int init_hw(struct nmk_i2c_dev *dev) dev->cli.operation = I2C_NO_OPERATION; exit: - clk_disable(dev->clk); - udelay(I2C_DELAY); return stat; } -- cgit v1.2.3 From 93bbe4dbd7974a9d4c85314afc5a6138cc607032 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Mar 2011 10:39:49 +0100 Subject: nmk-i2c: use pm_runtime API Use the pm_runtime API for pins control. ST-Ericsson Linux next: - ST-Ericsson ID: ER323382 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib847143b96950c25221c6aa25dae541017840677 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16045 Tested-by: Rabin VINCENT Reviewed-by: Srinidhi KASAGAR Reviewed-by: Jonas ABERG --- drivers/i2c/busses/i2c-nomadik.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index f108c77d50d..b7b89aa3a32 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -253,6 +253,8 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; + clk_enable(dev->clk); + stat = flush_i2c_fifo(dev); if (stat) goto exit; -- cgit v1.2.3 From c8e4b64a1fa7ecf95ca472ff76137823100ff950 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Mar 2011 11:31:20 +0100 Subject: i2c-nomadik: Add code to retry on timeout failure and set i2c clock to 400KHz It is seen that i2c-nomadik controller randomly stops generating the interrupts leading to a i2c timeout. As a workaround to this problem add retries, to the on going transfer on failure. Since this behaviour does not get changed with a wait for longer duration, the timeout can be reduced to a lower value, leading to a quicker retry attempt. ST-Ericsson ID: ER 325661 Signed-off-by: Virupax Sadashivpetimath Change-Id: Ic9db2b15ff5ce7e656cbbdfeb19270da9e32f9d1 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16972 Tested-by: Virupax SADASHIVPETIMATH Reviewed-by: Jonas ABERG --- drivers/i2c/busses/i2c-nomadik.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index b7b89aa3a32..f108c77d50d 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -253,8 +253,6 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; - clk_enable(dev->clk); - stat = flush_i2c_fifo(dev); if (stat) goto exit; -- cgit v1.2.3 From a40a7633f7506d32bdced4181e545a4dc364833a Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 23 Mar 2011 15:47:22 +0100 Subject: backlight/leds: add low threshold to pwm backlight/led The intensity of the backlight/led can be varied from a range of max_brightness to zero. Though most, if not all the pwm based backlight/led devices start flickering at lower brightness value. And also for each device there exists a brightness value below which the backlight appears to be turned off though the value is not equal to zero. If the range of brightness for a device is from zero to max_brightness. A graph is plotted for brightness Vs intensity fo the pwm based backlight/led device has to be a linear graph. intensity | / | / | / |/ --------- 0 max_brightness But pratically on measuring the above we note that the intensity of backlight/led goes to zero(OFF) when the value in not zero almost nearing to zero(some x%). so the graph looks like intensity | / | / | / | | ------------ 0 x max_brightness In order to overcome this drawback knowing this x% i.e nothing but the low threshold beyond which the backlight/led is off and will have no effect, the brightness value is being offset by the low threshold value(retaining the linearity of the graph). Now the graph becomes intensity | / | / | / | / ------------- 0 max_brightness With this for each and every digit increment in the brightness from zero there is a change in the intensity of backlight/led. Devices having this behaviour can set the low threshold brightness(lth_brightness) and pass the same as platform data else can have it as zero. ST-Ericsson ID: Task168737 Change-Id: I7198ec89aa69e0c687d329b21f723fd8d5368928 Signed-off-by: Prajadevi H Signed-off-by: Arun Murthy Acked-by: Linus Walleij Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/5231 Reviewed-by: Linus WALLEIJ --- drivers/leds/leds-pwm.c | 8 +++++++- include/linux/leds_pwm.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 3ed92f34bd4..4d086e87bc1 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -27,6 +27,7 @@ struct led_pwm_data { struct led_classdev cdev; struct pwm_device *pwm; unsigned int active_low; + unsigned int lth_brightness; unsigned int period; }; @@ -42,7 +43,10 @@ static void led_pwm_set(struct led_classdev *led_cdev, pwm_config(led_dat->pwm, 0, period); pwm_disable(led_dat->pwm); } else { - pwm_config(led_dat->pwm, brightness * period / max, period); + brightness = led_dat->lth_brightness + (brightness * + (led_dat->period - led_dat->lth_brightness) / max); + pwm_config(led_dat->pwm, brightness, led_dat->period); + pwm_enable(led_dat->pwm); } } @@ -79,6 +83,8 @@ static int led_pwm_probe(struct platform_device *pdev) led_dat->cdev.default_trigger = cur_led->default_trigger; led_dat->active_low = cur_led->active_low; led_dat->period = cur_led->pwm_period_ns; + led_dat->lth_brightness = cur_led->lth_brightness * + (cur_led->pwm_period_ns / cur_led->max_brightness); led_dat->cdev.brightness_set = led_pwm_set; led_dat->cdev.brightness = LED_OFF; led_dat->cdev.max_brightness = cur_led->max_brightness; diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h index 33a07116748..9c5eab6e086 100644 --- a/include/linux/leds_pwm.h +++ b/include/linux/leds_pwm.h @@ -11,6 +11,7 @@ struct led_pwm { u8 active_low; unsigned max_brightness; unsigned pwm_period_ns; + unsigned int lth_brightness; }; struct led_pwm_platform_data { -- cgit v1.2.3 From 963d6f04d0ca72c3cfe5c6340d453317555f1b07 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 09:09:06 +0200 Subject: abx500: big merge from GLK 2.6.35 Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/include/mach/ab8500_gpadc.h | 36 ++ drivers/hwmon/Kconfig | 26 + drivers/hwmon/Makefile | 2 + drivers/hwmon/ab8500.c | 715 ++++++++++++++++++++++++ drivers/hwmon/db8500.c | 403 +++++++++++++ drivers/mfd/Kconfig | 26 +- drivers/mfd/Makefile | 2 + drivers/mfd/ab8500-core.c | 3 + drivers/mfd/ab8500-debugfs.c | 230 +++++++- drivers/mfd/ab8500-denc.c | 515 +++++++++++++++++ drivers/mfd/ab8500-gpadc.c | 12 +- drivers/mfd/ab8500-sysctrl.c | 22 + drivers/misc/ab8500-pwm.c | 45 +- include/linux/mfd/ab8500/denc-regs.h | 357 ++++++++++++ include/linux/mfd/ab8500/denc.h | 82 +++ include/linux/mfd/abx500/ab8500.h | 20 +- 16 files changed, 2479 insertions(+), 17 deletions(-) create mode 100644 arch/arm/mach-ux500/include/mach/ab8500_gpadc.h create mode 100644 drivers/hwmon/ab8500.c create mode 100755 drivers/hwmon/db8500.c create mode 100644 drivers/mfd/ab8500-denc.c create mode 100644 include/linux/mfd/ab8500/denc-regs.h create mode 100644 include/linux/mfd/ab8500/denc.h diff --git a/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h b/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h new file mode 100644 index 00000000000..4289dcfc0aa --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h @@ -0,0 +1,36 @@ +/* + * ab8500_gpadc.c - AB8500 GPADC Driver + * + * Copyright (C) 2010 ST-Ericsson SA + * Licensed under GPLv2. + * + * Author: Arun R Murthy + */ + +#ifndef _AB8500_GPADC_H +#define _Ab8500_GPADC_H + +/* GPADC source: From datasheer(ADCSwSel[4:0] in GPADCCtrl2) */ +#define BAT_CTRL 0x01 +#define ACC_DETECT1 0x04 +#define ACC_DETECT2 0x05 +#define MAIN_BAT_V 0x08 +#define BK_BAT_V 0x0C +#define VBUS_V 0x09 +#define MAIN_CHARGER_V 0x03 +#define MAIN_CHARGER_C 0x0A +#define USB_CHARGER_C 0x0B +#define DIE_TEMP 0x0D +#define BTEMP_BALL 0x02 + +struct ab8500_gpadc_device_info { + struct completion ab8500_gpadc_complete; + struct mutex ab8500_gpadc_lock; +#if defined(CONFIG_REGULATOR) + struct regulator *regu; +#endif +}; + +int ab8500_gpadc_conversion(int input); + +#endif /* _AB8500_GPADC_H */ diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 8deedc1b984..95a4a2f878b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -39,6 +39,32 @@ config HWMON_DEBUG_CHIP comment "Native drivers" +config SENSORS_AB8500 + tristate "AB8500 thermal monitoring" + depends on AB8500_CORE + default n + help + If you say yes here you get support for the thermal sensor part + of the AB8500 chip. The driver includes thermal management for + AB8500 die and two GPADC channels. The GPADC channel are preferably + used to access sensors outside the AB8500 chip. + + This driver can also be built as a module. If so, the module + will be called ab8500-temp. + +config SENSORS_DB8500 + tristate "DB8500 thermal monitoring" + depends on UX500_SOC_DB8500 + default n + help + If you say yes here you get support for the thermal sensor part + of the DB8500 chip. The driver includes thermal management for + DB8500 die. + + This driver can also be built as a module. If so, the module + will be called db8500_temp. + + config SENSORS_ABITUGURU tristate "Abit uGuru (rev 1 & 2)" depends on X86 && DMI && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6d3f11f7181..6d6bf2564e6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -19,6 +19,8 @@ obj-$(CONFIG_SENSORS_W83795) += w83795.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o +obj-$(CONFIG_SENSORS_AB8500) += ab8500.o +obj-$(CONFIG_SENSORS_DB8500) += db8500.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o obj-$(CONFIG_SENSORS_AD7314) += ad7314.o diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c new file mode 100644 index 00000000000..cdec2c5712d --- /dev/null +++ b/drivers/hwmon/ab8500.c @@ -0,0 +1,715 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Martin Persson for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + * Note: + * + * AB8500 does not provide auto ADC, so to monitor the required + * temperatures, a periodic work is used. It is more important + * to not wake up the CPU than to perform this job, hence the use + * of a deferred delay. + * + * A deferred delay for thermal monitor is considered safe because: + * If the chip gets too hot during a sleep state it's most likely + * due to external factors, such as the surrounding temperature. + * I.e. no SW decisions will make any difference. + * + * If/when the AB8500 thermal warning temperature is reached (threshold + * cannot be changed by SW), an interrupt is set and the driver + * notifies user space via a sysfs event. If a shut down is not + * triggered by user space within a certain time frame, + * pm_power off is called. + * + * If/when AB8500 thermal shutdown temperature is reached a hardware + * shutdown of the AB8500 will occur. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * If AB8500 warm interrupt is set, user space will be notified. + * If user space doesn't shut down the platform within this time + * frame, this driver will. Time unit is ms. + */ +#define DEFAULT_POWER_OFF_DELAY 10000 + +#define NUM_SENSORS 4 + +/* The driver monitors GPADC - ADC_AUX1 and ADC_AUX2 */ +#define NUM_MONITORED_SENSORS 2 + +struct ab8500_temp { + struct platform_device *pdev; + struct device *hwmon_dev; + struct ab8500_gpadc *gpadc; + u8 gpadc_addr[NUM_SENSORS]; + unsigned long min[NUM_SENSORS]; + unsigned long max[NUM_SENSORS]; + unsigned long max_hyst[NUM_SENSORS]; + unsigned long crit[NUM_SENSORS]; + unsigned long min_alarm[NUM_SENSORS]; + unsigned long max_alarm[NUM_SENSORS]; + unsigned long max_hyst_alarm[NUM_SENSORS]; + unsigned long crit_alarm[NUM_SENSORS]; + struct delayed_work work; + struct delayed_work power_off_work; + struct mutex lock; + /* Delay (ms) between temperature readings */ + unsigned long gpadc_monitor_delay; + /* Delay (ms) before power off */ + unsigned long power_off_delay; +}; + +/* + * Thresholds are considered inactive if set to 0. + * To avoid confusion for user space applications, + * the temp monitor delay is set to 0 if all thresholds + * are 0. + */ +static bool find_active_thresholds(struct ab8500_temp *data) +{ + int i; + for (i = 0; i < NUM_MONITORED_SENSORS; i++) + if (data->max[i] != 0 || data->max_hyst[i] != 0 + || data->min[i] != 0) + return true; + + dev_dbg(&data->pdev->dev, "No active thresholds," + "cancel deferred job (if it exists)" + "and reset temp monitor delay\n"); + mutex_lock(&data->lock); + data->gpadc_monitor_delay = 0; + cancel_delayed_work_sync(&data->work); + mutex_unlock(&data->lock); + return false; +} + +static void thermal_power_off(struct work_struct *work) +{ + struct ab8500_temp *data = container_of(work, struct ab8500_temp, + power_off_work.work); + + dev_warn(&data->pdev->dev, "Power off due to AB8500 thermal warning\n"); + pm_power_off(); +} + +static void gpadc_monitor(struct work_struct *work) +{ + unsigned long delay_in_jiffies; + int val, i, ret; + /* Container for alarm node name */ + char alarm_node[30]; + + bool updated_min_alarm = false; + bool updated_max_alarm = false; + bool updated_max_hyst_alarm = false; + struct ab8500_temp *data = container_of(work, struct ab8500_temp, + work.work); + + for (i = 0; i < NUM_MONITORED_SENSORS; i++) { + /* Thresholds are considered inactive if set to 0 */ + if (data->max[i] == 0 && data->max_hyst[i] == 0 + && data->min[i] == 0) + continue; + + val = ab8500_gpadc_convert(data->gpadc, data->gpadc_addr[i]); + if (val < 0) { + dev_err(&data->pdev->dev, "GPADC read failed\n"); + continue; + } + + mutex_lock(&data->lock); + if (data->min[i] != 0) { + if (val < data->min[i]) { + if (data->min_alarm[i] == 0) { + data->min_alarm[i] = 1; + updated_min_alarm = true; + } + } else { + if (data->min_alarm[i] == 1) { + data->min_alarm[i] = 0; + updated_min_alarm = true; + } + } + + } + if (data->max[i] != 0) { + if (val > data->max[i]) { + if (data->max_alarm[i] == 0) { + data->max_alarm[i] = 1; + updated_max_alarm = true; + } + } else { + if (data->max_alarm[i] == 1) { + data->max_alarm[i] = 0; + updated_max_alarm = true; + } + } + + } + if (data->max_hyst[i] != 0) { + if (val > data->max_hyst[i]) { + if (data->max_hyst_alarm[i] == 0) { + data->max_hyst_alarm[i] = 1; + updated_max_hyst_alarm = true; + } + } else { + if (data->max_hyst_alarm[i] == 1) { + data->max_hyst_alarm[i] = 0; + updated_max_hyst_alarm = true; + } + } + } + mutex_unlock(&data->lock); + + /* hwmon attr index starts at 1, thus "i+1" below */ + if (updated_min_alarm) { + ret = snprintf(alarm_node, 16, "temp%d_min_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + if (updated_max_alarm) { + ret = snprintf(alarm_node, 16, "temp%d_max_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + if (updated_max_hyst_alarm) { + ret = snprintf(alarm_node, 21, "temp%d_max_hyst_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + } + delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); + schedule_delayed_work(&data->work, delay_in_jiffies); +} + +static inline void gpadc_monitor_exit(struct platform_device *pdev) +{ + struct ab8500_temp *data = platform_get_drvdata(pdev); + cancel_delayed_work_sync(&data->work); +} + +static ssize_t set_temp_monitor_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_jiffies, delay_in_s; + struct ab8500_temp *data = dev_get_drvdata(dev); + + if (!find_active_thresholds(data)) { + dev_dbg(dev, "No thresholds to monitor, disregarding delay\n"); + return count; + } + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->gpadc_monitor_delay = delay_in_s * 1000; + mutex_unlock(&data->lock); + delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); + schedule_delayed_work(&data->work, delay_in_jiffies); + + return count; +} + +static ssize_t set_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_jiffies, delay_in_s; + struct ab8500_temp *data = dev_get_drvdata(dev); + + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->power_off_delay = delay_in_s * 1000; + mutex_unlock(&data->lock); + delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); + + return count; +} + +static ssize_t show_temp_monitor_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->gpadc_monitor_delay) / 1000); +} + +static ssize_t show_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); +} + +/* HWMON sysfs interface */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + /* + * To avoid confusion between sensor label and chip name, the function + * "show_label" is not used to return the chip name. + */ + return sprintf(buf, "ab8500\n"); +} + +static ssize_t show_label(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + char *name; + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = attr->index; + + /* + * Make sure these labels correspond to the attribute indexes + * used when calling SENSOR_DEVICE_ATRR. + * Temperature sensors outside ab8500 (read via GPADC) are marked + * with prefix ext_ + */ + switch (index) { + case 1: + name = "ext_rtc_xtal"; + break; + case 2: + name = "ext_db8500"; + break; + case 3: + name = "battery"; + break; + case 4: + name = "ab8500"; + break; + default: + return -EINVAL; + } + return sprintf(buf, "%s\n", name); +} + +static ssize_t show_input(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int val; + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + u8 gpadc_addr = data->gpadc_addr[attr->index - 1]; + + val = ab8500_gpadc_convert(data->gpadc, gpadc_addr); + if (val < 0) + dev_err(&data->pdev->dev, "GPADC read failed\n"); + + return sprintf(buf, "%d\n", val); +} + +/* set functions (RW nodes) */ +static ssize_t set_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->min_alarm[attr->index - 1] = 0; + + data->min[attr->index - 1] = val; + mutex_unlock(&data->lock); + if (val == 0) + (void) find_active_thresholds(data); + + return count; +} + +static ssize_t set_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->max_alarm[attr->index - 1] = 0; + + data->max[attr->index - 1] = val; + mutex_unlock(&data->lock); + if (val == 0) + (void) find_active_thresholds(data); + + return count; +} + +static ssize_t set_max_hyst(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->max_hyst_alarm[attr->index - 1] = 0; + + data->max_hyst[attr->index - 1] = val; + mutex_unlock(&data->lock); + if (val == 0) + (void) find_active_thresholds(data); + + return count; +} + +/* + * show functions (RO nodes) + * Notice that min/max/max_hyst refer to millivolts and not millidegrees + */ +static ssize_t show_min(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->min[attr->index - 1]); +} + +static ssize_t show_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max[attr->index - 1]); +} + +static ssize_t show_max_hyst(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_hyst[attr->index - 1]); +} + +/* Alarms */ +static ssize_t show_min_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->min_alarm[attr->index - 1]); +} + +static ssize_t show_max_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_alarm[attr->index - 1]); +} + +static ssize_t show_max_hyst_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_hyst_alarm[attr->index - 1]); +} + +static ssize_t show_crit_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct ab8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->crit_alarm[attr->index - 1]); +} + +/*These node are not included in the kernel hwmon sysfs interface */ +static SENSOR_DEVICE_ATTR(temp_monitor_delay, S_IRUGO | S_IWUSR, + show_temp_monitor_delay, set_temp_monitor_delay, 0); +static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, + show_temp_power_off_delay, + set_temp_power_off_delay, 0); + +/* Chip name, required by hwmon*/ +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +/* GPADC - ADC_AUX1 */ +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 1); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 1); + +/* GPADC - ADC_AUX2 */ +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, 2); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, 2); +static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 2); +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_min_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_max_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 2); + +/* GPADC - BTEMP_BALL */ +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 3); + +/* AB8500 */ +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, + show_crit_alarm, NULL, 4); + +static struct attribute *ab8500_temp_attributes[] = { + &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, + &sensor_dev_attr_temp_monitor_delay.dev_attr.attr, + &sensor_dev_attr_name.dev_attr.attr, + /* GPADC - ADC_AUX1 */ + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst_alarm.dev_attr.attr, + /* GPADC - ADC_AUX2 */ + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst_alarm.dev_attr.attr, + /* GPADC - BTEMP_BALL */ + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + /* AB8500 */ + &sensor_dev_attr_temp4_label.dev_attr.attr, + &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group ab8500_temp_group = { + .attrs = ab8500_temp_attributes, +}; + +static irqreturn_t ab8500_temp_irq_handler(int irq, void *irq_data) +{ + unsigned long delay_in_jiffies; + struct platform_device *pdev = irq_data; + struct ab8500_temp *data = platform_get_drvdata(pdev); + + /* + * Make sure the magic numbers below corresponds to the node + * used for AB8500 thermal warning from HW. + */ + mutex_lock(&data->lock); + data->crit_alarm[3] = 1; + mutex_unlock(&data->lock); + sysfs_notify(&pdev->dev.kobj, NULL, "temp4_crit_alarm"); + dev_info(&pdev->dev, "AB8500 thermal warning, power off in %lu s\n", + data->power_off_delay); + delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); + schedule_delayed_work(&data->power_off_work, delay_in_jiffies); + return IRQ_HANDLED; +} + +static int setup_irqs(struct platform_device *pdev) +{ + int ret; + int irq = platform_get_irq_byname(pdev, "AB8500_TEMP_WARM"); + + if (irq < 0) + dev_err(&pdev->dev, "Get irq by name failed\n"); + + ret = request_threaded_irq(irq, NULL, ab8500_temp_irq_handler, + IRQF_NO_SUSPEND, "ab8500-temp", pdev); + if (ret < 0) + dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); + + return ret; +} + +static int __devinit ab8500_temp_probe(struct platform_device *pdev) +{ + struct ab8500_temp *data; + int err; + + data = kzalloc(sizeof(struct ab8500_temp), GFP_KERNEL); + if (!data) + return -ENOMEM; + + err = setup_irqs(pdev); + if (err < 0) + goto exit; + + data->gpadc = ab8500_gpadc_get(); + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + dev_err(&pdev->dev, "Class registration failed (%d)\n", err); + goto exit; + } + + INIT_DELAYED_WORK_DEFERRABLE(&data->work, gpadc_monitor); + INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); + + /* + * Setup HW defined data. + * + * Reference hardware (HREF): + * + * GPADC - ADC_AUX1, connected to NTC R2148 next to RTC_XTAL on HREF + * GPADC - ADC_AUX2, connected to NTC R2150 near DB8500 on HREF + * Hence, temp#_min/max/max_hyst refer to millivolts and not + * millidegrees + * + * HREF HW does not support reading AB8500 temperature. BUT an + * AB8500 IRQ will be launched if die crit temp limit is reached. + * + * Also: + * Battery temperature thresholds will not be exposed via hwmon. + * + * Make sure indexes correspond to the attribute indexes + * used when calling SENSOR_DEVICE_ATRR + */ + data->gpadc_addr[0] = ADC_AUX1; + data->gpadc_addr[1] = ADC_AUX2; + data->gpadc_addr[2] = BTEMP_BALL; + + mutex_init(&data->lock); + data->pdev = pdev; + data->power_off_delay = DEFAULT_POWER_OFF_DELAY; + + platform_set_drvdata(pdev, data); + + err = sysfs_create_group(&pdev->dev.kobj, &ab8500_temp_group); + if (err < 0) { + dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); + goto exit_platform_data; + } + + return 0; + +exit_platform_data: + platform_set_drvdata(pdev, NULL); +exit: + kfree(data); + return err; +} + +static int __devexit ab8500_temp_remove(struct platform_device *pdev) +{ + struct ab8500_temp *data = platform_get_drvdata(pdev); + + gpadc_monitor_exit(pdev); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &ab8500_temp_group); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +/* No action required in suspend/resume, thus the lack of functions */ +static struct platform_driver ab8500_temp_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ab8500-temp", + }, + .probe = ab8500_temp_probe, + .remove = __devexit_p(ab8500_temp_remove), +}; + +static int __init ab8500_temp_init(void) +{ + return platform_driver_register(&ab8500_temp_driver); +} + +static void __exit ab8500_temp_exit(void) +{ + platform_driver_unregister(&ab8500_temp_driver); +} + +MODULE_AUTHOR("Martin Persson "); +MODULE_DESCRIPTION("AB8500 temperature driver"); +MODULE_LICENSE("GPL"); + +module_init(ab8500_temp_init) +module_exit(ab8500_temp_exit) diff --git a/drivers/hwmon/db8500.c b/drivers/hwmon/db8500.c new file mode 100755 index 00000000000..09630f2f707 --- /dev/null +++ b/drivers/hwmon/db8500.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + * + * Author: WenHai Fang for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * If DB8500 warm interrupt is set, user space will be notified. + * If user space doesn't shut down the platform within this time + * frame, this driver will. Time unit is ms. + */ +#define DEFAULT_POWER_OFF_DELAY 10000 + +/* + * Default measure period to 0xFF x cycle32k + */ +#define DEFAULT_MEASURE_TIME 0xFF + +/* This driver monitors DB thermal*/ +#define NUM_SENSORS 1 + +struct db8500_temp { + struct platform_device *pdev; + struct device *hwmon_dev; + unsigned char min[NUM_SENSORS]; + unsigned char max[NUM_SENSORS]; + unsigned char crit[NUM_SENSORS]; + unsigned short measure_time; + struct delayed_work power_off_work; + struct mutex lock; + /* Delay (ms) before power off */ + unsigned long power_off_delay; +}; + +static void thermal_power_off(struct work_struct *work) +{ + struct db8500_temp *data = container_of(work, struct db8500_temp, + power_off_work.work); + + dev_warn(&data->pdev->dev, "Power off due to DB8500 thermal warning\n"); + pm_power_off(); +} + +static ssize_t set_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_s; + struct db8500_temp *data = dev_get_drvdata(dev); + + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) { + dev_warn(&data->pdev->dev, "Set power_off_delay wrong\n"); + return res; + } + + mutex_lock(&data->lock); + data->power_off_delay = delay_in_s * 1000; + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); +} + +/* HWMON sysfs interface */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "db8500\n"); +} + +/* set functions (RW nodes) */ +static ssize_t set_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val &= 0xFF; + if (val > data->max[attr->index - 1]) + val = data->max[attr->index - 1]; + + data->min[attr->index - 1] = val; + + (void)prcmu_config_hotmon(data->min[attr->index - 1], + data->max[attr->index - 1]); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t set_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val &= 0xFF; + if (val < data->min[attr->index - 1]) + val = data->min[attr->index - 1]; + + data->max[attr->index - 1] = val; + + (void)prcmu_config_hotmon(data->min[attr->index - 1], + data->max[attr->index - 1]); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_crit(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val = (val > 255) ? 0xFF : val; + + data->crit[attr->index - 1] = val; + (void)prcmu_config_hotdog(data->crit[attr->index - 1]); + mutex_unlock(&data->lock); + + return count; +} + +/* set functions (W nodes) */ +static ssize_t start_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct db8500_temp *data = dev_get_drvdata(dev); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->measure_time = val & 0xFFFF; + mutex_unlock(&data->lock); + + (void)prcmu_start_temp_sense(data->measure_time); + dev_dbg(&data->pdev->dev, "DB8500 thermal start measurement\n"); + return count; +} + +static ssize_t stop_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct db8500_temp *data = dev_get_drvdata(dev); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + (void)prcmu_stop_temp_sense(); + dev_dbg(&data->pdev->dev, "DB8500 thermal stop measurement\n"); + + return count; +} + +/* + * show functions (RO nodes) + * Notice that min/max/max_hyst refer to millivolts and not millidegrees + */ +static ssize_t show_min(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->min[attr->index - 1]); +} + +static ssize_t show_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->max[attr->index - 1]); +} + +static ssize_t show_crit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->crit[attr->index - 1]); +} + + +/*These node are not included in the kernel hwmon sysfs interface */ +static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, + show_temp_power_off_delay, + set_temp_power_off_delay, 0); + +/* Chip name, required by hwmon*/ +static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 0); +static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 0); +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, + show_crit, set_crit, 1); + +static struct attribute *db8500_temp_attributes[] = { + &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, + &sensor_dev_attr_name.dev_attr.attr, + &sensor_dev_attr_temp1_start.dev_attr.attr, + &sensor_dev_attr_temp1_stop.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + NULL +}; + +static const struct attribute_group db8500_temp_group = { + .attrs = db8500_temp_attributes, +}; + +static irqreturn_t prcmu_hotmon_low_irq_handler(int irq, void *irq_data) +{ + struct platform_device *pdev = irq_data; + sysfs_notify(&pdev->dev.kobj, NULL, "prcmu_hotmon_low alarm"); + dev_dbg(&pdev->dev, "DB8500 thermal low warning\n"); + return IRQ_HANDLED; +} + +static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) +{ + unsigned long delay_in_jiffies; + struct platform_device *pdev = irq_data; + struct db8500_temp *data = platform_get_drvdata(pdev); + + sysfs_notify(&pdev->dev.kobj, NULL, "prcmu_hotmon_high alarm"); + dev_dbg(&pdev->dev, "DB8500 thermal warning, power off in %lu s\n", + (data->power_off_delay) / 1000); + delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); + schedule_delayed_work(&data->power_off_work, delay_in_jiffies); + return IRQ_HANDLED; +} + +static int __devinit db8500_temp_probe(struct platform_device *pdev) +{ + struct db8500_temp *data; + int err = 0, i; + int irq; + + dev_dbg(&pdev->dev, "db8500_temp: Function db8500_temp_probe.\n"); + + data = kzalloc(sizeof(struct db8500_temp), GFP_KERNEL); + if (!data) + return -ENOMEM; + + irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW"); + if (irq < 0) { + dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed\n"); + goto exit; + } + + err = request_threaded_irq(irq, NULL, prcmu_hotmon_low_irq_handler, + IRQF_NO_SUSPEND, "db8500_temp_low", pdev); + if (err < 0) { + dev_err(&pdev->dev, "db8500: Failed allocate HOTMON_LOW.\n"); + goto exit; + } else { + dev_dbg(&pdev->dev, "db8500: Succeed allocate HOTMON_LOW.\n"); + } + + irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH"); + if (irq < 0) { + dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed\n"); + goto exit; + } + + err = request_threaded_irq(irq, NULL, prcmu_hotmon_high_irq_handler, + IRQF_NO_SUSPEND, "db8500_temp_high", pdev); + if (err < 0) { + dev_err(&pdev->dev, "db8500: Failed allocate HOTMON_HIGH.\n"); + goto exit; + } else { + dev_dbg(&pdev->dev, "db8500: Succeed allocate HOTMON_HIGH.\n"); + } + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + dev_err(&pdev->dev, "Class registration failed (%d)\n", err); + goto exit; + } + + for (i = 0; i < NUM_SENSORS; i++) { + data->min[i] = 0; + data->max[i] = 0xFF; + } + + mutex_init(&data->lock); + INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); + + data->pdev = pdev; + data->power_off_delay = DEFAULT_POWER_OFF_DELAY; + data->measure_time = DEFAULT_MEASURE_TIME; + + platform_set_drvdata(pdev, data); + + err = sysfs_create_group(&pdev->dev.kobj, &db8500_temp_group); + if (err < 0) { + dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); + goto exit_platform_data; + } + + return 0; + +exit_platform_data: + platform_set_drvdata(pdev, NULL); +exit: + kfree(data); + return err; +} + +static int __devexit db8500_temp_remove(struct platform_device *pdev) +{ + struct db8500_temp *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &db8500_temp_group); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +/* No action required in suspend/resume, thus the lack of functions */ +static struct platform_driver db8500_temp_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "db8500_temp", + }, + .probe = db8500_temp_probe, + .remove = __devexit_p(db8500_temp_remove), +}; + +static int __init db8500_temp_init(void) +{ + return platform_driver_register(&db8500_temp_driver); +} + +static void __exit db8500_temp_exit(void) +{ + platform_driver_unregister(&db8500_temp_driver); +} + +MODULE_AUTHOR("WenHai Fang "); +MODULE_DESCRIPTION("DB8500 temperature driver"); +MODULE_LICENSE("GPL"); + +module_init(db8500_temp_init) +module_exit(db8500_temp_exit) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 11e44386fa9..92155341493 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -359,6 +359,20 @@ config MFD_TC6393XB help Support for Toshiba Mobile IO Controller TC6393XB +config AB5500_CORE + bool "ST-Ericsson AB5500 Mixed Signal Circuit core functions" + select MFD_CORE + depends on GENERIC_HARDIRQS && ABX500_CORE + help + Select this to enable the AB5500 Mixed Signal IC core + functionality. This connects to a AB5500 chip on the I2C bus via + the Power and Reset Management Unit (PRCMU). It exposes a number + of symbols needed for dependent devices to read and write + registers and subscribe to events from this multi-functional IC. + This is needed to use other features of the AB5500 such as + battery-backed RTC, charging control, Regulators, LEDs, vibrator, + system power and temperature, power management and ALSA sound. + config PMIC_DA903X bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" depends on I2C=y @@ -686,6 +700,14 @@ config AB8500_I2C_CORE the I2C bus is connected to the Power Reset and Mangagement Unit, PRCMU. +config AB8500_DENC + bool "AB8500_DENC driver support(CVBS)" + depends on AB8500_CORE + help + Select this option to add driver support for analog TV out through + AB8500. + + config AB8500_DEBUG bool "Enable debug info via debugfs" depends on AB8500_CORE && DEBUG_FS @@ -696,10 +718,10 @@ config AB8500_DEBUG config AB8500_GPADC bool "AB8500 GPADC driver" - depends on AB8500_CORE && REGULATOR_AB8500 + depends on AB8500_CORE default y help - AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage + AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage. config MFD_DB8500_PRCMU bool "ST-Ericsson DB8500 Power Reset Control Management Unit" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 05fa538c5ef..2d4adfd0ee7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -2,6 +2,7 @@ # Makefile for multifunction miscellaneous devices # +obj-$(CONFIG_AB5500_CORE) += ab5500-core.o 88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o obj-$(CONFIG_MFD_SM501) += sm501.o @@ -91,6 +92,7 @@ obj-$(CONFIG_AB5500_CORE) += ab5500-core.o obj-$(CONFIG_AB5500_DEBUG) += ab5500-debugfs.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o +obj-$(CONFIG_AB8500_DENC) += ab8500-denc.o obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-i2c need to come after db8500-prcmu (which provides the channel) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 1f08704f7ae..35114f86a9e 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -767,6 +767,9 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { { .name = "ab8500-regulator", }, + { + .name = "ab8500-regulator-debug", + }, { .name = "ab8500-gpadc", .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 9a0211aa889..7b051c820d3 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include #include @@ -18,6 +21,13 @@ static u32 debug_bank; static u32 debug_address; +static int irq_first; +static int irq_last; +static u32 irq_count[AB8500_NR_IRQS]; + +static struct device_attribute *dev_attr[AB8500_NR_IRQS]; +static char *event_name[AB8500_NR_IRQS]; + /** * struct ab8500_reg_range * @first: the first address of the range @@ -50,7 +60,7 @@ struct ab8500_i2c_ranges { static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { [0x0] = { .num_ranges = 0, - .range = 0, + .range = NULL, }, [AB8500_SYS_CTRL1_BLOCK] = { .num_ranges = 3, @@ -354,6 +364,24 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { }, }; +static irqreturn_t ab8500_debug_handler(int irq, void *data) +{ + char buf[16]; + struct kobject *kobj = (struct kobject *)data; + unsigned int irq_abb = irq - irq_first; + + if (irq_abb < AB8500_NR_IRQS) + irq_count[irq_abb]++; + /* + * This makes it possible to use poll for events (POLLPRI | POLLERR) + * from userspace on sysfs file named + */ + sprintf(buf, "%d", irq); + sysfs_notify(kobj, NULL, buf); + + return IRQ_HANDLED; +} + static int ab8500_registers_print(struct seq_file *s, void *p) { struct device *dev = s->private; @@ -515,6 +543,151 @@ static ssize_t ab8500_val_write(struct file *file, printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__); return -EINVAL; } + return count; +} + +static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p) +{ + seq_printf(s, "%d\n", irq_first); + + return 0; +} + +static int ab8500_subscribe_unsubscribe_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_subscribe_unsubscribe_print, + inode->i_private); +} + +/* + * Userspace should use poll() on this file. When an event occur + * the blocking poll will be released. + */ +static ssize_t show_irq(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned long name; + unsigned int irq_index; + int err; + + err = strict_strtoul(attr->attr.name, 0, &name); + if (err) + return err; + + irq_index = name - irq_first; + if (irq_index >= AB8500_NR_IRQS) + return -EINVAL; + else + return sprintf(buf, "%u\n", irq_count[irq_index]); +} + +static ssize_t ab8500_subscribe_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct device *dev = ((struct seq_file *)(file->private_data))->private; + char buf[32]; + int buf_size; + unsigned long user_val; + int err; + unsigned int irq_index; + + /* Get userspace string and assure termination */ + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + err = strict_strtoul(buf, 0, &user_val); + if (err) + return -EINVAL; + if (user_val < irq_first) { + dev_err(dev, "debugfs error input < %d\n", irq_first); + return -EINVAL; + } + if (user_val > irq_last) { + dev_err(dev, "debugfs error input > %d\n", irq_last); + return -EINVAL; + } + + irq_index = user_val - irq_first; + if (irq_index >= AB8500_NR_IRQS) + return -EINVAL; + + /* + * This will create a sysfs file named which userspace can + * use to select or poll and get the AB8500 events + */ + dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute), + GFP_KERNEL); + event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL); + sprintf(event_name[irq_index], "%lu", user_val); + dev_attr[irq_index]->show = show_irq; + dev_attr[irq_index]->store = NULL; + dev_attr[irq_index]->attr.name = event_name[irq_index]; + dev_attr[irq_index]->attr.mode = S_IRUGO; + err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr); + if (err < 0) { + printk(KERN_ERR "sysfs_create_file failed %d\n", err); + return err; + } + + err = request_threaded_irq(user_val, NULL, ab8500_debug_handler, + IRQF_SHARED | IRQF_NO_SUSPEND, "ab8500-debug", &dev->kobj); + if (err < 0) { + printk(KERN_ERR "request_threaded_irq failed %d, %lu\n", + err, user_val); + sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr); + return err; + } + + return buf_size; +} + +static ssize_t ab8500_unsubscribe_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct device *dev = ((struct seq_file *)(file->private_data))->private; + char buf[32]; + int buf_size; + unsigned long user_val; + int err; + unsigned int irq_index; + + /* Get userspace string and assure termination */ + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + err = strict_strtoul(buf, 0, &user_val); + if (err) + return -EINVAL; + if (user_val < irq_first) { + dev_err(dev, "debugfs error input < %d\n", irq_first); + return -EINVAL; + } + if (user_val > irq_last) { + dev_err(dev, "debugfs error input > %d\n", irq_last); + return -EINVAL; + } + + irq_index = user_val - irq_first; + if (irq_index >= AB8500_NR_IRQS) + return -EINVAL; + + /* Set irq count to 0 when unsubscribe */ + irq_count[irq_index] = 0; + + if (dev_attr[irq_index]) + sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr); + + + free_irq(user_val, &dev->kobj); + kfree(event_name[irq_index]); + kfree(dev_attr[irq_index]); return count; } @@ -546,17 +719,51 @@ static const struct file_operations ab8500_val_fops = { .owner = THIS_MODULE, }; +static const struct file_operations ab8500_subscribe_fops = { + .open = ab8500_subscribe_unsubscribe_open, + .write = ab8500_subscribe_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations ab8500_unsubscribe_fops = { + .open = ab8500_subscribe_unsubscribe_open, + .write = ab8500_unsubscribe_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static struct dentry *ab8500_dir; static struct dentry *ab8500_reg_file; static struct dentry *ab8500_bank_file; static struct dentry *ab8500_address_file; static struct dentry *ab8500_val_file; +static struct dentry *ab8500_subscribe_file; +static struct dentry *ab8500_unsubscribe_file; static int __devinit ab8500_debug_probe(struct platform_device *plf) { debug_bank = AB8500_MISC; debug_address = AB8500_REV_REG & 0x00FF; + irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); + if (irq_first < 0) { + dev_err(&plf->dev, "First irq not found, err %d\n", + irq_first); + return irq_first; + } + + irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); + if (irq_last < 0) { + dev_err(&plf->dev, "Last irq not found, err %d\n", + irq_last); + return irq_last; + } + ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); if (!ab8500_dir) goto exit_no_debugfs; @@ -567,23 +774,38 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) goto exit_destroy_dir; ab8500_bank_file = debugfs_create_file("register-bank", - (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops); + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); if (!ab8500_bank_file) goto exit_destroy_reg; ab8500_address_file = debugfs_create_file("register-address", - (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_address_fops); if (!ab8500_address_file) goto exit_destroy_bank; ab8500_val_file = debugfs_create_file("register-value", - (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops); + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); if (!ab8500_val_file) goto exit_destroy_address; + ab8500_subscribe_file = debugfs_create_file("irq-subscribe", + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, + &ab8500_subscribe_fops); + if (!ab8500_subscribe_file) + goto exit_destroy_val; + + ab8500_unsubscribe_file = debugfs_create_file("irq-unsubscribe", + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, + &ab8500_unsubscribe_fops); + if (!ab8500_unsubscribe_file) + goto exit_destroy_subscribe; return 0; +exit_destroy_subscribe: + debugfs_remove(ab8500_subscribe_file); +exit_destroy_val: + debugfs_remove(ab8500_val_file); exit_destroy_address: debugfs_remove(ab8500_address_file); exit_destroy_bank: diff --git a/drivers/mfd/ab8500-denc.c b/drivers/mfd/ab8500-denc.c new file mode 100644 index 00000000000..06e4b282cbf --- /dev/null +++ b/drivers/mfd/ab8500-denc.c @@ -0,0 +1,515 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * + * ST-Ericsson AB8500 DENC base driver + * + * Author: Marcel Tunnissen + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AB8500_NAME "ab8500" +#define AB8500_DENC_NAME "ab8500_denc" + +struct device_usage { + struct list_head list; + struct platform_device *pdev; + bool taken; +}; +static LIST_HEAD(device_list); + +/* To get rid of the extra bank parameter: */ +#define AB8500_REG_BANK_NR(__reg) ((0xff00 & (__reg)) >> 8) +static inline u8 ab8500_rreg(struct device *dev, u32 reg) +{ + u8 val; + if (abx500_get_register_interruptible(dev, AB8500_REG_BANK_NR(reg), + reg, &val) < 0) + return 0; + else + return val; +} + +static inline int ab8500_wreg(struct device *dev, u32 reg, u8 val) +{ + return abx500_set_register_interruptible(dev, AB8500_REG_BANK_NR(reg), + reg, val); +} + +/* Only use in the macro below: */ +static inline int _ab8500_wreg_fld(struct device *dev, u32 reg, u8 val, + u8 mask, u8 shift) +{ + int ret; + u8 org_val; + + ret = abx500_get_register_interruptible(dev, AB8500_REG_BANK_NR(reg), + reg, &org_val); + if (ret < 0) + return ret; + else + ab8500_wreg(dev, reg, + (org_val & ~mask) | ((val << shift) & mask)); + return 0; +} + +#define ab8500_wr_fld(__d, __reg, __fld, __val) \ + _ab8500_wreg_fld(__d, __reg, __val, __reg##_##__fld##_MASK, \ + __reg##_##__fld##_SHIFT) + +#define ab8500_set_fld(__cur_val, __reg, __fld, __val) \ + (((__cur_val) & ~__reg##_##__fld##_MASK) | \ + (((__val) << __reg##_##__fld##_SHIFT) & __reg##_##__fld##_MASK)) + +#define AB8500_DENC_TRACE(__pd) dev_dbg(&(__pd)->dev, "%s\n", __func__) + +#ifdef CONFIG_DEBUG_FS +static struct dentry *debugfs_ab8500_denc_dir; +static struct dentry *debugfs_ab8500_dump_regs_file; +static void ab8500_denc_conf_ddr(struct platform_device *pdev); +static int debugfs_ab8500_open_file(struct inode *inode, struct file *file); +static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, + size_t count, loff_t *f_pos); + +static const struct file_operations debugfs_ab8500_dump_regs_fops = { + .owner = THIS_MODULE, + .open = debugfs_ab8500_open_file, + .read = debugfs_ab8500_dump_regs, +}; +#endif /* CONFIG_DEBUG_FS */ + +static int __devinit ab8500_denc_probe(struct platform_device *pdev) +{ + int ret = 0; + struct ab8500_platform_data *ab8500_pdata = + dev_get_platdata(pdev->dev.parent); + struct ab8500_denc_platform_data *pdata; + struct device_usage *device_data; + + AB8500_DENC_TRACE(pdev); + + if (ab8500_pdata == NULL) { + dev_err(&pdev->dev, "AB8500 platform data missing\n"); + return -EINVAL; + } + + pdata = ab8500_pdata->denc; + if (pdata == NULL) { + dev_err(&pdev->dev, "Denc platform data missing\n"); + return -EINVAL; + } + + device_data = kzalloc(sizeof(struct device_usage), GFP_KERNEL); + if (!device_data) { + dev_err(&pdev->dev, "Failed to allocate device data\n"); + return -ENOMEM; + } + device_data->pdev = pdev; + list_add_tail(&device_data->list, &device_list); + +#ifdef CONFIG_DEBUG_FS + debugfs_ab8500_denc_dir = debugfs_create_dir(pdev->name, NULL); + debugfs_ab8500_dump_regs_file = debugfs_create_file( + "dumpregs", S_IRUGO, + debugfs_ab8500_denc_dir, &pdev->dev, + &debugfs_ab8500_dump_regs_fops + ); +#endif /* CONFIG_DEBUG_FS */ + return ret; +} + +static int __devexit ab8500_denc_remove(struct platform_device *pdev) +{ + struct list_head *element; + struct device_usage *device_data; + + AB8500_DENC_TRACE(pdev); + +#ifdef CONFIG_DEBUG_FS + debugfs_remove(debugfs_ab8500_dump_regs_file); + debugfs_remove(debugfs_ab8500_denc_dir); +#endif /* CONFIG_DEBUG_FS */ + + list_for_each(element, &device_list) { + device_data = list_entry(element, struct device_usage, list); + if (device_data->pdev == pdev) { + list_del(element); + kzfree(device_data); + } + } + + return 0; +} + +static struct platform_driver ab8500_denc_driver = { + .probe = ab8500_denc_probe, + .remove = ab8500_denc_remove, + .driver = { + .name = "ab8500-denc", + }, +}; + +static void setup_27mhz(struct platform_device *pdev, bool enable) +{ + u8 data = ab8500_rreg(&pdev->dev, AB8500_SYS_ULP_CLK_CONF); + + AB8500_DENC_TRACE(pdev); + /* TODO: check if this field needs to be set */ + data = ab8500_set_fld(data, AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_PD_ENA, + true); + data = ab8500_set_fld(data, AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_BUF_ENA, + enable); + data = ab8500_set_fld(data, AB8500_SYS_ULP_CLK_CONF, TVOUT_CLK_INV, + false); + data = ab8500_set_fld(data, AB8500_SYS_ULP_CLK_CONF, TVOUT_CLK_DE_IN, + false); + data = ab8500_set_fld(data, AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_STRE, + 1); + ab8500_wreg(&pdev->dev, AB8500_SYS_ULP_CLK_CONF, data); + + data = ab8500_rreg(&pdev->dev, AB8500_SYS_CLK_CTRL); + data = ab8500_set_fld(data, AB8500_SYS_CLK_CTRL, TVOUT_CLK_VALID, + enable); + data = ab8500_set_fld(data, AB8500_SYS_CLK_CTRL, TVOUT_PLL_ENA, + enable); + ab8500_wreg(&pdev->dev, AB8500_SYS_CLK_CTRL, data); +} + +static u32 map_tv_std(enum ab8500_denc_TV_std std) +{ + switch (std) { + case TV_STD_PAL_BDGHI: + return AB8500_DENC_CONF0_STD_PAL_BDGHI; + case TV_STD_PAL_N: + return AB8500_DENC_CONF0_STD_PAL_N; + case TV_STD_PAL_M: + return AB8500_DENC_CONF0_STD_PAL_M; + case TV_STD_NTSC_M: + return AB8500_DENC_CONF0_STD_NTSC_M; + default: + return 0; + } +} + +static u32 map_cr_filter(enum ab8500_denc_cr_filter_bandwidth bw) +{ + switch (bw) { + case TV_CR_NTSC_LOW_DEF_FILTER: + return AB8500_DENC_CONF1_FLT_1_1MHZ; + case TV_CR_PAL_LOW_DEF_FILTER: + return AB8500_DENC_CONF1_FLT_1_3MHZ; + case TV_CR_NTSC_HIGH_DEF_FILTER: + return AB8500_DENC_CONF1_FLT_1_6MHZ; + case TV_CR_PAL_HIGH_DEF_FILTER: + return AB8500_DENC_CONF1_FLT_1_9MHZ; + default: + return 0; + } +} + +static u32 map_phase_rst_mode(enum ab8500_denc_phase_reset_mode mode) +{ + switch (mode) { + case TV_PHASE_RST_MOD_DISABLE: + return AB8500_DENC_CONF8_PH_RST_MODE_DISABLED; + case TV_PHASE_RST_MOD_FROM_PHASE_BUF: + return AB8500_DENC_CONF8_PH_RST_MODE_UPDATE_FROM_PHASE_BUF; + case TV_PHASE_RST_MOD_FROM_INC_DFS: + return AB8500_DENC_CONF8_PH_RST_MODE_UPDATE_FROM_INC_DFS; + case TV_PHASE_RST_MOD_RST: + return AB8500_DENC_CONF8_PH_RST_MODE_RESET; + default: + return 0; + } +} + +static u32 map_plug_time(enum ab8500_denc_plug_time time) +{ + switch (time) { + case TV_PLUG_TIME_0_5S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_0_5S; + case TV_PLUG_TIME_1S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_1S; + case TV_PLUG_TIME_1_5S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_1_5S; + case TV_PLUG_TIME_2S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_2S; + case TV_PLUG_TIME_2_5S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_2_5S; + case TV_PLUG_TIME_3S: + return AB8500_TVOUT_CTRL_PLUG_TV_TIME_3S; + default: + return 0; + } +} + +struct platform_device *ab8500_denc_get_device(void) +{ + struct list_head *element; + struct device_usage *device_data; + + pr_debug("%s\n", __func__); + list_for_each(element, &device_list) { + device_data = list_entry(element, struct device_usage, list); + if (!device_data->taken) { + device_data->taken = true; + return device_data->pdev; + } + } + return NULL; +} +EXPORT_SYMBOL(ab8500_denc_get_device); + +void ab8500_denc_put_device(struct platform_device *pdev) +{ + struct list_head *element; + struct device_usage *device_data; + + AB8500_DENC_TRACE(pdev); + list_for_each(element, &device_list) { + device_data = list_entry(element, struct device_usage, list); + if (device_data->pdev == pdev) + device_data->taken = false; + } +} +EXPORT_SYMBOL(ab8500_denc_put_device); + +void ab8500_denc_reset(struct platform_device *pdev, bool hard) +{ + AB8500_DENC_TRACE(pdev); + if (hard) { + u8 data = ab8500_rreg(&pdev->dev, AB8500_CTRL3); + /* reset start */ + ab8500_wreg(&pdev->dev, AB8500_CTRL3, + ab8500_set_fld(data, AB8500_CTRL3, RESET_DENC_N, 0) + ); + /* reset done */ + ab8500_wreg(&pdev->dev, AB8500_CTRL3, + ab8500_set_fld(data, AB8500_CTRL3, RESET_DENC_N, 1) + ); + } else { + ab8500_wr_fld(&pdev->dev, AB8500_DENC_CONF6, SOFT_RESET, 1); + mdelay(10); + } +} +EXPORT_SYMBOL(ab8500_denc_reset); + +void ab8500_denc_power_up(struct platform_device *pdev) +{ + setup_27mhz(pdev, true); +} +EXPORT_SYMBOL(ab8500_denc_power_up); + +void ab8500_denc_power_down(struct platform_device *pdev) +{ + setup_27mhz(pdev, false); +} +EXPORT_SYMBOL(ab8500_denc_power_down); + +void ab8500_denc_conf(struct platform_device *pdev, + struct ab8500_denc_conf *conf) +{ + u8 data; + + AB8500_DENC_TRACE(pdev); + + ab8500_wreg(&pdev->dev, AB8500_DENC_CONF0, + AB8500_VAL2REG(AB8500_DENC_CONF0, STD, map_tv_std(conf->TV_std)) + | + AB8500_VAL2REG(AB8500_DENC_CONF0, SYNC, + conf->test_pattern ? AB8500_DENC_CONF0_SYNC_AUTO_TEST : + AB8500_DENC_CONF0_SYNC_F_BASED_SLAVE + ) + ); + ab8500_wreg(&pdev->dev, AB8500_DENC_CONF1, + AB8500_VAL2REG(AB8500_DENC_CONF1, BLK_LI, + !conf->partial_blanking) + | + AB8500_VAL2REG(AB8500_DENC_CONF1, FLT, + map_cr_filter(conf->cr_filter)) + | + AB8500_VAL2REG(AB8500_DENC_CONF1, CO_KI, conf->suppress_col) + | + AB8500_VAL2REG(AB8500_DENC_CONF1, SETUP_MAIN, + conf->black_level_setup) + /* TODO: handle cc field: set to 0 now */ + ); + + data = ab8500_rreg(&pdev->dev, AB8500_DENC_CONF2); + data = ab8500_set_fld(data, AB8500_DENC_CONF2, N_INTRL, + conf->progressive); + ab8500_wreg(&pdev->dev, AB8500_DENC_CONF2, data); + + ab8500_wreg(&pdev->dev, AB8500_DENC_CONF8, + AB8500_VAL2REG(AB8500_DENC_CONF8, PH_RST_MODE, + map_phase_rst_mode(conf->phase_reset_mode)) + | + AB8500_VAL2REG(AB8500_DENC_CONF8, VAL_422_MUX, + conf->act_output) + | + AB8500_VAL2REG(AB8500_DENC_CONF8, BLK_ALL, + conf->blank_all) + ); + data = ab8500_rreg(&pdev->dev, AB8500_TVOUT_CTRL); + data = ab8500_set_fld(data, AB8500_TVOUT_CTRL, DAC_CTRL0, + conf->dac_enable); + data = ab8500_set_fld(data, AB8500_TVOUT_CTRL, DAC_CTRL1, + conf->act_dc_output); + ab8500_wreg(&pdev->dev, AB8500_TVOUT_CTRL, data); + + /* no support for DDR in early versions */ + if (AB8500_REG2VAL(AB8500_REV, FULL_MASK, + ab8500_rreg(&pdev->dev, AB8500_REV)) > 0) + ab8500_denc_conf_ddr(pdev); +} +EXPORT_SYMBOL(ab8500_denc_conf); + +void ab8500_denc_conf_plug_detect(struct platform_device *pdev, + bool enable, bool load_RC, + enum ab8500_denc_plug_time time) +{ + u8 data; + + AB8500_DENC_TRACE(pdev); + data = ab8500_rreg(&pdev->dev, AB8500_TVOUT_CTRL); + data = ab8500_set_fld(data, AB8500_TVOUT_CTRL, TV_PLUG_ON, enable); + data = ab8500_set_fld(data, AB8500_TVOUT_CTRL, TV_LOAD_RC, load_RC); + data = ab8500_set_fld(data, AB8500_TVOUT_CTRL, PLUG_TV_TIME, + map_plug_time(time)); + ab8500_wreg(&pdev->dev, AB8500_TVOUT_CTRL, data); +} +EXPORT_SYMBOL(ab8500_denc_conf_plug_detect); + +void ab8500_denc_mask_int_plug_det(struct platform_device *pdev, bool plug, + bool unplug) +{ + u8 data = ab8500_rreg(&pdev->dev, AB8500_IT_MASK1); + + AB8500_DENC_TRACE(pdev); + data = ab8500_set_fld(data, AB8500_IT_MASK1, PLUG_TV_DET, plug); + data = ab8500_set_fld(data, AB8500_IT_MASK1, UNPLUG_TV_DET, unplug); + ab8500_wreg(&pdev->dev, AB8500_IT_MASK1, data); +} +EXPORT_SYMBOL(ab8500_denc_mask_int_plug_det); + +static void ab8500_denc_conf_ddr(struct platform_device *pdev) +{ + struct ab8500_platform_data *core_pdata; + struct ab8500_denc_platform_data *denc_pdata; + + AB8500_DENC_TRACE(pdev); + core_pdata = dev_get_platdata(pdev->dev.parent); + denc_pdata = core_pdata->denc; + ab8500_wreg(&pdev->dev, AB8500_TVOUT_CTRL2, + AB8500_VAL2REG(AB8500_TVOUT_CTRL2, + DENC_DDR, denc_pdata->ddr_enable) | + AB8500_VAL2REG(AB8500_TVOUT_CTRL2, SWAP_DDR_DATA_IN, + denc_pdata->ddr_little_endian)); +} + +#ifdef CONFIG_DEBUG_FS +static int debugfs_ab8500_open_file(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#define DEBUG_BUF_SIZE 900 + +static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, + size_t count, loff_t *f_pos) +{ + int ret = 0; + size_t data_size = 0; + char buffer[DEBUG_BUF_SIZE]; + struct device *dev = file->private_data; + + data_size += sprintf(buffer + data_size, + "AB8500 DENC registers:\n" + "CTRL3 : 0x%04x = 0x%02x\n" + "SYSULPCLK_CONF: 0x%04x = 0x%02x\n" + "SYSCLK_CTRL : 0x%04x = 0x%02x\n" + "REGU_MISC1 : 0x%04x = 0x%02x\n" + "VAUX12_REGU : 0x%04x = 0x%02x\n" + "VAUX1_SEL1 : 0x%04x = 0x%02x\n" + "DENC_CONF0 : 0x%04x = 0x%02x\n" + "DENC_CONF1 : 0x%04x = 0x%02x\n" + "DENC_CONF2 : 0x%04x = 0x%02x\n" + "DENC_CONF6 : 0x%04x = 0x%02x\n" + "DENC_CONF8 : 0x%04x = 0x%02x\n" + "TVOUT_CTRL : 0x%04x = 0x%02x\n" + "TVOUT_CTRL2 : 0x%04x = 0x%02x\n" + "IT_MASK1 : 0x%04x = 0x%02x\n" + , + AB8500_CTRL3, ab8500_rreg(dev, AB8500_CTRL3), + AB8500_SYS_ULP_CLK_CONF, ab8500_rreg(dev, + AB8500_SYS_ULP_CLK_CONF), + AB8500_SYS_CLK_CTRL, ab8500_rreg(dev, AB8500_SYS_CLK_CTRL), + AB8500_REGU_MISC1, ab8500_rreg(dev, AB8500_REGU_MISC1), + AB8500_VAUX12_REGU, ab8500_rreg(dev, AB8500_VAUX12_REGU), + AB8500_VAUX1_SEL, ab8500_rreg(dev, AB8500_VAUX1_SEL), + AB8500_DENC_CONF0, ab8500_rreg(dev, AB8500_DENC_CONF0), + AB8500_DENC_CONF1, ab8500_rreg(dev, AB8500_DENC_CONF1), + AB8500_DENC_CONF2, ab8500_rreg(dev, AB8500_DENC_CONF2), + AB8500_DENC_CONF6, ab8500_rreg(dev, AB8500_DENC_CONF6), + AB8500_DENC_CONF8, ab8500_rreg(dev, AB8500_DENC_CONF8), + AB8500_TVOUT_CTRL, ab8500_rreg(dev, AB8500_TVOUT_CTRL), + AB8500_TVOUT_CTRL2, ab8500_rreg(dev, AB8500_TVOUT_CTRL2), + AB8500_IT_MASK1, ab8500_rreg(dev, AB8500_IT_MASK1) + ); + if (data_size >= DEBUG_BUF_SIZE) { + printk(KERN_EMERG "AB8500 DENC: Buffer overrun\n"); + ret = -EINVAL; + goto out; + } + + /* check if read done */ + if (*f_pos > data_size) + goto out; + + if (*f_pos + count > data_size) + count = data_size - *f_pos; + + if (copy_to_user(buf, buffer + *f_pos, count)) + ret = -EINVAL; + *f_pos += count; + ret = count; +out: + return ret; +} +#endif /* CONFIG_DEBUG_FS */ + +/* Module init */ +static int __init ab8500_denc_init(void) +{ + return platform_driver_register(&ab8500_denc_driver); +} +module_init(ab8500_denc_init); + +static void __exit ab8500_denc_exit(void) +{ + platform_driver_unregister(&ab8500_denc_driver); +} +module_exit(ab8500_denc_exit); + +MODULE_AUTHOR("Marcel Tunnissen "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ST-Ericsson AB8500 DENC driver"); diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index c39fc716e1d..301510b5824 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -57,7 +57,7 @@ #define SW_AVG_16 0x60 #define ADC_SW_CONV 0x04 #define EN_ICHAR 0x80 -#define BTEMP_PULL_UP 0x08 +#define BATTEMP_PULL_UP 0x04 #define EN_BUF 0x40 #define DIS_ZERO 0x00 #define GPADC_BUSY 0x01 @@ -130,16 +130,12 @@ static LIST_HEAD(ab8500_gpadc_list); * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC * (i.e. the first GPADC in the instance list) */ -struct ab8500_gpadc *ab8500_gpadc_get(char *name) +struct ab8500_gpadc *ab8500_gpadc_get(void) { struct ab8500_gpadc *gpadc; + gpadc = list_first_entry(&ab8500_gpadc_list, struct ab8500_gpadc, node); - list_for_each_entry(gpadc, &ab8500_gpadc_list, node) { - if (!strcmp(name, dev_name(gpadc->dev))) - return gpadc; - } - - return ERR_PTR(-ENOENT); + return gpadc; } EXPORT_SYMBOL(ab8500_gpadc_get); diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index c28d4eb1eff..799fb5e696a 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -7,12 +7,29 @@ #include #include #include +#include +#include #include #include #include static struct device *sysctrl_dev; +void ab8500_power_off(void) +{ + sigset_t old; + sigset_t all; + + sigfillset(&all); + + if (!sigprocmask(SIG_BLOCK, &all, &old)) { + (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, + AB8500_STW4500CTRL1_SWOFF | + AB8500_STW4500CTRL1_SWRESET4500N); + (void)sigprocmask(SIG_SETMASK, &old, NULL); + } +} + static inline bool valid_bank(u8 bank) { return ((bank == AB8500_SYS_CTRL1_BLOCK) || @@ -51,7 +68,12 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev) { + struct ab8500_platform_data *plat; + sysctrl_dev = &pdev->dev; + plat = dev_get_platdata(pdev->dev.parent); + if (plat->pm_power_off) + pm_power_off = ab8500_power_off; return 0; } diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index d7a9aa14e5d..01faa7f2c1a 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -27,8 +28,10 @@ struct pwm_device { struct device *dev; struct list_head node; + struct clk *clk; const char *label; unsigned int pwm_id; + bool clk_enabled; }; static LIST_HEAD(pwm_list); @@ -67,9 +70,17 @@ int pwm_enable(struct pwm_device *pwm) { int ret; + if (!pwm->clk_enabled) { + ret = clk_enable(pwm->clk); + if (ret < 0) { + dev_err(pwm->dev, "failed to enable sysclk\n"); + return ret; + } + pwm->clk_enabled = true; + } ret = abx500_mask_and_set_register_interruptible(pwm->dev, AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, - 1 << (pwm->pwm_id-1), ENABLE_PWM); + 1 << (pwm->pwm_id-1), 1 << (pwm->pwm_id-1)); if (ret < 0) dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", pwm->label, ret); @@ -84,9 +95,27 @@ void pwm_disable(struct pwm_device *pwm) ret = abx500_mask_and_set_register_interruptible(pwm->dev, AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 1 << (pwm->pwm_id-1), DISABLE_PWM); + /* + * Workaround to set PWM in disable. + * If enable bit is not toggled the PWM might output 50/50 duty cycle + * even though it should be disabled + */ + ret &= abx500_mask_and_set_register_interruptible(pwm->dev, + AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, + 1 << (pwm->pwm_id-1), + ENABLE_PWM << (pwm->pwm_id-1)); + ret &= abx500_mask_and_set_register_interruptible(pwm->dev, + AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, + 1 << (pwm->pwm_id-1), DISABLE_PWM); + if (ret < 0) dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", pwm->label, ret); + if (pwm->clk_enabled) { + clk_disable(pwm->clk); + pwm->clk_enabled = false; + } + return; } EXPORT_SYMBOL(pwm_disable); @@ -116,6 +145,8 @@ EXPORT_SYMBOL(pwm_free); static int __devinit ab8500_pwm_probe(struct platform_device *pdev) { struct pwm_device *pwm; + int ret = 0; + /* * Nothing to be done in probe, this is required to get the * device which is required for ab8500 read and write @@ -129,14 +160,24 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev) pwm->pwm_id = pdev->id; list_add_tail(&pwm->node, &pwm_list); platform_set_drvdata(pdev, pwm); + + pwm->clk = clk_get(pwm->dev, "sysclk"); + if (IS_ERR(pwm->clk)) { + dev_err(pwm->dev, "clock request failed\n"); + ret = PTR_ERR(pwm->clk); + kfree(pwm); + return ret; + } + pwm->clk_enabled = false; dev_dbg(pwm->dev, "pwm probe successful\n"); - return 0; + return ret; } static int __devexit ab8500_pwm_remove(struct platform_device *pdev) { struct pwm_device *pwm = platform_get_drvdata(pdev); list_del(&pwm->node); + clk_put(pwm->clk); dev_dbg(&pdev->dev, "pwm driver removed\n"); kfree(pwm); return 0; diff --git a/include/linux/mfd/ab8500/denc-regs.h b/include/linux/mfd/ab8500/denc-regs.h new file mode 100644 index 00000000000..a6683ca7470 --- /dev/null +++ b/include/linux/mfd/ab8500/denc-regs.h @@ -0,0 +1,357 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * ST-Ericsson AB8500 DENC related registers + * + * Author: Marcus Tunnissen + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __AB8500_DENC_H +#define __AB8500_DENC_H + +#define AB8500_VAL2REG(__reg, __fld, __val) \ + (((__val) << __reg##_##__fld##_SHIFT) & __reg##_##__fld##_MASK) +#define AB8500_REG2VAL(__reg, __fld, __val) \ + (((__val) & __reg##_##__fld##_MASK) >> __reg##_##__fld##_SHIFT) + +#define AB8500_CTRL3 0x00000200 +#define AB8500_CTRL3_TH_SD_ENA_SHIFT 3 +#define AB8500_CTRL3_TH_SD_ENA_MASK 0x00000008 +#define AB8500_CTRL3_TH_SD_ENA(__x) \ + AB8500_VAL2REG(AB8500_CTRL3, TH_SD_ENA, __x) +#define AB8500_CTRL3_RESET_DENC_N_SHIFT 2 +#define AB8500_CTRL3_RESET_DENC_N_MASK 0x00000004 +#define AB8500_CTRL3_RESET_DENC_N(__x) \ + AB8500_VAL2REG(AB8500_CTRL3, RESET_DENC_N, __x) +#define AB8500_CTRL3_RESET_AUD_N_SHIFT 1 +#define AB8500_CTRL3_RESET_AUD_N_MASK 0x00000002 +#define AB8500_CTRL3_RESET_AUD_N(__x) \ + AB8500_VAL2REG(AB8500_CTRL3, RESET_AUD_N, __x) +#define AB8500_CTRL3_CLK_32K_OUT2_IS_SHIFT 0 +#define AB8500_CTRL3_CLK_32K_OUT2_IS_MASK 0x00000001 +#define AB8500_CTRL3_CLK_32K_OUT2_IS(__x) \ + AB8500_VAL2REG(AB8500_CTRL3, CLK_32K_OUT2_IS, __x) +#define AB8500_SYS_ULP_CLK_CONF 0x0000020A +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_PD_ENA_SHIFT 7 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_PD_ENA_MASK 0x00000080 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_PD_ENA(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_PD_ENA, __x) +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_BUF_ENA_SHIFT 6 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_BUF_ENA_MASK 0x00000040 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_BUF_ENA(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_BUF_ENA, __x) +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_STRE_SHIFT 5 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_STRE_MASK 0x00000020 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_STRE(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, ULP_CLK_STRE, __x) +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_INV_SHIFT 4 +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_INV_MASK 0x00000010 +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_INV(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, TVOUT_CLK_INV, __x) +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_DE_IN_SHIFT 3 +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_DE_IN_MASK 0x00000008 +#define AB8500_SYS_ULP_CLK_CONF_TVOUT_CLK_DE_IN(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, TVOUT_CLK_DE_IN, __x) +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_STRE_SHIFT 2 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_STRE_MASK 0x00000004 +#define AB8500_SYS_ULP_CLK_CONF_CLK_27MHZ_STRE(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, CLK_27MHZ_STRE, __x) +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_SHIFT 0 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_MASK 0x00000003 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_NO_FUNC 0 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_AS_OUTPUT 1 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_AS_INPUT 2 +#define AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF(__x) \ + AB8500_VAL2REG(AB8500_SYS_ULP_CLK_CONF, ULP_CLK_CONF, \ + AB8500_SYS_ULP_CLK_CONF_ULP_CLK_CONF_##__x) +#define AB8500_SYS_CLK_CTRL 0x0000020C +#define AB8500_SYS_CLK_CTRL_USB_CLK_VALID_SHIFT 2 +#define AB8500_SYS_CLK_CTRL_USB_CLK_VALID_MASK 0x00000004 +#define AB8500_SYS_CLK_CTRL_USB_CLK_VALID(__x) \ + AB8500_VAL2REG(AB8500_SYS_CLK_CTRL, USB_CLK_VALID, __x) +#define AB8500_SYS_CLK_CTRL_TVOUT_CLK_VALID_SHIFT 1 +#define AB8500_SYS_CLK_CTRL_TVOUT_CLK_VALID_MASK 0x00000002 +#define AB8500_SYS_CLK_CTRL_TVOUT_CLK_VALID(__x) \ + AB8500_VAL2REG(AB8500_SYS_CLK_CTRL, TVOUT_CLK_VALID, __x) +#define AB8500_SYS_CLK_CTRL_TVOUT_PLL_ENA_SHIFT 0 +#define AB8500_SYS_CLK_CTRL_TVOUT_PLL_ENA_MASK 0x00000001 +#define AB8500_SYS_CLK_CTRL_TVOUT_PLL_ENA(__x) \ + AB8500_VAL2REG(AB8500_SYS_CLK_CTRL, TVOUT_PLL_ENA, __x) +#define AB8500_REGU_MISC1 0x00000380 +#define AB8500_REGU_MISC1_V_TVOUT_LP_SHIFT 7 +#define AB8500_REGU_MISC1_V_TVOUT_LP_MASK 0x00000080 +#define AB8500_REGU_MISC1_V_TVOUT_LP(__x) \ + AB8500_VAL2REG(AB8500_REGU_MISC1, V_TVOUT_LP, __x) +#define AB8500_REGU_MISC1_V_INT_CORE_12_LP_SHIFT 6 +#define AB8500_REGU_MISC1_V_INT_CORE_12_LP_MASK 0x00000040 +#define AB8500_REGU_MISC1_V_INT_CORE_12_LP(__x) \ + AB8500_VAL2REG(AB8500_REGU_MISC1, V_INT_CORE_12_LP, __x) +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_SHIFT 3 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_MASK 0x00000038 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_2V 0 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_225V 1 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_25V 2 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_275V 3 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_3V 4 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_325V 5 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL_1_35V 6 +#define AB8500_REGU_MISC1_V_INT_CORE_12_SEL(__x) \ + AB8500_VAL2REG(AB8500_REGU_MISC1, V_INT_CORE_12_SEL, \ + AB8500_REGU_MISC1_V_INT_CORE_12_SEL_##__x) +#define AB8500_REGU_MISC1_V_INT_CORE_12_ENA_SHIFT 2 +#define AB8500_REGU_MISC1_V_INT_CORE_12_ENA_MASK 0x00000004 +#define AB8500_REGU_MISC1_V_INT_CORE_12_ENA(__x) \ + AB8500_VAL2REG(AB8500_REGU_MISC1, V_INT_CORE_12_ENA, __x) +#define AB8500_REGU_MISC1_V_TVOUT_ENA_SHIFT 1 +#define AB8500_REGU_MISC1_V_TVOUT_ENA_MASK 0x00000002 +#define AB8500_REGU_MISC1_V_TVOUT_ENA(__x) \ + AB8500_VAL2REG(AB8500_REGU_MISC1, V_TVOUT_ENA, __x) +#define AB8500_VAUX12_REGU 0x00000409 +#define AB8500_VAUX12_REGU_VAUX_1_SHIFT 2 +#define AB8500_VAUX12_REGU_VAUX_1_MASK 0x0000000C +#define AB8500_VAUX12_REGU_VAUX_1_DISABLE 0 +#define AB8500_VAUX12_REGU_VAUX_1_FORCE_HP 1 +#define AB8500_VAUX12_REGU_VAUX_1_BY_CTRL_REG 2 +#define AB8500_VAUX12_REGU_VAUX_1_FORCE_LP 3 +#define AB8500_VAUX12_REGU_VAUX_1(__x) \ + AB8500_VAL2REG(AB8500_VAUX12_REGU, VAUX_1, \ + AB8500_VAUX12_REGU_VAUX_1_##__x) +#define AB8500_VAUX12_REGU_VAUX_2_SHIFT 0 +#define AB8500_VAUX12_REGU_VAUX_2_MASK 0x00000003 +#define AB8500_VAUX12_REGU_VAUX_2_DISABLE 0 +#define AB8500_VAUX12_REGU_VAUX_2_FORCE_HP 1 +#define AB8500_VAUX12_REGU_VAUX_2_BY_CTRL_REG 2 +#define AB8500_VAUX12_REGU_VAUX_2_FORCE_LP 3 +#define AB8500_VAUX12_REGU_VAUX_2(__x) \ + AB8500_VAL2REG(AB8500_VAUX12_REGU, VAUX_2, \ + AB8500_VAUX12_REGU_VAUX_2_##__x) +#define AB8500_VAUX1_SEL 0x0000041F +#define AB8500_VAUX1_SEL_VAL_SHIFT 0 +#define AB8500_VAUX1_SEL_VAL_MASK 0x0000000F +#define AB8500_VAUX1_SEL_VAL_1_1V 0 +#define AB8500_VAUX1_SEL_VAL_1_2V 1 +#define AB8500_VAUX1_SEL_VAL_1_3V 2 +#define AB8500_VAUX1_SEL_VAL_1_4V 3 +#define AB8500_VAUX1_SEL_VAL_1_5V 4 +#define AB8500_VAUX1_SEL_VAL_1_8V 5 +#define AB8500_VAUX1_SEL_VAL_1_85V 6 +#define AB8500_VAUX1_SEL_VAL_1_9V 7 +#define AB8500_VAUX1_SEL_VAL_2_5V 8 +#define AB8500_VAUX1_SEL_VAL_2_65V 9 +#define AB8500_VAUX1_SEL_VAL_2_7V 10 +#define AB8500_VAUX1_SEL_VAL_2_75V 11 +#define AB8500_VAUX1_SEL_VAL_2_8V 12 +#define AB8500_VAUX1_SEL_VAL_2_9V 13 +#define AB8500_VAUX1_SEL_VAL_3_0V 14 +#define AB8500_VAUX1_SEL_VAL_3_3V 15 +#define AB8500_VAUX1_SEL_VAL(__x) \ + AB8500_VAL2REG(AB8500_VAUX1_SEL, VAL, AB8500_VAUX1_SEL_VAL_##__x) +#define AB8500_DENC_CONF0 0x00000600 +#define AB8500_DENC_CONF0_STD_SHIFT 6 +#define AB8500_DENC_CONF0_STD_MASK 0x000000C0 +#define AB8500_DENC_CONF0_STD_PAL_BDGHI 0 +#define AB8500_DENC_CONF0_STD_PAL_N 1 +#define AB8500_DENC_CONF0_STD_NTSC_M 2 +#define AB8500_DENC_CONF0_STD_PAL_M 3 +#define AB8500_DENC_CONF0_STD(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF0, STD, AB8500_DENC_CONF0_STD_##__x) +#define AB8500_DENC_CONF0_SYNC_SHIFT 3 +#define AB8500_DENC_CONF0_SYNC_MASK 0x00000038 +#define AB8500_DENC_CONF0_SYNC_F_BASED_SLAVE 1 +#define AB8500_DENC_CONF0_SYNC_AUTO_TEST 7 +#define AB8500_DENC_CONF0_SYNC(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF0, SYNC, AB8500_DENC_CONF0_SYNC_##__x) +#define AB8500_DENC_CONF1 0x00000601 +#define AB8500_DENC_CONF1_BLK_LI_SHIFT 7 +#define AB8500_DENC_CONF1_BLK_LI_MASK 0x00000080 +#define AB8500_DENC_CONF1_BLK_LI_PARTIAL 0 +#define AB8500_DENC_CONF1_BLK_LI_FULL 1 +#define AB8500_DENC_CONF1_BLK_LI(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF1, BLK_LI, \ + AB8500_DENC_CONF1_BLK_LI_##__x) +#define AB8500_DENC_CONF1_FLT_SHIFT 5 +#define AB8500_DENC_CONF1_FLT_MASK 0x00000060 +#define AB8500_DENC_CONF1_FLT_1_1MHZ 0 +#define AB8500_DENC_CONF1_FLT_1_3MHZ 1 +#define AB8500_DENC_CONF1_FLT_1_6MHZ 2 +#define AB8500_DENC_CONF1_FLT_1_9MHZ 3 +#define AB8500_DENC_CONF1_FLT(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF1, FLT, AB8500_DENC_CONF1_FLT_##__x) +#define AB8500_DENC_CONF1_CO_KI_SHIFT 3 +#define AB8500_DENC_CONF1_CO_KI_MASK 0x00000008 +#define AB8500_DENC_CONF1_CO_KI(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF1, CO_KI, __x) +#define AB8500_DENC_CONF1_SETUP_MAIN_SHIFT 2 +#define AB8500_DENC_CONF1_SETUP_MAIN_MASK 0x00000004 +#define AB8500_DENC_CONF1_SETUP_MAIN_BLACK_EQ_BLANK 0 +#define AB8500_DENC_CONF1_SETUP_MAIN_BLACK_GT_BLANK 1 +#define AB8500_DENC_CONF1_SETUP_MAIN(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF1, SETUP_MAIN, \ + AB8500_DENC_CONF1_SETUP_MAIN_##__x) +#define AB8500_DENC_CONF1_CC_SHIFT 0 +#define AB8500_DENC_CONF1_CC_MASK 0x00000003 +#define AB8500_DENC_CONF1_CC_NONE 0 +#define AB8500_DENC_CONF1_CC_FIELD_1 1 +#define AB8500_DENC_CONF1_CC_FIELD_2 2 +#define AB8500_DENC_CONF1_CC_ALL 3 +#define AB8500_DENC_CONF1_CC(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF1, CC, AB8500_DENC_CONF1_CC_##__x) +#define AB8500_DENC_CONF2 0x00000602 +#define AB8500_DENC_CONF2_N_INTRL_SHIFT 7 +#define AB8500_DENC_CONF2_N_INTRL_MASK 0x00000080 +#define AB8500_DENC_CONF2_N_INTRL(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, N_INTRL, __x) +#define AB8500_DENC_CONF2_EN_RST_SHIFT 6 +#define AB8500_DENC_CONF2_EN_RST_MASK 0x00000040 +#define AB8500_DENC_CONF2_EN_RST(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, EN_RST, __x) +#define AB8500_DENC_CONF2_BURST_EN_SHIFT 5 +#define AB8500_DENC_CONF2_BURST_EN_MASK 0x00000020 +#define AB8500_DENC_CONF2_BURST_EN(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, BURST_EN, __x) +#define AB8500_DENC_CONF2_SEL_RST_SHIFT 4 +#define AB8500_DENC_CONF2_SEL_RST_MASK 0x00000010 +#define AB8500_DENC_CONF2_SEL_RST_USE_HW_VAL 0 +#define AB8500_DENC_CONF2_SEL_RST_USE_PROG_VAL 1 +#define AB8500_DENC_CONF2_SEL_RST(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, SEL_RST, \ + AB8500_DENC_CONF2_SEL_RST_##__x) +#define AB8500_DENC_CONF2_RST_OSC_BUF_SHIFT 2 +#define AB8500_DENC_CONF2_RST_OSC_BUF_MASK 0x00000004 +#define AB8500_DENC_CONF2_RST_OSC_BUF(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, RST_OSC_BUF, __x) +#define AB8500_DENC_CONF2_VAL_RST_SHIFT 0 +#define AB8500_DENC_CONF2_VAL_RST_MASK 0x00000003 +#define AB8500_DENC_CONF2_VAL_RST_ALL_LINES 0 +#define AB8500_DENC_CONF2_VAL_RST_EVERY_2ND_FIELD 1 +#define AB8500_DENC_CONF2_VAL_RST_EVERY_4TH_FIELD 2 +#define AB8500_DENC_CONF2_VAL_RST_EVERY_8TH_FIELD 3 +#define AB8500_DENC_CONF2_VAL_RST(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF2, VAL_RST, \ + AB8500_DENC_CONF2_VAL_RST_##__x) +#define AB8500_DENC_CONF6 0x00000606 +#define AB8500_DENC_CONF6_SOFT_RESET_SHIFT 7 +#define AB8500_DENC_CONF6_SOFT_RESET_MASK 0x00000080 +#define AB8500_DENC_CONF6_SOFT_RESET(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF6, SOFT_RESET, __x) +#define AB8500_DENC_CONF6_JUMP_SHIFT 6 +#define AB8500_DENC_CONF6_JUMP_MASK 0x00000040 +#define AB8500_DENC_CONF6_JUMP(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF6, JUMP, __x) +#define AB8500_DENC_CONF6_DEC_NINC_SHIFT 5 +#define AB8500_DENC_CONF6_DEC_NINC_MASK 0x00000020 +#define AB8500_DENC_CONF6_DEC_NINC(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF6, DEC_NINC, __x) +#define AB8500_DENC_CONF6_FREE_JUMP_SHIFT 4 +#define AB8500_DENC_CONF6_FREE_JUMP_MASK 0x00000010 +#define AB8500_DENC_CONF6_FREE_JUMP(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF6, FREE_JUMP, __x) +#define AB8500_DENC_CONF6_MAX_DYN_SHIFT 0 +#define AB8500_DENC_CONF6_MAX_DYN_MASK 0x00000001 +#define AB8500_DENC_CONF6_MAX_DYN(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF6, MAX_DYN, __x) +#define AB8500_DENC_CONF8 0x00000608 +#define AB8500_DENC_CONF8_PH_RST_MODE_SHIFT 6 +#define AB8500_DENC_CONF8_PH_RST_MODE_MASK 0x000000C0 +#define AB8500_DENC_CONF8_PH_RST_MODE_DISABLED 0 +#define AB8500_DENC_CONF8_PH_RST_MODE_UPDATE_FROM_PHASE_BUF 1 +#define AB8500_DENC_CONF8_PH_RST_MODE_UPDATE_FROM_INC_DFS 2 +#define AB8500_DENC_CONF8_PH_RST_MODE_RESET 3 +#define AB8500_DENC_CONF8_PH_RST_MODE(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF8, PH_RST_MODE, \ + AB8500_DENC_CONF8_PH_RST_MODE_##__x) +#define AB8500_DENC_CONF8_VAL_422_MUX_SHIFT 4 +#define AB8500_DENC_CONF8_VAL_422_MUX_MASK 0x00000010 +#define AB8500_DENC_CONF8_VAL_422_MUX_TEST 0 +#define AB8500_DENC_CONF8_VAL_422_MUX_ACTIVE 1 +#define AB8500_DENC_CONF8_VAL_422_MUX(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF8, VAL_422_MUX, \ + AB8500_DENC_CONF8_VAL_422_MUX_##__x) +#define AB8500_DENC_CONF8_BLK_ALL_SHIFT 3 +#define AB8500_DENC_CONF8_BLK_ALL_MASK 0x00000008 +#define AB8500_DENC_CONF8_BLK_ALL(__x) \ + AB8500_VAL2REG(AB8500_DENC_CONF8, BLK_ALL, __x) +#define AB8500_TVOUT_CTRL 0x00000680 +#define AB8500_TVOUT_CTRL_TV_LOAD_RC_SHIFT 6 +#define AB8500_TVOUT_CTRL_TV_LOAD_RC_MASK 0x00000040 +#define AB8500_TVOUT_CTRL_TV_LOAD_RC(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL, TV_LOAD_RC, __x) +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_SHIFT 3 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_MASK 0x00000038 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_0_5S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_1S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_1_5S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_2S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_2_5S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME_3S 0 +#define AB8500_TVOUT_CTRL_PLUG_TV_TIME(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL, PLUG_TV_TIME, \ + AB8500_TVOUT_CTRL_PLUG_TV_TIME_##__x) +#define AB8500_TVOUT_CTRL_TV_PLUG_ON_SHIFT 2 +#define AB8500_TVOUT_CTRL_TV_PLUG_ON_MASK 0x00000004 +#define AB8500_TVOUT_CTRL_TV_PLUG_ON(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL, TV_PLUG_ON, __x) +#define AB8500_TVOUT_CTRL_DAC_CTRL0_SHIFT 1 +#define AB8500_TVOUT_CTRL_DAC_CTRL0_MASK 0x00000002 +#define AB8500_TVOUT_CTRL_DAC_CTRL0(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL, DAC_CTRL0, __x) +#define AB8500_TVOUT_CTRL_DAC_CTRL1_SHIFT 0 +#define AB8500_TVOUT_CTRL_DAC_CTRL1_MASK 0x00000001 +#define AB8500_TVOUT_CTRL_DAC_CTRL1(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL, DAC_CTRL1, __x) +#define AB8500_TVOUT_CTRL2 0x00000681 +#define AB8500_TVOUT_CTRL2_SWAP_DDR_DATA_IN_SHIFT 1 +#define AB8500_TVOUT_CTRL2_SWAP_DDR_DATA_IN_MASK 0x00000002 +#define AB8500_TVOUT_CTRL2_SWAP_DDR_DATA_IN(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL2, SWAP_DDR_DATA_IN, __x) +#define AB8500_TVOUT_CTRL2_DENC_DDR_SHIFT 0 +#define AB8500_TVOUT_CTRL2_DENC_DDR_MASK 0x00000001 +#define AB8500_TVOUT_CTRL2_DENC_DDR(__x) \ + AB8500_VAL2REG(AB8500_TVOUT_CTRL2, DENC_DDR, __x) +#define AB8500_IT_MASK1 0x00000E40 +#define AB8500_IT_MASK1_PON_KEY1_DBR_SHIFT 7 +#define AB8500_IT_MASK1_PON_KEY1_DBR_MASK 0x00000080 +#define AB8500_IT_MASK1_PON_KEY1_DBR(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, PON_KEY1_DBR, __x) +#define AB8500_IT_MASK1_PON_KEY1_DBF_SHIFT 6 +#define AB8500_IT_MASK1_PON_KEY1_DBF_MASK 0x00000040 +#define AB8500_IT_MASK1_PON_KEY1_DBF(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, PON_KEY1_DBF, __x) +#define AB8500_IT_MASK1_PON_KEY2_DBR_SHIFT 5 +#define AB8500_IT_MASK1_PON_KEY2_DBR_MASK 0x00000020 +#define AB8500_IT_MASK1_PON_KEY2_DBR(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, PON_KEY2_DBR, __x) +#define AB8500_IT_MASK1_PON_KEY2_DBF_SHIFT 4 +#define AB8500_IT_MASK1_PON_KEY2_DBF_MASK 0x00000010 +#define AB8500_IT_MASK1_PON_KEY2_DBF(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, PON_KEY2_DBF, __x) +#define AB8500_IT_MASK1_TEMP_WARN_SHIFT 3 +#define AB8500_IT_MASK1_TEMP_WARN_MASK 0x00000008 +#define AB8500_IT_MASK1_TEMP_WARN(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, TEMP_WARN, __x) +#define AB8500_IT_MASK1_PLUG_TV_DET_SHIFT 2 +#define AB8500_IT_MASK1_PLUG_TV_DET_MASK 0x00000004 +#define AB8500_IT_MASK1_PLUG_TV_DET(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, PLUG_TV_DET, __x) +#define AB8500_IT_MASK1_UNPLUG_TV_DET_SHIFT 1 +#define AB8500_IT_MASK1_UNPLUG_TV_DET_MASK 0x00000002 +#define AB8500_IT_MASK1_UNPLUG_TV_DET(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, UNPLUG_TV_DET, __x) +#define AB8500_IT_MASK1_MAIN_EXT_CH_NOK_SHIFT 0 +#define AB8500_IT_MASK1_MAIN_EXT_CH_NOK_MASK 0x00000001 +#define AB8500_IT_MASK1_MAIN_EXT_CH_NOK(__x) \ + AB8500_VAL2REG(AB8500_IT_MASK1, MAIN_EXT_CH_NOK, __x) +#define AB8500_REV 0x00001080 +#define AB8500_REV_FULL_MASK_SHIFT 4 +#define AB8500_REV_FULL_MASK_MASK 0x000000F0 +#define AB8500_REV_FULL_MASK(__x) \ + AB8500_VAL2REG(AB8500_REV, FULL_MASK, __x) +#define AB8500_REV_METAL_FIX_SHIFT 0 +#define AB8500_REV_METAL_FIX_MASK 0x0000000F +#define AB8500_REV_METAL_FIX(__x) \ + AB8500_VAL2REG(AB8500_REV, METAL_FIX, __x) + +#endif /* __AB8500_DENC_H */ diff --git a/include/linux/mfd/ab8500/denc.h b/include/linux/mfd/ab8500/denc.h new file mode 100644 index 00000000000..25a09a2c2bd --- /dev/null +++ b/include/linux/mfd/ab8500/denc.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * AB8500 tvout driver interface + * + * Author: Marcel Tunnissen + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ +#ifndef __AB8500_DENC__H__ +#define __AB8500_DENC__H__ + +#include + +struct ab8500_denc_platform_data { + /* Platform info */ + bool ddr_enable; + bool ddr_little_endian; +}; + +enum ab8500_denc_TV_std { + TV_STD_PAL_BDGHI, + TV_STD_PAL_N, + TV_STD_PAL_M, + TV_STD_NTSC_M, +}; + +enum ab8500_denc_cr_filter_bandwidth { + TV_CR_NTSC_LOW_DEF_FILTER, + TV_CR_PAL_LOW_DEF_FILTER, + TV_CR_NTSC_HIGH_DEF_FILTER, + TV_CR_PAL_HIGH_DEF_FILTER, +}; + +enum ab8500_denc_phase_reset_mode { + TV_PHASE_RST_MOD_DISABLE, + TV_PHASE_RST_MOD_FROM_PHASE_BUF, + TV_PHASE_RST_MOD_FROM_INC_DFS, + TV_PHASE_RST_MOD_RST, +}; + +enum ab8500_denc_plug_time { + TV_PLUG_TIME_0_5S, + TV_PLUG_TIME_1S, + TV_PLUG_TIME_1_5S, + TV_PLUG_TIME_2S, + TV_PLUG_TIME_2_5S, + TV_PLUG_TIME_3S, +}; + +struct ab8500_denc_conf { + /* register settings for DENC_configuration */ + bool act_output; + enum ab8500_denc_TV_std TV_std; + bool progressive; + bool test_pattern; + bool partial_blanking; + bool blank_all; + bool black_level_setup; + enum ab8500_denc_cr_filter_bandwidth cr_filter; + bool suppress_col; + enum ab8500_denc_phase_reset_mode phase_reset_mode; + bool dac_enable; + bool act_dc_output; +}; + +struct platform_device *ab8500_denc_get_device(void); +void ab8500_denc_put_device(struct platform_device *pdev); + +void ab8500_denc_reset(struct platform_device *pdev, bool hard); +void ab8500_denc_power_up(struct platform_device *pdev); +void ab8500_denc_power_down(struct platform_device *pdev); + +void ab8500_denc_conf(struct platform_device *pdev, + struct ab8500_denc_conf *conf); +void ab8500_denc_conf_plug_detect(struct platform_device *pdev, + bool enable, bool load_RC, + enum ab8500_denc_plug_time time); +void ab8500_denc_mask_int_plug_det(struct platform_device *pdev, bool plug, + bool unplug); +#endif /* __AB8500_DENC__H__ */ diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index fccc3002f27..c1016272ab2 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -211,6 +211,9 @@ enum ab8500_version { #define AB8500_NUM_IRQ_REGS 14 #define AB9540_NUM_IRQ_REGS 17 +/* Forward declaration */ +struct ab8500_charger; + /** * struct ab8500 - ab8500 internal structure * @dev: parent device @@ -229,12 +232,12 @@ enum ab8500_version { * @mask_size: Actual number of valid entries in mask[], oldmask[] and * irq_reg_offset * @irq_reg_offset: Array of offsets into IRQ registers + * @charger: pointer to the charger driver device information. */ struct ab8500 { struct device *dev; struct mutex lock; struct mutex irq_lock; - int irq_base; int irq; enum ab8500_version version; @@ -251,10 +254,14 @@ struct ab8500 { u8 *oldmask; int mask_size; const int *irq_reg_offset; + + struct ab8500_charger *charger; }; struct regulator_reg_init; struct regulator_init_data; +struct ab8500_denc_platform_data; +struct ab8500_audio_platform_data; struct ab8500_gpio_platform_data; /** @@ -265,14 +272,25 @@ struct ab8500_gpio_platform_data; * @regulator_reg_init: regulator init registers * @num_regulator: number of regulators * @regulator: machine-specific constraints for regulators + * @battery: machine-specific battery management data + * @charger: machine-specific charger data + * @btemp: machine-specific battery temp data */ struct ab8500_platform_data { int irq_base; + bool pm_power_off; void (*init) (struct ab8500 *); int num_regulator_reg_init; struct ab8500_regulator_reg_init *regulator_reg_init; int num_regulator; struct regulator_init_data *regulator; + struct ab8500_bm_data *battery; + struct ab8500_denc_platform_data *denc; + struct ab8500_audio_platform_data *audio; + struct ab8500_charger_platform_data *charger; + struct ab8500_btemp_platform_data *btemp; + struct ab8500_fg_platform_data *fg; + struct ab8500_chargalg_platform_data *chargalg; struct ab8500_gpio_platform_data *gpio; }; -- cgit v1.2.3 From 89f1289bab27aafdbabd88571218603895064d3a Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 10:00:39 +0200 Subject: hwmon db8500: update for new prcmu interface --- drivers/hwmon/db8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/db8500.c b/drivers/hwmon/db8500.c index 09630f2f707..e28f9938eb4 100755 --- a/drivers/hwmon/db8500.c +++ b/drivers/hwmon/db8500.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 7ef0b5717dd7edcae9f2602cc69e48cf148ec87f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 28 Mar 2011 13:18:24 +0200 Subject: ux500-ARM : make backup RAM as an executable area On the v1.0/ED boards, during the deep sleep resume, it is required to make the backup RAM area as "executable" in order manage MMU settings for a single core mode. As a result, the rom code requires such a condition for aligning SMP strategy for different per-core MMU configuration. This patch makes the backup RAM configuration area as executable by adding a new memory type. *This change will not be needed for U8500 v2.0 as the rom code would (hopefully as discussions are showing) be updated with a minor API change* This patch is a part of patches for the deep sleep feature for the U8500 and FIDO_IR_ER: 258539 This patch *must* be re-visisted during u8500 v2.0 cut or mainlining the deep sleep to community Signed-off-by: Sundar R Iyer Acked-By: Biju C Das Signed-off-by: Mian Yousaf Kaukab Change-Id: Id4d8215ca1e9aaf8f327ff3f55f3f9ca1e68aef5 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2190 Reviewed-by: Jonas ABERG --- arch/arm/include/asm/io.h | 6 ++++++ arch/arm/mm/mmu.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 9af5563dd3e..d9a9a19cb68 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -62,6 +62,12 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define MT_DEVICE_NONSHARED 1 #define MT_DEVICE_CACHED 2 #define MT_DEVICE_WC 3 +/* + * NOTE : U8500 v1.0/ED cut specific hack. + * look at the commit message for more details + */ +#define MT_BACKUP_RAM 4 + /* * types 4 onwards can be found in asm/mach/map.h and are undefined * for ioremap diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index aa78de8bfdd..4ecd1f8bbb5 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -288,6 +288,20 @@ static struct mem_type mem_types[] = { PMD_SECT_UNCACHED | PMD_SECT_XN, .domain = DOMAIN_KERNEL, }, + /* NOTE : this is only a temporary hack!!! + * The U8500 ED/V1.0 cuts require such a + * memory type for deep sleep resume. + * This is expected to be solved in cut v2.0 + * and we clean this up then. for more details + * look @ the commit message please + */ + [MT_BACKUP_RAM] = { + .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | + L_PTE_SHARED, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, + .domain = DOMAIN_IO, + }, }; const struct mem_type *get_mem_type(unsigned int type) -- cgit v1.2.3 From 17ef9643d378f3c12ec33a2040e2e3b394db3133 Mon Sep 17 00:00:00 2001 From: Sundar R Iyer Date: Tue, 9 Feb 2010 15:52:26 +0530 Subject: ARM : handle preempt count in cpu_idle Signed-off-by: Sundar R Iyer Acked-by: Linus Walleij Signed-off-by: Mian Yousaf Kaukab --- arch/arm/kernel/process.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 2b7b017a20c..5b644d3e831 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -212,8 +212,17 @@ void cpu_idle(void) leds_event(led_idle_start); while (!need_resched()) { #ifdef CONFIG_HOTPLUG_CPU - if (cpu_is_offline(smp_processor_id())) + if (cpu_is_offline(smp_processor_id())) { + + /* NOTE : preempt_count() should be 0 for dying CPU + * as the CPU will use this very thread when + * it is alive + */ + if (preempt_count()) + preempt_enable_no_resched(); + cpu_die(); + } #endif /* -- cgit v1.2.3 From e3b6400a1b55e9e5b691a513a1fd407b2757b622 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 28 Mar 2011 10:49:09 +0200 Subject: u8500: enable u8500 configurations Signed-off-by: Mian Yousaf Kaukab --- arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 36586dba6fa..d83b199fd54 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -933,9 +933,11 @@ config ARCH_U8500 select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK select ARCH_HAS_CPUFREQ select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 + select NOMADIK_GPIO help Support for ST-Ericsson's Ux500 architecture -- cgit v1.2.3 From d406ed2f763ea85223c38b33a0de4376b999b100 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 28 Mar 2011 11:08:15 +0200 Subject: Add clean and flush_dcache_all to ARM cache API This patch adds functions to flush and clean the entire data cache. Since the existing flush/clean range functions take more time to flush/clean the entire data cache, they cannot be used. Whenever the range of data to be flushed/cleaned from the data cache is more than some threshold value, it is better to do the entire data flush/clean, this will reduce the time taken and effectively increases the performance of the system. ST-Ericsson ID: IR275682 ER275397 Change-Id: I8d7e6004232301cc2c9922738fa728cdc833cfde Signed-off-by: Johan Mossberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/7161 Reviewed-by: Robert FEKETE Reviewed-by: Srinidhi KASAGAR Conflicts: arch/arm/mm/cache-v7.S --- arch/arm/include/asm/cacheflush.h | 15 +++++++ arch/arm/mm/cache-fa.S | 18 ++++++++ arch/arm/mm/cache-v3.S | 18 ++++++++ arch/arm/mm/cache-v4.S | 18 ++++++++ arch/arm/mm/cache-v4wb.S | 18 ++++++++ arch/arm/mm/cache-v4wt.S | 18 ++++++++ arch/arm/mm/cache-v6.S | 18 ++++++++ arch/arm/mm/cache-v7.S | 94 ++++++++++++++++++++++++++++++++++++--- arch/arm/mm/proc-macros.S | 2 + arch/arm/mm/proc-v7.S | 2 +- 10 files changed, 214 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d5d8d5c7268..a4bf3199819 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -84,6 +84,14 @@ * - kaddr - page address * - size - region size * + * clean_dcache_all() + * + * Cleans the entire d-cache. + * + * flush_dcache_all() + * + * Flushes the entire d-cache. + * * DMA Cache Coherency * =================== * @@ -104,6 +112,9 @@ struct cpu_cache_fns { void (*coherent_user_range)(unsigned long, unsigned long); void (*flush_kern_dcache_area)(void *, size_t); + void (*clean_dcache_all)(void); + void (*flush_dcache_all)(void); + void (*dma_map_area)(const void *, size_t, int); void (*dma_unmap_area)(const void *, size_t, int); @@ -124,6 +135,8 @@ extern struct cpu_cache_fns cpu_cache; #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range #define __cpuc_coherent_user_range cpu_cache.coherent_user_range #define __cpuc_flush_dcache_area cpu_cache.flush_kern_dcache_area +#define __cpuc_clean_dcache_all cpu_cache.clean_dcache_all +#define __cpuc_flush_dcache_all cpu_cache.flush_dcache_all /* * These are private to the dma-mapping API. Do not use directly. @@ -144,6 +157,8 @@ extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); extern void __cpuc_coherent_user_range(unsigned long, unsigned long); extern void __cpuc_flush_dcache_area(void *, size_t); +extern void __cpuc_clean_dcache_all(void); +extern void __cpuc_flush_dcache_all(void); /* * These are private to the dma-mapping API. Do not use directly. diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 07201637109..226f8736152 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -240,6 +240,24 @@ ENTRY(fa_dma_unmap_area) mov pc, lr ENDPROC(fa_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(fa_clean_dcache_all) + mov pc, lr +ENDPROC(fa_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(fa_flush_dcache_all) + mov pc, lr +ENDPROC(fa_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index c2301f22610..ab5bf508a2a 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -127,6 +127,24 @@ ENTRY(v3_dma_map_area) ENDPROC(v3_dma_unmap_area) ENDPROC(v3_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v3_clean_dcache_all) + mov pc, lr +ENDPROC(v3_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v3_flush_dcache_all) + mov pc, lr +ENDPROC(v3_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index fd9bb7addc8..9d3a055127e 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -139,6 +139,24 @@ ENTRY(v4_dma_map_area) ENDPROC(v4_dma_unmap_area) ENDPROC(v4_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4_clean_dcache_all) + mov pc, lr +ENDPROC(v4_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4_flush_dcache_all) + mov pc, lr +ENDPROC(v4_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 4f2c14151cc..54d3cda4a89 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -251,6 +251,24 @@ ENTRY(v4wb_dma_unmap_area) mov pc, lr ENDPROC(v4wb_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4wb_clean_dcache_all) + mov pc, lr +ENDPROC(v4wb_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4wb_flush_dcache_all) + mov pc, lr +ENDPROC(v4wb_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 4d7b467631c..40f7dba11f5 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -195,6 +195,24 @@ ENTRY(v4wt_dma_map_area) ENDPROC(v4wt_dma_unmap_area) ENDPROC(v4wt_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4wt_clean_dcache_all) + mov pc, lr +ENDPROC(v4wt_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4wt_flush_dcache_all) + mov pc, lr +ENDPROC(v4wt_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 74c2e5a33a4..b88dd4ab038 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -328,6 +328,24 @@ ENTRY(v6_dma_unmap_area) mov pc, lr ENDPROC(v6_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v6_clean_dcache_all) + mov pc, lr +ENDPROC(v6_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v6_flush_dcache_all) + mov pc, lr +ENDPROC(v6_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index a655d3da386..70744d6a066 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -33,7 +33,7 @@ ENTRY(v7_flush_icache_all) ENDPROC(v7_flush_icache_all) /* - * v7_flush_dcache_all() + * __v7_flush_dcache_all() * * Flush the whole D-cache. * @@ -41,7 +41,7 @@ ENDPROC(v7_flush_icache_all) * * - mm - mm_struct describing address space */ -ENTRY(v7_flush_dcache_all) +ENTRY(__v7_flush_dcache_all) dmb @ ensure ordering with previous memory accesses mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr @@ -94,8 +94,92 @@ finished: dsb isb mov pc, lr +ENDPROC(__v7_flush_dcache_all) + +/* + * __v7_clean_dcache_all() + * + * Clean the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + */ +ENTRY(__v7_clean_dcache_all) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished1 @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop21: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip1 @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop22: + mov r9, r4 @ create working copy of max way size +loop23: + ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r9, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r7, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 + mcr p15, 0, r11, c7, c10, 2 @ clean by set/way + subs r9, r9, #1 @ decrement the way + bge loop23 + subs r7, r7, #1 @ decrement the index + bge loop22 +skip1: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop21 +finished1: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb + isb + mov pc, lr +ENDPROC(__v7_clean_dcache_all) + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v7_flush_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_flush_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr ENDPROC(v7_flush_dcache_all) +/* + * v7_clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v7_clean_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_clean_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr +ENDPROC(v7_clean_dcache_all) + /* * v7_flush_cache_all() * @@ -108,14 +192,12 @@ ENDPROC(v7_flush_dcache_all) * */ ENTRY(v7_flush_kern_cache_all) - ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) - THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + stmfd sp!, {lr} bl v7_flush_dcache_all mov r0, #0 ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate - ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) - THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + ldmfd sp!, {lr} mov pc, lr ENDPROC(v7_flush_kern_cache_all) diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 2d8ff3ad86d..518ab10fea5 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -304,6 +304,8 @@ ENTRY(\name\()_cache_fns) .long \name\()_coherent_kern_range .long \name\()_coherent_user_range .long \name\()_flush_kern_dcache_area + .long \name\()_clean_dcache_all + .long \name\()_flush_dcache_all .long \name\()_dma_map_area .long \name\()_dma_unmap_area .long \name\()_dma_flush_range diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index c2e2b66f72b..d1c42ead765 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -172,7 +172,7 @@ __v7_ca15mp_setup: __v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all + bl __v7_flush_dcache_all ldmia r12, {r0-r5, r7, r9, r11, lr} mrc p15, 0, r0, c0, c0, 0 @ read main ID register -- cgit v1.2.3 From 7ad8c791b913fa602dcfeb597d566daa71dff7f9 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 28 Mar 2011 11:24:09 +0200 Subject: ARM: Translate delay.S into (mostly) C We want to allow machines to override the __delay() implementation at runtime so they can use a timer based __delay() routine. It's easier to do this using C, so let's write udelay and friends in C. We lose the #if 0 code, which according to Russell is used "to make the delay loop more stable and predictable on older CPUs" (see http://article.gmane.org/gmane.linux.kernel/888867 for more info). We shouldn't be too worried though, since we'll soon add functionality allowing a machine to set the __delay() loop themselves, thus allowing machines to resurrect the commented out code should they need it. Nico expressed concern that fixed lpj cmdlines will break due to compiler optimizations. That doesn't seem to be the case since before and after this patch I get the same lpj value when running my CPU at 19.2 MHz. That should be sufficiently slow enough to cover any machine running Linux. Reviewed-by: Saravana Kannan Acked-by: Nicolas Pitre Signed-off-by: Stephen Boyd Change-Id: I84311dc3955250960ffa8dc56d45a4833b3ad0f2 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/13562 Tested-by: Mattias WALLIN Reviewed-by: Jonas ABERG Conflicts: arch/arm/lib/delay.S --- arch/arm/include/asm/delay.h | 2 +- arch/arm/kernel/armksyms.c | 4 --- arch/arm/lib/delay.S | 69 -------------------------------------------- arch/arm/lib/delay.c | 56 +++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 74 deletions(-) delete mode 100644 arch/arm/lib/delay.S create mode 100644 arch/arm/lib/delay.c diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index b2deda18154..ccc5ed573fa 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -8,7 +8,7 @@ #include /* HZ */ -extern void __delay(int loops); +extern void __delay(unsigned long loops); /* * This function intentionally does not exist; if you see references to diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index b57c75e0b01..f1a50f37efd 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -48,10 +48,6 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); - /* platform dependent support */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__const_udelay); - /* networking */ EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_from_user); diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S deleted file mode 100644 index 3c9a05c8d20..00000000000 --- a/arch/arm/lib/delay.S +++ /dev/null @@ -1,69 +0,0 @@ -/* - * linux/arch/arm/lib/delay.S - * - * Copyright (C) 1995, 1996 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include - .text - -.LC0: .word loops_per_jiffy -.LC1: .word (2199023*HZ)>>11 - -/* - * r0 <= 2000 - * lpj <= 0x01ffffff (max. 3355 bogomips) - * HZ <= 1000 - */ - -ENTRY(__udelay) - ldr r2, .LC1 - mul r0, r2, r0 -ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 - mov r1, #-1 - ldr r2, .LC0 - ldr r2, [r2] @ max = 0x01ffffff - add r0, r0, r1, lsr #32-14 - mov r0, r0, lsr #14 @ max = 0x0001ffff - add r2, r2, r1, lsr #32-10 - mov r2, r2, lsr #10 @ max = 0x00007fff - mul r0, r2, r0 @ max = 2^32-1 - add r0, r0, r1, lsr #32-6 - movs r0, r0, lsr #6 - moveq pc, lr - -/* - * loops = r0 * HZ * loops_per_jiffy / 1000000 - * - * Oh, if only we had a cycle counter... - */ - -@ Delay routine -ENTRY(__delay) - subs r0, r0, #1 -#if 0 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 -#endif - bhi __delay - mov pc, lr -ENDPROC(__udelay) -ENDPROC(__const_udelay) -ENDPROC(__delay) diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c new file mode 100644 index 00000000000..f92aca011ba --- /dev/null +++ b/arch/arm/lib/delay.c @@ -0,0 +1,56 @@ +/* + * Originally from linux/arch/arm/lib/delay.S + * + * Copyright (C) 1995, 1996 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + +/* + * loops = usecs * HZ * loops_per_jiffy / 1000000 + * + * Oh, if only we had a cycle counter... + */ +void __delay(unsigned long loops) +{ + asm volatile( + "1: subs %0, %0, #1 \n" + " bhi 1b \n" + : /* No output */ + : "r" (loops) + ); +} +EXPORT_SYMBOL(__delay); + +/* + * 0 <= xloops <= 0x7fffff06 + * loops_per_jiffy <= 0x01ffffff (max. 3355 bogomips) + */ +void __const_udelay(unsigned long xloops) +{ + unsigned long lpj; + unsigned long loops; + + xloops >>= 14; /* max = 0x01ffffff */ + lpj = loops_per_jiffy >> 10; /* max = 0x0001ffff */ + loops = lpj * xloops; /* max = 0x00007fff */ + loops >>= 6; /* max = 2^32-1 */ + + if (likely(loops)) + __delay(loops); +} +EXPORT_SYMBOL(__const_udelay); + +/* + * usecs <= 2000 + * HZ <= 1000 + */ +void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * ((2199023*HZ)>>11)); +} +EXPORT_SYMBOL(__udelay); -- cgit v1.2.3 From 958c216e22e59927b49edc01bbc513b21db7611d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 20 Dec 2010 14:20:31 -0800 Subject: ARM: Allow machines to override __delay() Some machines want to implement their own __delay() routine based on fixed rate timers. Expose functionality to set the __delay() routine at runtime. This should allow two machines with different __delay() routines to happily co-exist within the same kernel with minimal overhead. Russell expressed concern that using a timer based __delay() would cause problems when an iomapped device isn't mapped in prior to a delay call being made (see http://article.gmane.org/gmane.linux.ports.arm.kernel/78543 for more info). We can sidestep that issue with this approach since the __delay() routine _should_ only be pointed to a timer based delay once the timer has been properly mapped. Up until that point __delay() and udelay() will use delay_loop() which is always safe to call. This patch is inspired by x86's delay.c Reviewed-by: Saravana Kannan Signed-off-by: Stephen Boyd Change-Id: I269f101b40ba50c2b635dc92d50f6e82bb934b32 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/13563 Tested-by: Mattias WALLIN Reviewed-by: Jonas ABERG --- arch/arm/include/asm/delay.h | 7 +++++++ arch/arm/lib/delay.c | 14 +++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index ccc5ed573fa..82ef82a417b 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -40,5 +40,12 @@ extern void __const_udelay(unsigned long); __const_udelay((n) * ((2199023U*HZ)>>11))) : \ __udelay(n)) +extern void (*delay_fn)(unsigned long); + +static inline void set_delay_fn(void (*fn)(unsigned long)) +{ + delay_fn = fn; +} + #endif /* defined(_ARM_DELAY_H) */ diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index f92aca011ba..7468bc64b35 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -11,11 +11,9 @@ #include /* - * loops = usecs * HZ * loops_per_jiffy / 1000000 - * * Oh, if only we had a cycle counter... */ -void __delay(unsigned long loops) +static void delay_loop(unsigned long loops) { asm volatile( "1: subs %0, %0, #1 \n" @@ -24,6 +22,16 @@ void __delay(unsigned long loops) : "r" (loops) ); } + +void (*delay_fn)(unsigned long) = delay_loop; + +/* + * loops = usecs * HZ * loops_per_jiffy / 1000000 + */ +void __delay(unsigned long loops) +{ + delay_fn(loops); +} EXPORT_SYMBOL(__delay); /* -- cgit v1.2.3 From 5eabe9def7766552059f9d6602e67252b2ed55f5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 20 Dec 2010 14:20:32 -0800 Subject: ARM: Implement a timer based __delay() loop udelay() can be incorrect on SMP machines that scale their CPU frequencies independently of one another (as pointed out here http://article.gmane.org/gmane.linux.kernel/977567). The delay loop can either be too fast or too slow depending on which CPU the loops_per_jiffy counter is calibrated on and which CPU the delay loop is running on. udelay() can also be incorrect if the CPU frequency switches during the __delay() loop, causing the loop to either terminate too early, or too late. Forcing udelay() to run on one CPU is unreasonable and taking the penalty of a rather large loops_per_jiffy in udelay() when the CPU is actually running slower is bad for performance. Solve the problem by adding a timer based__delay() loop unaffected by CPU frequency scaling. Machines should set this loop as their __delay() implementation by calling set_timer_fn() during their timer initialization. The kernel is already prepared for a timer based approach (evident by the read_current_timer() function). If an arch implements read_current_timer(), calibrate_delay() will use calibrate_delay_direct() to calculate loops_per_jiffy (in which case loops_per_jiffy should really be renamed to timer_ticks_per_jiffy). Since the loops_per_jiffy will be based on timer ticks, __delay() should be implemented as a loop around read_current_timer(). Doing this makes the expensive loops_per_jiffy calculation go away (saving ~150ms on boot time on my machine) and fixes udelay() by making it safe in the face of independently scaling CPUs. The only prerequisite is that read_current_timer() is monotonically increasing across calls (and doesn't overflow within ~2000us). There is a downside to this approach though. BogoMIPS is no longer "accurate" in that it reflects the BogoMIPS of the timer and not the CPU. On most SoC's the timer isn't running anywhere near as fast as the CPU so BogoMIPS will be ridiculously low (my timer runs at 4.8 MHz and thus my BogoMIPS is 9.6 compared to my CPU's 800). This shouldn't be too much of a concern though since BogoMIPS are bogus anyway (hence the name). This loop is pretty much a copy of AVR's version. Reported-and-reviewed-by: Saravana Kannan Signed-off-by: Stephen Boyd Change-Id: I9a4bee236ff1f26e1f2ae7e15e92b9ba14b46952 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/13564 Tested-by: Mattias WALLIN Reviewed-by: Jonas ABERG --- arch/arm/include/asm/delay.h | 2 ++ arch/arm/lib/delay.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index 82ef82a417b..91063a3976f 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -47,5 +47,7 @@ static inline void set_delay_fn(void (*fn)(unsigned long)) delay_fn = fn; } +extern void read_current_timer_delay_loop(unsigned long loops); + #endif /* defined(_ARM_DELAY_H) */ diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 7468bc64b35..f24c956e4fd 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -9,6 +9,7 @@ */ #include #include +#include /* * Oh, if only we had a cycle counter... @@ -23,6 +24,22 @@ static void delay_loop(unsigned long loops) ); } +#ifdef ARCH_HAS_READ_CURRENT_TIMER +/* + * Assumes read_current_timer() is monotonically increasing + * across calls and wraps at most once within MAX_UDELAY_MS. + */ +void read_current_timer_delay_loop(unsigned long loops) +{ + unsigned long bclock, now; + + read_current_timer(&bclock); + do { + read_current_timer(&now); + } while ((now - bclock) < loops); +} +#endif + void (*delay_fn)(unsigned long) = delay_loop; /* -- cgit v1.2.3 From a55813dffeb7a0527ae29b64b3de19fab967be67 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 28 Feb 2011 16:43:44 +0100 Subject: ARM: kernel: Remove warnings This patch removes a warning in order to reach a point where we have zero warnings and Hudson can start to give -1 results on any added ones. This patch shall never reach mainline. ST-Ericsson Linux next: Never ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Jonas Aaberg Change-Id: Ic80fb9b7280a52c1e03948de91b602d148b1a760 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17154 Reviewed-by: Mattias WALLIN --- arch/arm/kernel/return_address.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 8085417555d..0697db65efa 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -58,10 +58,6 @@ void *return_address(unsigned int level) #else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */ -#if defined(CONFIG_ARM_UNWIND) -#warning "TODO: return_address should use unwind tables" -#endif - void *return_address(unsigned int level) { return NULL; -- cgit v1.2.3 From 39a9b128042ca61a7c4868f694c5472e747b2224 Mon Sep 17 00:00:00 2001 From: "Mathieu J. Poirier" Date: Tue, 29 Mar 2011 16:29:14 -0600 Subject: Adding configuration options for cg2900. Signed-off-by: Mathieu Poirier --- arch/arm/configs/u8500_defconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 7e84f453e8a..4125f5b022a 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -93,6 +93,13 @@ CONFIG_STE_DMA40=y CONFIG_STAGING=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y +CONFIG_CG2900=y +CONFIG_CG2900_CHIP=y +CONFIG_STLC2690_CHIP=y +CONFIG_CG2900_UART=y +CONFIG_CG2900_AUDIO=y +CONFIG_CG2900_TEST=y +CONFIG_BT_CG2900=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -105,6 +112,8 @@ CONFIG_CONFIGFS_FS=m # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_BLKDEV_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y -- cgit v1.2.3 From 76097ff3a5e028d3f7837f8372a38b23fe63c0c3 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 17 Mar 2011 09:45:22 +0100 Subject: amba-pl022: Add loopback support for the SPI on 5500 Add new amba-pl022 vendor for the DB5500 pl023, as the pl023 on db8500 and db5500 vary. Signed-off-by: Prajadevi H Signed-off-by: Philippe Langlais --- drivers/spi/spi-pl022.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 7a137e9bde6..97351afc7c8 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2270,14 +2270,6 @@ static struct vendor_data vendor_db5500_pl023 = { .loopback = true, }; -static struct vendor_data vendor_db5500_pl023 = { - .fifodepth = 32, - .max_bpw = 32, - .unidir = false, - .extended_cr = true, - .pl023 = true, -}; - static struct amba_id pl022_ids[] = { { /* -- cgit v1.2.3 From ec0d6dca5bdd0df5372ee2bf2a04fd4e19ffd384 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 7 Mar 2011 11:39:35 +0100 Subject: mfd: add a core driver for TI TPS61050/TPS61052 chips v2 The TPS61050/TPS61052 are boost converters, LED drivers, LED flash drivers and a simple GPIO pin chips. Cc: Liam Girdwood Cc: Mark Brown Cc: Jonas Aberg Cc: Ola Lilja Signed-off-by: Linus Walleij --- drivers/mfd/tps6105x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index a293b978e27..d7b9e0c60ea 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -195,6 +195,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, return 0; fail: + i2c_set_clientdata(client, NULL); kfree(tps6105x); return ret; } -- cgit v1.2.3 From 03d5567aa5b1cfd89e01bd828763277c384fcc8c Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 1 Apr 2011 16:17:19 +0200 Subject: BH1780: Fix regulator name --- drivers/misc/bh1780gli.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index b3f6e54596a..a7c012a6545 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -177,9 +177,8 @@ static int __devinit bh1780_probe(struct i2c_client *client, ddata->client = client; i2c_set_clientdata(client, ddata); - dev_set_name(&client->dev, "bh1780"); - ddata->regulator = regulator_get(&client->dev, "v-als"); + ddata->regulator = regulator_get(&client->dev, "vcc"); if (IS_ERR(ddata->regulator)) { dev_err(&client->dev, "failed to get regulator\n"); ret = PTR_ERR(ddata->regulator); -- cgit v1.2.3 From 8f792e2f6a7dc01fd3c96cd6950afc5c9c56e29c Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 11 Apr 2011 11:36:54 +0200 Subject: ux500: Align u8500 defconfig with 2.6.35 one, u5500 is enabled too Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 160 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 12 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4125f5b022a..13d926e2150 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,26 +1,53 @@ CONFIG_EXPERIMENTAL=y -# CONFIG_SWAP is not set +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y CONFIG_KALLSYMS_ALL=y +CONFIG_PERF_EVENTS=y +CONFIG_SLAB=y +CONFIG_BOOTTIME=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -# CONFIG_LBDAF is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_HREFV60=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y +CONFIG_DB8500_MLOADER=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 +CONFIG_UX500_SUSPEND=y +CONFIG_UX500_SUSPEND_STANDBY=y +CONFIG_UX500_SUSPEND_MEM=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y -CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" +CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM_RUNTIME=y @@ -28,15 +55,44 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_IPV6_SIT is not set CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y -# CONFIG_WIRELESS is not set +CONFIG_PHONET_PIPECTRLR=y +CONFIG_NET_SCHED=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_WEXT is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_NETDEVICES=y @@ -44,10 +100,26 @@ CONFIG_SMSC911X=y CONFIG_SMSC_PHY=y # CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_STE_TRACE_MODEM=y +CONFIG_STM_TRACE=y +CONFIG_U8500_SHRM=y +CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y +CONFIG_STM_I2S_TEST_PROTOCOL_DRIVER=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_NETDEVICES=y +CONFIG_TUN=y +CONFIG_USB_USBNET=y +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_BELKIN is not set +# CONFIG_USB_ARMLINUX is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_NOMADIK=y +CONFIG_KEYBOARD_NOMADIK_SKE=y CONFIG_KEYBOARD_STMPE=y CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set @@ -55,36 +127,76 @@ CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_BU21013=y CONFIG_INPUT_MISC=y CONFIG_INPUT_AB8500_PONKEY=y -# CONFIG_SERIO is not set +CONFIG_INPUT_UINPUT=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_NOMADIK=y CONFIG_SPI=y +# CONFIG_STM_MSP_SPI is not set CONFIG_SPI_PL022=y +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y +CONFIG_SENSORS_AB8500=y +CONFIG_SENSORS_DB8500=y +CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_L3G4200D=y +CONFIG_WATCHDOG=y +CONFIG_MPCORE_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y -# CONFIG_HID_SUPPORT is not set +CONFIG_REGULATOR_AB8500_DEBUG=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +# CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_FB=y +CONFIG_FB_MCDE=y +CONFIG_MCDE_DISPLAY_GENERIC_DSI=y +CONFIG_FB_B2R2=y +CONFIG_B2R2_PLUG_CONF=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_OTG_WHITELIST is not set +CONFIG_USB_MON=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_NOP_USB_XCEIV=y CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_CLKGATE=y +CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y +CONFIG_LEDS_PWM=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB8500=y CONFIG_RTC_DRV_PL031=y @@ -105,6 +217,11 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y @@ -112,15 +229,34 @@ CONFIG_CONFIGFS_FS=m # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y +# CONFIG_NETWORK_FILESYSTEMS is not set CONFIG_PARTITION_ADVANCED=y CONFIG_BLKDEV_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_FS=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y -# CONFIG_SCHED_DEBUG is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_SCHED_TRACER=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_KEYS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_CRYP=y +CONFIG_CRC7=y -- cgit v1.2.3 From 6a38e7c3aefc539971dff3a1ae1326f045aa9af1 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 13 Apr 2011 15:07:44 +0200 Subject: Update USB configurations in u8500_defconfig Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 13d926e2150..a1d66f49b6f 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -174,8 +174,8 @@ CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y CONFIG_USB=y -CONFIG_USB_DEBUG=y -CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y CONFIG_USB_MUSB_HDRC=y @@ -186,7 +186,13 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_MULTI=m +# CONFIG_USB_G_MULTI_RNDIS is not set CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_CLKGATE=y -- cgit v1.2.3 From 27ef67f240d39608192476076320f4ff372bb66a Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 14:10:09 +0200 Subject: wdt: Warnings fix Signed-off-by: Philippe Langlais --- drivers/watchdog/mpcore_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 8d814e0470d..96ae2465c25 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -41,7 +41,7 @@ #include struct mpcore_wdt { - unsigned long timer_alive; + cpumask_t timer_alive; struct device *dev; void __iomem *base; int irq; -- cgit v1.2.3 From db386aae7543a612c3310a4de29c79a2fcd04f53 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 14:30:52 +0200 Subject: ux500: Adding board, smsc911x and DHCP configuration for snowball Signed-off-by: Mathieu Poirier Conflicts: arch/arm/configs/u8500_defconfig --- arch/arm/configs/u8500_defconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index a1d66f49b6f..f79cbc557c3 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -22,10 +22,13 @@ CONFIG_ARCH_U8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_HREFV60=y +CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y CONFIG_DB8500_MLOADER=y CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 +CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y @@ -55,6 +58,8 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set @@ -109,6 +114,9 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y CONFIG_TUN=y +CONFIG_SMSC_PHY=y +CONFIG_NET_ETHERNET=y +CONFIG_SMSC911X=y CONFIG_USB_USBNET=y # CONFIG_USB_NET_AX8817X is not set # CONFIG_USB_NET_NET1080 is not set @@ -167,7 +175,6 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_FB=y CONFIG_FB_MCDE=y -CONFIG_MCDE_DISPLAY_GENERIC_DSI=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y CONFIG_SOUND=y -- cgit v1.2.3 From ca1f43ab6ef8578c2f1f0a1c7f68a06a85e01dc2 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 14:36:29 +0200 Subject: mach-ux500: cleanup u8500_defconfig Signed-off-by: Philippe Langlais Conflicts: arch/arm/configs/u8500_defconfig --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index f79cbc557c3..49736c7227b 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -29,6 +29,7 @@ CONFIG_DB8500_MLOADER=y CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y +CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y @@ -168,7 +169,6 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set -- cgit v1.2.3 From ec8c5ee71a22a925986eddb0e1c5e26f684bbb90 Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Thu, 5 May 2011 10:33:05 +0530 Subject: ux500:Removing warnings from USB Disabling USB_USBNET which is not used and which is resulting in warnings for the compiler. Signed-off-by: Sakethram Bommisetti --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 49736c7227b..9f0bd6073d0 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -118,7 +118,7 @@ CONFIG_TUN=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y -CONFIG_USB_USBNET=y +#CONFIG_USB_USBNET is not set # CONFIG_USB_NET_AX8817X is not set # CONFIG_USB_NET_NET1080 is not set # CONFIG_USB_BELKIN is not set -- cgit v1.2.3 From 76340aa63fa7f5214f4f97eb2ae393c2364cc0fb Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 4 May 2011 15:06:19 +0200 Subject: i2c-nomadik: Remove the unnecessary delay The delay in the driver seems to be not needed, so remove it. ST-Ericsson ID: 323012 Change-Id: Id7d3c286063b271bc5f204fb08c289653ba76776 Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17673 Reviewed-by: Markus GRAPE Tested-by: Per PERSSON Tested-by: Chethan Krishna N Reviewed-by: Srinidhi KASAGAR Conflicts: drivers/i2c/busses/i2c-nomadik.c --- drivers/i2c/busses/i2c-nomadik.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index f108c77d50d..b3436b88b9f 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -267,7 +267,6 @@ static int init_hw(struct nmk_i2c_dev *dev) dev->cli.operation = I2C_NO_OPERATION; exit: - udelay(I2C_DELAY); return stat; } -- cgit v1.2.3 From 30516c408422c28eaee2021700f6b4fbb82e1d89 Mon Sep 17 00:00:00 2001 From: Johan Palsson Date: Tue, 8 Mar 2011 13:20:04 +0100 Subject: mfd: ab8500_gpadc: Corrected the name and bitmask for BTempPullUp The bitmask for enabling the BatTemp pull-up was wrong and is corrected. The name is also changed to be inline with the AB8500 register description ST-Ericsson Linux next: - ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie697c3d5958938dd0c741f63f7424980367f7abc Signed-off-by: Johan Palsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17830 Reviewed-by: Mattias WALLIN --- drivers/mfd/ab8500-gpadc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 301510b5824..4b16f50dd1c 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -57,7 +57,7 @@ #define SW_AVG_16 0x60 #define ADC_SW_CONV 0x04 #define EN_ICHAR 0x80 -#define BATTEMP_PULL_UP 0x04 +#define BTEMP_PULL_UP 0x08 #define EN_BUF 0x40 #define DIS_ZERO 0x00 #define GPADC_BUSY 0x01 -- cgit v1.2.3 From 4aab67993c3d6e3a324ad25e9614ff321cfa4c2e Mon Sep 17 00:00:00 2001 From: efanwen Date: Wed, 9 Mar 2011 08:47:26 +0100 Subject: DB Thermal Driver: Add label,min/max_alarm ST-Ericsson ID: CR267428 Change-Id: I848d0a779eb4a3d3719a8d6e5f5448dc122331e0 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17929 Reviewed-by: Wenhai FANG Tested-by: Wenhai FANG Reviewed-by: Martin PERSSON --- drivers/hwmon/db8500.c | 63 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/db8500.c b/drivers/hwmon/db8500.c index e28f9938eb4..b9b4312b8c1 100755 --- a/drivers/hwmon/db8500.c +++ b/drivers/hwmon/db8500.c @@ -47,6 +47,8 @@ struct db8500_temp { unsigned char min[NUM_SENSORS]; unsigned char max[NUM_SENSORS]; unsigned char crit[NUM_SENSORS]; + unsigned char min_alarm[NUM_SENSORS]; + unsigned char max_alarm[NUM_SENSORS]; unsigned short measure_time; struct delayed_work power_off_work; struct mutex lock; @@ -100,6 +102,12 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "db8500\n"); } +static ssize_t show_label(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "db8500\n"); +} + /* set functions (RW nodes) */ static ssize_t set_min(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) @@ -160,8 +168,7 @@ static ssize_t set_crit(struct device *dev, return res; mutex_lock(&data->lock); - val = (val > 255) ? 0xFF : val; - + val &= 0xFF; data->crit[attr->index - 1] = val; (void)prcmu_config_hotdog(data->crit[attr->index - 1]); mutex_unlock(&data->lock); @@ -169,18 +176,21 @@ static ssize_t set_crit(struct device *dev, return count; } -/* set functions (W nodes) */ +/* start/stop temperature measurement */ static ssize_t start_temp(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { unsigned long val; struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); int res = strict_strtoul(buf, 10, &val); if (res < 0) return res; mutex_lock(&data->lock); data->measure_time = val & 0xFFFF; + data->min_alarm[attr->index - 1] = 0; + data->max_alarm[attr->index - 1] = 0; mutex_unlock(&data->lock); (void)prcmu_start_temp_sense(data->measure_time); @@ -205,7 +215,7 @@ static ssize_t stop_temp(struct device *dev, struct device_attribute *devattr, /* * show functions (RO nodes) - * Notice that min/max/max_hyst refer to millivolts and not millidegrees + * Notice that min/max/crit refer to degrees */ static ssize_t show_min(struct device *dev, struct device_attribute *devattr, char *buf) @@ -234,6 +244,24 @@ static ssize_t show_crit(struct device *dev, return sprintf(buf, "%d\n", data->crit[attr->index - 1]); } +/* Alarms */ +static ssize_t show_min_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->min_alarm[attr->index - 1]); +} + +static ssize_t show_max_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct db8500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->max_alarm[attr->index - 1]); +} /*These node are not included in the kernel hwmon sysfs interface */ static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, @@ -241,13 +269,16 @@ static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, set_temp_power_off_delay, 0); /* Chip name, required by hwmon*/ -static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 0); -static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 0); static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 1); static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_crit, set_crit, 1); +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); static struct attribute *db8500_temp_attributes[] = { &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, @@ -257,6 +288,9 @@ static struct attribute *db8500_temp_attributes[] = { &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, NULL }; @@ -267,7 +301,13 @@ static const struct attribute_group db8500_temp_group = { static irqreturn_t prcmu_hotmon_low_irq_handler(int irq, void *irq_data) { struct platform_device *pdev = irq_data; - sysfs_notify(&pdev->dev.kobj, NULL, "prcmu_hotmon_low alarm"); + struct db8500_temp *data = platform_get_drvdata(pdev); + + mutex_lock(&data->lock); + data->min_alarm[0] = 1; + mutex_unlock(&data->lock); + + sysfs_notify(&pdev->dev.kobj, NULL, "temp1_min_alarm"); dev_dbg(&pdev->dev, "DB8500 thermal low warning\n"); return IRQ_HANDLED; } @@ -278,7 +318,11 @@ static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) struct platform_device *pdev = irq_data; struct db8500_temp *data = platform_get_drvdata(pdev); - sysfs_notify(&pdev->dev.kobj, NULL, "prcmu_hotmon_high alarm"); + mutex_lock(&data->lock); + data->max_alarm[0] = 1; + mutex_unlock(&data->lock); + + sysfs_notify(&pdev->dev.kobj, NULL, "temp1_max_alarm"); dev_dbg(&pdev->dev, "DB8500 thermal warning, power off in %lu s\n", (data->power_off_delay) / 1000); delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); @@ -338,6 +382,9 @@ static int __devinit db8500_temp_probe(struct platform_device *pdev) for (i = 0; i < NUM_SENSORS; i++) { data->min[i] = 0; data->max[i] = 0xFF; + data->crit[i] = 0xFF; + data->min_alarm[i] = 0; + data->max_alarm[i] = 0; } mutex_init(&data->lock); -- cgit v1.2.3 From 20b8878f2320ea214b7ba0f64266a0ab2ba1043d Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 15:21:50 +0200 Subject: drivers: video: add regulator for CVBS out - Adds a regulator that is used for CVBS TV out by AB8500 DENC and AV8100 DENC. The regulator is for the switch at the AV connector that switches between video out and mic in. ST-Ericsson ID: AP 322391 Linux-next: ST-Ericsson ID: ER 282779 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie7a821b8d3965aa65384b4393e3083ef406c8282 Signed-off-by: Marcel Tunnissen Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16819 Tested-by: Marcel TUNNISSEN Reviewed-by: Per PERSSON Reviewed-by: Robert FEKETE --- drivers/mfd/ab8500-denc.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-denc.c b/drivers/mfd/ab8500-denc.c index 06e4b282cbf..1bf61e41bcd 100644 --- a/drivers/mfd/ab8500-denc.c +++ b/drivers/mfd/ab8500-denc.c @@ -434,6 +434,20 @@ static int debugfs_ab8500_open_file(struct inode *inode, struct file *file) #define DEBUG_BUF_SIZE 900 +#define AB8500_GPIO_DIR5 0x1014 +#define AB8500_GPIO_DIR5_35_SHIFT 2 +#define AB8500_GPIO_DIR5_35_MASK (1 << AB8500_GPIO_DIR5_35_SHIFT) +#define AB8500_GPIO_OUT5 0x1024 +#define AB8500_GPIO_OUT5_35_SHIFT 2 +#define AB8500_GPIO_OUT5_35_MASK (1 << AB8500_GPIO_OUT5_35_SHIFT) +#define AB8500_GPIO_OUT5_35_VIDEO 0 +#define AB8500_GPIO_OUT5_35_AUDIO 1 +#define AB8500_GPIO_NPUD5 0x1034 +#define AB8500_GPIO_NPUD5_35_SHIFT 2 +#define AB8500_GPIO_NPUD5_35_MASK (1 << AB8500_GPIO_NPUD5_35_SHIFT) +#define AB8500_GPIO_NPUD5_35_ACTIVE 0 +#define AB8500_GPIO_NPUD5_35_INACTIVE 1 + static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, size_t count, loff_t *f_pos) { @@ -444,12 +458,14 @@ static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, data_size += sprintf(buffer + data_size, "AB8500 DENC registers:\n" + "------Regulators etc ----------\n" "CTRL3 : 0x%04x = 0x%02x\n" "SYSULPCLK_CONF: 0x%04x = 0x%02x\n" "SYSCLK_CTRL : 0x%04x = 0x%02x\n" "REGU_MISC1 : 0x%04x = 0x%02x\n" "VAUX12_REGU : 0x%04x = 0x%02x\n" "VAUX1_SEL1 : 0x%04x = 0x%02x\n" + "------TVout only --------------\n" "DENC_CONF0 : 0x%04x = 0x%02x\n" "DENC_CONF1 : 0x%04x = 0x%02x\n" "DENC_CONF2 : 0x%04x = 0x%02x\n" @@ -458,6 +474,10 @@ static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, "TVOUT_CTRL : 0x%04x = 0x%02x\n" "TVOUT_CTRL2 : 0x%04x = 0x%02x\n" "IT_MASK1 : 0x%04x = 0x%02x\n" + "------AV connector-------------\n" + "GPIO_DIR5 : 0x%04x = 0x%02x\n" + "GPIO_OUT5 : 0x%04x = 0x%02x\n" + "GPIO_NPUD5 : 0x%04x = 0x%02x\n" , AB8500_CTRL3, ab8500_rreg(dev, AB8500_CTRL3), AB8500_SYS_ULP_CLK_CONF, ab8500_rreg(dev, @@ -473,7 +493,10 @@ static ssize_t debugfs_ab8500_dump_regs(struct file *file, char __user *buf, AB8500_DENC_CONF8, ab8500_rreg(dev, AB8500_DENC_CONF8), AB8500_TVOUT_CTRL, ab8500_rreg(dev, AB8500_TVOUT_CTRL), AB8500_TVOUT_CTRL2, ab8500_rreg(dev, AB8500_TVOUT_CTRL2), - AB8500_IT_MASK1, ab8500_rreg(dev, AB8500_IT_MASK1) + AB8500_IT_MASK1, ab8500_rreg(dev, AB8500_IT_MASK1), + AB8500_GPIO_DIR5, ab8500_rreg(dev, AB8500_GPIO_DIR5), + AB8500_GPIO_OUT5, ab8500_rreg(dev, AB8500_GPIO_OUT5), + AB8500_GPIO_NPUD5, ab8500_rreg(dev, AB8500_GPIO_NPUD5) ); if (data_size >= DEBUG_BUF_SIZE) { printk(KERN_EMERG "AB8500 DENC: Buffer overrun\n"); -- cgit v1.2.3 From b8f207b56a72f894f033388ec88ed95ad2cd0bf4 Mon Sep 17 00:00:00 2001 From: Mikael Larsson Date: Fri, 11 Mar 2011 15:56:34 +0100 Subject: setlocalversion: Add support for version from specific tag This patch makes it possible to specify a tag as input to setlocalversion. If specified the version is then calculated from this tag and not the latest tag as when not using this option. ST-Ericsson ID: None ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I168546efeb95978b53a5f7de992ddc955be26477 Signed-off-by: Mikael Larsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18195 Reviewed-by: Robert ROSENGREN Reviewed-by: Jonas ABERG --- Makefile | 2 +- scripts/setlocalversion | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index a6879630a3e..cd2916d5c8f 100644 --- a/Makefile +++ b/Makefile @@ -947,7 +947,7 @@ $(vmlinux-dirs): prepare scripts # Store (new) KERNELRELASE string in include/config/kernel.release include/config/kernel.release: include/config/auto.conf FORCE $(Q)rm -f $@ - $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@ + $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion -s $(srctree) -t v$(KERNELVERSION))" > $@ # Things we need to do before we recursively start building the kernel diff --git a/scripts/setlocalversion b/scripts/setlocalversion index bd6dca8a0ab..f090355733e 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -10,23 +10,37 @@ # usage() { - echo "Usage: $0 [--save-scmversion] [srctree]" >&2 + echo "Usage: $0 [--save-scmversion] [-s srctree] [-t ref_tag]" >&2 exit 1 } scm_only=false srctree=. -if test "$1" = "--save-scmversion"; then - scm_only=true - shift -fi -if test $# -gt 0; then - srctree=$1 +match_option=--exact-match + +while [ $# -ne 0 ]; do + if test "$1" = "--save-scmversion"; then + scm_only=true + elif test "$1" = "-s"; then + shift + if test $# -ne 0 -a -d "$1"; then + srctree=$1 + else + usage + fi + elif test "$1" = "-t"; then + shift + if [ $# -ne 0 ]; then + match=" --tags --match "$1 + rev_refs="--refs refs/tags/"$1 + else + usage + fi + else + usage + fi shift -fi -if test $# -gt 0 -o ! -d "$srctree"; then - usage -fi +done scm_version() { @@ -47,8 +61,8 @@ scm_version() # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore # it, because this version is defined in the top level Makefile. - if [ -z "`git describe --exact-match 2>/dev/null`" ]; then - + if git name-rev --tags $rev_refs HEAD | \ + grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then # If only the short version is requested, don't bother # running further git commands if $short; then @@ -57,7 +71,7 @@ scm_version() fi # If we are past a tagged commit (like # "v2.6.30-rc5-302-g72357d5"), we pretty print it. - if atag="`git describe 2>/dev/null`"; then + if atag="`git describe $match 2>/dev/null`"; then echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' # If we don't have a tag at all we print -g{commitish}. -- cgit v1.2.3 From 031147f98e9dd4b28f397cb0469b9d15400ae953 Mon Sep 17 00:00:00 2001 From: Chethan Krishna N Date: Tue, 15 Mar 2011 11:58:24 +0530 Subject: bh1780gli: correct mutex locking behaviour Multiple activation and deactivation calls for BH1780GLI Ambient Light Sensor will not crash now. ST Ericsson ID: ER326054 Signed-off-by: Chethan Krishna N Change-Id: I3bfeb6a371ae567e14300339b1b18dc750a59b14 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18319 Reviewed-by: Srinidhi KASAGAR --- drivers/misc/bh1780gli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index a7c012a6545..0b9ff5e8825 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -116,11 +116,11 @@ static ssize_t bh1780_store_power_state(struct device *dev, if (val < BH1780_POFF || val > BH1780_PON) return -EINVAL; - mutex_lock(&ddata->lock); - if (ddata->power_state == val) return count; + mutex_lock(&ddata->lock); + if (ddata->power_state == BH1780_POFF) regulator_enable(ddata->regulator); -- cgit v1.2.3 From fd8b43e2dc596e8c7fe6a5f9b0c3d731a3b0d6ec Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 24 Mar 2011 17:24:19 +0530 Subject: rtc: add AB5500 RTC driver Add a driver for the RTC block on the AB5500. The AB5500 RTC has similarities with both the AB8500 and the AB3100, so this driver is made generic in order to replace the other two drivers by adding some variant specific information. ST-Ericsson Linux next: - ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I35c7ee245ea68e435c800151dbb8f6e10c7abe5d Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19331 Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Bibek BASU Reviewed-by: Srinidhi KASAGAR --- drivers/rtc/Kconfig | 7 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-ab.c | 480 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 488 insertions(+) create mode 100644 drivers/rtc/rtc-ab.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8c8377d50c4..595d02b1117 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -704,6 +704,13 @@ config RTC_DRV_PCF50633 If you say yes here you get support for the RTC subsystem of the NXP PCF50633 used in embedded systems. +config RTC_DRV_AB + tristate "ST-Ericsson AB5500 RTC" + depends on AB5500_CORE + help + Select this to enable the ST-Ericsson AB5500 Mixed Signal IC RTC + support. This chip contains a battery- and capacitor-backed RTC. + config RTC_DRV_AB3100 tristate "ST-Ericsson AB3100 RTC" depends on AB3100_CORE diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 727ae7786e6..56766bbc519 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,6 +16,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o # Keep the list ordered. obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o +obj-$(CONFIG_RTC_DRV_AB) += rtc-ab.o obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o diff --git a/drivers/rtc/rtc-ab.c b/drivers/rtc/rtc-ab.c new file mode 100644 index 00000000000..3d3c216995d --- /dev/null +++ b/drivers/rtc/rtc-ab.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + * Author: Rabin Vincent + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define AB5500_RTC_CLOCK_RATE 32768 +#define AB5500_RTC 0x00 +#define AB5500_RTC_ALARM (1 << 1) +#define AB5500_READREQ 0x01 +#define AB5500_READREQ_REQ 0x01 +#define AB5500_AL0 0x02 +#define AB5500_TI0 0x06 + +/** + * struct ab_rtc - variant specific data + * @irqname: optional name for the alarm interrupt resource + * @epoch: epoch to adjust year to + * @bank: AB bank where this block is present + * @rtc: address of the "RTC" (control) register + * @rtc_alarmon: mask of the alarm enable bit in the above register + * @ti0: address of the TI0 register. The rest of the TI + * registers are assumed to contiguously follow this one. + * @nr_ti: number of TI* registers + * @al0: address of the AL0 register. The rest of the + * AL registers are assumed to contiguously follow this one. + * @nr_al: number of AL* registers + * @startup: optional function to initialize the RTC + * @alarm_to_regs: function to convert alarm time in seconds + * to a list of AL register values + * @time_to_regs: function to convert alarm time in seconds + * to a list of TI register values + * @regs_to_alarm: function to convert a list of AL register + * values to the alarm time in seconds + * @regs_to_time: function to convert a list of TI register + * values to the alarm time in seconds + * @request_read: optional function to request a read from the TI* registers + * @request_write: optional function to request a write to the TI* registers + */ +struct ab_rtc { + const char *irqname; + unsigned int epoch; + + u8 bank; + u8 rtc; + u8 rtc_alarmon; + u8 ti0; + int nr_ti; + u8 al0; + int nr_al; + + int (*startup)(struct device *dev); + void (*alarm_to_regs)(struct device *dev, unsigned long secs, u8 *regs); + void (*time_to_regs)(struct device *dev, unsigned long secs, u8 *regs); + unsigned long (*regs_to_alarm)(struct device *dev, u8 *regs); + unsigned long (*regs_to_time)(struct device *dev, u8 *regs); + int (*request_read)(struct device *dev); + int (*request_write)(struct device *dev); +}; + +static const struct ab_rtc *to_ab_rtc(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return (struct ab_rtc *)pdev->id_entry->driver_data; +} + +/* Calculate the number of seconds since year, for epoch adjustment */ +static unsigned long ab_rtc_get_elapsed_seconds(unsigned int year) +{ + unsigned long secs; + struct rtc_time tm = { + .tm_year = year - 1900, + .tm_mday = 1, + }; + + rtc_tm_to_time(&tm, &secs); + + return secs; +} + +static int ab5500_rtc_request_read(struct device *dev) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + unsigned long timeout; + int err; + + err = abx500_set_register_interruptible(dev, variant->bank, + AB5500_READREQ, + AB5500_READREQ_REQ); + if (err < 0) + return err; + + timeout = jiffies + HZ; + while (time_before(jiffies, timeout)) { + u8 value; + + err = abx500_get_register_interruptible(dev, variant->bank, + AB5500_READREQ, &value); + if (err < 0) + return err; + + if (!(value & AB5500_READREQ_REQ)) + return 0; + + msleep(1); + } + + return -EIO; +} + +static void +ab5500_rtc_time_to_regs(struct device *dev, unsigned long secs, u8 *regs) +{ + unsigned long mins = secs / 60; + u64 fat_time; + + secs %= 60; + + fat_time = secs * AB5500_RTC_CLOCK_RATE; + fat_time |= (u64)mins << 21; + + regs[0] = (fat_time) & 0xFF; + regs[1] = (fat_time >> 8) & 0xFF; + regs[2] = (fat_time >> 16) & 0xFF; + regs[3] = (fat_time >> 24) & 0xFF; + regs[4] = (fat_time >> 32) & 0xFF; + regs[5] = (fat_time >> 40) & 0xFF; +} + +static unsigned long +ab5500_rtc_regs_to_time(struct device *dev, u8 *regs) +{ + u64 fat_time = ((u64)regs[5] << 40) | ((u64)regs[4] << 32) | + (regs[3] << 24) | (regs[2] << 16) | + (regs[1] << 8) | regs[0]; + unsigned long secs = (fat_time & 0x1fffff) / AB5500_RTC_CLOCK_RATE; + unsigned long mins = fat_time >> 21; + + return mins * 60 + secs; +} + +static void +ab5500_rtc_alarm_to_regs(struct device *dev, unsigned long secs, u8 *regs) +{ + unsigned long mins = secs / 60; + +#ifdef CONFIG_ANDROID + /* + * Needed because Android believes all hw have a wake-up resolution in + * seconds. + */ + mins++; +#endif + + regs[0] = mins & 0xFF; + regs[1] = (mins >> 8) & 0xFF; + regs[2] = (mins >> 16) & 0xFF; +} + +static unsigned long +ab5500_rtc_regs_to_alarm(struct device *dev, u8 *regs) +{ + unsigned long mins = (regs[2] << 16) | (regs[1] << 8) | regs[0]; + unsigned long secs = mins * 60; + + return secs; +} + +static const struct ab_rtc ab5500_rtc = { + .irqname = "RTC_Alarm", + .bank = AB5500_BANK_RTC, + .rtc = AB5500_RTC, + .rtc_alarmon = AB5500_RTC_ALARM, + .ti0 = AB5500_TI0, + .nr_ti = 6, + .al0 = AB5500_AL0, + .nr_al = 3, + .epoch = 2000, + .time_to_regs = ab5500_rtc_time_to_regs, + .regs_to_time = ab5500_rtc_regs_to_time, + .alarm_to_regs = ab5500_rtc_alarm_to_regs, + .regs_to_alarm = ab5500_rtc_regs_to_alarm, + .request_read = ab5500_rtc_request_read, +}; + +static int ab_rtc_request_read(struct device *dev) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + + if (!variant->request_read) + return 0; + + return variant->request_read(dev); +} + +static int ab_rtc_request_write(struct device *dev) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + + if (!variant->request_write) + return 0; + + return variant->request_write(dev); +} + +static bool ab_rtc_valid_time(struct device *dev, struct rtc_time *time) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + + if (!variant->epoch) + return true; + + return time->tm_year >= variant->epoch - 1900; +} + +static int +ab_rtc_tm_to_time(struct device *dev, struct rtc_time *tm, unsigned long *secs) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + + rtc_tm_to_time(tm, secs); + + if (variant->epoch) + *secs -= ab_rtc_get_elapsed_seconds(variant->epoch); + + return 0; +} + +static int +ab_rtc_time_to_tm(struct device *dev, unsigned long secs, struct rtc_time *tm) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + + if (variant->epoch) + secs += ab_rtc_get_elapsed_seconds(variant->epoch); + + rtc_time_to_tm(secs, tm); + + return 0; +} + +static int ab_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + unsigned char buf[variant->nr_ti]; + unsigned long secs; + int err; + + err = ab_rtc_request_read(dev); + if (err) + return err; + + err = abx500_get_register_page_interruptible(dev, variant->bank, + variant->ti0, + buf, variant->nr_ti); + if (err) + return err; + + secs = variant->regs_to_time(dev, buf); + ab_rtc_time_to_tm(dev, secs, tm); + + return rtc_valid_tm(tm); +} + +static int ab_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + unsigned char buf[variant->nr_ti]; + unsigned long secs; + u8 reg = variant->ti0; + int err; + int i; + + if (!ab_rtc_valid_time(dev, tm)) + return -EINVAL; + + ab_rtc_tm_to_time(dev, tm, &secs); + variant->time_to_regs(dev, secs, buf); + + for (i = 0; i < variant->nr_ti; i++, reg++) { + err = abx500_set_register_interruptible(dev, variant->bank, + reg, buf[i]); + if (err) + return err; + } + + return ab_rtc_request_write(dev); +} + +static int ab_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + unsigned long secs; + u8 buf[variant->nr_al]; + u8 rtcval; + int err; + + err = abx500_get_register_interruptible(dev, variant->bank, + variant->rtc, &rtcval); + if (err) + return err; + + alarm->enabled = !!(rtcval & variant->rtc_alarmon); + alarm->pending = 0; + + err = abx500_get_register_page_interruptible(dev, variant->bank, + variant->al0, buf, + variant->nr_al); + if (err) + return err; + + secs = variant->regs_to_alarm(dev, buf); + ab_rtc_time_to_tm(dev, secs, &alarm->time); + + return rtc_valid_tm(&alarm->time); +} + +static int ab_rtc_alarm_enable(struct device *dev, unsigned int enabled) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + u8 mask = variant->rtc_alarmon; + u8 value = enabled ? mask : 0; + + return abx500_mask_and_set_register_interruptible(dev, variant->bank, + variant->rtc, mask, + value); +} + +static int ab_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + const struct ab_rtc *variant = to_ab_rtc(dev); + unsigned char buf[variant->nr_al]; + unsigned long secs; + u8 reg = variant->al0; + int err; + int i; + + if (!ab_rtc_valid_time(dev, &alarm->time)) + return -EINVAL; + + ab_rtc_tm_to_time(dev, &alarm->time, &secs); + variant->alarm_to_regs(dev, secs, buf); + + /* + * Disable alarm first. Otherwise the RTC may not detect an alarm + * reprogrammed for the same time without disabling the alarm in + * between the programmings. + */ + err = ab_rtc_alarm_enable(dev, false); + if (err) + return err; + + for (i = 0; i < variant->nr_al; i++, reg++) { + err = abx500_set_register_interruptible(dev, variant->bank, + reg, buf[i]); + if (err) + return err; + } + + return ab_rtc_alarm_enable(dev, true); +} + +static const struct rtc_class_ops ab_rtc_ops = { + .read_time = ab_rtc_read_time, + .set_time = ab_rtc_set_time, + .read_alarm = ab_rtc_read_alarm, + .set_alarm = ab_rtc_set_alarm, + .alarm_irq_enable = ab_rtc_alarm_enable, +}; + +static irqreturn_t ab_rtc_irq(int irq, void *dev_id) +{ + unsigned long events = RTC_IRQF | RTC_AF; + struct rtc_device *rtc = dev_id; + + rtc_update_irq(rtc, 1, events); + + return IRQ_HANDLED; +} + +static int __devinit ab_rtc_probe(struct platform_device *pdev) +{ + const struct ab_rtc *variant = to_ab_rtc(&pdev->dev); + int err; + struct rtc_device *rtc; + int irq = -ENXIO; + + if (variant->irqname) { + irq = platform_get_irq_byname(pdev, variant->irqname); + if (irq < 0) + return irq; + } + + if (variant->startup) { + err = variant->startup(&pdev->dev); + if (err) + return err; + } + + rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab_rtc_ops, + THIS_MODULE); + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "Registration failed\n"); + err = PTR_ERR(rtc); + return err; + } + + if (irq >= 0) { + err = request_any_context_irq(irq, ab_rtc_irq, + IRQF_NO_SUSPEND, + pdev->id_entry->name, + rtc); + if (err < 0) { + dev_err(&pdev->dev, "could not get irq: %d\n", err); + goto out_unregister; + } + } + + platform_set_drvdata(pdev, rtc); + + return 0; + +out_unregister: + rtc_device_unregister(rtc); + return err; +} + +static int __devexit ab_rtc_remove(struct platform_device *pdev) +{ + const struct ab_rtc *variant = to_ab_rtc(&pdev->dev); + struct rtc_device *rtc = platform_get_drvdata(pdev); + int irq = platform_get_irq_byname(pdev, variant->irqname); + + if (irq >= 0) + free_irq(irq, rtc); + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_device_id ab_rtc_id_table[] = { + { "ab5500-rtc", (kernel_ulong_t)&ab5500_rtc, }, + { }, +}; +MODULE_DEVICE_TABLE(platform, ab_rtc_id_table); + +static struct platform_driver ab_rtc_driver = { + .driver.name = "ab-rtc", + .driver.owner = THIS_MODULE, + .id_table = ab_rtc_id_table, + .probe = ab_rtc_probe, + .remove = __devexit_p(ab_rtc_remove), +}; + +static int __init ab_rtc_init(void) +{ + return platform_driver_register(&ab_rtc_driver); +} +module_init(ab_rtc_init); + +static void __exit ab_rtc_exit(void) +{ + platform_driver_unregister(&ab_rtc_driver); +} +module_exit(ab_rtc_exit); + +MODULE_AUTHOR("Rabin Vincent "); +MODULE_DESCRIPTION("AB5500 RTC Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 9f7a5efa487033d9ef53aba11ab0a58e7fbb2db3 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 1 Apr 2011 11:33:40 +0530 Subject: rtc-ab: add missing casts Only the << 24 one is strictly required, but let's just be explicit about all of them. ST-Ericsson Linux next: - ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib8ae749d6ad21c12160fb4af62b79c347bf1dc75 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19672 Reviewed-by: Jonas ABERG --- drivers/rtc/rtc-ab.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-ab.c b/drivers/rtc/rtc-ab.c index 3d3c216995d..8e595e05d99 100644 --- a/drivers/rtc/rtc-ab.c +++ b/drivers/rtc/rtc-ab.c @@ -141,8 +141,8 @@ static unsigned long ab5500_rtc_regs_to_time(struct device *dev, u8 *regs) { u64 fat_time = ((u64)regs[5] << 40) | ((u64)regs[4] << 32) | - (regs[3] << 24) | (regs[2] << 16) | - (regs[1] << 8) | regs[0]; + ((u64)regs[3] << 24) | ((u64)regs[2] << 16) | + ((u64)regs[1] << 8) | regs[0]; unsigned long secs = (fat_time & 0x1fffff) / AB5500_RTC_CLOCK_RATE; unsigned long mins = fat_time >> 21; @@ -170,7 +170,9 @@ ab5500_rtc_alarm_to_regs(struct device *dev, unsigned long secs, u8 *regs) static unsigned long ab5500_rtc_regs_to_alarm(struct device *dev, u8 *regs) { - unsigned long mins = (regs[2] << 16) | (regs[1] << 8) | regs[0]; + unsigned long mins = ((unsigned long)regs[2] << 16) | + ((unsigned long)regs[1] << 8) | + regs[0]; unsigned long secs = mins * 60; return secs; -- cgit v1.2.3 From c99923699409b9b2540f06b723d5d4e65681a1c5 Mon Sep 17 00:00:00 2001 From: carriere etienne Date: Fri, 8 Apr 2011 16:26:36 +0200 Subject: ab8500 debugfs: formated access AB8500 registers from debugfs entry Add debugfs entry ab8500/hwreg to read/write bit-field in AB8500 registers. Check the debugfs entries usage from heading comments in ab8500-debugfs.c ST-Ericsson Linux next: - ST-Ericsson ID: ER 334167 ST-Ericsson FOSS-OUT ID: Trivial Patch tested on: relC 'u8500-android-2.3_v0.44' Signed-off-by: carriere etienne Change-Id: Ibb59f3e0bd3dc4e67f82b080aea66bf63b306b45 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20179 Reviewed-by: Mattias WALLIN --- drivers/mfd/ab8500-debugfs.c | 375 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 331 insertions(+), 44 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 7b051c820d3..5c871ae4554 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -4,6 +4,72 @@ * Author: Mattias Wallin for ST-Ericsson. * License Terms: GNU General Public License v2 */ +/* + * AB8500 register access + * ====================== + * + * read: + * # echo BANK > /ab8500/register-bank + * # echo ADDR > /ab8500/register-address + * # cat /ab8500/register-value + * + * write: + * # echo BANK > /ab8500/register-bank + * # echo ADDR > /ab8500/register-address + * # echo VALUE > /ab8500/register-value + * + * read all registers from a bank: + * # echo BANK > /ab8500/register-bank + * # cat /ab8500/all-bank-register + * + * BANK target AB8500 register bank + * ADDR target AB8500 register address + * VALUE decimal or 0x-prefixed hexadecimal + * + * + * User Space notification on AB8500 IRQ + * ===================================== + * + * Allows user space entity to be notified when target AB8500 IRQ occurs. + * When subscribed, a sysfs entry is created in ab8500.i2c platform device. + * One can pool this file to get target IRQ occurence information. + * + * subscribe to an AB8500 IRQ: + * # echo IRQ > /ab8500/irq-subscribe + * + * unsubscribe from an AB8500 IRQ: + * # echo IRQ > /ab8500/irq-unsubscribe + * + * + * AB8500 register formated read/write access + * ========================================== + * + * Read: read data, data>>SHIFT, data&=MASK, output data + * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE + * Write: read data, data &= ~(MASK< [0xAB123F98] + * + * Usage: + * # echo "CMD [OPTIONS] BANK ADRESS [VALUE]" > $debugfs/ab8500/hwreg + * + * CMD read read access + * write write access + * + * BANK target reg bank + * ADDRESS target reg address + * VALUE (write) value to be updated + * + * OPTIONS + * -d|-dec (read) output in decimal + * -h|-hexa (read) output in 0x-hexa (default) + * -l|-w|-b 32bit (default), 16bit or 8bit reg access + * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF) + * -s|-shift SHIFT bit shift value (read:left, write:right) + * -o|-offset OFFSET address offset to add to ADDRESS value + * + * Warning: bit shift operation is applied to bit-mask. + * Warning: bit shift direction depends on read or right command. + */ #include #include @@ -18,6 +84,11 @@ #include #include +#ifdef CONFIG_DEBUG_FS +#include +#include +#endif + static u32 debug_bank; static u32 debug_address; @@ -52,6 +123,25 @@ struct ab8500_i2c_ranges { const struct ab8500_reg_range *range; }; +/* hwreg- "mask" and "shift" entries ressources */ +struct hwreg_cfg { + u32 bank; /* target bank */ + u32 addr; /* target address */ + uint fmt; /* format */ + uint mask; /* read/write mask, applied before any bit shift */ + int shift; /* bit shift (read:right shift, write:left shift */ +}; +/* fmt bit #0: 0=hexa, 1=dec */ +#define REG_FMT_DEC(c) ((c)->fmt & 0x1) +#define REG_FMT_HEX(c) (!REG_FMT_DEC(c)) + +static struct hwreg_cfg hwreg_cfg = { + .addr = 0, /* default: invalid phys addr */ + .fmt = 0, /* default: 32bit access, hex output */ + .mask = 0xFFFFFFFF, /* default: no mask */ + .shift = 0, /* default: no bit shift */ +}; + #define AB8500_NAME_STRING "ab8500" #define AB8500_NUM_BANKS 22 @@ -546,6 +636,203 @@ static ssize_t ab8500_val_write(struct file *file, return count; } +/* + * - HWREG DB8500 formated routines + */ +static int ab8500_hwreg_print(struct seq_file *s, void *d) +{ + struct device *dev = s->private; + int ret; + u8 regvalue; + + ret = abx500_get_register_interruptible(dev, + (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, ®value); + if (ret < 0) { + dev_err(dev, "abx500_get_reg fail %d, %d\n", + ret, __LINE__); + return -EINVAL; + } + + if (hwreg_cfg.shift >= 0) + regvalue >>= hwreg_cfg.shift; + else + regvalue <<= -hwreg_cfg.shift; + regvalue &= hwreg_cfg.mask; + + if (REG_FMT_DEC(&hwreg_cfg)) + seq_printf(s, "%d\n", regvalue); + else + seq_printf(s, "0x%02X\n", regvalue); + return 0; +} + +static int ab8500_hwreg_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_hwreg_print, inode->i_private); +} + +/* + * return length of an ASCII numerical value, 0 is string is not a + * numerical value. + * string shall start at value 1st char. + * string can be tailed with \0 or space or newline chars only. + * value can be decimal or hexadecimal (prefixed 0x or 0X). + */ +static int strval_len(char *b) +{ + char *s = b; + if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) { + s += 2; + for (; *s && (*s != ' ') && (*s != '\n'); s++) { + if (!isxdigit(*s)) + return 0; + } + } else { + if (*s == '-') + s++; + for (; *s && (*s != ' ') && (*s != '\n'); s++) { + if (!isdigit(*s)) + return 0; + } + } + return (int) (s-b); +} + +/* + * parse hwreg input data. + * update global hwreg_cfg only if input data syntax is ok. + */ +static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg, + struct device *dev) +{ + uint write, val = 0; + struct hwreg_cfg loc = { + .bank = 0, /* default: invalid phys addr */ + .addr = 0, /* default: invalid phys addr */ + .fmt = 0, /* default: 32bit access, hex output */ + .mask = 0xFFFFFFFF, /* default: no mask */ + .shift = 0, /* default: no bit shift */ + }; + + /* read or write ? */ + if (!strncmp(b, "read ", 5)) { + write = 0; + b += 5; + } else if (!strncmp(b, "write ", 6)) { + write = 1; + b += 6; + } else + return -EINVAL; + + /* OPTIONS -l|-w|-b -s -m -o */ + while ((*b == ' ') || (*b == '-')) { + if (*(b-1) != ' ') { + b++; + continue; + } + if ((!strncmp(b, "-d ", 3)) || + (!strncmp(b, "-dec ", 5))) { + b += (*(b+2) == ' ') ? 3 : 5; + loc.fmt |= (1<<0); + } else if ((!strncmp(b, "-h ", 3)) || + (!strncmp(b, "-hex ", 5))) { + b += (*(b+2) == ' ') ? 3 : 5; + loc.fmt &= ~(1<<0); + } else if ((!strncmp(b, "-m ", 3)) || + (!strncmp(b, "-mask ", 6))) { + b += (*(b+2) == ' ') ? 3 : 6; + if (strval_len(b) == 0) + return -EINVAL; + loc.mask = simple_strtoul(b, &b, 0); + } else if ((!strncmp(b, "-s ", 3)) || + (!strncmp(b, "-shift ", 7))) { + b += (*(b+2) == ' ') ? 3 : 7; + if (strval_len(b) == 0) + return -EINVAL; + loc.shift = simple_strtol(b, &b, 0); + } else { + return -EINVAL; + } + } + /* get arg BANK and ADDRESS */ + if (strval_len(b) == 0) + return -EINVAL; + loc.bank = simple_strtoul(b, &b, 0); + while (*b == ' ') + b++; + if (strval_len(b) == 0) + return -EINVAL; + loc.addr = simple_strtoul(b, &b, 0); + + if (write) { + while (*b == ' ') + b++; + if (strval_len(b) == 0) + return -EINVAL; + val = simple_strtoul(b, &b, 0); + } + + /* args are ok, update target cfg (mainly for read) */ + *cfg = loc; + +#if ABB_HWREG_DEBUG + pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d + value=0x%X\n", (write) ? "write" : "read", + REG_FMT_DEC(cfg) ? "decimal" : "hexa", + cfg->addr, cfg->mask, cfg->shift, val); +#endif + + if (write) { + u8 regvalue; + int ret = abx500_get_register_interruptible(dev, + (u8)cfg->bank, (u8)cfg->addr, ®value); + if (ret < 0) { + dev_err(dev, "abx500_get_reg fail %d, %d\n", + ret, __LINE__); + return -EINVAL; + } + + if (cfg->shift >= 0) { + regvalue &= ~(cfg->mask << (cfg->shift)); + val = (val & cfg->mask) << (cfg->shift); + } else { + regvalue &= ~(cfg->mask >> (-cfg->shift)); + val = (val & cfg->mask) >> (-cfg->shift); + } + val = val | regvalue; + + ret = abx500_set_register_interruptible(dev, + (u8)cfg->bank, (u8)cfg->addr, (u8)val); + if (ret < 0) { + pr_err("abx500_set_reg failed %d, %d", ret, __LINE__); + return -EINVAL; + } + + } + return 0; +} + +static ssize_t ab8500_hwreg_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct device *dev = ((struct seq_file *)(file->private_data))->private; + char buf[128]; + int buf_size, ret; + + /* Get userspace string and assure termination */ + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + /* get args and process */ + ret = hwreg_common_write(buf, &hwreg_cfg, dev); + return (ret) ? ret : buf_size; +} + +/* + * - irq subscribe/unsubscribe stuff + */ static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p) { seq_printf(s, "%d\n", irq_first); @@ -692,6 +979,10 @@ static ssize_t ab8500_unsubscribe_write(struct file *file, return count; } +/* + * - several deubgfs nodes fops + */ + static const struct file_operations ab8500_bank_fops = { .open = ab8500_bank_open, .write = ab8500_bank_write, @@ -737,16 +1028,20 @@ static const struct file_operations ab8500_unsubscribe_fops = { .owner = THIS_MODULE, }; +static const struct file_operations ab8500_hwreg_fops = { + .open = ab8500_hwreg_open, + .write = ab8500_hwreg_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static struct dentry *ab8500_dir; -static struct dentry *ab8500_reg_file; -static struct dentry *ab8500_bank_file; -static struct dentry *ab8500_address_file; -static struct dentry *ab8500_val_file; -static struct dentry *ab8500_subscribe_file; -static struct dentry *ab8500_unsubscribe_file; static int __devinit ab8500_debug_probe(struct platform_device *plf) { + struct dentry *file; debug_bank = AB8500_MISC; debug_address = AB8500_REV_REG & 0x00FF; @@ -766,67 +1061,59 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); if (!ab8500_dir) - goto exit_no_debugfs; + goto err; - ab8500_reg_file = debugfs_create_file("all-bank-registers", + file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops); - if (!ab8500_reg_file) - goto exit_destroy_dir; + if (!file) + goto err; - ab8500_bank_file = debugfs_create_file("register-bank", + file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); - if (!ab8500_bank_file) - goto exit_destroy_reg; + if (!file) + goto err; - ab8500_address_file = debugfs_create_file("register-address", + file = debugfs_create_file("register-address", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_address_fops); - if (!ab8500_address_file) - goto exit_destroy_bank; + if (!file) + goto err; - ab8500_val_file = debugfs_create_file("register-value", + file = debugfs_create_file("register-value", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); - if (!ab8500_val_file) - goto exit_destroy_address; + if (!file) + goto err; - ab8500_subscribe_file = debugfs_create_file("irq-subscribe", + file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_subscribe_fops); - if (!ab8500_subscribe_file) - goto exit_destroy_val; + if (!file) + goto err; - ab8500_unsubscribe_file = debugfs_create_file("irq-unsubscribe", + file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); - if (!ab8500_unsubscribe_file) - goto exit_destroy_subscribe; + if (!file) + goto err; + + file = debugfs_create_file("hwreg", + (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, + &ab8500_hwreg_fops); + if (!file) + goto err; + return 0; -exit_destroy_subscribe: - debugfs_remove(ab8500_subscribe_file); -exit_destroy_val: - debugfs_remove(ab8500_val_file); -exit_destroy_address: - debugfs_remove(ab8500_address_file); -exit_destroy_bank: - debugfs_remove(ab8500_bank_file); -exit_destroy_reg: - debugfs_remove(ab8500_reg_file); -exit_destroy_dir: - debugfs_remove(ab8500_dir); -exit_no_debugfs: +err: + if (ab8500_dir) + debugfs_remove_recursive(ab8500_dir); dev_err(&plf->dev, "failed to create debugfs entries.\n"); return -ENOMEM; } static int __devexit ab8500_debug_remove(struct platform_device *plf) { - debugfs_remove(ab8500_val_file); - debugfs_remove(ab8500_address_file); - debugfs_remove(ab8500_bank_file); - debugfs_remove(ab8500_reg_file); - debugfs_remove(ab8500_dir); - + debugfs_remove_recursive(ab8500_dir); return 0; } -- cgit v1.2.3 From 17b3fbe4bbc9f46ab3b56fb9270c7c7d2d407fe3 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 10 May 2011 09:33:09 +0200 Subject: ARM: enable CONFIG_KTIME_SCALAR Use straight 64-bit values as 64-bit operations are fairly efficient on ARM. Comparing the asm output with and without KTIME_SCALAR, using 64-bit math generates clearly better code. Comparing kernel/hrtimer.c .text size, it goes from 0x1414 to 0x119c with this change. ST-Ericsson ID: 329353 Signed-off-by: Rob Herring Signed-off-by: Mian Yousaf Kaukab Change-Id: Ic9d31ff64d7c60354f85055e3a74efd84d447e7f Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21192 Reviewed-by: Jonas ABERG --- arch/arm/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d83b199fd54..9324e33e531 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -73,6 +73,10 @@ config KTIME_SCALAR bool default y +config KTIME_SCALAR + bool + default y + config HAVE_TCM bool select GENERIC_ALLOCATOR -- cgit v1.2.3 From b45848a2980d1003746fd83cd46a09bf031ec887 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Thu, 7 Apr 2011 12:19:48 +0200 Subject: ARM: Fix buffer overflow if HZ=1000 This patch fix a buffer overflow bug in timer based delay code if HZ=1000. ST-Ericsson ID: ER 334336 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Mattias Wallin Change-Id: I83326c808d992d76ec74fbb86958ca63f80e6f0c Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20261 Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- arch/arm/lib/delay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index f24c956e4fd..b8d636e8ef8 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -76,6 +76,6 @@ EXPORT_SYMBOL(__const_udelay); */ void __udelay(unsigned long usecs) { - __const_udelay(usecs * ((2199023*HZ)>>11)); + __const_udelay(usecs * ((2199023UL*HZ)>>11)); } EXPORT_SYMBOL(__udelay); -- cgit v1.2.3 From 115ce085c89048f32210496999cc0237d2fd67ab Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 10 May 2011 11:07:02 +0200 Subject: i2c-nomadik: Reset the hw after status check In case of I2C timeout, reset the HW only after the HW status is read, otherwise the staus will be lost. ST-Ericsson ID: ER334949 Change-Id: I93295122fa38d0ea82780d54af7f5de1fa099369 Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20986 Reviewed-by: Jonas ABERG Reviewed-by: Srinidhi KASAGAR Conflicts: drivers/i2c/busses/i2c-nomadik.c --- drivers/i2c/busses/i2c-nomadik.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index b3436b88b9f..e6f2abba469 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -430,10 +430,9 @@ static int read_i2c(struct nmk_i2c_dev *dev) } if (timeout == 0) { - /* controller has timedout, re-init the h/w */ + /* Controller timed out */ dev_err(&dev->pdev->dev, "Read from Slave 0x%x timed out\n", dev->cli.slave_adr); - (void) init_hw(dev); status = -ETIMEDOUT; } return status; @@ -518,10 +517,9 @@ static int write_i2c(struct nmk_i2c_dev *dev) } if (timeout == 0) { - /* controller has timedout, re-init the h/w */ + /* Controller timed out */ dev_err(&dev->pdev->dev, "Write to slave 0x%x timed out\n", dev->cli.slave_adr); - (void) init_hw(dev); status = -ETIMEDOUT; } -- cgit v1.2.3 From 046f2f7c37f1f1ce83f623dcf5f7096f78956b4c Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 15:24:13 +0200 Subject: arm: ux500: change the ab8500-pwm clock from sysclk to ab_ulpclk This patch removes the explicit request for sysclk from the ab8500-pwm driver, and changes the clock it is given to the internal AB8500 ULP PLL. ST Ericsson ID: 335424 ST Ericsson FOSS-OUT ID: trivial ST Ericsson Linux next: - Change-Id: I9ddb05e6caa480976286024bb305e962b86da636 Signed-off-by: Mattias Nilsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21198 Reviewed-by: Bengt JONSSON Reviewed-by: Jonas ABERG Conflicts: arch/arm/mach-ux500/clock-db8500.c --- drivers/misc/ab8500-pwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 01faa7f2c1a..7a928667169 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -73,7 +73,7 @@ int pwm_enable(struct pwm_device *pwm) if (!pwm->clk_enabled) { ret = clk_enable(pwm->clk); if (ret < 0) { - dev_err(pwm->dev, "failed to enable sysclk\n"); + dev_err(pwm->dev, "failed to enable clock\n"); return ret; } pwm->clk_enabled = true; @@ -161,7 +161,7 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev) list_add_tail(&pwm->node, &pwm_list); platform_set_drvdata(pdev, pwm); - pwm->clk = clk_get(pwm->dev, "sysclk"); + pwm->clk = clk_get(pwm->dev, NULL); if (IS_ERR(pwm->clk)) { dev_err(pwm->dev, "clock request failed\n"); ret = PTR_ERR(pwm->clk); -- cgit v1.2.3 From 195c54954f4bf82c1b7aad3adb54015941daaf65 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 28 Apr 2011 13:33:36 +0530 Subject: abx500: provide simpler function names There are no non-interruptible versions of these functions, and all of them operate on registers, so provide shorter names to make subdrivers more readable while sticking to the 80-column line length limit. ST-Ericsson Linux next: - ST-Ericsson ID: WP257121 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I98dc8152e3e8064edb95ba5679277ed8c229b537 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21816 Reviewed-by: QATEST Reviewed-by: Mattias WALLIN --- include/linux/mfd/abx500.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index ee96cd51d8b..33bf25b9e58 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -445,6 +445,12 @@ int abx500_get_chip_id(struct device *dev); int abx500_event_registers_startup_state_get(struct device *dev, u8 *event); int abx500_startup_irq_enabled(struct device *dev, unsigned int irq); +#define abx500_get abx500_get_register_interruptible +#define abx500_set abx500_set_register_interruptible +#define abx500_get_page abx500_get_register_page_interruptible +#define abx500_set_page abx500_set_register_page_interruptible +#define abx500_mask_and_set abx500_mask_and_set_register_interruptible + struct abx500_ops { int (*get_chip_id) (struct device *); int (*get_register) (struct device *, u8, u8, u8 *); -- cgit v1.2.3 From fe19483d1aa037de30f95447342f5cd94cf295ec Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 15:37:42 +0200 Subject: ab5500: provide a driver for power off ST-Ericsson Linux next: - ST-Ericsson ID: WP257121 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I3fcc5c9f1d88c433edc3698da739ecdd11e51711 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22352 Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/Makefile | 2 +- drivers/mfd/ab5500-power.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/ab5500-power.c diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2d4adfd0ee7..9bce327bf6e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -2,7 +2,7 @@ # Makefile for multifunction miscellaneous devices # -obj-$(CONFIG_AB5500_CORE) += ab5500-core.o +obj-$(CONFIG_AB5500_CORE) += ab5500-core.o ab5500-power.o 88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o obj-$(CONFIG_MFD_SM501) += sm501.o diff --git a/drivers/mfd/ab5500-power.c b/drivers/mfd/ab5500-power.c new file mode 100644 index 00000000000..5bf6a4c5e97 --- /dev/null +++ b/drivers/mfd/ab5500-power.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include + +#include +#include + +static struct device *dev; + +#define AB5500_SYSPOR_CONTROL 0x30 + +static void ab5500_power_off(void) +{ + sigset_t old; + sigset_t all; + + sigfillset(&all); + + if (!sigprocmask(SIG_BLOCK, &all, &old)) { + /* Clear dbb_on */ + int ret = abx500_set(dev, AB5500_BANK_STARTUP, + AB5500_SYSPOR_CONTROL, 0); + WARN_ON(ret); + } +} + +static int __devinit ab5500_power_probe(struct platform_device *pdev) +{ + struct ab5500_platform_data *plat = dev_get_platdata(pdev->dev.parent); + + if (!plat->pm_power_off) + return -ENODEV; + + dev = &pdev->dev; + pm_power_off = ab5500_power_off; + + return 0; +} + +static int __devexit ab5500_power_remove(struct platform_device *pdev) +{ + pm_power_off = NULL; + dev = NULL; + + return 0; +} + +static struct platform_driver ab5500_power_driver = { + .driver = { + .name = "ab5500-power", + .owner = THIS_MODULE, + }, + .probe = ab5500_power_probe, + .remove = __devexit_p(ab5500_power_remove), +}; + +static int __init ab8500_sysctrl_init(void) +{ + return platform_driver_register(&ab5500_power_driver); +} + +subsys_initcall(ab8500_sysctrl_init); + +MODULE_DESCRIPTION("AB5500 power driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8f154c0fc9fa3bcba0ed8f4527a15054ae013023 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 16:00:23 +0200 Subject: ab5500: leds: driver for ab5500 leds Simple HV LED controller driver for AB5500v1.0 MFD chips ST-Ericsson ID: WP 332221 ST-Ericsson Linux next: ER 336280 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic787cd1a2277a4c5782dd18d3436cd95b763c81a Signed-off-by: Shreshtha Kumar Sahu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21898 Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/leds/Kconfig | 8 + drivers/leds/Makefile | 1 + drivers/leds/leds-ab5500.c | 432 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/leds-ab5500.h | 31 ++++ 4 files changed, 472 insertions(+) create mode 100644 drivers/leds/leds-ab5500.c create mode 100644 include/linux/leds-ab5500.h diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index ff4b8cfda58..5183a2d4fd5 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -50,6 +50,14 @@ config LEDS_LM3530 controlled manually or using PWM input or using ambient light automatically. +config LEDS_AB5500 + tristate "HVLED driver for AB5500" + depends on AB5500_CORE + help + This option enables support for the HVLED in AB5500 + multi function device. Currently Ab5500 v1.0 chip leds + are supported. + config LEDS_LOCOMO tristate "LED Support for Locomo device" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 890481cb09f..59a569b376e 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o +obj-$(CONFIG_LEDS_AB5500) += leds-ab5500.o obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o diff --git a/drivers/leds/leds-ab5500.c b/drivers/leds/leds-ab5500.c new file mode 100644 index 00000000000..94db3a6feea --- /dev/null +++ b/drivers/leds/leds-ab5500.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA. + * + * License Terms: GNU General Public License v2 + * + * Driver for LED in ST-Ericsson AB5500 v1.0 Analog baseband Controller + * + * Author: Shreshtha Kumar SAHU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AB5500LED_NAME "ab5500-leds" + +/* Register offsets */ +#define AB5500_LED_REG_ENABLE 0x03 +#define AB5500_LED_FADE_CTL 0x0D + +/* LED-0 */ +#define AB5500_LED0_PWM_DUTY 0x01 +#define AB5500_LED0_PWMFREQ 0x02 +#define AB5500_LED0_SINKCTL 0x0A + +/* LED-1 */ +#define AB5500_LED1_PWM_DUTY 0x05 +#define AB5500_LED1_PWMFREQ 0x06 +#define AB5500_LED1_SINKCTL 0x0B + +/* LED-2 */ +#define AB5500_LED2_PWM_DUTY 0x08 +#define AB5500_LED2_PWMFREQ 0x09 +#define AB5500_LED2_SINKCTL 0x0C + +/* pwm duty cycle */ +#define AB5500_LED_PWMDUTY_OFF 0x0 +#define AB5500_LED_PWMDUTY_MAX 0x3FF +#define AB5500_LED_PWMDUTY_STEP (AB5500_LED_PWMDUTY_MAX/LED_FULL) + +/* pwm frequency */ +#define AB5500_LED_PWMFREQ_MAX 0x0F /* 373.39 @sysclk=26MHz */ +#define AB5500_LED_PWMFREQ_SHIFT 4 + +/* LED sink current control */ +#define AB5500_LED_SINKCURR_MAX 0x0F /* 40mA */ +#define AB5500_LED_SINKCURR_SHIFT 4 + +struct ab5500_led { + u8 id; + u8 max_current; + u16 brt_val; + enum ab5500_led_status status; + struct led_classdev led_cdev; + struct work_struct led_work; +}; + +struct ab5500_hvleds { + struct mutex lock; + struct device *dev; + struct ab5500_hvleds_platform_data *pdata; + struct ab5500_led leds[AB5500_HVLEDS_MAX]; +}; + +static u8 ab5500_led_pwmduty_reg[] = { + AB5500_LED0_PWM_DUTY, + AB5500_LED1_PWM_DUTY, + AB5500_LED2_PWM_DUTY, +}; + +static u8 ab5500_led_pwmfreq_reg[] = { + AB5500_LED0_PWMFREQ, + AB5500_LED1_PWMFREQ, + AB5500_LED2_PWMFREQ, +}; + +static u8 ab5500_led_sinkctl_reg[] = { + AB5500_LED0_SINKCTL, + AB5500_LED1_SINKCTL, + AB5500_LED2_SINKCTL +}; + +#define to_led(_x) container_of(_x, struct ab5500_led, _x) + +static inline struct ab5500_hvleds *led_to_hvleds(struct ab5500_led *led) +{ + return container_of(led, struct ab5500_hvleds, leds[led->id]); +} + +static int ab5500_led_pwmduty_write(struct ab5500_hvleds *hvleds, + unsigned int led_id, u16 val) +{ + int ret; + int val_lsb = val & 0xFF; + int val_msb = (val & 0x300) >> 8; + + mutex_lock(&hvleds->lock); + + dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val = %d\n" + "reg[%d] w val = %d\n", + ab5500_led_pwmduty_reg[led_id] - 1, val_lsb, + ab5500_led_pwmduty_reg[led_id], val_msb); + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmduty_reg[led_id] - 1, val_lsb); + ret |= abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmduty_reg[led_id], val_msb); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + ab5500_led_pwmduty_reg[led_id], ret); + mutex_unlock(&hvleds->lock); + + return ret; +} + +static int ab5500_led_pwmfreq_write(struct ab5500_hvleds *hvleds, + unsigned int led_id, u8 val) +{ + int ret; + + val = (val & 0x0F) << AB5500_LED_PWMFREQ_SHIFT; + + mutex_lock(&hvleds->lock); + + dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val=%d\n", + ab5500_led_pwmfreq_reg[led_id], val); + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmfreq_reg[led_id], val); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + ab5500_led_pwmfreq_reg[led_id], ret); + mutex_unlock(&hvleds->lock); + + return ret; +} + +static int ab5500_led_sinkctl_write(struct ab5500_hvleds *hvleds, + unsigned int led_id, u8 val) +{ + int ret; + + val = (val & 0x0F) << AB5500_LED_SINKCURR_SHIFT; + + mutex_lock(&hvleds->lock); + + dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val=%d\n", + ab5500_led_sinkctl_reg[led_id], val); + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_sinkctl_reg[led_id], val); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + ab5500_led_sinkctl_reg[led_id], ret); + mutex_unlock(&hvleds->lock); + + return ret; +} + +static int ab5500_led_sinkctl_read(struct ab5500_hvleds *hvleds, + unsigned int led_id) +{ + int ret; + u8 val; + + mutex_lock(&hvleds->lock); + ret = abx500_get_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_sinkctl_reg[led_id], &val); + if (ret < 0) { + dev_err(hvleds->dev, "reg[%d] r failed: %d\n", + ab5500_led_sinkctl_reg[led_id], ret); + mutex_unlock(&hvleds->lock); + return ret; + } + val = (val & 0xF0) >> AB5500_LED_SINKCURR_SHIFT; + mutex_unlock(&hvleds->lock); + + return val; +} + +static void ab5500_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brt_val) +{ + struct ab5500_led *led = to_led(led_cdev); + + /* adjust LED_FULL to 10bit range */ + brt_val &= LED_FULL; + led->brt_val = brt_val * AB5500_LED_PWMDUTY_STEP; + schedule_work(&led->led_work); +} + +static void ab5500_led_work(struct work_struct *led_work) +{ + struct ab5500_led *led = to_led(led_work); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + if (led->status == AB5500_LED_ON) + ab5500_led_pwmduty_write(hvleds, led->id, led->brt_val); +} + +static ssize_t ab5500_led_show_current(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int led_curr = 0; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ab5500_led *led = to_led(led_cdev); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + led_curr = ab5500_led_sinkctl_read(hvleds, led->id); + + if (led_curr < 0) + return led_curr; + + return sprintf(buf, "%d\n", led_curr); +} + +static ssize_t ab5500_led_store_current(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + int ret; + unsigned long led_curr; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ab5500_led *led = to_led(led_cdev); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + if (strict_strtoul(buf, 0, &led_curr)) + return -EINVAL; + + if (led_curr > led->max_current) + led_curr = led->max_current; + + ret = ab5500_led_sinkctl_write(hvleds, led->id, led_curr); + if (ret < 0) + return ret; + + return len; +} + +/* led class device attributes */ +static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, + ab5500_led_show_current, ab5500_led_store_current); + +static int ab5500_led_init_registers(struct ab5500_hvleds *hvleds) +{ + int ret = 0; + unsigned int led_id; + + /* fade - manual : dur mid : pwm duty mid */ + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + AB5500_LED_REG_ENABLE, true); + if (ret < 0) { + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + AB5500_LED_REG_ENABLE, ret); + return ret; + } + + for (led_id = 0; led_id < AB5500_HVLEDS_MAX; led_id++) { + /* Set pwm freq. and sink current to mid values */ + ret = ab5500_led_pwmfreq_write( + hvleds, led_id, AB5500_LED_PWMFREQ_MAX); + if (ret < 0) + return ret; + + ret = ab5500_led_sinkctl_write( + hvleds, led_id, AB5500_LED_SINKCURR_MAX); + if (ret < 0) + return ret; + + /* init led off */ + ret = ab5500_led_pwmduty_write( + hvleds, led_id, AB5500_LED_PWMDUTY_OFF); + if (ret < 0) + return ret; + } + + return ret; +} + +static int ab5500_led_register_leds(struct device *dev, + struct ab5500_hvleds_platform_data *pdata, + struct ab5500_hvleds *hvleds) +{ + int i_led; + int err; + struct ab5500_led_conf *pled; + struct ab5500_led *led; + + hvleds->dev = dev; + hvleds->pdata = pdata; + for (i_led = 0; i_led < AB5500_HVLEDS_MAX; i_led++) { + pled = &pdata->leds[i_led]; + led = &hvleds->leds[i_led]; + + INIT_WORK(&led->led_work, ab5500_led_work); + + led->id = pled->led_id; + led->max_current = pled->max_current; + led->status = pled->status; + led->led_cdev.name = pled->name; + led->led_cdev.brightness_set = ab5500_led_brightness_set; + + err = led_classdev_register(dev, &led->led_cdev); + if (err < 0) { + dev_err(dev, "Register led class failed: %d\n", err); + goto bailout1; + } + + err = device_create_file(led->led_cdev.dev, + &dev_attr_led_current); + if (err < 0) { + dev_err(dev, "sysfs device creation failed: %d\n", err); + goto bailout2; + } + } + + return err; + for (; i_led >= 0; i_led--) { + device_remove_file(led->led_cdev.dev, &dev_attr_led_current); +bailout2: + led_classdev_unregister(&hvleds->leds[i_led].led_cdev); +bailout1: + cancel_work_sync(&hvleds->leds[i_led].led_work); + } + return err; +} + +static int __devinit ab5500_hvleds_probe(struct platform_device *pdev) +{ + struct ab5500_hvleds_platform_data *pdata = pdev->dev.platform_data; + struct ab5500_hvleds *hvleds = NULL; + int err = 0, i; + + if (pdata == NULL) { + dev_err(&pdev->dev, "platform data required\n"); + err = -ENODEV; + goto err_out; + } + + hvleds = kzalloc(sizeof(struct ab5500_hvleds), GFP_KERNEL); + if (hvleds == NULL) { + err = -ENOMEM; + goto err_out; + } + + mutex_init(&hvleds->lock); + + /* init leds data and register led_classdev */ + err = ab5500_led_register_leds(&pdev->dev, pdata, hvleds); + if (err < 0) { + dev_err(&pdev->dev, "leds registeration failed\n"); + goto err_out; + } + + /* init device registers and set initial led current */ + err = ab5500_led_init_registers(hvleds); + if (err < 0) { + dev_err(&pdev->dev, "reg init failed: %d\n", err); + goto err_reg_init; + } + + dev_info(&pdev->dev, "enabled\n"); + + return err; + +err_reg_init: + for (i = 0; i < AB5500_HVLEDS_MAX; i++) { + struct ab5500_led *led = &hvleds->leds[i]; + + led_classdev_unregister(&led->led_cdev); + device_remove_file(led->led_cdev.dev, &dev_attr_led_current); + cancel_work_sync(&led->led_work); + } +err_out: + kfree(hvleds); + return err; +} + +static int __devexit ab5500_hvleds_remove(struct platform_device *pdev) +{ + struct ab5500_hvleds *hvleds = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < AB5500_HVLEDS_MAX; i++) { + struct ab5500_led *led = &hvleds->leds[i]; + + led_classdev_unregister(&led->led_cdev); + device_remove_file(led->led_cdev.dev, &dev_attr_led_current); + cancel_work_sync(&led->led_work); + } + kfree(hvleds); + return 0; +} + +static struct platform_driver ab5500_hvleds_driver = { + .driver = { + .name = AB5500LED_NAME, + .owner = THIS_MODULE, + }, + .probe = ab5500_hvleds_probe, + .remove = __devexit_p(ab5500_hvleds_remove), +}; + +static int __init ab5500_hvleds_module_init(void) +{ + return platform_driver_register(&ab5500_hvleds_driver); +} + +static void __exit ab5500_hvleds_module_exit(void) +{ + platform_driver_unregister(&ab5500_hvleds_driver); +} + +module_init(ab5500_hvleds_module_init); +module_exit(ab5500_hvleds_module_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Shreshtha Kumar SAHU "); +MODULE_DESCRIPTION("Driver for AB5500 HVLED"); + diff --git a/include/linux/leds-ab5500.h b/include/linux/leds-ab5500.h new file mode 100644 index 00000000000..2db6ffd188e --- /dev/null +++ b/include/linux/leds-ab5500.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA. + * + * License Terms: GNU General Public License v2 + * + * Simple driver for HVLED in ST-Ericsson AB5500 Analog baseband Controller + * + * Author: Shreshtha Kumar SAHU + */ + +#define AB5500_HVLED0 0 +#define AB5500_HVLED1 1 +#define AB5500_HVLED2 2 +#define AB5500_HVLEDS_MAX 3 + +enum ab5500_led_status { + AB5500_LED_OFF = 0x00, + AB5500_LED_ON, +}; + +struct ab5500_led_conf { + char *name; + u8 led_id; + enum ab5500_led_status status; + u8 max_current; +}; + +struct ab5500_hvleds_platform_data { + bool hw_blink; + struct ab5500_led_conf leds[AB5500_HVLEDS_MAX]; +}; -- cgit v1.2.3 From 85f0024fc3e9eedeb30c25cc93c93305aa5c63ac Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 16:18:34 +0200 Subject: Fix Introduced warnings Signed-off-by: Philippe Langlais --- drivers/mfd/ab8500-debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 5c871ae4554..a1330deef31 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -775,9 +775,9 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg, /* args are ok, update target cfg (mainly for read) */ *cfg = loc; -#if ABB_HWREG_DEBUG - pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d - value=0x%X\n", (write) ? "write" : "read", +#ifdef ABB_HWREG_DEBUG + pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d" + "value=0x%X\n", (write) ? "write" : "read", REG_FMT_DEC(cfg) ? "decimal" : "hexa", cfg->addr, cfg->mask, cfg->shift, val); #endif -- cgit v1.2.3 From cd7989010cf67bf492fbcd7930b1775b80d65444 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 16:19:40 +0200 Subject: mach-ux500: ux500 defconfig update Merge all u8500 & u5500 defconfigs in one. FIXME: SND_SOC_UX500_AB8500 (AB8500 audio codec) not set conflicts with U5500 Signed-off-by: Philippe Langlais Conflicts: arch/arm/configs/u8500_defconfig --- arch/arm/configs/u8500_defconfig | 53 ++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 9f0bd6073d0..36e25e88e25 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,5 +1,6 @@ CONFIG_EXPERIMENTAL=y # CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=18 @@ -26,7 +27,7 @@ CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y CONFIG_DB8500_MLOADER=y -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 +CONFIG_UX500_DEBUG_HWREG=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y @@ -87,12 +88,11 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_CFG80211=m # CONFIG_CFG80211_WEXT is not set -CONFIG_MAC80211=m CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=y CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set @@ -110,7 +110,7 @@ CONFIG_STE_TRACE_MODEM=y CONFIG_STM_TRACE=y CONFIG_U8500_SHRM=y CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y -CONFIG_STM_I2S_TEST_PROTOCOL_DRIVER=y +# CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y @@ -118,15 +118,10 @@ CONFIG_TUN=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y -#CONFIG_USB_USBNET is not set -# CONFIG_USB_NET_AX8817X is not set -# CONFIG_USB_NET_NET1080 is not set -# CONFIG_USB_BELKIN is not set -# CONFIG_USB_ARMLINUX is not set -# CONFIG_USB_NET_ZAURUS is not set # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_DB5500=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_NOMADIK_SKE=y CONFIG_KEYBOARD_STMPE=y @@ -135,6 +130,7 @@ CONFIG_KEYBOARD_TC3589X=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_BU21013=y CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_ACCDET=y CONFIG_INPUT_AB8500_PONKEY=y CONFIG_INPUT_UINPUT=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -211,11 +207,14 @@ CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_AUTOFS_FS=m CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y CONFIG_CG2900=y @@ -225,6 +224,9 @@ CONFIG_CG2900_UART=y CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y +CONFIG_CW1200=m +CONFIG_CW1200_NON_POWER_OF_TWO_BLOCKSIZES=y +CONFIG_CW1200_USE_GPIO_IRQ=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -235,16 +237,33 @@ CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_CONFIGFS_FS=m -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_HFS_FS=m +CONFIG_BEFS_FS=m +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_9P_FS=y CONFIG_PARTITION_ADVANCED=y CONFIG_BLKDEV_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y @@ -267,9 +286,13 @@ CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y CONFIG_KEYS=y CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HMAC=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_CRYP=y CONFIG_CRC7=y +CONFIG_LIBCRC32C=m -- cgit v1.2.3 From 83c1c0464daa4e2638976b579a0a3d2ee55dbea6 Mon Sep 17 00:00:00 2001 From: Dmitry Tarnyagin Date: Wed, 25 May 2011 00:05:09 +0200 Subject: cw1200: Enable WEXT compatibility. User-space tools like wpa_supplicant still use legacy wireless extensions for wlan device management. CONFIG_CFG80211_WEXT should be set in the kernel config to enable wireless extension compatibility in the kernel wireless stack. Change-Id: I661eaa0cf3b854b2bb08ecac309d5d050c027a2b Signed-off-by: Dmitry Tarnyagin Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23802 Reviewed-by: Bartosz MARKOWSKI Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 36e25e88e25..62d92ba0e87 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -88,7 +88,6 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -# CONFIG_CFG80211_WEXT is not set CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y -- cgit v1.2.3 From e21f367428afb531f180735d006f3fd5ce9c9cbc Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 27 May 2011 12:03:53 +0200 Subject: serial: pl011: Fix enable of pins ST-Ericsson Linux next: 342766 ST-Ericsson ID: 340139 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: I47692d7a7993cbeda53dfca737d6346f043336f3 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24059 Reviewed-by: Par-Gunnar HJALMDAHL Reviewed-by: Dmitry TARNYAGIN Reviewed-by: Philippe LANGLAIS --- drivers/tty/serial/amba-pl011.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3d569cd68f5..59d48f8b0c5 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1529,6 +1529,14 @@ static void pl011_shutdown(struct uart_port *port) if (uap->lcrh_rx != uap->lcrh_tx) pl011_shutdown_channel(uap, uap->lcrh_tx); + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->exit) + plat->exit(); + } + /* * Shut down the clock producer */ -- cgit v1.2.3 From 80022ca82a98ec687c00772b66bb05c4a41d2a61 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 18 May 2011 18:08:48 +0200 Subject: config: Add fixed regulator driver ST-Ericsson Linux next: 340134 ST-Ericsson ID: 340139 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: Ic187bf313f2f420c4cd4cbbe1a6bf69a0bb48a95 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24084 Reviewed-by: Philippe LANGLAIS Reviewed-by: Dmitry TARNYAGIN Reviewed-by: Par-Gunnar HJALMDAHL --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 62d92ba0e87..f8df7692386 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -164,6 +164,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set -- cgit v1.2.3 From 20d5c8913554ba67d3392b4c3d708de244848a8a Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Thu, 19 May 2011 17:54:50 +0200 Subject: config: Add cg2900 deps BT and HCIUART ST-Ericsson Linux next: 340134 ST-Ericsson ID: 340139 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: Ie01c6904beb23f0c72163ab262d4a34ed253115e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24087 Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index f8df7692386..456eb65da2c 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -80,6 +80,7 @@ CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y CONFIG_PHONET_PIPECTRLR=y CONFIG_NET_SCHED=y +CONFIG_BT=y CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y @@ -88,6 +89,8 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y +CONFIG_CFG80211_WEXT=y +CONFIG_BT_HCIUART=y CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y -- cgit v1.2.3 From 778202b5b0e68df077517403fb9e317ac3b511df Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 13 Oct 2011 16:43:12 +0200 Subject: mfd: abx500: Move ab5500 include Move the content of linux/mfd/abx500/ab5500.h to the mainline header linux/mfd/abx500.h Also change the clients of this file. ST-Ericsson Linux next: OK ST-Ericsson ID: 342253 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: I30f7e2978d7bb00408597fdbdce8e7b6fdca397f Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24725 Reviewed-by: Philippe LANGLAIS --- drivers/leds/leds-ab5500.c | 1 - drivers/mfd/ab5500-power.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/leds/leds-ab5500.c b/drivers/leds/leds-ab5500.c index 94db3a6feea..e4376d1b59b 100644 --- a/drivers/leds/leds-ab5500.c +++ b/drivers/leds/leds-ab5500.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/drivers/mfd/ab5500-power.c b/drivers/mfd/ab5500-power.c index 5bf6a4c5e97..46c2ae8c321 100644 --- a/drivers/mfd/ab5500-power.c +++ b/drivers/mfd/ab5500-power.c @@ -10,7 +10,6 @@ #include #include -#include static struct device *dev; -- cgit v1.2.3 From 980f1c6e3b572ac6287bac4cee050f6a3b3554b1 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 25 May 2011 17:44:23 +0200 Subject: config: u8500: Enable the new asoc drivers ST-Ericsson Linux next: 342252 ST-Ericsson ID: 342253 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: I0f379ee7deeccabe9cbaad29f9ad3f67f269a24d Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24729 Reviewed-by: Ola LILJA2 Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 456eb65da2c..a7928dc01f8 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -20,9 +20,12 @@ CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB8500=y +CONFIG_SND_SOC_UX500_AB8500=y +CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_SND_SOC_UX500_CG29XX=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y -CONFIG_MACH_HREFV60=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y @@ -176,9 +179,14 @@ CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y +# CONFIG_AV8100_HWTRIG_DSI_TE is not set +CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_AB8500=y CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_SUSPEND=y -- cgit v1.2.3 From c2c3ab729556898b501c67e5b78a2d2b0369d528 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 3 May 2011 15:32:06 +0200 Subject: arm: add functions to control prefetch in outer_cache_fns This patch introduces the outer_cache_fns.prefetch_enable and outer_cache_fns.prefetch_disable function pointers. These can be used to control prefetching in the outer cache. ST-Ericsson ID: ER337734 Change-Id: I0885dbba0658f7d7b1081e30418dc0aab66a148a Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22901 Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- arch/arm/include/asm/outercache.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 53426c66352..e76b9eae8e4 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -33,6 +33,8 @@ struct outer_cache_fns { #ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void); #endif + void (*prefetch_enable)(void); + void (*prefetch_disable)(void); void (*set_debug)(unsigned long); void (*resume)(void); }; @@ -81,6 +83,18 @@ static inline void outer_resume(void) outer_cache.resume(); } +static inline void outer_prefetch_enable(void) +{ + if (outer_cache.prefetch_enable) + outer_cache.prefetch_enable(); +} + +static inline void outer_prefetch_disable(void) +{ + if (outer_cache.prefetch_disable) + outer_cache.prefetch_disable(); +} + #else static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) -- cgit v1.2.3 From 799203e20d7fd3e0ad24ec076a31669a22d30368 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 14 Oct 2011 09:29:10 +0200 Subject: u5500: support RTC_CLK1/2 ST-Ericsson Linux next: - ST-Ericsson ID: WP257121 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5feb1dea92e5cc5d4ce57120cfbd320fc54629af Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22993 Reviewed-by: Bibek BASU Reviewed-by: Srinidhi KASAGAR Fix to merge with 335a4a "u5500: support RTC_CLK1/2" --- drivers/mfd/ab5500-power.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/ab5500-power.c b/drivers/mfd/ab5500-power.c index 46c2ae8c321..d23960bc976 100644 --- a/drivers/mfd/ab5500-power.c +++ b/drivers/mfd/ab5500-power.c @@ -13,8 +13,29 @@ static struct device *dev; +/* STARTUP */ #define AB5500_SYSPOR_CONTROL 0x30 +/* VINT IO I2C CLOCK */ +#define AB5500_RTC_VINT 0x01 + +int ab5500_clock_rtc_enable(int num, bool enable) +{ + /* RTC_CLK{0,1,2} are bits {4,3,2}, active low */ + u8 mask = BIT(4 - num); + u8 value = enable ? 0 : mask; + + /* Don't allow RTC_CLK0 to be controlled. */ + if (num < 1 || num > 2) + return -EINVAL; + + if (!dev) + return -EAGAIN; + + return abx500_mask_and_set(dev, AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + AB5500_RTC_VINT, mask, value); +} + static void ab5500_power_off(void) { sigset_t old; @@ -34,18 +55,20 @@ static int __devinit ab5500_power_probe(struct platform_device *pdev) { struct ab5500_platform_data *plat = dev_get_platdata(pdev->dev.parent); - if (!plat->pm_power_off) - return -ENODEV; - dev = &pdev->dev; - pm_power_off = ab5500_power_off; + + if (plat->pm_power_off) + pm_power_off = ab5500_power_off; return 0; } static int __devexit ab5500_power_remove(struct platform_device *pdev) { - pm_power_off = NULL; + struct ab5500_platform_data *plat = dev_get_platdata(pdev->dev.parent); + + if (plat->pm_power_off) + pm_power_off = NULL; dev = NULL; return 0; -- cgit v1.2.3 From de31a99a4e7fe3317aa1d17ef7cc75f69b7330e7 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 14 Oct 2011 09:39:29 +0200 Subject: kernel-doc: fix kernel-doc warnings fix the potential kernel-doc warnings ST-Ericsson Linux next: - ST-Ericsson ID: 327425 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: om prakash Change-Id: Ibaa302ddbaa8e223b81bd047fceaf7c3b97af491 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23345 Reviewed-by: Rabin VINCENT Reviewed-by: Jonas ABERG Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- Documentation/DocBook/stmpe.tmpl | 6 +----- drivers/gpio/gpio-nomadik.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Documentation/DocBook/stmpe.tmpl b/Documentation/DocBook/stmpe.tmpl index 6759149d6ce..9e64a00f6b3 100644 --- a/Documentation/DocBook/stmpe.tmpl +++ b/Documentation/DocBook/stmpe.tmpl @@ -101,11 +101,7 @@
stmpe-keypad.c !Idrivers/input/keyboard/stmpe-keypad.c -
-
- stmpe-gpio.c -!Idrivers/gpio/stmpe-gpio.c -
+ diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 839624f9fe6..d350c8d7d2d 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -359,7 +359,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) /** * nmk_config_pin - configure a pin's mux attributes * @cfg: pin confguration - * + * @sleep: Non-zero to apply the sleep mode configuration * Configures a pin's mode (alternate function or GPIO), its pull up status, * and its sleep mode based on the specified configuration. The @cfg is * usually one of the SoC specific macros defined in mach/-pins.h. These -- cgit v1.2.3 From 8c95c326c57c95241fc1567e51bf71580f3260b1 Mon Sep 17 00:00:00 2001 From: Vijaya Kumar Kilari Date: Wed, 27 Apr 2011 16:56:26 +0530 Subject: AB5500: AB5500 Analog to Digital conversion driver AB5500 GPADC driver for battery/usb voltage, current and temperature measurement ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ia841694711cbba168e7e705a5a2bc78c6e3db8dc Signed-off-by: Vijaya Kumar Kilari Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21775 Reviewed-by: Arun MURTHY Tested-by: Arun MURTHY Reviewed-by: Johan PALSSON Reviewed-by: QATEST Reviewed-by: Linus WALLEIJ Fix to merge with 4e75305 "AB5500: AB5500 Analog to Digital conversion driver" --- drivers/mfd/Kconfig | 7 + drivers/mfd/Makefile | 1 + drivers/mfd/ab5500-gpadc.c | 1167 +++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab5500-gpadc.h | 69 ++ 4 files changed, 1244 insertions(+) create mode 100644 drivers/mfd/ab5500-gpadc.c create mode 100644 include/linux/mfd/abx500/ab5500-gpadc.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 92155341493..41a3e482cb5 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -373,6 +373,13 @@ config AB5500_CORE battery-backed RTC, charging control, Regulators, LEDs, vibrator, system power and temperature, power management and ALSA sound. +config AB5500_GPADC + bool "AB5500 GPADC driver" + depends on AB5500_CORE + default y + help + AB5500 GPADC driver used to convert battery/usb voltage. + config PMIC_DA903X bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9bce327bf6e..e1f64f9403a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-i2c need to come after db8500-prcmu (which provides the channel) obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o obj-$(CONFIG_MFD_DB5500_PRCMU) += db5500-prcmu.o +obj-$(CONFIG_AB5500_GPADC) += ab5500-gpadc.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c new file mode 100644 index 00000000000..e90bd9a3aaa --- /dev/null +++ b/drivers/mfd/ab5500-gpadc.c @@ -0,0 +1,1167 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * Author: Vijaya Kumar K + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Manual mode ADC registers + */ +#define AB5500_GPADC_MANUAL_STAT_REG 0x1F +#define AB5500_GPADC_MANDATAL_REG 0x21 +#define AB5500_GPADC_MANDATAH_REG 0x20 +#define AB5500_GPADC_MANUAL_MUX_CTRL 0x22 +#define AB5500_GPADC_MANUAL_MODE_CTRL 0x23 +#define AB5500_GPADC_MANUAL_MODE_CTRL2 0x24 +/* + * Auto/Polling mode ADC registers + */ +#define AB5500_GPADC_AUTO_VBAT_MAX 0x26 +#define AB5500_GPADC_AUTO_VBAT_MIN_TXON 0x27 +#define AB5500_GPADC_AUTO_VBAT_MIN_NOTX 0x28 +#define AB5500_GPADC_AUTO_VBAT_AVGH 0x29 +#define AB5500_GPADC_AUTO_VBAT_AVGL 0x2A +#define AB5500_GPADC_AUTO_ICHAR_MAX 0x2B +#define AB5500_GPADC_AUTO_ICHAR_MIN 0x2C +#define AB5500_GPADC_AUTO_ICHAR_AVG 0x2D +#define AB5500_GPADC_AUTO_CTRL2 0x2F +#define AB5500_GPADC_AUTO_CTRL1 0x30 +#define AB5500_GPADC_AUTO_PWR_CTRL 0x31 +#define AB5500_GPADC_AUTO_TRIG_VBAT_MIN_TXON 0x32 +#define AB5500_GPADC_AUTO_TRIG_VBAT_MIN_NOTX 0x33 +#define AB5500_GPADC_AUTO_TRIG_ADOUT0_CTRL 0x34 +#define AB5500_GPADC_AUTO_TRIG_ADOUT1_CTRL 0x35 +#define AB5500_GPADC_AUTO_TRIG0_MUX_CTRL 0x37 +#define AB5500_GPADC_AUTO_XALTEMP_CTRL 0x57 +#define AB5500_GPADC_KELVIN_CTRL 0xFE + +/* gpadc constants */ +#define AB5500_INT_ADC_TRIG0 0x0 +#define AB5500_INT_ADC_TRIG1 0x1 +#define AB5500_INT_ADC_TRIG2 0x2 +#define AB5500_INT_ADC_TRIG3 0x3 +#define AB5500_INT_ADC_TRIG4 0x4 +#define AB5500_INT_ADC_TRIG5 0x5 +#define AB5500_INT_ADC_TRIG6 0x6 +#define AB5500_INT_ADC_TRIG7 0x7 + +#define AB5500_GPADC_AUTO_TRIG_INDEX AB5500_GPADC_AUTO_TRIG0_MUX_CTRL +#define GPADC_MANUAL_READY 0x01 +#define GPADC_MANUAL_ADOUT0_MASK 0x30 +#define GPADC_MANUAL_ADOUT1_MASK 0xC0 +#define GPADC_MANUAL_ADOUT0_ON 0x10 +#define GPADC_MANUAL_ADOUT1_ON 0x40 +#define MUX_SCALE_VBAT_MASK 0x02 +#define MUX_SCALE_45 0x02 +#define MUX_SCALE_BDATA_MASK 0x01 +#define MUX_SCALE_BDATA27 0x00 +#define MUX_SCALE_BDATA18 0x01 +#define MUX_SCALE_ACCDET2_MASK 0x01 +#define MUX_SCALE_ACCDET3_MASK 0x02 +#define ACCDET2_SCALE_VOL27 0x00 +#define ACCDET3_SCALE_VOL27 0x00 +#define TRIGX_FREQ_MASK 0x07 +#define AUTO_VBAT_MASK 0x10 +#define AUTO_VBAT_ON 0x10 +#define TRIG_VBAT_TXON_ARM_MASK 0x08 +#define TRIG_VBAT_NOTX_ARM_MASK 0x04 +#define TRIGX_ARM_MASK 0x20 +#define TRIGX_ARM 0x20 +#define TRIGX_MUX_SELECT 0x1F +#define ADC_CAL_OFF_MASK 0x04 +#define ADC_ON_MODE_MASK 0x03 +#define ADC_CAL_ON 0x00 +#define ADC_FULLPWR 0x03 +#define ADC_XTAL_FORCE_MASK 0x80 +#define ADC_XTAL_FORCE_EN 0x80 +#define ADC_XTAL_FORCE_DI 0x00 +#define ADOUT0 0x01 +#define ADOUT1 0x02 +#define MIN_INDEX 0x02 +#define MAX_INDEX 0x03 +#define CTRL_INDEX 0x01 + +/* GPADC constants from AB5500 spec */ +#define BTEMP_MIN 0 +#define BTEMP_MAX 1800 +#define BDATA_MIN 0 +#define BDATA_MAX 2750 +#define PCBTEMP_MIN 0 +#define PCBTEMP_MAX 1800 +#define XTALTEMP_MIN 0 +#define XTALTEMP_MAX 1800 +#define DIETEMP_MIN 0 +#define DIETEMP_MAX 1800 +#define VBUS_I_MIN 0 +#define VBUS_I_MAX 1600 +#define VBUS_V_MIN 0 +#define VBUS_V_MAX 20000 +#define ACCDET2_MIN 0 +#define ACCDET2_MAX 2500 +#define ACCDET3_MIN 0 +#define ACCDET3_MAX 2500 +#define VBAT_MIN 2300 +#define VBAT_MAX 4500 +#define BKBAT_MIN 0 +#define BKBAT_MAX 2750 +#define USBID_MIN 0 +#define USBID_MAX 1800 +#define KELVIN_MIN 0 +#define KELVIN_MAX 4500 + +/* This is used for calibration */ +#define ADC_RESOLUTION 1023 +#define AUTO_ADC_RESOLUTION 255 + +enum adc_auto_channels { + ADC_INPUT_TRIG0 = 0, + ADC_INPUT_TRIG1, + ADC_INPUT_TRIG2, + ADC_INPUT_TRIG3, + ADC_INPUT_TRIG4, + ADC_INPUT_TRIG5, + ADC_INPUT_TRIG6, + ADC_INPUT_TRIG7, + ADC_INPUT_VBAT_TXOFF, + ADC_INPUT_VBAT_TXON, + N_AUTO_TRIGGER +}; + +/** + * struct adc_auto_trigger - AB5500 GPADC auto trigger + * @adc_mux Mux input + * @flag Status of trigger + * @freq Frequency of conversion + * @adout Adout to pull + * @trig_min trigger minimum value + * @trig_max trigger maximum value + * @auto_adc_callback notification callback + */ +struct adc_auto_trigger { + u8 auto_mux; + u8 flag; + u8 freq; + u8 adout; + u8 trig_min; + u8 trig_max; + int (*auto_callb)(int mux); +}; + +/** + * struct ab5500_btemp_interrupts - ab5500 interrupts + * @name: name of the interrupt + * @isr function pointer to the isr + */ +struct ab5500_adc_interrupts { + char *name; + irqreturn_t (*isr)(int irq, void *data); +}; + +/** + * struct ab5500_gpadc - AB5500 GPADC device information + * @chip_id ABB chip id + * @dev: pointer to the struct device + * @node: a list of AB5500 GPADCs, hence prepared for + reentrance + * @ab5500_gpadc_complete: pointer to the struct completion, to indicate + * the completion of gpadc conversion + * @ab5500_gpadc_lock: structure of type mutex + * @regu: pointer to the struct regulator + * @irq: interrupt number that is used by gpadc + * @cal_data array of ADC calibration data structs + * @auto_trig auto trigger channel + * @gpadc_trigX_work work items for trigger channels + */ +struct ab5500_gpadc { + u8 chip_id; + struct device *dev; + struct list_head node; + struct mutex ab5500_gpadc_lock; + struct regulator *regu; + int irq; + spinlock_t gpadc_auto_lock; + struct adc_auto_trigger adc_trig[N_AUTO_TRIGGER]; + struct workqueue_struct *gpadc_wq; + struct work_struct gpadc_trig0_work; + struct work_struct gpadc_trig1_work; + struct work_struct gpadc_trig2_work; + struct work_struct gpadc_trig3_work; + struct work_struct gpadc_trig4_work; + struct work_struct gpadc_trig5_work; + struct work_struct gpadc_trig6_work; + struct work_struct gpadc_trig7_work; + struct work_struct gpadc_trig_vbat_txon_work; + struct work_struct gpadc_trig_vbat_txoff_work; +}; + +static LIST_HEAD(ab5500_gpadc_list); + +struct adc_data { + u8 mux; + int min; + int max; + int adout; +}; + +#define ADC_DATA(_id, _mux, _min, _max, _adout) \ + [_id] = { \ + .mux = _mux, \ + .min = _min, \ + .max = _max, \ + .adout = _adout \ + } + +struct adc_data adc_tab[] = { + ADC_DATA(BTEMP_BALL, 0x0D, BTEMP_MIN, BTEMP_MAX, ADOUT0), + ADC_DATA(BAT_CTRL, 0x0D, BDATA_MIN, BDATA_MAX, 0), + ADC_DATA(MAIN_BAT_V, 0x0C, VBAT_MIN, VBAT_MAX, 0), + ADC_DATA(MAIN_BAT_V_TXON, 0x0C, VBAT_MIN, VBAT_MAX, 0), + ADC_DATA(VBUS_V, 0x10, VBUS_V_MIN, VBUS_V_MAX, 0), + ADC_DATA(USB_CHARGER_C, 0x0A, VBUS_I_MIN, VBUS_I_MAX, 0), + ADC_DATA(BK_BAT_V, 0x07, BKBAT_MIN, BKBAT_MAX, 0), + ADC_DATA(DIE_TEMP, 0x0F, DIETEMP_MIN, DIETEMP_MAX, ADOUT0), + ADC_DATA(PCB_TEMP, 0x13, PCBTEMP_MIN, PCBTEMP_MAX, ADOUT0), + ADC_DATA(XTAL_TEMP, 0x06, XTALTEMP_MIN, XTALTEMP_MAX, ADOUT0), + ADC_DATA(USB_ID, 0x1A, USBID_MIN, USBID_MAX, 0), + ADC_DATA(ACC_DETECT2, 0x18, ACCDET2_MIN, ACCDET2_MAX, 0), + ADC_DATA(ACC_DETECT3, 0x19, ACCDET3_MIN, ACCDET3_MAX, 0), + ADC_DATA(MAIN_BAT_V_TRIG_MIN, 0x0C, VBAT_MIN, VBAT_MAX, 0), + ADC_DATA(MAIN_BAT_V_TXON_TRIG_MIN, 0x0C, VBAT_MIN, VBAT_MAX, 0), +}; +/** + * ab5500_gpadc_get() - returns a reference to the primary AB5500 GPADC + * (i.e. the first GPADC in the instance list) + */ +struct ab5500_gpadc *ab5500_gpadc_get(const char *name) +{ + struct ab5500_gpadc *gpadc; + list_for_each_entry(gpadc, &ab5500_gpadc_list, node) { + if (!strcmp(name, dev_name(gpadc->dev))) + return gpadc; + } + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(ab5500_gpadc_get); + +#define CONV(min, max, x)\ + ((min) + ((((max)-(min))*(x))/ADC_RESOLUTION)) + +static int ab5500_gpadc_ad_to_voltage(struct ab5500_gpadc *gpadc, + u8 in, u16 ad_val) +{ + int res; + + switch (in) { + case PCB_TEMP: + case BTEMP_BALL: + case MAIN_BAT_V: + case MAIN_BAT_V_TXON: + case ACC_DETECT2: + case ACC_DETECT3: + case VBUS_V: + case USB_CHARGER_C: + case BK_BAT_V: + case XTAL_TEMP: + case USB_ID: + case BAT_CTRL: + res = CONV(adc_tab[in].min, adc_tab[in].max, ad_val); + break; + case DIE_TEMP: + /* + * From the AB5500 product specification + * T(deg cel) = 27 - ((ADCode - 709)/2.4213) + * 27 + 709/2.4213 - ADCode/2.4123 + * (320 - ADCode)/2.4213 + */ + res = 320 - (((unsigned long)ad_val * 1000000) / 242130) / 10; + break; + default: + dev_err(gpadc->dev, + "unknown channel, not possible to convert\n"); + res = -EINVAL; + break; + } + return res; +} + +/** + * ab5500_gpadc_convert() - gpadc conversion + * @input: analog input to be converted to digital data + * + * This function converts the selected analog i/p to digital + * data. + */ +int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) +{ + int result, ret = -EINVAL; + u16 data = 0; + u8 looplimit = 0; + u8 status = 0; + u8 low_data, high_data, adout_mask, adout_val; + + if (!gpadc) + return -ENODEV; + + mutex_lock(&gpadc->ab5500_gpadc_lock); + + switch (input) { + case MAIN_BAT_V: + case MAIN_BAT_V_TXON: + /* + * The value of mux scale volatage depends + * on the type of battery + * for LI-ion use MUX_SCALE_35 => 2.3-3.5V + * for LiFePo4 use MUX_SCALE_45 => 2.3-4.5V + * Check type of battery from platform data TODO ??? + */ + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_VBAT_MASK, MUX_SCALE_45); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: failed to read status\n"); + goto out; + } + break; + case BTEMP_BALL: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_BDATA_MASK, MUX_SCALE_BDATA27); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set mux scale\n"); + goto out; + } + break; + case BAT_CTRL: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_BDATA_MASK, MUX_SCALE_BDATA27); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set mux scale\n"); + goto out; + } + break; + case XTAL_TEMP: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_XALTEMP_CTRL, + ADC_XTAL_FORCE_MASK, ADC_XTAL_FORCE_EN); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set xtaltemp\n"); + goto out; + } + break; + case ACC_DETECT2: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL2, + MUX_SCALE_ACCDET2_MASK, ACCDET2_SCALE_VOL27); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set accdet2\n"); + goto out; + } + break; + case ACC_DETECT3: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL2, + MUX_SCALE_ACCDET3_MASK, ACCDET3_SCALE_VOL27); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set accdet3\n"); + goto out; + } + break; + case USB_CHARGER_C: + case VBUS_V: + case BK_BAT_V: + case USB_ID: + case PCB_TEMP: + case DIE_TEMP: + break; + default: + dev_err(gpadc->dev, "gpadc: Wrong adc\n"); + goto out; + break; + } + if (adc_tab[input].adout) { + adout_mask = adc_tab[input].adout == ADOUT0 ? + GPADC_MANUAL_ADOUT0_MASK : GPADC_MANUAL_ADOUT1_MASK; + adout_val = adc_tab[input].adout == ADOUT0 ? + GPADC_MANUAL_ADOUT0_ON : GPADC_MANUAL_ADOUT1_ON; + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + adout_mask, adout_val); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set ADOUT\n"); + goto out; + } + } + ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_MANUAL_MUX_CTRL, adc_tab[input].mux); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc: fail to trigger manual conv\n"); + goto out; + } + /* wait for completion of conversion */ + looplimit = 0; + do { + msleep(1); + ret = abx500_get_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_STAT_REG, + &status); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: failed to read status\n"); + goto out; + } + if (status & GPADC_MANUAL_READY) + break; + } while (++looplimit < 2); + if (looplimit >= 2) { + dev_err(gpadc->dev, "timeout:failed to complete conversion\n"); + ret = -EINVAL; + goto out; + } + + /* + * Disable ADOUT for measurement + */ + if (adc_tab[input].adout) { + adout_mask = adc_tab[input].adout == ADOUT0 ? + GPADC_MANUAL_ADOUT0_MASK : GPADC_MANUAL_ADOUT1_MASK; + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + adout_mask, 0x0); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to disable ADOUT\n"); + goto out; + } + } + /* + * Disable XTAL TEMP + */ + if (input == XTAL_TEMP) { + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_XALTEMP_CTRL, + ADC_XTAL_FORCE_MASK, ADC_XTAL_FORCE_DI); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc: fail to disable xtaltemp\n"); + goto out; + } + } + /* Read the converted RAW data */ + ret = abx500_get_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_MANDATAL_REG, &low_data); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: read low data failed\n"); + goto out; + } + + ret = abx500_get_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_MANDATAH_REG, &high_data); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: read high data failed\n"); + goto out; + } + + data = (high_data << 2) | (low_data >> 6); + result = ab5500_gpadc_ad_to_voltage(gpadc, input, data); + + mutex_unlock(&gpadc->ab5500_gpadc_lock); + return result; + +out: + mutex_unlock(&gpadc->ab5500_gpadc_lock); + dev_err(gpadc->dev, + "gpadc: Failed to AD convert channel %d\n", input); + return ret; +} +EXPORT_SYMBOL(ab5500_gpadc_convert); + +/** + * ab5500_gpadc_program_auto() - gpadc conversion auto conversion + * @trig_index: Generic trigger channel for conversion + * + * This function program the auto trigger channel + */ +static int ab5500_gpadc_program_auto(struct ab5500_gpadc *gpadc, int trig) +{ + int ret; + u8 adout; +#define MIN_INDEX 0x02 +#define MAX_INDEX 0x03 +#define CTRL_INDEX 0x01 + ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2) + MIN_INDEX, + gpadc->adc_trig[trig].trig_min); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to program min\n"); + return ret; + } + ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2) + MAX_INDEX, + gpadc->adc_trig[trig].trig_max); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to program max\n"); + return ret; + } + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2), + TRIGX_MUX_SELECT, gpadc->adc_trig[trig].auto_mux); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to select mux\n"); + return ret; + } + if (gpadc->adc_trig[trig].adout) { + adout = gpadc->adc_trig[trig].adout == ADOUT0 ? + gpadc->adc_trig[trig].adout << 6 : + gpadc->adc_trig[trig].adout << 5; + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2) + CTRL_INDEX, + adout, adout); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to program adout\n"); + return ret; + } + } + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2) + CTRL_INDEX, + TRIGX_FREQ_MASK, gpadc->adc_trig[trig].freq); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to program freq\n"); + return ret; + } + return ret; + +} + +#define TRIG_V(trigval, min, max) \ + ((((trigval) - (min)) * AUTO_ADC_RESOLUTION) / ((max) - (min))) + +static int ab5500_gpadc_vbat_auto_conf(struct ab5500_gpadc *gpadc, + struct adc_auto_input *in) +{ + int trig_min, ret; + u8 trig_reg, trig_arm; + + /* Scale mux voltage */ + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, + AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_VBAT_MASK, MUX_SCALE_45); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: failed to set vbat scale\n"); + return ret; + } + + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, + AB5500_GPADC_AUTO_CTRL1, + AUTO_VBAT_MASK, AUTO_VBAT_ON); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: failed to set vbat on\n"); + return ret; + } + + trig_min = TRIG_V(in->min, adc_tab[in->mux].min, adc_tab[in->mux].max); + + if (in->mux == MAIN_BAT_V_TRIG_MIN) { + trig_reg = AB5500_GPADC_AUTO_TRIG_VBAT_MIN_NOTX; + trig_arm = TRIG_VBAT_NOTX_ARM_MASK; + } else { + trig_reg = AB5500_GPADC_AUTO_TRIG_VBAT_MIN_TXON; + trig_arm = TRIG_VBAT_TXON_ARM_MASK; + } + ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, + trig_reg, trig_min); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to program vbat min\n"); + return ret; + } + /* + * arm the trigger + */ + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_CTRL1, trig_arm, trig_arm); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: failed to trig vbat\n"); + return ret; + } + return ret; +} +/** + * ab5500_gpadc_convert_auto() - gpadc conversion + * @auto_input: input trigger for conversion + * + * This function converts the selected channel from + * analog to digital data in auto mode + */ + +int ab5500_gpadc_convert_auto(struct ab5500_gpadc *gpadc, + struct adc_auto_input *in) +{ + int ret, trig; + unsigned long flags; + + if (!gpadc) + return -ENODEV; + mutex_lock(&gpadc->ab5500_gpadc_lock); + + if (in->mux == MAIN_BAT_V_TXON_TRIG_MIN) { + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + if (gpadc->adc_trig[ADC_INPUT_VBAT_TXON].flag == true) { + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + ret = -EBUSY; + dev_err(gpadc->dev, "gpadc: Auto vbat txon busy"); + goto out; + } + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + + ret = ab5500_gpadc_vbat_auto_conf(gpadc, in); + if (ret < 0) + goto out; + + gpadc->adc_trig[ADC_INPUT_VBAT_TXON].auto_mux = in->mux; + gpadc->adc_trig[ADC_INPUT_VBAT_TXON].auto_callb = + in->auto_adc_callback; + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + gpadc->adc_trig[ADC_INPUT_VBAT_TXON].flag = true; + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + } else if (in->mux == MAIN_BAT_V_TRIG_MIN) { + + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + if (gpadc->adc_trig[ADC_INPUT_VBAT_TXOFF].flag == true) { + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + ret = -EBUSY; + dev_err(gpadc->dev, "gpadc: Auto vbat busy"); + goto out; + } + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + + ret = ab5500_gpadc_vbat_auto_conf(gpadc, in); + if (ret < 0) + goto out; + + gpadc->adc_trig[ADC_INPUT_VBAT_TXOFF].auto_mux = in->mux; + gpadc->adc_trig[ADC_INPUT_VBAT_TXOFF].auto_callb = + in->auto_adc_callback; + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + gpadc->adc_trig[ADC_INPUT_VBAT_TXOFF].flag = true; + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + } else { + /* + * check if free trigger is available + */ + trig = ADC_INPUT_TRIG0; + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + while (gpadc->adc_trig[trig].flag == true && + trig <= ADC_INPUT_TRIG7) + trig++; + + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + if (trig > ADC_INPUT_TRIG7) { + ret = -EBUSY; + dev_err(gpadc->dev, "gpadc: no free channel\n"); + goto out; + } + switch (in->mux) { + case BTEMP_BALL: + case MAIN_BAT_V: + /* + * The value of mux scale volatage depends + * on the type of battery + * for LI-ion use MUX_SCALE_35 => 2.3-3.5V + * for LiFePo4 use MUX_SCALE_45 => 2.3-4.5V + * Check type of battery from platform data TODO ??? + */ + ret = abx500_mask_and_set_register_interruptible( + gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_VBAT_MASK, MUX_SCALE_45); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc: failed to read status\n"); + goto out; + } + case ACC_DETECT2: + case ACC_DETECT3: + case VBUS_V: + case USB_CHARGER_C: + case BK_BAT_V: + case PCB_TEMP: + case USB_ID: + case BAT_CTRL: + gpadc->adc_trig[trig].trig_min = + (u8)TRIG_V(in->min, adc_tab[in->mux].min, + adc_tab[in->mux].max); + gpadc->adc_trig[trig].trig_max = + (u8)TRIG_V(in->max, adc_tab[in->mux].min, + adc_tab[in->mux].max); + gpadc->adc_trig[trig].adout = + adc_tab[in->mux].adout; + break; + case DIE_TEMP: + /* + * From the AB5500 product specification + * T(deg_cel) = 27 -(ADCode - 709)/2.4123) + * adc min and max values are based on the above formula. + */ + gpadc->adc_trig[trig].trig_min = + 709 - (22413 * (in->min - 27))/10000; + gpadc->adc_trig[trig].trig_max = + 709 - (22413 * (in->max - 27))/10000; + gpadc->adc_trig[trig].adout = + adc_tab[in->mux].adout; + break; + default: + dev_err(gpadc->dev, "Unknow GPADC request\n"); + break; + } + gpadc->adc_trig[trig].freq = in->freq; + gpadc->adc_trig[trig].auto_mux = + adc_tab[in->mux].mux; + gpadc->adc_trig[trig].auto_callb = in->auto_adc_callback; + + ret = ab5500_gpadc_program_auto(gpadc, trig); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc: fail to program auto ch\n"); + goto out; + } + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_INDEX + (trig * 4), + TRIGX_ARM_MASK, TRIGX_ARM); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to trigger\n"); + goto out; + } + spin_lock_irqsave(&gpadc->gpadc_auto_lock, flags); + gpadc->adc_trig[trig].flag = true; + spin_unlock_irqrestore(&gpadc->gpadc_auto_lock, flags); + } +out: + mutex_unlock(&gpadc->ab5500_gpadc_lock); + return ret; + +} +EXPORT_SYMBOL(ab5500_gpadc_convert_auto); + +static void ab5500_gpadc_trigx_work(struct ab5500_gpadc *gp, int trig) +{ + unsigned long flags; + if (gp->adc_trig[trig].auto_callb != NULL) { + gp->adc_trig[trig].auto_callb(gp->adc_trig[trig].auto_mux); + spin_lock_irqsave(&gp->gpadc_auto_lock, flags); + gp->adc_trig[trig].flag = false; + spin_unlock_irqrestore(&gp->gpadc_auto_lock, flags); + } else { + dev_err(gp->dev, "Unknown trig for %d\n", trig); + } +} +/** + * ab5500_gpadc_trig0_work() - work item for trig0 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 0 auto conversion. + */ +static void ab5500_gpadc_trig0_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig0_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG0); +} + +/** + * ab5500_gpadc_trig1_work() - work item for trig1 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig1 auto conversion. + */ +static void ab5500_gpadc_trig1_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig1_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG1); +} + +/** + * ab5500_gpadc_trig2_work() - work item for trig2 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 2 auto conversion. + */ +static void ab5500_gpadc_trig2_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig2_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG2); +} + +/** + * ab5500_gpadc_trig3_work() - work item for trig3 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 3 auto conversion. + */ +static void ab5500_gpadc_trig3_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig3_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG3); +} + +/** + * ab5500_gpadc_trig4_work() - work item for trig4 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 4 auto conversion. + */ +static void ab5500_gpadc_trig4_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig4_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG4); +} + +/** + * ab5500_gpadc_trig5_work() - work item for trig5 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 5 auto conversion. + */ +static void ab5500_gpadc_trig5_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig5_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG5); +} + +/** + * ab5500_gpadc_trig6_work() - work item for trig6 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 6 auto conversion. + */ +static void ab5500_gpadc_trig6_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig6_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG6); +} + +/** + * ab5500_gpadc_trig7_work() - work item for trig7 auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for trig 7 auto conversion. + */ +static void ab5500_gpadc_trig7_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig7_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_TRIG7); +} + +/** + * ab5500_gpadc_vbat_txon_work() - work item for vbat_txon trigger auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for vbat_txon trigger auto adc. + */ +static void ab5500_gpadc_vbat_txon_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig_vbat_txon_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_VBAT_TXON); +} + +/** + * ab5500_gpadc_vbat_txoff_work() - work item for vbat_txoff trigger auto adc + * @irq: irq number + * @work: work pointer + * + * This is a work handler for vbat_txoff trigger auto adc. + */ +static void ab5500_gpadc_vbat_txoff_work(struct work_struct *work) +{ + struct ab5500_gpadc *gpadc = container_of(work, + struct ab5500_gpadc, gpadc_trig_vbat_txoff_work); + ab5500_gpadc_trigx_work(gpadc, ADC_INPUT_VBAT_TXOFF); +} + +/** + * ab5500_adc_trigx_handler() - isr for auto gpadc conversion trigger + * @irq: irq number + * @data: pointer to the data passed during request irq + * + * This is a interrupt service routine for auto gpadc conversion. + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_adc_trigx_handler(int irq, void *_gpadc) +{ + struct ab5500_platform_data *plat; + struct ab5500_gpadc *gpadc = _gpadc; + int dev_irq; + + plat = dev_get_platdata(gpadc->dev->parent); + dev_irq = irq - plat->irq.base; + + switch (dev_irq) { + case AB5500_INT_ADC_TRIG0: + dev_dbg(gpadc->dev, "Trigger 0 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig0_work); + break; + case AB5500_INT_ADC_TRIG1: + dev_dbg(gpadc->dev, "Trigger 1 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig1_work); + break; + case AB5500_INT_ADC_TRIG2: + dev_dbg(gpadc->dev, "Trigger 2 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig2_work); + break; + case AB5500_INT_ADC_TRIG3: + dev_dbg(gpadc->dev, "Trigger 3 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig3_work); + break; + case AB5500_INT_ADC_TRIG4: + dev_dbg(gpadc->dev, "Trigger 4 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig4_work); + break; + case AB5500_INT_ADC_TRIG5: + dev_dbg(gpadc->dev, "Trigger 5 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig5_work); + break; + case AB5500_INT_ADC_TRIG6: + dev_dbg(gpadc->dev, "Trigger 6 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig6_work); + break; + case AB5500_INT_ADC_TRIG7: + dev_dbg(gpadc->dev, "Trigger 7 received\n"); + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig7_work); + break; + default: + dev_dbg(gpadc->dev, "unknown trigx handler input\n"); + break; + } + return IRQ_HANDLED; +} + +/** + * ab5500_adc_vbat_txon_handler() - isr for auto vbat_txon conversion trigger + * @irq: irq number + * @data: pointer to the data passed during request irq + * + * This is a interrupt service routine for auto vbat_txon conversion + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_adc_vbat_txon_handler(int irq, void *_gpadc) +{ + struct ab5500_gpadc *gpadc = _gpadc; + + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig_vbat_txon_work); + return IRQ_HANDLED; +} + +/** + * ab5500_adc_vbat_txoff_handler() - isr for auto vbat_txoff conversion trigger + * @irq: irq number + * @data: pointer to the data passed during request irq + * + * This is a interrupt service routine for auto vbat_txoff conversion + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_adc_vbat_txoff_handler(int irq, void *_gpadc) +{ + struct ab5500_gpadc *gpadc = _gpadc; + + queue_work(gpadc->gpadc_wq, &gpadc->gpadc_trig_vbat_txoff_work); + return IRQ_HANDLED; +} + +/** + * ab5500_gpadc_configuration() - function for gpadc conversion + * @irq: irq number + * @data: pointer to the data passed during request irq + * + * This function configures the gpadc + */ +static int ab5500_gpadc_configuration(struct ab5500_gpadc *gpadc) +{ + int ret; + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_CTRL2, + ADC_CAL_OFF_MASK | ADC_ON_MODE_MASK, + ADC_CAL_ON | ADC_FULLPWR); + return ret; +} + +/* ab5500 btemp driver interrupts and their respective isr */ +static struct ab5500_adc_interrupts ab5500_adc_irq[] = { + {"TRIGGER-0", ab5500_adc_trigx_handler}, + {"TRIGGER-1", ab5500_adc_trigx_handler}, + {"TRIGGER-2", ab5500_adc_trigx_handler}, + {"TRIGGER-3", ab5500_adc_trigx_handler}, + {"TRIGGER-4", ab5500_adc_trigx_handler}, + {"TRIGGER-5", ab5500_adc_trigx_handler}, + {"TRIGGER-6", ab5500_adc_trigx_handler}, + {"TRIGGER-7", ab5500_adc_trigx_handler}, + {"TRIGGER-VBAT-TXON", ab5500_adc_vbat_txon_handler}, + {"TRIGGER-VBAT", ab5500_adc_vbat_txoff_handler}, +}; + +static int __devinit ab5500_gpadc_probe(struct platform_device *pdev) +{ + int ret, irq, i, j; + struct ab5500_gpadc *gpadc; + + gpadc = kzalloc(sizeof(struct ab5500_gpadc), GFP_KERNEL); + if (!gpadc) { + dev_err(&pdev->dev, "Error: No memory\n"); + return -ENOMEM; + } + gpadc->dev = &pdev->dev; + mutex_init(&gpadc->ab5500_gpadc_lock); + spin_lock_init(&gpadc->gpadc_auto_lock); + + /* Register interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_adc_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_adc_irq[i].name); + ret = request_threaded_irq(irq, NULL, ab5500_adc_irq[i].isr, + IRQF_NO_SUSPEND, + ab5500_adc_irq[i].name, gpadc); + + if (ret) { + dev_err(gpadc->dev, "failed to request %s IRQ %d: %d\n" + , ab5500_adc_irq[i].name, irq, ret); + goto fail_irq; + } + dev_dbg(gpadc->dev, "Requested %s IRQ %d: %d\n", + ab5500_adc_irq[i].name, irq, ret); + } + + /* Get Chip ID of the ABB ASIC */ + ret = abx500_get_chip_id(gpadc->dev); + if (ret < 0) { + dev_err(gpadc->dev, "failed to get chip ID\n"); + goto fail_irq; + } + gpadc->chip_id = (u8) ret; + + /* Create a work queue for gpadc auto */ + gpadc->gpadc_wq = + create_singlethread_workqueue("ab5500_gpadc_wq"); + if (gpadc->gpadc_wq == NULL) { + dev_err(gpadc->dev, "failed to create work queue\n"); + goto fail_irq; + } + + INIT_WORK(&gpadc->gpadc_trig0_work, ab5500_gpadc_trig0_work); + INIT_WORK(&gpadc->gpadc_trig1_work, ab5500_gpadc_trig1_work); + INIT_WORK(&gpadc->gpadc_trig2_work, ab5500_gpadc_trig2_work); + INIT_WORK(&gpadc->gpadc_trig3_work, ab5500_gpadc_trig3_work); + INIT_WORK(&gpadc->gpadc_trig4_work, ab5500_gpadc_trig4_work); + INIT_WORK(&gpadc->gpadc_trig5_work, ab5500_gpadc_trig5_work); + INIT_WORK(&gpadc->gpadc_trig6_work, ab5500_gpadc_trig6_work); + INIT_WORK(&gpadc->gpadc_trig7_work, ab5500_gpadc_trig7_work); + INIT_WORK(&gpadc->gpadc_trig_vbat_txon_work, + ab5500_gpadc_vbat_txon_work); + INIT_WORK(&gpadc->gpadc_trig_vbat_txoff_work, + ab5500_gpadc_vbat_txoff_work); + + for (j = 0; j < N_AUTO_TRIGGER; j++) + gpadc->adc_trig[j].flag = false; + + ret = ab5500_gpadc_configuration(gpadc); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: configuration failed\n"); + goto free_wq; + } + list_add_tail(&gpadc->node, &ab5500_gpadc_list); + + return 0; +free_wq: + destroy_workqueue(gpadc->gpadc_wq); +fail_irq: + for (i = i - 1; i >= 0; i--) { + irq = platform_get_irq_byname(pdev, ab5500_adc_irq[i].name); + free_irq(irq, gpadc); + } + kfree(gpadc); + gpadc = NULL; + return ret; +} + +static int __devexit ab5500_gpadc_remove(struct platform_device *pdev) +{ + int i, irq; + struct ab5500_gpadc *gpadc = platform_get_drvdata(pdev); + + /* remove this gpadc entry from the list */ + list_del(&gpadc->node); + /* Disable interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_adc_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_adc_irq[i].name); + free_irq(irq, gpadc); + } + /* Flush work */ + flush_workqueue(gpadc->gpadc_wq); + + /* Delete the work queue */ + destroy_workqueue(gpadc->gpadc_wq); + + kfree(gpadc); + gpadc = NULL; + return 0; +} + +static struct platform_driver ab5500_gpadc_driver = { + .probe = ab5500_gpadc_probe, + .remove = __devexit_p(ab5500_gpadc_remove), + .driver = { + .name = "ab5500-adc", + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_gpadc_init(void) +{ + return platform_driver_register(&ab5500_gpadc_driver); +} + +static void __exit ab5500_gpadc_exit(void) +{ + platform_driver_unregister(&ab5500_gpadc_driver); +} + +subsys_initcall_sync(ab5500_gpadc_init); +module_exit(ab5500_gpadc_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Vijaya Kumar K"); +MODULE_ALIAS("platform:ab5500_adc"); +MODULE_DESCRIPTION("AB5500 GPADC driver"); diff --git a/include/linux/mfd/abx500/ab5500-gpadc.h b/include/linux/mfd/abx500/ab5500-gpadc.h new file mode 100644 index 00000000000..3282b44114e --- /dev/null +++ b/include/linux/mfd/abx500/ab5500-gpadc.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 ST-Ericsson SA + * Licensed under GPLv2. + * + * Author: Vijaya Kumar K + */ + +#ifndef _AB5500_GPADC_H +#define _AB5500_GPADC_H + +/* + * GPADC source: + * The BTEMP_BALL and PCB_TEMP are same. They differ if the + * battery supports internal NTC resistor connected to BDATA + * line. In this case, the BTEMP_BALL correspondss to BDATA + * of GPADC as per AB5500 product spec. + */ + +#define BTEMP_BALL 0 +#define ACC_DETECT2 1 +#define ACC_DETECT3 2 +#define MAIN_BAT_V 3 +#define MAIN_BAT_V_TXON 4 +#define VBUS_V 5 +#define USB_CHARGER_C 6 +#define BK_BAT_V 7 +#define DIE_TEMP 8 +#define PCB_TEMP 9 +#define XTAL_TEMP 10 +#define USB_ID 11 +#define BAT_CTRL 12 +/* VBAT with TXON only min trigger */ +#define MAIN_BAT_V_TXON_TRIG_MIN 13 +/* VBAT with TX off only min trigger */ +#define MAIN_BAT_V_TRIG_MIN 14 + +/* + * Frequency of auto adc conversion + */ +#define MS1000 0x0 +#define MS500 0x1 +#define MS200 0x2 +#define MS100 0x3 +#define MS10 0x4 + +struct ab5500_gpadc; + +/* + * struct adc_auto_input - AB5500 GPADC auto trigger + * @adc_mux Mux input + * @freq freq of conversion + * @min min value for trigger + * @max max value for trigger + * @auto_adc_callback notification callback + */ +struct adc_auto_input { + u8 mux; + u8 freq; + int min; + int max; + int (*auto_adc_callback)(int mux); +}; + +struct ab5500_gpadc *ab5500_gpadc_get(const char *name); +int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input); +int ab5500_gpadc_convert_auto(struct ab5500_gpadc *gpadc, + struct adc_auto_input *auto_input); + +#endif /* _AB5500_GPADC_H */ -- cgit v1.2.3 From c48df53c8bc8405eaab8c6ac020f105efd622013 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 14 Oct 2011 11:49:26 +0200 Subject: arm: ux500: common dbx500 prcmu driver api This patch updates the PRCMU driver API to be the same (as far as possible) in U8500 and U4500. - has been renamed . - The platform specific APIs have moved to and (but these should not be directly included). - The PRCMU QoS API has been put in . ST Ericsson ID: 334772 ST Ericsson FOSS-OUT ID: trivial ST Ericsson Linux next: 318371 Change-Id: I6ce117ec35ebf2e987178ccacce09afb554d2736 Signed-off-by: Mattias Nilsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23863 Reviewed-by: Jonas ABERG --- drivers/hwmon/db8500.c | 2 +- drivers/mfd/ab8500-i2c.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/db8500.c b/drivers/hwmon/db8500.c index b9b4312b8c1..c08ab033ada 100755 --- a/drivers/hwmon/db8500.c +++ b/drivers/hwmon/db8500.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c index b83045f102b..5ee90fd125e 100644 --- a/drivers/mfd/ab8500-i2c.c +++ b/drivers/mfd/ab8500-i2c.c @@ -13,6 +13,7 @@ #include #include + static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) { int ret; -- cgit v1.2.3 From 9a648dd53d393c6523daa06338c860b984ac3692 Mon Sep 17 00:00:00 2001 From: Huan DUAN Date: Thu, 26 May 2011 17:08:21 +0200 Subject: hwmon: ab8500: Add BatCtrl thermal sensor Support for monitoring BatCtrl in AB8500 has been added ST-Ericsson Linux next: ER282986 ST-Ericsson ID: CR339643 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I71cfa8b8ecaeae9291d910bc1928ad0e36834709 Signed-off-by: Huan DUAN Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23986 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Jonas ABERG Reviewed-by: Martin PERSSON --- drivers/hwmon/ab8500.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index cdec2c5712d..f22d4ac5fdc 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -47,7 +47,7 @@ */ #define DEFAULT_POWER_OFF_DELAY 10000 -#define NUM_SENSORS 4 +#define NUM_SENSORS 5 /* The driver monitors GPADC - ADC_AUX1 and ADC_AUX2 */ #define NUM_MONITORED_SENSORS 2 @@ -316,11 +316,14 @@ static ssize_t show_label(struct device *dev, name = "ext_db8500"; break; case 3: - name = "battery"; + name = "bat_temp"; break; case 4: name = "ab8500"; break; + case 5: + name = "bat_ctrl"; + break; default: return -EINVAL; } @@ -534,6 +537,10 @@ static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4); static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_crit_alarm, NULL, 4); +/* GPADC - BAT_CTRL */ +static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5); + static struct attribute *ab8500_temp_attributes[] = { &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, &sensor_dev_attr_temp_monitor_delay.dev_attr.attr, @@ -562,6 +569,9 @@ static struct attribute *ab8500_temp_attributes[] = { /* AB8500 */ &sensor_dev_attr_temp4_label.dev_attr.attr, &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, + /* GPADC - BAT_CTRL */ + &sensor_dev_attr_temp5_label.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, NULL }; @@ -645,7 +655,8 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) * AB8500 IRQ will be launched if die crit temp limit is reached. * * Also: - * Battery temperature thresholds will not be exposed via hwmon. + * Battery temperature (BatTemp and BatCtrl) thresholds will + * not be exposed via hwmon. * * Make sure indexes correspond to the attribute indexes * used when calling SENSOR_DEVICE_ATRR @@ -653,7 +664,7 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) data->gpadc_addr[0] = ADC_AUX1; data->gpadc_addr[1] = ADC_AUX2; data->gpadc_addr[2] = BTEMP_BALL; - + data->gpadc_addr[4] = BAT_CTRL; mutex_init(&data->lock); data->pdev = pdev; data->power_off_delay = DEFAULT_POWER_OFF_DELAY; -- cgit v1.2.3 From 67c14de83e2b4c310f8d3a5849b593871d3629d5 Mon Sep 17 00:00:00 2001 From: John Beckett Date: Tue, 31 May 2011 13:54:27 +0100 Subject: AB8500: Export all AB8500 ADCs as debugfs nodes ST-Ericsson ID: 326039 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I30ca4ef74046397d4b498b7cf5673a153a2f62e1 Signed-off-by: John Beckett Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23456 Reviewed-by: Mattias WALLIN --- drivers/mfd/ab8500-debugfs.c | 486 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 465 insertions(+), 21 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index a1330deef31..f36390c0d3d 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -82,7 +82,7 @@ #include #include -#include +#include #ifdef CONFIG_DEBUG_FS #include @@ -143,6 +143,7 @@ static struct hwreg_cfg hwreg_cfg = { }; #define AB8500_NAME_STRING "ab8500" +#define AB8500_ADC_NAME_STRING "gpadc" #define AB8500_NUM_BANKS 22 #define AB8500_REV_REG 0x80 @@ -671,6 +672,382 @@ static int ab8500_hwreg_open(struct inode *inode, struct file *file) return single_open(file, ab8500_hwreg_print, inode->i_private); } +static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) +{ + int bat_ctrl_raw; + int bat_ctrl_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL); + bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, + BAT_CTRL, bat_ctrl_raw); + + return seq_printf(s, "%d,0x%X\n", + bat_ctrl_convert, bat_ctrl_raw); +} + +static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_bat_ctrl_fops = { + .open = ab8500_gpadc_bat_ctrl_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) +{ + int btemp_ball_raw; + int btemp_ball_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL); + btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, + btemp_ball_raw); + + return seq_printf(s, + "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); +} + +static int ab8500_gpadc_btemp_ball_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_btemp_ball_fops = { + .open = ab8500_gpadc_btemp_ball_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) +{ + int main_charger_v_raw; + int main_charger_v_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V); + main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, + MAIN_CHARGER_V, main_charger_v_raw); + + return seq_printf(s, "%d,0x%X\n", + main_charger_v_convert, main_charger_v_raw); +} + +static int ab8500_gpadc_main_charger_v_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_main_charger_v_print, + inode->i_private); +} + +static const struct file_operations ab8500_gpadc_main_charger_v_fops = { + .open = ab8500_gpadc_main_charger_v_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) +{ + int acc_detect1_raw; + int acc_detect1_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1); + acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, + acc_detect1_raw); + + return seq_printf(s, "%d,0x%X\n", + acc_detect1_convert, acc_detect1_raw); +} + +static int ab8500_gpadc_acc_detect1_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_acc_detect1_print, + inode->i_private); +} + +static const struct file_operations ab8500_gpadc_acc_detect1_fops = { + .open = ab8500_gpadc_acc_detect1_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) +{ + int acc_detect2_raw; + int acc_detect2_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2); + acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, + ACC_DETECT2, acc_detect2_raw); + + return seq_printf(s, "%d,0x%X\n", + acc_detect2_convert, acc_detect2_raw); +} + +static int ab8500_gpadc_acc_detect2_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_acc_detect2_print, + inode->i_private); +} + +static const struct file_operations ab8500_gpadc_acc_detect2_fops = { + .open = ab8500_gpadc_acc_detect2_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) +{ + int aux1_raw; + int aux1_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1); + aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, + aux1_raw); + + return seq_printf(s, "%d,0x%X\n", + aux1_convert, aux1_raw); +} + +static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_aux1_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_aux1_fops = { + .open = ab8500_gpadc_aux1_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) +{ + int aux2_raw; + int aux2_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2); + aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, + aux2_raw); + + return seq_printf(s, "%d,0x%X\n", + aux2_convert, aux2_raw); +} + +static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_aux2_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_aux2_fops = { + .open = ab8500_gpadc_aux2_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) +{ + int main_bat_v_raw; + int main_bat_v_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V); + main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, + main_bat_v_raw); + + return seq_printf(s, "%d,0x%X\n", + main_bat_v_convert, main_bat_v_raw); +} + +static int ab8500_gpadc_main_bat_v_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_main_bat_v_fops = { + .open = ab8500_gpadc_main_bat_v_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) +{ + int vbus_v_raw; + int vbus_v_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V); + vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, + vbus_v_raw); + + return seq_printf(s, "%d,0x%X\n", + vbus_v_convert, vbus_v_raw); +} + +static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_vbus_v_fops = { + .open = ab8500_gpadc_vbus_v_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) +{ + int main_charger_c_raw; + int main_charger_c_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C); + main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, + MAIN_CHARGER_C, main_charger_c_raw); + + return seq_printf(s, "%d,0x%X\n", + main_charger_c_convert, main_charger_c_raw); +} + +static int ab8500_gpadc_main_charger_c_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_main_charger_c_print, + inode->i_private); +} + +static const struct file_operations ab8500_gpadc_main_charger_c_fops = { + .open = ab8500_gpadc_main_charger_c_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) +{ + int usb_charger_c_raw; + int usb_charger_c_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C); + usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, + USB_CHARGER_C, usb_charger_c_raw); + + return seq_printf(s, "%d,0x%X\n", + usb_charger_c_convert, usb_charger_c_raw); +} + +static int ab8500_gpadc_usb_charger_c_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ab8500_gpadc_usb_charger_c_print, + inode->i_private); +} + +static const struct file_operations ab8500_gpadc_usb_charger_c_fops = { + .open = ab8500_gpadc_usb_charger_c_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) +{ + int bk_bat_v_raw; + int bk_bat_v_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V); + bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, + BK_BAT_V, bk_bat_v_raw); + + return seq_printf(s, "%d,0x%X\n", + bk_bat_v_convert, bk_bat_v_raw); +} + +static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_bk_bat_v_fops = { + .open = ab8500_gpadc_bk_bat_v_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) +{ + int die_temp_raw; + int die_temp_convert; + struct ab8500_gpadc *gpadc; + + gpadc = ab8500_gpadc_get(); + die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP); + die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, + die_temp_raw); + + return seq_printf(s, "%d,0x%X\n", + die_temp_convert, die_temp_raw); +} + +static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private); +} + +static const struct file_operations ab8500_gpadc_die_temp_fops = { + .open = ab8500_gpadc_die_temp_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + /* * return length of an ASCII numerical value, 0 is string is not a * numerical value. @@ -1038,6 +1415,7 @@ static const struct file_operations ab8500_hwreg_fops = { }; static struct dentry *ab8500_dir; +static struct dentry *ab8500_gpadc_dir; static int __devinit ab8500_debug_probe(struct platform_device *plf) { @@ -1048,14 +1426,14 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); if (irq_first < 0) { dev_err(&plf->dev, "First irq not found, err %d\n", - irq_first); + irq_first); return irq_first; } irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); if (irq_last < 0) { dev_err(&plf->dev, "Last irq not found, err %d\n", - irq_last); + irq_last); return irq_last; } @@ -1063,42 +1441,108 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) if (!ab8500_dir) goto err; - file = debugfs_create_file("all-bank-registers", - S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops); + ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, + ab8500_dir); + if (!ab8500_gpadc_dir) + goto err; + + file = debugfs_create_file("all-bank-registers", S_IRUGO, + ab8500_dir, &plf->dev, &ab8500_registers_fops); + if (!file) + goto err; + + file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_bank_fops); + if (!file) + goto err; + + file = debugfs_create_file("register-address", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_address_fops); + if (!file) + goto err; + + file = debugfs_create_file("register-value", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_val_fops); + if (!file) + goto err; + + file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_subscribe_fops); + if (!file) + goto err; + + file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); + if (!file) + goto err; + + file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUGO), + ab8500_dir, &plf->dev, &ab8500_hwreg_fops); + if (!file) + goto err; + + file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops); + if (!file) + goto err; + + file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops); + if (!file) + goto err; + + file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops); + if (!file) + goto err; + + file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops); + if (!file) + goto err; + + file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops); + if (!file) + goto err; + + file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops); + if (!file) + goto err; + + file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops); if (!file) goto err; - file = debugfs_create_file("register-bank", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); + file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops); if (!file) goto err; - file = debugfs_create_file("register-address", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, - &ab8500_address_fops); + file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops); if (!file) goto err; - file = debugfs_create_file("register-value", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); + file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops); if (!file) goto err; - file = debugfs_create_file("irq-subscribe", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, - &ab8500_subscribe_fops); + file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops); if (!file) goto err; - file = debugfs_create_file("irq-unsubscribe", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, - &ab8500_unsubscribe_fops); + file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops); if (!file) goto err; - file = debugfs_create_file("hwreg", - (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, - &ab8500_hwreg_fops); + file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops); if (!file) goto err; -- cgit v1.2.3 From c34667fb507ff5ebcc9e63e04be54bf484b64b41 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 20:41:55 +0200 Subject: config: Add mmio driver to the u8500 config Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index a7928dc01f8..3481ea714e4 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -224,7 +224,7 @@ CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_U8500_MMIO=y CONFIG_AUTOFS_FS=m CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y -- cgit v1.2.3 From 5c006d022fbf2be6e8ff3881e64279d844f2358a Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 21:10:11 +0200 Subject: config: Add CM driver to u8500 Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3481ea714e4..efa4b4039ec 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -225,6 +225,7 @@ CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y CONFIG_U8500_MMIO=y +CONFIG_U8500_CM=y CONFIG_AUTOFS_FS=m CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y -- cgit v1.2.3 From fe64ac83bcaead17091478522e76488a2a82b89b Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 15 Jun 2011 15:57:28 +0200 Subject: config: Align u8500_defconfig and withdraw u5500 compilation FIXME: U5500 doesn't compile due to function redefinitions in PRCMU Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index efa4b4039ec..d7677d539fb 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -21,19 +21,18 @@ CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y -CONFIG_SND_SOC_UX500_AB8500=y -CONFIG_SND_SOC_UX500_AV8100=y -CONFIG_SND_SOC_UX500_CG29XX=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y +CONFIG_UX500_PRCMU_TIMER=y CONFIG_DB8500_MLOADER=y CONFIG_UX500_DEBUG_HWREG=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y +CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y @@ -83,7 +82,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y CONFIG_PHONET_PIPECTRLR=y CONFIG_NET_SCHED=y -CONFIG_BT=y CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y @@ -92,8 +90,6 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_CFG80211_WEXT=y -CONFIG_BT_HCIUART=y CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y @@ -118,6 +114,10 @@ CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y # CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y CONFIG_TUN=y CONFIG_SMSC_PHY=y @@ -126,7 +126,6 @@ CONFIG_SMSC911X=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_DB5500=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_NOMADIK_SKE=y CONFIG_KEYBOARD_STMPE=y @@ -170,7 +169,6 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -179,14 +177,16 @@ CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y -# CONFIG_AV8100_HWTRIG_DSI_TE is not set CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_AB5500=y CONFIG_SND_SOC_UX500_AB8500=y +CONFIG_SND_SOC_UX500_CG29XX=y +CONFIG_SND_SOC_UX500_AV8100=y CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_SUSPEND=y @@ -211,6 +211,7 @@ CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_CLKGATE=y CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -298,11 +299,11 @@ CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y CONFIG_KEYS=y CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HMAC=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_CRYP=y -- cgit v1.2.3 From 70891cbf58f55c28e26c8bb123d9ed980c3bb615 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 21:18:10 +0200 Subject: config: Add flash driver to u8500 Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index d7677d539fb..f5eea1e948f 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -227,6 +227,7 @@ CONFIG_STE_DMA40=y CONFIG_STAGING=y CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y +CONFIG_U8500_FLASH=y CONFIG_AUTOFS_FS=m CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y -- cgit v1.2.3 From 599943bd2f70732e9f34f428d58a95d9676034ef Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 5 Jul 2011 10:41:40 +0100 Subject: configs: update to a working u8500 defconfig U5500 & CW1200 withdrawn (To be fixed) Signed-off-by: Philippe Langlais Conflicts: arch/arm/configs/u8500_defconfig --- arch/arm/configs/u8500_defconfig | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index f5eea1e948f..a068ffea6a3 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -8,8 +8,8 @@ CONFIG_CGROUPS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y -CONFIG_EMBEDDED=y CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y CONFIG_SLAB=y CONFIG_BOOTTIME=y @@ -28,7 +28,6 @@ CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_PRCMU_TIMER=y CONFIG_DB8500_MLOADER=y -CONFIG_UX500_DEBUG_HWREG=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y @@ -36,8 +35,6 @@ CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -80,7 +77,6 @@ CONFIG_IP_NF_FILTER=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y -CONFIG_PHONET_PIPECTRLR=y CONFIG_NET_SCHED=y CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y @@ -90,6 +86,8 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y @@ -102,11 +100,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y -CONFIG_NETDEVICES=y -CONFIG_SMSC911X=y -CONFIG_SMSC_PHY=y -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_STE_TRACE_MODEM=y CONFIG_STM_TRACE=y CONFIG_U8500_SHRM=y @@ -123,6 +116,9 @@ CONFIG_TUN=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -175,9 +171,9 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_FB=y CONFIG_FB_MCDE=y +CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y -CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y @@ -193,6 +189,7 @@ CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_UX500=y CONFIG_USB_MUSB_OTG=y CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ACM=y @@ -209,8 +206,8 @@ CONFIG_USB_G_MULTI=m # CONFIG_USB_G_MULTI_RNDIS is not set CONFIG_AB8500_USB=y CONFIG_MMC=y -CONFIG_MMC_CLKGATE=y CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_CLKGATE=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y @@ -225,10 +222,6 @@ CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y -CONFIG_U8500_MMIO=y -CONFIG_U8500_CM=y -CONFIG_U8500_FLASH=y -CONFIG_AUTOFS_FS=m CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y CONFIG_CG2900=y @@ -238,9 +231,9 @@ CONFIG_CG2900_UART=y CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y -CONFIG_CW1200=m -CONFIG_CW1200_NON_POWER_OF_TWO_BLOCKSIZES=y -CONFIG_CW1200_USE_GPIO_IRQ=y +CONFIG_U8500_MMIO=y +CONFIG_U8500_CM=y +CONFIG_U8500_FLASH=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -290,14 +283,9 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y -# CONFIG_FTRACE is not set -CONFIG_DEBUG_USER=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_SCHED_TRACER=y -CONFIG_DYNAMIC_DEBUG=y +# CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y CONFIG_KEYS=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_MD5=m -- cgit v1.2.3 From c7d89df1b6b727b070e8df06e2fe49af17b79b2a Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 6 Jul 2011 14:09:38 +0200 Subject: configs: u8500 defconfig: Activate U5500 platforms support Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index a068ffea6a3..30592258f07 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -20,6 +20,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB5500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y -- cgit v1.2.3 From dfb523b733d2a03c29c4d984f5f9f27d559d3dd0 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 20 Jun 2011 10:56:04 +0200 Subject: ux500: config: Align u8500_defconfig with u5500+u8500+u9500 default configs Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 30592258f07..4e7c812d103 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -117,9 +117,7 @@ CONFIG_TUN=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_WLAN is not set +CONFIG_CAIF_SHM=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -147,7 +145,6 @@ CONFIG_SPI=y # CONFIG_STM_MSP_SPI is not set CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y @@ -216,6 +213,7 @@ CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y -- cgit v1.2.3 From 24853a4e39f00c9f2434454f24ddbfe17c5b25b5 Mon Sep 17 00:00:00 2001 From: Chris Kimber Date: Wed, 8 Jun 2011 15:49:59 +0100 Subject: hwmon: ab8500: Automatically monitor sensors when an alarm is set When setting a min/max/max_hyst alarm value for a sensor, it is no longer neccessary to manually kick of a monitoring job. ST-Ericsson Linux next: - ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I24f8f81481f3ff96b54c197ffcbe60f2e50a0d7c Signed-off-by: Chris Kimber Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24714 Reviewed-by: QATEST Reviewed-by: Martin PERSSON Reviewed-by: Linus WALLEIJ --- drivers/hwmon/ab8500.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index f22d4ac5fdc..3167d9adf84 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -46,6 +46,7 @@ * frame, this driver will. Time unit is ms. */ #define DEFAULT_POWER_OFF_DELAY 10000 +#define DEFAULT_MONITOR_DELAY 1000 #define NUM_SENSORS 5 @@ -91,13 +92,17 @@ static bool find_active_thresholds(struct ab8500_temp *data) dev_dbg(&data->pdev->dev, "No active thresholds," "cancel deferred job (if it exists)" "and reset temp monitor delay\n"); - mutex_lock(&data->lock); - data->gpadc_monitor_delay = 0; cancel_delayed_work_sync(&data->work); - mutex_unlock(&data->lock); return false; } + +static inline void schedule_monitor(struct ab8500_temp *data) { + unsigned long delay_in_jiffies; + delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); + schedule_delayed_work(&data->work, delay_in_jiffies); +} + static void thermal_power_off(struct work_struct *work) { struct ab8500_temp *data = container_of(work, struct ab8500_temp, @@ -226,22 +231,21 @@ static ssize_t set_temp_monitor_delay(struct device *dev, const char *buf, size_t count) { int res; - unsigned long delay_in_jiffies, delay_in_s; + unsigned long delay_in_s; struct ab8500_temp *data = dev_get_drvdata(dev); - if (!find_active_thresholds(data)) { - dev_dbg(dev, "No thresholds to monitor, disregarding delay\n"); - return count; - } res = strict_strtoul(buf, 10, &delay_in_s); if (res < 0) return res; mutex_lock(&data->lock); data->gpadc_monitor_delay = delay_in_s * 1000; + + if (find_active_thresholds(data)) { + schedule_monitor(data); + } + mutex_unlock(&data->lock); - delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); - schedule_delayed_work(&data->work, delay_in_jiffies); return count; } @@ -251,7 +255,7 @@ static ssize_t set_temp_power_off_delay(struct device *dev, const char *buf, size_t count) { int res; - unsigned long delay_in_jiffies, delay_in_s; + unsigned long delay_in_s; struct ab8500_temp *data = dev_get_drvdata(dev); res = strict_strtoul(buf, 10, &delay_in_s); @@ -261,7 +265,6 @@ static ssize_t set_temp_power_off_delay(struct device *dev, mutex_lock(&data->lock); data->power_off_delay = delay_in_s * 1000; mutex_unlock(&data->lock); - delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); return count; } @@ -366,9 +369,13 @@ static ssize_t set_min(struct device *dev, struct device_attribute *devattr, data->min_alarm[attr->index - 1] = 0; data->min[attr->index - 1] = val; - mutex_unlock(&data->lock); + if (val == 0) (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); return count; } @@ -392,9 +399,13 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr, data->max_alarm[attr->index - 1] = 0; data->max[attr->index - 1] = val; - mutex_unlock(&data->lock); + if (val == 0) (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); return count; } @@ -419,9 +430,13 @@ static ssize_t set_max_hyst(struct device *dev, data->max_hyst_alarm[attr->index - 1] = 0; data->max_hyst[attr->index - 1] = val; - mutex_unlock(&data->lock); + if (val == 0) (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); return count; } @@ -668,6 +683,7 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) mutex_init(&data->lock); data->pdev = pdev; data->power_off_delay = DEFAULT_POWER_OFF_DELAY; + data->gpadc_monitor_delay = DEFAULT_MONITOR_DELAY; platform_set_drvdata(pdev, data); -- cgit v1.2.3 From 5555ee0a6c89afb500ff55d17568e172380ebd72 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 20 Jun 2011 14:27:33 +0200 Subject: u8500: defconfig: Enable CONFIG_MODEM & CONFIG_MODEM_U8500 Enables the Modem Access Framework Enables the STE U8500 Modem Access driver ST-Ericsson ID: CR329459 Change-Id: I1ce4c4f4e3fcd42f50f5f82d1f04f2fe52abe5aa Signed-off-by: Kumar Sanghvi Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23556 Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR Conflicts: arch/arm/configs/u8500_defconfig --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4e7c812d103..c1a041514c2 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -36,6 +36,8 @@ CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y +CONFIG_MODEM=y +CONFIG_MODEM_U8500=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From e2c9e6cdfbeb4c0d264c682acbe7781f361aec5c Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:47:51 +0530 Subject: power: ab5500-charger: ab5500 usb charger driver Adds a power supply class for usb, used to charge the battery. It includes enabling/disabling of usb charging and monitoring the usb. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP256401 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I4fa42b3dbe82103ad49293b784243dc0edb61558 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23149 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 1837 ++++++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab5500-bm.h | 108 ++ 2 files changed, 1945 insertions(+) create mode 100644 drivers/power/ab5500_charger.c create mode 100644 include/linux/mfd/abx500/ab5500-bm.h diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c new file mode 100644 index 00000000000..1b6bfa21d00 --- /dev/null +++ b/drivers/power/ab5500_charger.c @@ -0,0 +1,1837 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Charger driver for AB5500 + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson + * Karl Komierowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Charger constants */ +#define NO_PW_CONN 0 +#define USB_PW_CONN 2 + +/* HW failure constants */ +#define VBUS_CH_NOK 0x0A +#define VBUS_OVV_TH 0x06 + +/* AB5500 Charger constants */ +#define AB5500_USB_LINK_STATUS 0x78 +#define USB_CHARG_DET_ENA_MASK 0x01 +#define USB_CHARG_DET_ENA 0x01 +#define CHARGER_REV_SUP 0x10 +#define SW_EOC 0x40 +#define USB_CHAR_DET 0x02 +#define USB_CHAR_DET_DONE 0x02 +#define VBUS_RISING 0x20 +#define USB_LINK_UPDATE 0x02 +#define USB_CH_TH_PROT_LOW 0x02 +#define USB_CH_TH_PROT_HIGH 0x01 +#define USB_ID_HOST_DET_ENA_MASK 0x02 +#define USB_ID_HOST_DET_ENA 0x02 +#define USB_ID_DEVICE_DET_ENA_MASK 0x01 +#define USB_ID_DEVICE_DET_ENA 0x01 +#define CHARGER_ISET_IN_1_1A 0x0C +#define LED_ENABLE 0x01 +#define RESET 0x00 +#define SSW_ENABLE_REBOOT 0x80 +#define SSW_REBOOT_EN 0x40 +#define SSW_CONTROL_AUTOC 0x04 +#define SSW_PSEL_480S 0x00 + +/* UsbLineStatus register - usb types */ +enum ab5500_charger_link_status { + USB_STAT_NOT_CONFIGURED, + USB_STAT_STD_HOST_NC, + USB_STAT_STD_HOST_C_NS, + USB_STAT_STD_HOST_C_S, + USB_STAT_HOST_CHG_NM, + USB_STAT_HOST_CHG_HS, + USB_STAT_HOST_CHG_HS_CHIRP, + USB_STAT_DEDICATED_CHG, + USB_STAT_ACA_RID_A, + USB_STAT_ACA_RID_B, + USB_STAT_ACA_RID_C_NM, + USB_STAT_ACA_RID_C_HS, + USB_STAT_ACA_RID_C_HS_CHIRP, + USB_STAT_HM_IDGND, + USB_STAT_RESERVED, + USB_STAT_NOT_VALID_LINK, +}; + +enum ab5500_usb_state { + AB5500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */ + AB5500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */ + AB5500_BM_USB_STATE_CONFIGURED, + AB5500_BM_USB_STATE_SUSPEND, + AB5500_BM_USB_STATE_RESUME, + AB5500_BM_USB_STATE_MAX, +}; + +/* VBUS input current limits supported in AB5500 in mA */ +#define USB_CH_IP_CUR_LVL_0P05 50 +#define USB_CH_IP_CUR_LVL_0P09 98 +#define USB_CH_IP_CUR_LVL_0P19 193 +#define USB_CH_IP_CUR_LVL_0P29 290 +#define USB_CH_IP_CUR_LVL_0P38 380 +#define USB_CH_IP_CUR_LVL_0P45 450 +#define USB_CH_IP_CUR_LVL_0P5 500 +#define USB_CH_IP_CUR_LVL_0P6 600 +#define USB_CH_IP_CUR_LVL_0P7 700 +#define USB_CH_IP_CUR_LVL_0P8 800 +#define USB_CH_IP_CUR_LVL_0P9 900 +#define USB_CH_IP_CUR_LVL_1P0 1000 +#define USB_CH_IP_CUR_LVL_1P1 1100 +#define USB_CH_IP_CUR_LVL_1P3 1300 +#define USB_CH_IP_CUR_LVL_1P4 1400 +#define USB_CH_IP_CUR_LVL_1P5 1500 + +#define to_ab5500_charger_usb_device_info(x) container_of((x), \ + struct ab5500_charger, usb_chg) + +/** + * struct ab5500_charger_interrupts - ab5500 interupts + * @name: name of the interrupt + * @isr function pointer to the isr + */ +struct ab5500_charger_interrupts { + char *name; + irqreturn_t (*isr)(int irq, void *data); +}; + +struct ab5500_charger_info { + int charger_connected; + int charger_online; + int charger_voltage; + int cv_active; + bool wd_expired; +}; + +struct ab5500_charger_event_flags { + bool usb_thermal_prot; + bool vbus_ovv; + bool usbchargernotok; + bool vbus_collapse; +}; + +struct ab5500_charger_usb_state { + bool usb_changed; + int usb_current; + enum ab5500_usb_state state; + spinlock_t usb_lock; +}; + +/** + * struct ab5500_charger - ab5500 Charger device information + * @dev: Pointer to the structure device + * @chip_id: Chip-Id of the ab5500 + * @max_usb_in_curr: Max USB charger input current + * @vbus_detected: VBUS detected + * @vbus_detected_start: + * VBUS detected during startup + * @parent: Pointer to the struct ab5500 + * @gpadc: Pointer to the struct gpadc + * @pdata: Pointer to the ab5500_charger platform data + * @bat: Pointer to the ab5500_bm platform data + * @flags: Structure for information about events triggered + * @usb_state: Structure for usb stack information + * @usb_chg: USB charger power supply + * @ac: Structure that holds the AC charger properties + * @usb: Structure that holds the USB charger properties + * @charger_wq: Work queue for the IRQs and checking HW state + * @check_hw_failure_work: Work for checking HW state + * @check_usbchgnotok_work: Work for checking USB charger not ok status + * @ac_work: Work for checking AC charger connection + * @detect_usb_type_work: Work for detecting the USB type connected + * @usb_link_status_work: Work for checking the new USB link status + * @usb_state_changed_work: Work for checking USB state + * @check_main_thermal_prot_work: + * Work for checking Main thermal status + * @check_usb_thermal_prot_work: + * Work for checking USB thermal status + */ +struct ab5500_charger { + struct device *dev; + u8 chip_id; + int max_usb_in_curr; + bool vbus_detected; + bool vbus_detected_start; + struct ab5500 *parent; + struct ab5500_gpadc *gpadc; + struct abx500_charger_platform_data *pdata; + struct abx500_bm_data *bat; + struct ab5500_charger_event_flags flags; + struct ab5500_charger_usb_state usb_state; + struct ux500_charger usb_chg; + struct ab5500_charger_info usb; + struct workqueue_struct *charger_wq; + struct delayed_work check_hw_failure_work; + struct delayed_work check_usbchgnotok_work; + struct work_struct detect_usb_type_work; + struct work_struct usb_link_status_work; + struct work_struct usb_state_changed_work; + struct work_struct check_usb_thermal_prot_work; +}; + +/* + * TODO: This variable is static in order to get information + * about maximum current and USB state from the USB driver + * This should be solved in a better way + */ +static struct ab5500_charger *static_di; + +/* USB properties */ +static enum power_supply_property ab5500_charger_usb_props[] = { + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, +}; + +/** + * ab5500_charger_get_vbus_voltage() - get vbus voltage + * @di: pointer to the ab5500_charger structure + * + * This function returns the vbus voltage. + * Returns vbus voltage (on success) + */ +static int ab5500_charger_get_vbus_voltage(struct ab5500_charger *di) +{ + int vch; + + /* Only measure voltage if the charger is connected */ + if (di->usb.charger_connected) { + vch = ab5500_gpadc_convert(di->gpadc, VBUS_V); + if (vch < 0) + dev_err(di->dev, "%s gpadc conv failed\n", __func__); + } else { + vch = 0; + } + return vch; +} + +/** + * ab5500_charger_get_usb_current() - get usb charger current + * @di: pointer to the ab5500_charger structure + * + * This function returns the usb charger current. + * Returns usb current (on success) and error code on failure + */ +static int ab5500_charger_get_usb_current(struct ab5500_charger *di) +{ + int ich; + + /* Only measure current if the charger is online */ + if (di->usb.charger_online) { + ich = ab5500_gpadc_convert(di->gpadc, USB_CHARGER_C); + if (ich < 0) + dev_err(di->dev, "%s gpadc conv failed\n", __func__); + } else { + ich = 0; + } + return ich; +} + +/** + * ab5500_charger_detect_chargers() - Detect the connected chargers + * @di: pointer to the ab5500_charger structure + * + * Returns the type of charger connected. + * For USB it will not mean we can actually charge from it + * but that there is a USB cable connected that we have to + * identify. This is used during startup when we don't get + * interrupts of the charger detection + * + * Returns an integer value, that means, + * NO_PW_CONN no power supply is connected + * USB_PW_CONN if the USB power supply is connected + */ +static int ab5500_charger_detect_chargers(struct ab5500_charger *di) +{ + int result = NO_PW_CONN; + int ret; + u8 val; + /* Check for USB charger */ + /* + * TODO: Since there are no status register validating by + * reading the IT souce registers + */ + ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_IT, + AB5500_IT_SOURCE8, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + + if (val & VBUS_RISING) + result |= USB_PW_CONN; + + ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_IT, + AB5500_IT_SOURCE9, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + + if (val & USB_CHAR_DET_DONE) + result |= USB_PW_CONN; + + return result; +} + +/** + * ab5500_charger_max_usb_curr() - get the max curr for the USB type + * @di: pointer to the ab5500_charger structure + * @link_status: the identified USB type + * + * Get the maximum current that is allowed to be drawn from the host + * based on the USB type. + * Returns error code in case of failure else 0 on success + */ +static int ab5500_charger_max_usb_curr(struct ab5500_charger *di, + enum ab5500_charger_link_status link_status) +{ + int ret = 0; + + switch (link_status) { + case USB_STAT_STD_HOST_NC: + case USB_STAT_STD_HOST_C_NS: + case USB_STAT_STD_HOST_C_S: + dev_dbg(di->dev, "USB Type - Standard host is " + "detected through USB driver\n"); + ret = -1; + break; + case USB_STAT_HOST_CHG_HS_CHIRP: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; + break; + case USB_STAT_HOST_CHG_HS: + case USB_STAT_ACA_RID_C_HS: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; + break; + case USB_STAT_ACA_RID_A: + /* + * Dedicated charger level minus maximum current accessory + * can consume (300mA). Closest level is 1100mA + */ + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; + break; + case USB_STAT_ACA_RID_B: + /* + * Dedicated charger level minus 120mA (20mA for ACA and + * 100mA for potential accessory). Closest level is 1300mA + */ + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; + break; + case USB_STAT_DEDICATED_CHG: + case USB_STAT_HOST_CHG_NM: + case USB_STAT_ACA_RID_C_HS_CHIRP: + case USB_STAT_ACA_RID_C_NM: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; + break; + case USB_STAT_RESERVED: + /* + * This state is used to indicate that VBUS has dropped below + * the detection level 4 times in a row. This is due to the + * charger output current is set to high making the charger + * voltage collapse. This have to be propagated through to + * chargalg. This is done using the property + * POWER_SUPPLY_PROP_CURRENT_AVG = 1 + */ + di->flags.vbus_collapse = true; + dev_dbg(di->dev, "USB Type - USB_STAT_RESERVED " + "VBUS has collapsed\n"); + ret = -1; + break; + case USB_STAT_HM_IDGND: + case USB_STAT_NOT_CONFIGURED: + case USB_STAT_NOT_VALID_LINK: + dev_err(di->dev, "USB Type - Charging not allowed\n"); + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; + ret = -ENXIO; + break; + default: + dev_err(di->dev, "USB Type - Unknown\n"); + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; + ret = -ENXIO; + break; + }; + + dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", + link_status, di->max_usb_in_curr); + + return ret; +} + +/** + * ab5500_charger_read_usb_type() - read the type of usb connected + * @di: pointer to the ab5500_charger structure + * + * Detect the type of the plugged USB + * Returns error code in case of failure else 0 on success + */ +static int ab5500_charger_read_usb_type(struct ab5500_charger *di) +{ + int ret; + u8 val; + + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_IT, AB5500_IT_SOURCE22_REG, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_USB, + AB5500_USB_LINE_STATUS, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + + /* get the USB type */ + val = (val & AB5500_USB_LINK_STATUS) >> 3; + ret = ab5500_charger_max_usb_curr(di, + (enum ab5500_charger_link_status) val); + + return ret; +} + +/** + * ab5500_charger_detect_usb_type() - get the type of usb connected + * @di: pointer to the ab5500_charger structure + * + * Detect the type of the plugged USB + * Returns error code in case of failure else 0 on success + */ +static int ab5500_charger_detect_usb_type(struct ab5500_charger *di) +{ + int i, ret; + u8 val; + + /* + * On getting the VBUS rising edge detect interrupt there + * is a 250ms delay after which the register UsbLineStatus + * is filled with valid data. + */ + for (i = 0; i < 10; i++) { + msleep(250); + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_IT, AB5500_IT_SOURCE22_REG, + &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + if (!(val & USB_LINK_UPDATE)) + continue; + + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_LINE_STATUS, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; + } + /* + * Until the IT source register is read the UsbLineStatus + * register is not updated, hence doing the same + * Revisit this: + */ + + /* get the USB type */ + val = (val & AB5500_USB_LINK_STATUS) >> 3; + if (val) { + dev_dbg(di->dev, "values = %d\n", val); + break; + } + } + ret = ab5500_charger_max_usb_curr(di, + (enum ab5500_charger_link_status) val); + + return ret; +} + +static int ab5500_charger_voltage_map[] = { + 3500 , + 3525 , + 3550 , + 3575 , + 3600 , + 3625 , + 3650 , + 3675 , + 3700 , + 3725 , + 3750 , + 3775 , + 3800 , + 3825 , + 3850 , + 3875 , + 3900 , + 3925 , + 3950 , + 3975 , + 4000 , + 4025 , + 4050 , + 4060 , + 4070 , + 4080 , + 4090 , + 4100 , + 4110 , + 4120 , + 4130 , + 4140 , + 4150 , + 4160 , + 4170 , + 4180 , + 4190 , + 4200 , + 4210 , + 4220 , + 4230 , + 4240 , + 4250 , + 4260 , + 4270 , + 4280 , + 4290 , + 4300 , + 4310 , + 4320 , + 4330 , + 4340 , + 4350 , + 4360 , + 4370 , + 4380 , + 4390 , + 4400 , + 4410 , + 4420 , + 4430 , + 4440 , + 4450 , + 4460 , + 4470 , + 4480 , + 4490 , + 4500 , + 4510 , + 4520 , + 4530 , + 4540 , + 4550 , + 4560 , + 4570 , + 4580 , + 4590 , + 4600 , +}; + +/* + * This array maps the raw hex value to charger current used by the ab5500 + * Values taken from the AB5500 product specification manual + */ +static int ab5500_charger_current_map[] = { + 100 , + 200 , + 300 , + 400 , + 500 , + 600 , + 700 , + 800 , + 900 , + 1000, + 1100, + 1200, + 1300, + 1400, + 1500, + 1500, +}; + +static int ab5500_icsr_current_map[] = { + 50, + 93, + 193, + 290, + 380, + 450, + 500 , + 600 , + 700 , + 800 , + 900 , + 1000, + 1100, + 1300, + 1400, + 1500, +}; + +static int ab5500_cvrec_voltage_map[] = { + 3300, + 3325, + 3350, + 3375, + 3400, + 3425, + 3450, + 3475, + 3500, + 3525, + 3550, + 3575, + 3600, + 3625, + 3650, + 3675, + 3700, + 3725, + 3750, + 3775, + 3800, + 3825, + 3850, + 3875, + 3900, + 3925, + 4000, + 4025, + 4050, + 4075, + 4100, + 4125, + 4150, + 4175, + 4200, + 4225, + 4250, + 4275, + 4300, + 4325, + 4350, + 4375, + 4400, + 4425, + 4450, + 4475, + 4500, + 4525, + 4550, + 4575, + 4600, +}; + +static int ab5500_cvrec_voltage_to_regval(int voltage) +{ + int i; + + /* Special case for voltage below 3.3V */ + if (voltage < ab5500_cvrec_voltage_map[0]) + return 0; + + for (i = 1; i < ARRAY_SIZE(ab5500_cvrec_voltage_map); i++) { + if (voltage < ab5500_cvrec_voltage_map[i]) + return i - 1; + } + + /* If not last element, return error */ + i = ARRAY_SIZE(ab5500_cvrec_voltage_map) - 1; + if (voltage == ab5500_cvrec_voltage_map[i]) + return i; + else + return -1; +} + +static int ab5500_voltage_to_regval(int voltage) +{ + int i; + + /* Special case for voltage below 3.3V */ + if (voltage < ab5500_charger_voltage_map[0]) + return 0; + + for (i = 1; i < ARRAY_SIZE(ab5500_charger_voltage_map); i++) { + if (voltage < ab5500_charger_voltage_map[i]) + return i - 1; + } + + /* If not last element, return error */ + i = ARRAY_SIZE(ab5500_charger_voltage_map) - 1; + if (voltage == ab5500_charger_voltage_map[i]) + return i; + else + return -1; +} + +static int ab5500_icsr_curr_to_regval(int curr) +{ + int i; + + if (curr < ab5500_icsr_current_map[0]) + return 0; + + for (i = 0; i < ARRAY_SIZE(ab5500_icsr_current_map); i++) { + if (curr < ab5500_icsr_current_map[i]) + return i - 1; + } + + /* If not last element, return error */ + i = ARRAY_SIZE(ab5500_icsr_current_map) - 1; + if (curr == ab5500_icsr_current_map[i]) + return i; + else + return -1; +} + +static int ab5500_current_to_regval(int curr) +{ + int i; + + if (curr < ab5500_charger_current_map[0]) + return 0; + + for (i = 0; i < ARRAY_SIZE(ab5500_charger_current_map); i++) { + if (curr < ab5500_charger_current_map[i]) + return i - 1; + } + + /* If not last element, return error */ + i = ARRAY_SIZE(ab5500_charger_current_map) - 1; + if (curr == ab5500_charger_current_map[i]) + return i; + else + return -1; +} + +/** + * ab5500_charger_get_usb_cur() - get usb current + * @di: pointer to the ab5500_charger structre + * + * The usb stack provides the maximum current that can be drawn from + * the standard usb host. This will be in mA. + * This function converts current in mA to a value that can be written + * to the register. Returns -1 if charging is not allowed + */ +static int ab5500_charger_get_usb_cur(struct ab5500_charger *di) +{ + switch (di->usb_state.usb_current) { + case 50: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; + break; + case 100: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; + break; + case 200: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P19; + break; + case 300: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P29; + break; + case 400: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P38; + break; + case 500: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; + break; + default: + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; + return -1; + break; + }; + return 0; +} + +/** + * ab5500_charger_set_vbus_in_curr() - set VBUS input current limit + * @di: pointer to the ab5500_charger structure + * @ich_in: charger input current limit + * + * Sets the current that can be drawn from the USB host + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_charger_set_vbus_in_curr(struct ab5500_charger *di, + int ich_in) +{ + int ret; + int input_curr_index; + int min_value; + + /* We should always use to lowest current limit */ + min_value = min(di->bat->chg_params->usb_curr_max, ich_in); + + input_curr_index = ab5500_icsr_curr_to_regval(min_value); + if (input_curr_index < 0) { + dev_err(di->dev, "VBUS input current limit too high\n"); + return -ENXIO; + } + + ret = abx500_set_register_interruptible(di->dev, AB5500_BANK_CHG, + AB5500_ICSR, input_curr_index); + if (ret) + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + + return ret; +} + +/** + * ab5500_charger_usb_en() - enable usb charging + * @di: pointer to the ab5500_charger structure + * @enable: enable/disable flag + * @vset: charging voltage + * @ich_out: charger output current + * + * Enable/Disable USB charging and turns on/off the charging led respectively. + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_charger_usb_en(struct ux500_charger *charger, + int enable, int vset, int ich_out) +{ + int ret; + int volt_index; + int curr_index; + + struct ab5500_charger *di = to_ab5500_charger_usb_device_info(charger); + + if (enable) { + /* Check if USB is connected */ + if (!di->usb.charger_connected) { + dev_err(di->dev, "USB charger not connected\n"); + return -ENXIO; + } + + /* Enable USB charging */ + dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out); + + volt_index = ab5500_voltage_to_regval(vset); + curr_index = ab5500_current_to_regval(ich_out) ; + + /* ChVoltLevel: max voltage upto which battery can be charged */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_VSRC, (u8) volt_index); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + + /* current that can be drawn from the usb */ + ret = ab5500_charger_set_vbus_in_curr(di, ich_out); + if (ret) { + dev_err(di->dev, "%s setting icsr failed %d\n", + __func__, __LINE__); + return ret; + } + + /* ChOutputCurentLevel: protected output current */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_OCSRV, (u8) curr_index); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + + /* + * Battery voltage when charging should be resumed after + * completion of charging + */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_CVREC, + ab5500_cvrec_voltage_to_regval( + di->bat->bat_type[di->bat->batt_id].recharge_vol)); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + /* + * Battery temperature: + * Input to the TBDATA register corresponds to the battery + * temperature(temp being multiples of 2) + * In order to obatain the value to be written to this reg + * divide the temperature obtained from gpadc by 2 + */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_TBDATA, + di->bat->temp_now / 2); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + + /* If success power on charging LED indication */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_LEDT, LED_ENABLE); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + di->usb.charger_online = 1; + } else { + /* ChVoltLevel: max voltage upto which battery can be charged */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_VSRC, RESET); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + /* USBChInputCurr: current that can be drawn from the usb */ + ret = ab5500_charger_set_vbus_in_curr(di, RESET); + if (ret) { + dev_err(di->dev, "%s resetting icsr failed %d\n", + __func__, __LINE__); + return ret; + } + /* If success power off charging LED indication */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_LEDT, RESET); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + di->usb.charger_online = 0; + di->usb.wd_expired = false; + dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); + } + power_supply_changed(&di->usb_chg.psy); + + return ret; +} + +/** + * ab5500_charger_watchdog_kick() - kick charger watchdog + * @di: pointer to the ab5500_charger structure + * + * Kick charger watchdog + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_charger_watchdog_kick(struct ux500_charger *charger) +{ + int ret; + struct ab5500_charger *di; + int volt_index, curr_index; + u8 value = 0; + + /* TODO: update */ + if (charger->psy.type == POWER_SUPPLY_TYPE_USB) + di = to_ab5500_charger_usb_device_info(charger); + else + return -ENXIO; + + ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_STARTUP, + AB5500_MCB, &value); + if (ret) + dev_err(di->dev, "Failed to read!\n"); + + value = value | (SSW_ENABLE_REBOOT | SSW_REBOOT_EN | + SSW_CONTROL_AUTOC | SSW_PSEL_480S); + ret = abx500_set_register_interruptible(di->dev, AB5500_BANK_STARTUP, + AB5500_MCB, value); + if (ret) + dev_err(di->dev, "Failed to kick WD!\n"); + + volt_index = ab5500_voltage_to_regval( + di->bat->bat_type[di->bat->batt_id].normal_vol_lvl); + curr_index = ab5500_current_to_regval(di->max_usb_in_curr); + + /* ChVoltLevel: max voltage upto which battery can be charged */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_VSRC, (u8) volt_index); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + + /* current that can be drawn from the usb */ + ret = ab5500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); + if (ret) { + dev_err(di->dev, "%s setting icsr failed %d\n", + __func__, __LINE__); + return ret; + } + + /* ChOutputCurentLevel: protected output current */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_OCSRV, (u8) curr_index); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + + /* + * Battery voltage when charging should be resumed after + * completion of charging + */ + /* Charger_Vrechar[5:0] = '4.025 V' */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_CVREC, + ab5500_cvrec_voltage_to_regval( + di->bat->bat_type[di->bat->batt_id].recharge_vol)); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + /* + * Battery temperature: + * Input to the TBDATA register corresponds to the battery + * temperature(temp being multiples of 2) + * In order to obatain the value to be written to this reg + * divide the temperature obtained from gpadc by 2 + */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_TBDATA, + di->bat->temp_now / 2); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + return ret; +} + +/** + * ab5500_charger_update_charger_current() - update charger current + * @di: pointer to the ab5500_charger structure + * + * Update the charger output current for the specified charger + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_charger_update_charger_current(struct ux500_charger *charger, + int ich_out) +{ + int ret = 0; + int curr_index; + struct ab5500_charger *di; + + if (charger->psy.type == POWER_SUPPLY_TYPE_USB) + di = to_ab5500_charger_usb_device_info(charger); + else + return -ENXIO; + + curr_index = ab5500_current_to_regval(ich_out); + if (curr_index < 0) { + dev_err(di->dev, + "Charger current too high, " + "charging not started\n"); + return -ENXIO; + } + + ret = abx500_set_register_interruptible(di->dev, AB5500_BANK_CHG, + AB5500_OCSRV, (u8) curr_index); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + + return ret; +} + +/** + * ab5500_charger_check_hw_failure_work() - check main charger failure + * @work: pointer to the work_struct structure + * + * Work queue function for checking the main charger status + */ +static void ab5500_charger_check_hw_failure_work(struct work_struct *work) +{ + int ret; + u8 reg_value; + + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, check_hw_failure_work.work); + + /* Check if the status bits for HW failure is still active */ + if (di->flags.vbus_ovv) { + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_PHY_STATUS, + ®_value); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return; + } + if (!(reg_value & VBUS_OVV_TH)) { + di->flags.vbus_ovv = false; + power_supply_changed(&di->usb_chg.psy); + } + } + /* If we still have a failure, schedule a new check */ + if (di->flags.vbus_ovv) { + queue_delayed_work(di->charger_wq, + &di->check_hw_failure_work, round_jiffies(HZ)); + } +} + +/** + * ab5500_charger_detect_usb_type_work() - work to detect USB type + * @work: Pointer to the work_struct structure + * + * Detect the type of USB plugged + */ +void ab5500_charger_detect_usb_type_work(struct work_struct *work) +{ + int ret; + + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, detect_usb_type_work); + + /* + * Since we can't be sure that the events are received + * synchronously, we have the check if is + * connected by reading the status register + */ + ret = ab5500_charger_detect_chargers(di); + if (ret < 0) + return; + + if (!(ret & USB_PW_CONN)) { + di->vbus_detected = 0; + di->usb.charger_connected = 0; + power_supply_changed(&di->usb_chg.psy); + } else { + di->vbus_detected = 1; + + ret = ab5500_charger_detect_usb_type(di); + if (!ret) { + di->usb.charger_connected = 1; + power_supply_changed(&di->usb_chg.psy); + } + + } +} + +/** + * ab5500_charger_usb_link_status_work() - work to detect USB type + * @work: pointer to the work_struct structure + * + * Detect the type of USB plugged + */ +static void ab5500_charger_usb_link_status_work(struct work_struct *work) +{ + int ret; + + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, usb_link_status_work); + + /* + * Since we can't be sure that the events are received + * synchronously, we have the check if is + * connected by reading the status register + */ + ret = ab5500_charger_detect_chargers(di); + if (ret < 0) + return; + + if (!(ret & USB_PW_CONN)) { + di->vbus_detected = 0; + di->usb.charger_connected = 0; + power_supply_changed(&di->usb_chg.psy); + } else { + di->vbus_detected = 1; + ret = ab5500_charger_read_usb_type(di); + if (!ret) { + /* Update maximum input current */ + ret = ab5500_charger_set_vbus_in_curr(di, + di->max_usb_in_curr); + if (ret) + return; + + di->usb.charger_connected = 1; + power_supply_changed(&di->usb_chg.psy); + } else if (ret == -ENXIO) { + /* No valid charger type detected */ + di->usb.charger_connected = 0; + power_supply_changed(&di->usb_chg.psy); + } + } +} + +static void ab5500_charger_usb_state_changed_work(struct work_struct *work) +{ + int ret; + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, usb_state_changed_work); + + if (!di->vbus_detected) + return; + + spin_lock(&di->usb_state.usb_lock); + di->usb_state.usb_changed = false; + spin_unlock(&di->usb_state.usb_lock); + + /* + * wait for some time until you get updates from the usb stack + * and negotiations are completed + */ + msleep(250); + + if (di->usb_state.usb_changed) + return; + + dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", + __func__, di->usb_state.state, di->usb_state.usb_current); + + switch (di->usb_state.state) { + case AB5500_BM_USB_STATE_RESET_HS: + case AB5500_BM_USB_STATE_RESET_FS: + case AB5500_BM_USB_STATE_SUSPEND: + case AB5500_BM_USB_STATE_MAX: + di->usb.charger_connected = 0; + power_supply_changed(&di->usb_chg.psy); + break; + + case AB5500_BM_USB_STATE_RESUME: + /* + * when suspend->resume there should be delay + * of 1sec for enabling charging + */ + msleep(1000); + /* Intentional fall through */ + case AB5500_BM_USB_STATE_CONFIGURED: + /* + * USB is configured, enable charging with the charging + * input current obtained from USB driver + */ + if (!ab5500_charger_get_usb_cur(di)) { + /* Update maximum input current */ + ret = ab5500_charger_set_vbus_in_curr(di, + di->max_usb_in_curr); + if (ret) + return; + + di->usb.charger_connected = 1; + power_supply_changed(&di->usb_chg.psy); + } + break; + + default: + break; + }; +} + +/** + * ab5500_charger_check_usbchargernotok_work() - check USB chg not ok status + * @work: pointer to the work_struct structure + * + * Work queue function for checking the USB charger Not OK status + */ +static void ab5500_charger_check_usbchargernotok_work(struct work_struct *work) +{ + int ret; + u8 reg_value; + bool prev_status; + + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, check_usbchgnotok_work.work); + + /* Check if the status bit for usbchargernotok is still active */ + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_CHGFSM_CHARGER_DETECT, ®_value); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return; + } + prev_status = di->flags.usbchargernotok; + + if (reg_value & VBUS_CH_NOK) { + di->flags.usbchargernotok = true; + /* Check again in 1sec */ + queue_delayed_work(di->charger_wq, + &di->check_usbchgnotok_work, HZ); + } else { + di->flags.usbchargernotok = false; + di->flags.vbus_collapse = false; + } + + if (prev_status != di->flags.usbchargernotok) + power_supply_changed(&di->usb_chg.psy); +} + +/** + * ab5500_charger_check_usb_thermal_prot_work() - check usb thermal status + * @work: pointer to the work_struct structure + * + * Work queue function for checking the USB thermal prot status + */ +static void ab5500_charger_check_usb_thermal_prot_work( + struct work_struct *work) +{ + int ret; + u8 reg_value; + + struct ab5500_charger *di = container_of(work, + struct ab5500_charger, check_usb_thermal_prot_work); + + /* Check if the status bit for usb_thermal_prot is still active */ + /* TODO: Interrupt source reg 15 bit 4 */ + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_CHGFSM_USB_BTEMP_CURR_LIM, ®_value); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return; + } + if (reg_value & USB_CH_TH_PROT_LOW || reg_value & USB_CH_TH_PROT_HIGH) + di->flags.usb_thermal_prot = true; + else + di->flags.usb_thermal_prot = false; + + power_supply_changed(&di->usb_chg.psy); +} + +/** + * ab5500_charger_vbusdetf_handler() - VBUS falling detected + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_vbusdetf_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, "VBUS falling detected\n"); + queue_work(di->charger_wq, &di->detect_usb_type_work); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_vbusdetr_handler() - VBUS rising detected + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_vbusdetr_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + di->vbus_detected = true; + dev_dbg(di->dev, "VBUS rising detected\n"); + queue_work(di->charger_wq, &di->detect_usb_type_work); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_usblinkstatus_handler() - USB link status has changed + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_usblinkstatus_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, "USB link status changed\n"); + + queue_work(di->charger_wq, &di->usb_link_status_work); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_usbchthprotr_handler() - Die temp is above usb charger + * thermal protection threshold + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_usbchthprotr_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, + "Die temp above USB charger thermal protection threshold\n"); + queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_usbchargernotokr_handler() - USB charger not ok detected + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_usbchargernotokr_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, "Not allowed USB charger detected\n"); + queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_chwdexp_handler() - Charger watchdog expired + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_chwdexp_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, "Charger watchdog expired\n"); + + /* + * The charger that was online when the watchdog expired + * needs to be restarted for charging to start again + */ + if (di->usb.charger_online) { + di->usb.wd_expired = true; + power_supply_changed(&di->usb_chg.psy); + } + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_vbusovv_handler() - VBUS overvoltage detected + * @irq: interrupt number + * @_di: pointer to the ab5500_charger structure + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_charger_vbusovv_handler(int irq, void *_di) +{ + struct ab5500_charger *di = _di; + + dev_dbg(di->dev, "VBUS overvoltage detected\n"); + di->flags.vbus_ovv = true; + power_supply_changed(&di->usb_chg.psy); + + /* Schedule a new HW failure check */ + queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); + + return IRQ_HANDLED; +} + +/** + * ab5500_charger_usb_get_property() - get the usb properties + * @psy: pointer to the power_supply structure + * @psp: pointer to the power_supply_property structure + * @val: pointer to the power_supply_propval union + * + * This function gets called when an application tries to get the usb + * properties by reading the sysfs files. + * USB properties are online, present and voltage. + * online: usb charging is in progress or not + * present: presence of the usb + * voltage: vbus voltage + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_charger_usb_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ab5500_charger *di; + + di = to_ab5500_charger_usb_device_info(psy_to_ux500_charger(psy)); + + switch (psp) { + case POWER_SUPPLY_PROP_HEALTH: + if (di->flags.usbchargernotok) + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + else if (di->usb.wd_expired) + val->intval = POWER_SUPPLY_HEALTH_DEAD; + else if (di->flags.usb_thermal_prot) + val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + else if (di->flags.vbus_ovv) + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_ONLINE: + val->intval = di->usb.charger_online; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = di->usb.charger_connected; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + di->usb.charger_voltage = ab5500_charger_get_vbus_voltage(di); + val->intval = di->usb.charger_voltage * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = ab5500_charger_get_usb_current(di) * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + /* + * This property is used to indicate when VBUS has collapsed + * due to too high output current from the USB charger + */ + if (di->flags.vbus_collapse) + val->intval = 1; + else + val->intval = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +/** + * ab5500_charger_hw_registers() - Set up charger related registers + * @di: pointer to the ab5500_charger structure + * + * Set up charger OVV, watchdog and maximum voltage registers as well as + * charging of the backup battery + */ +static int ab5500_charger_init_hw_registers(struct ab5500_charger *di) +{ + int ret = 0; + + /* Enable ID Host and Device detection */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_OTG_CTRL, + USB_ID_HOST_DET_ENA_MASK, USB_ID_HOST_DET_ENA); + if (ret) { + dev_err(di->dev, "failed to enable usb charger detection\n"); + goto out; + } + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_OTG_CTRL, + USB_ID_DEVICE_DET_ENA_MASK, USB_ID_DEVICE_DET_ENA); + if (ret) { + dev_err(di->dev, "failed to enable usb charger detection\n"); + goto out; + } + + /* Enable USB Charger Detection */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_LINE_CTRL2, + USB_CHARG_DET_ENA_MASK, USB_CHARG_DET_ENA); + if (ret) { + dev_err(di->dev, "failed to enable usb charger detection\n"); + goto out; + } + + /* Over current protection for reverse supply */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_CREVS, CHARGER_REV_SUP, + CHARGER_REV_SUP); + if (ret) { + dev_err(di->dev, + "failed to enable over current protection for reverse supply\n"); + goto out; + } + + /* Enable SW EOC at flatcurrent detection */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_CCTRL, SW_EOC, SW_EOC); + if (ret) { + dev_err(di->dev, + "failed to enable end of charge at flatcurrent detection\n"); + goto out; + } +out: + return ret; +} + +/* + * ab5500 charger driver interrupts and their respective isr + */ +static struct ab5500_charger_interrupts ab5500_charger_irq[] = { + {"VBUS_FALLING", ab5500_charger_vbusdetf_handler}, + {"VBUS_RISING", ab5500_charger_vbusdetr_handler}, + {"USB_LINK_UPDATE", ab5500_charger_usblinkstatus_handler}, + {"USB_CH_TH_PROTECTION", ab5500_charger_usbchthprotr_handler}, + {"USB_CH_NOT_OK", ab5500_charger_usbchargernotokr_handler}, + {"OVV", ab5500_charger_vbusovv_handler}, + /* TODO: Interrupt missing, will be available in cut 2 */ + /*{"CHG_SW_TIMER_OUT", ab5500_charger_chwdexp_handler},*/ +}; + +void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) +{ + struct ab5500_charger *di = static_di; + + dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", + __func__, bm_usb_state, mA); + + spin_lock(&di->usb_state.usb_lock); + di->usb_state.usb_changed = true; + spin_unlock(&di->usb_state.usb_lock); + + di->usb_state.state = bm_usb_state; + di->usb_state.usb_current = mA; + + queue_work(di->charger_wq, &di->usb_state_changed_work); + + return; +} +EXPORT_SYMBOL(ab5500_charger_usb_state_changed); + +#if defined(CONFIG_PM) +static int ab5500_charger_resume(struct platform_device *pdev) +{ + struct ab5500_charger *di = platform_get_drvdata(pdev); + + /* If we still have a HW failure, schedule a new check */ + if (di->flags.usbchargernotok || di->flags.vbus_ovv) { + queue_delayed_work(di->charger_wq, + &di->check_hw_failure_work, 0); + } + + return 0; +} + +static int ab5500_charger_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct ab5500_charger *di = platform_get_drvdata(pdev); + + /* Cancel any pending HW failure check */ + if (delayed_work_pending(&di->check_hw_failure_work)) + cancel_delayed_work(&di->check_hw_failure_work); + + return 0; +} +#else +#define ab5500_charger_suspend NULL +#define ab5500_charger_resume NULL +#endif + +static int __devexit ab5500_charger_remove(struct platform_device *pdev) +{ + struct ab5500_charger *di = platform_get_drvdata(pdev); + int i, irq; + + /* Disable USB charging */ + ab5500_charger_usb_en(&di->usb_chg, false, 0, 0); + + /* Disable interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_charger_irq[i].name); + free_irq(irq, di); + } + + /* Delete the work queue */ + destroy_workqueue(di->charger_wq); + + flush_scheduled_work(); + power_supply_unregister(&di->usb_chg.psy); + platform_set_drvdata(pdev, NULL); + kfree(di); + + return 0; +} + +static int __devinit ab5500_charger_probe(struct platform_device *pdev) +{ + int irq, i, charger_status, ret = 0; + struct abx500_bm_plat_data *plat_data; + + struct ab5500_charger *di = + kzalloc(sizeof(struct ab5500_charger), GFP_KERNEL); + if (!di) + return -ENOMEM; + + static_di = di; + + /* get parent data */ + di->dev = &pdev->dev; + di->parent = dev_get_drvdata(pdev->dev.parent); + di->gpadc = ab5500_gpadc_get("ab5500-adc.0"); + + /* initialize lock */ + spin_lock_init(&di->usb_state.usb_lock); + + plat_data = pdev->dev.platform_data; + di->pdata = plat_data->charger; + di->bat = plat_data->battery; + + /* get charger specific platform data */ + if (!di->pdata) { + dev_err(di->dev, "no charger platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + + /* get battery specific platform data */ + if (!di->bat) { + dev_err(di->dev, "no battery platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + /* USB supply */ + /* power_supply base class */ + di->usb_chg.psy.name = "ab5500_usb"; + di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB; + di->usb_chg.psy.properties = ab5500_charger_usb_props; + di->usb_chg.psy.num_properties = ARRAY_SIZE(ab5500_charger_usb_props); + di->usb_chg.psy.get_property = ab5500_charger_usb_get_property; + di->usb_chg.psy.supplied_to = di->pdata->supplied_to; + di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; + /* ux500_charger sub-class */ + di->usb_chg.ops.enable = &ab5500_charger_usb_en; + di->usb_chg.ops.kick_wd = &ab5500_charger_watchdog_kick; + di->usb_chg.ops.update_curr = &ab5500_charger_update_charger_current; + di->usb_chg.max_out_volt = ab5500_charger_voltage_map[ + ARRAY_SIZE(ab5500_charger_voltage_map) - 1]; + di->usb_chg.max_out_curr = ab5500_charger_current_map[ + ARRAY_SIZE(ab5500_charger_current_map) - 1]; + + + /* Create a work queue for the charger */ + di->charger_wq = + create_singlethread_workqueue("ab5500_charger_wq"); + if (di->charger_wq == NULL) { + dev_err(di->dev, "failed to create work queue\n"); + goto free_device_info; + } + + /* Init work for HW failure check */ + INIT_DELAYED_WORK_DEFERRABLE(&di->check_hw_failure_work, + ab5500_charger_check_hw_failure_work); + INIT_DELAYED_WORK_DEFERRABLE(&di->check_usbchgnotok_work, + ab5500_charger_check_usbchargernotok_work); + + /* Init work for charger detection */ + INIT_WORK(&di->usb_link_status_work, + ab5500_charger_usb_link_status_work); + INIT_WORK(&di->detect_usb_type_work, + ab5500_charger_detect_usb_type_work); + + INIT_WORK(&di->usb_state_changed_work, + ab5500_charger_usb_state_changed_work); + + /* Init work for checking HW status */ + INIT_WORK(&di->check_usb_thermal_prot_work, + ab5500_charger_check_usb_thermal_prot_work); + + /* Get Chip ID of the ABB ASIC */ + ret = abx500_get_chip_id(di->dev); + if (ret < 0) { + dev_err(di->dev, "failed to get chip ID\n"); + goto free_charger_wq; + } + di->chip_id = ret; + dev_dbg(di->dev, "AB5500 CID is: 0x%02x\n", di->chip_id); + + /* Initialize OVV, and other registers */ + ret = ab5500_charger_init_hw_registers(di); + if (ret) { + dev_err(di->dev, "failed to initialize ABB registers\n"); + goto free_device_info; + } + + /* Register USB charger class */ + ret = power_supply_register(di->dev, &di->usb_chg.psy); + if (ret) { + dev_err(di->dev, "failed to register USB charger\n"); + goto free_device_info; + } + + /* Identify the connected charger types during startup */ + charger_status = ab5500_charger_detect_chargers(di); + if (charger_status & USB_PW_CONN) { + dev_dbg(di->dev, "VBUS Detect during startup\n"); + di->vbus_detected = true; + di->vbus_detected_start = true; + queue_work(di->charger_wq, + &di->detect_usb_type_work); + } + + /* Register interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_charger_irq[i].name); + ret = request_threaded_irq(irq, NULL, ab5500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND, + ab5500_charger_irq[i].name, di); + + if (ret != 0) { + dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + , ab5500_charger_irq[i].name, irq, ret); + goto free_irq; + } + dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + ab5500_charger_irq[i].name, irq, ret); + } + + platform_set_drvdata(pdev, di); + + dev_info(di->dev, "probe success\n"); + return ret; + +free_irq: + power_supply_unregister(&di->usb_chg.psy); + + /* We also have to free all successfully registered irqs */ + for (i = i - 1; i >= 0; i--) { + irq = platform_get_irq_byname(pdev, ab5500_charger_irq[i].name); + free_irq(irq, di); + } +free_charger_wq: + destroy_workqueue(di->charger_wq); +free_device_info: + kfree(di); + + return ret; +} + +static struct platform_driver ab5500_charger_driver = { + .probe = ab5500_charger_probe, + .remove = __devexit_p(ab5500_charger_remove), + .suspend = ab5500_charger_suspend, + .resume = ab5500_charger_resume, + .driver = { + .name = "ab5500-charger", + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_charger_init(void) +{ + return platform_driver_register(&ab5500_charger_driver); +} + +static void __exit ab5500_charger_exit(void) +{ + platform_driver_unregister(&ab5500_charger_driver); +} + +subsys_initcall_sync(ab5500_charger_init); +module_exit(ab5500_charger_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); +MODULE_ALIAS("platform:ab5500-charger"); +MODULE_DESCRIPTION("AB5500 charger management driver"); diff --git a/include/linux/mfd/abx500/ab5500-bm.h b/include/linux/mfd/abx500/ab5500-bm.h new file mode 100644 index 00000000000..b9800cd8c19 --- /dev/null +++ b/include/linux/mfd/abx500/ab5500-bm.h @@ -0,0 +1,108 @@ +/* + * Copyright ST-Ericsson 2011. + * + * Author: Arun Murthy + * Licensed under GPLv2. + */ + +#ifndef _AB5500_BM_H +#define _AB5500_BM_H + +#define AB5500_MCB 0x2F +/* + * USB/ULPI register offsets + * Bank : 0x5 + */ +#define AB5500_USB_LINE_STATUS 0x80 +#define AB5500_USB_PHY_STATUS 0x89 +#define AB5500_CHGFSM_CHARGER_DETECT 0xBF +#define AB5500_CHGFSM_USB_BTEMP_CURR_LIM 0xAD +#define AB5500_USB_LINE_CTRL2 0x82 +#define AB5500_USB_OTG_CTRL 0x87 + +/* + * Charger / control register offfsets + * Bank : 0x0B + */ +#define AB5500_CVBUSM 0x11 +#define AB5500_LEDT 0x12 +#define AB5500_VSRC 0x13 +#define AB5500_ICSR 0x14 +#define AB5500_OCSRV 0x15 +#define AB5500_CVREC 0x16 +#define AB5500_CREVS 0x17 +#define AB5500_CCTRL 0x18 +#define AB5500_TBDATA 0x19 +#define AB5500_CPWM 0x1A +#define AB5500_DCIOCURRENT 0x1B +#define AB5500_USB_HS_CURR_LIM 0x1C +#define AB5500_WALL_HS_CURR_LIM 0x1D + +/* + * FG, Battcom and ACC registers offsets + * Bank : 0x0C + */ +#define AB5500_FG_CH0 0x00 +#define AB5500_FG_CH1 0x01 +#define AB5500_FG_CH2 0x02 +#define AB5500_FG_DIS_CH0 0x03 +#define AB5500_FG_DIS_CH1 0x04 +#define AB5500_FG_DIS_CH2 0x05 +#define AB5500_FGDIS_COUNT0 0x06 +#define AB5500_FGDIS_COUNT1 0x07 +#define AB5500_FG_VAL_COUNT0 0x08 +#define AB5500_FG_VAL_COUNT1 0x09 +#define AB5500_FGDIR_READ0 0x0A +#define AB5500_FGDIR_READ1 0x0B +#define AB5500_FG_CONTROL_A 0x0C +#define AB5500_FG_CONTROL_B 0x0F +#define AB5500_FG_CONTROL_C 0x10 +#define AB5500_FG_DIS 0x0D +#define AB5500_FG_EOC 0x0E +#define AB5500_FG_CB 0x0F +#define AB5500_FG_CC 0x10 +#define AB5500_UIOR 0x1A +#define AB5500_UART 0x1B +#define AB5500_URI 0x1C +#define AB5500_UART_RQ 0x1D +#define AB5500_ACC_DETECT1 0x20 +#define AB5500_ACC_DETECT2 0x21 +#define AB5500_ACC_DETECTCTRL 0x23 +#define AB5500_ACC_AVCTRL 0x24 +#define AB5500_ACC_DETECT3_DEG_LITCH_TIME 0x30 +#define AB5500_ACC_DETECT3_KEY_PRESS_TIME 0x31 +#define AB5500_ACC_DETECT3_LONG_KEY_TIME 0x32 +#define AB5500_ACC_DETECT3_TIME_READ_MS 0x33 +#define AB5500_ACC_DETECT3_TIME_READ_LS 0x34 +#define AB5500_ACC_DETECT3_CONTROL 0x35 +#define AB5500_ACC_DETECT3_LEVEL 0x36 +#define AB5500_ACC_DETECT3_TIMER_READ_CTL 0x37 + +/* + * Interrupt register offsets + * Bank : 0x0E + */ +#define AB5500_IT_SOURCE8 0x28 +#define AB5500_IT_SOURCE9 0x29 + +/* BatCtrl Current Source Constants */ +#define BAT_CTRL_7U_ENA (0x01 << 0) +#define BAT_CTRL_15U_ENA (0x01 << 1) +#define BAT_CTRL_30U_ENA (0x01 << 2) +#define BAT_CTRL_60U_ENA (0x01 << 3) +#define BAT_CTRL_120U_ENA (0x01 << 4) +#define BAT_CTRL_CMP_ENA 0x04 +#define FORCE_BAT_CTRL_CMP_HIGH 0x08 +#define BAT_CTRL_PULL_UP_ENA 0x10 + +/* Battery type */ +#define BATTERY_UNKNOWN 0 + +#ifdef CONFIG_AB5500_BM +void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA); +#else +static void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) +{ +} +#endif +#endif /* _AB5500_BM_H */ -- cgit v1.2.3 From a415794fefba2a86752202a8be02aa597ed8d804 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:49:55 +0530 Subject: power: ab5500-fg: fuel gauge driver for ab5500 This is a low level ab5500 fuel gauge driver. A power supply class of type fg is registered to display the battery parameters such as energy, charge, capacity, voltage. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ibe508dd84836a9a4873539ce194b50788ea25cba Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23151 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_fg.c | 1830 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1830 insertions(+) create mode 100644 drivers/power/ab5500_fg.c diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c new file mode 100644 index 00000000000..1c866e8fec5 --- /dev/null +++ b/drivers/power/ab5500_fg.c @@ -0,0 +1,1830 @@ +/* + * Copyright (C) ST-Ericsson AB 2011 + * + * Main and Back-up battery management driver. + * + * Note: Backup battery management is required in case of Li-Ion battery and not + * for capacitive battery. HREF boards have capacitive battery and hence backup + * battery management is not used and the supported code is available in this + * driver. + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson + * Karl Komierowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(ab5500_fg_list); + +/* U5500 Constants */ +#define FG_ON_MASK 0x04 +#define FG_ON 0x04 +#define FG_ACC_RESET_ON_READ_MASK 0x08 +#define FG_ACC_RESET_ON_READ 0x08 +#define EN_READOUT_MASK 0x01 +#define EN_READOUT 0x01 +#define RESET 0x00 +#define EOC_52_mA 0x04 +#define MILLI_TO_MICRO 1000 +#define FG_LSB_IN_MA 770 +#define QLSB_NANO_AMP_HOURS_X10 1129 +#define SEC_TO_SAMPLE(S) (S * 4) +#define NBR_AVG_SAMPLES 20 +#define LOW_BAT_CHECK_INTERVAL (2 * HZ) + +#define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */ + +#define interpolate(x, x1, y1, x2, y2) \ + ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1)))); + +#define to_ab5500_fg_device_info(x) container_of((x), \ + struct ab5500_fg, fg_psy); + +/** + * struct ab5500_fg_interrupts - ab5500 fg interupts + * @name: name of the interrupt + * @isr function pointer to the isr + */ +struct ab5500_fg_interrupts { + char *name; + irqreturn_t (*isr)(int irq, void *data); +}; + +enum ab5500_fg_discharge_state { + AB5500_FG_DISCHARGE_INIT, + AB5500_FG_DISCHARGE_INITMEASURING, + AB5500_FG_DISCHARGE_INIT_RECOVERY, + AB5500_FG_DISCHARGE_RECOVERY, + AB5500_FG_DISCHARGE_READOUT, + AB5500_FG_DISCHARGE_WAKEUP, +}; + +static char *discharge_state[] = { + "DISCHARGE_INIT", + "DISCHARGE_INITMEASURING", + "DISCHARGE_INIT_RECOVERY", + "DISCHARGE_RECOVERY", + "DISCHARGE_READOUT", + "DISCHARGE_WAKEUP", +}; + +enum ab5500_fg_charge_state { + AB5500_FG_CHARGE_INIT, + AB5500_FG_CHARGE_READOUT, +}; + +static char *charge_state[] = { + "CHARGE_INIT", + "CHARGE_READOUT", +}; + +enum ab5500_fg_calibration_state { + AB5500_FG_CALIB_INIT, + AB5500_FG_CALIB_WAIT, + AB5500_FG_CALIB_END, +}; + +struct ab5500_fg_avg_cap { + int avg; + int samples[NBR_AVG_SAMPLES]; + __kernel_time_t time_stamps[NBR_AVG_SAMPLES]; + int pos; + int nbr_samples; + int sum; +}; + +struct ab5500_fg_battery_capacity { + int max_mah_design; + int max_mah; + int mah; + int permille; + int level; + int prev_mah; + int prev_percent; + int prev_level; +}; + +struct ab5500_fg_flags { + bool fg_enabled; + bool conv_done; + bool charging; + bool fully_charged; + bool low_bat_delay; + bool low_bat; + bool bat_ovv; + bool batt_unknown; + bool calibrate; +}; + +/** + * struct ab5500_fg - ab5500 FG device information + * @dev: Pointer to the structure device + * @vbat: Battery voltage in mV + * @vbat_nom: Nominal battery voltage in mV + * @inst_curr: Instantenous battery current in mA + * @avg_curr: Average battery current in mA + * @fg_samples: Number of samples used in the FG accumulation + * @accu_charge: Accumulated charge from the last conversion + * @recovery_cnt: Counter for recovery mode + * @high_curr_cnt: Counter for high current mode + * @init_cnt: Counter for init mode + * @v_to_cap: capacity based on battery voltage + * @recovery_needed: Indicate if recovery is needed + * @high_curr_mode: Indicate if we're in high current mode + * @init_capacity: Indicate if initial capacity measuring should be done + * @calib_state State during offset calibration + * @discharge_state: Current discharge state + * @charge_state: Current charge state + * @flags: Structure for information about events triggered + * @bat_cap: Structure for battery capacity specific parameters + * @avg_cap: Average capacity filter + * @parent: Pointer to the struct ab5500 + * @gpadc: Pointer to the struct gpadc + * @gpadc_auto: Pointer tot he struct adc_auto_input + * @pdata: Pointer to the ab5500_fg platform data + * @bat: Pointer to the ab5500_bm platform data + * @fg_psy: Structure that holds the FG specific battery properties + * @fg_wq: Work queue for running the FG algorithm + * @fg_periodic_work: Work to run the FG algorithm periodically + * @fg_low_bat_work: Work to check low bat condition + * @fg_work: Work to run the FG algorithm instantly + * @fg_acc_cur_work: Work to read the FG accumulator + * @cc_lock: Mutex for locking the CC + * @node: struct of type list_head + */ +struct ab5500_fg { + struct device *dev; + int vbat; + int vbat_nom; + int inst_curr; + int avg_curr; + int fg_samples; + int accu_charge; + int recovery_cnt; + int high_curr_cnt; + int init_cnt; + int v_to_cap; + bool recovery_needed; + bool high_curr_mode; + bool init_capacity; + enum ab5500_fg_calibration_state calib_state; + enum ab5500_fg_discharge_state discharge_state; + enum ab5500_fg_charge_state charge_state; + struct ab5500_fg_flags flags; + struct ab5500_fg_battery_capacity bat_cap; + struct ab5500_fg_avg_cap avg_cap; + struct ab5500 *parent; + struct ab5500_gpadc *gpadc; + struct adc_auto_input *gpadc_auto; + struct abx500_fg_platform_data *pdata; + struct abx500_bm_data *bat; + struct power_supply fg_psy; + struct workqueue_struct *fg_wq; + struct delayed_work fg_periodic_work; + struct delayed_work fg_low_bat_work; + struct work_struct fg_work; + struct delayed_work fg_acc_cur_work; + struct mutex cc_lock; + struct list_head node; + struct timer_list avg_current_timer; +}; + +/* Main battery properties */ +static enum power_supply_property ab5500_fg_props[] = { + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, + POWER_SUPPLY_PROP_ENERGY_FULL, + POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CAPACITY_LEVEL, +}; + +struct ab5500_fg *ab5500_fg_get(void) +{ + struct ab5500_fg *di; + di = list_first_entry(&ab5500_fg_list, struct ab5500_fg, node); + + return di; +} + +/** + * ab5500_fg_is_low_curr() - Low or high current mode + * @di: pointer to the ab5500_fg structure + * @curr: the current to base or our decision on + * + * Low current mode if the current consumption is below a certain threshold + */ +static int ab5500_fg_is_low_curr(struct ab5500_fg *di, int curr) +{ + /* + * We want to know if we're in low current mode + */ + if (curr > -di->bat->fg_params->high_curr_threshold) + return true; + else + return false; +} + +/** + * ab5500_fg_add_cap_sample() - Add capacity to average filter + * @di: pointer to the ab5500_fg structure + * @sample: the capacity in mAh to add to the filter + * + * A capacity is added to the filter and a new mean capacity is calculated and + * returned + */ +static int ab5500_fg_add_cap_sample(struct ab5500_fg *di, int sample) +{ + struct timespec ts; + struct ab5500_fg_avg_cap *avg = &di->avg_cap; + + getnstimeofday(&ts); + + do { + avg->sum += sample - avg->samples[avg->pos]; + avg->samples[avg->pos] = sample; + avg->time_stamps[avg->pos] = ts.tv_sec; + avg->pos++; + + if (avg->pos == NBR_AVG_SAMPLES) + avg->pos = 0; + + if (avg->nbr_samples < NBR_AVG_SAMPLES) + avg->nbr_samples++; + + /* + * Check the time stamp for each sample. If too old, + * replace with latest sample + */ + } while (ts.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]); + + avg->avg = avg->sum / avg->nbr_samples; + + return avg->avg; +} + +/** + * ab5500_fg_fill_cap_sample() - Fill average filter + * @di: pointer to the ab5500_fg structure + * @sample: the capacity in mAh to fill the filter with + * + * The capacity filter is filled with a capacity in mAh + */ +static void ab5500_fg_fill_cap_sample(struct ab5500_fg *di, int sample) +{ + int i; + struct timespec ts; + struct ab5500_fg_avg_cap *avg = &di->avg_cap; + + getnstimeofday(&ts); + + for (i = 0; i < NBR_AVG_SAMPLES; i++) { + avg->samples[i] = sample; + avg->time_stamps[i] = ts.tv_sec; + } + + avg->pos = 0; + avg->nbr_samples = NBR_AVG_SAMPLES; + avg->sum = sample * NBR_AVG_SAMPLES; + avg->avg = sample; +} + +/** + * ab5500_fg_coulomb_counter() - enable coulomb counter + * @di: pointer to the ab5500_fg structure + * @enable: enable/disable + * + * Enable/Disable coulomb counter. + * On failure returns negative value. + */ +static int ab5500_fg_coulomb_counter(struct ab5500_fg *di, bool enable) +{ + int ret = 0; + mutex_lock(&di->cc_lock); + if (enable) { + /* Power-up the CC */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + (FG_ON | FG_ACC_RESET_ON_READ)); + if (ret) + goto cc_err; + + di->flags.fg_enabled = true; + } else { + /* Stop the CC */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + FG_ON_MASK, RESET); + if (ret) + goto cc_err; + + di->flags.fg_enabled = false; + + } + dev_dbg(di->dev, " CC enabled: %d Samples: %d\n", + enable, di->fg_samples); + + mutex_unlock(&di->cc_lock); + + return ret; +cc_err: + dev_err(di->dev, "%s Enabling coulomb counter failed\n", __func__); + mutex_unlock(&di->cc_lock); + return ret; +} + +/** + * ab5500_fg_inst_curr() - battery instantaneous current + * @di: pointer to the ab5500_fg structure + * + * Returns battery instantenous current(on success) else error code + */ +static int ab5500_fg_inst_curr(struct ab5500_fg *di) +{ + u8 low, high, value; + static int val; + int ret = 0; + bool fg_off = false; + + if (!di->flags.fg_enabled) { + fg_off = true; + /* Power-up the CC */ + ab5500_fg_coulomb_counter(di, true); + msleep(250); + } + + mutex_lock(&di->cc_lock); + /* + * Since there is no interrupt for this, just wait for 250ms + * 250ms is one sample conversion time with 32.768 Khz RTC clock + */ + msleep(250); + + /* Enable read request */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_B, + EN_READOUT_MASK, EN_READOUT); + if (ret) + goto inst_curr_err; + + /* Read CC Sample conversion value Low and high */ + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FGDIR_READ0, &low); + if (ret < 0) + goto inst_curr_err; + + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FGDIR_READ1, &high); + if (ret < 0) + goto inst_curr_err; + + /* + * negative value for Discharging + * convert 2's compliment into decimal + */ + if (high & 0x10) + val = (low | (high << 8) | 0xFFFFE000); + else + val = (low | (high << 8)); + + /* + * Convert to unit value in mA + * R(FGSENSE) = 20 mOhm + * Scaling of LSB: This corresponds fro R(FGSENSE) to a current of + * I = Q/t = 192.7 uC * 4 Hz = 0.77mA + */ + val = (val * 770) / 1000; + + mutex_unlock(&di->cc_lock); + + if (fg_off) { + dev_dbg(di->dev, "%s Disable FG\n", __func__); + /* Power-off the CC */ + ab5500_fg_coulomb_counter(di, false); + } + + return val; + +inst_curr_err: + dev_err(di->dev, "%s Get instanst current failed\n", __func__); + mutex_unlock(&di->cc_lock); + return ret; +} + +static void ab5500_fg_acc_cur_timer_expired(unsigned long data) +{ + struct ab5500_fg *di = (struct ab5500_fg *) data; + dev_dbg(di->dev, "Avg current timer expired\n"); + + /* Trigger execution of the algorithm instantly */ + queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); +} + +/** + * ab5500_fg_acc_cur_work() - average battery current + * @work: pointer to the work_struct structure + * + * Updated the average battery current obtained from the + * coulomb counter. + */ +static void ab5500_fg_acc_cur_work(struct work_struct *work) +{ + int val; + int ret; + u8 low, med, high, cnt_low, cnt_high; + + struct ab5500_fg *di = container_of(work, + struct ab5500_fg, fg_acc_cur_work.work); + + if (!di->flags.fg_enabled) { + /* Power-up the CC */ + ab5500_fg_coulomb_counter(di, true); + msleep(250); + } + mutex_lock(&di->cc_lock); + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_C, + EN_READOUT_MASK, EN_READOUT); + if (ret < 0) + goto exit; + /* If charging read charging registers for accumulated values */ + if (di->flags.charging) { + /* Read CC Sample conversion value Low and high */ + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_CH0, &low); + if (ret < 0) + goto exit; + + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_CH1, &med); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_CH2, &high); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_VAL_COUNT0, &cnt_low); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_VAL_COUNT1, &cnt_high); + if (ret < 0) + goto exit; + queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, + di->bat->interval_charging * HZ); + } else { /* discharging */ + /* Read CC Sample conversion value Low and high */ + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_DIS_CH0, &low); + if (ret < 0) + goto exit; + + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_DIS_CH1, &med); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_DIS_CH2, &high); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_VAL_COUNT0, &cnt_low); + if (ret < 0) + goto exit; + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, + AB5500_FG_VAL_COUNT1, &cnt_high); + if (ret < 0) + goto exit; + queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, + di->bat->interval_not_charging * HZ); + } + di->fg_samples = (cnt_low | (cnt_high << 8)); + val = (low | (med << 8) | (high << 16)); + + di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10)/10000; + di->avg_curr = (val * FG_LSB_IN_MA) / (di->fg_samples * 1000); + di->flags.conv_done = true; + + mutex_unlock(&di->cc_lock); + + queue_work(di->fg_wq, &di->fg_work); + + return; +exit: + dev_err(di->dev, + "Failed to read or write gas gauge registers\n"); + mutex_unlock(&di->cc_lock); + queue_work(di->fg_wq, &di->fg_work); +} + +/** + * ab5500_fg_bat_voltage() - get battery voltage + * @di: pointer to the ab5500_fg structure + * + * Returns battery voltage(on success) else error code + */ +static int ab5500_fg_bat_voltage(struct ab5500_fg *di) +{ + int vbat; + static int prev; + + vbat = ab5500_gpadc_convert(di->gpadc, MAIN_BAT_V); + if (vbat < 0) { + dev_err(di->dev, + "%s gpadc conversion failed, using previous value\n", + __func__); + return prev; + } + + prev = vbat; + return vbat; +} + +/** + * ab5500_fg_volt_to_capacity() - Voltage based capacity + * @di: pointer to the ab5500_fg structure + * @voltage: The voltage to convert to a capacity + * + * Returns battery capacity in per mille based on voltage + */ +static int ab5500_fg_volt_to_capacity(struct ab5500_fg *di, int voltage) +{ + int i, tbl_size; + struct abx500_v_to_cap *tbl; + int cap = 0; + + tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, + tbl_size = di->bat->bat_type[di->bat->batt_id].n_v_cap_tbl_elements; + + for (i = 0; i < tbl_size; ++i) { + if (di->vbat < tbl[i].voltage && di->vbat > tbl[i+1].voltage) + di->v_to_cap = tbl[i].capacity; + } + + for (i = 0; i < tbl_size; ++i) { + if (voltage > tbl[i].voltage) + break; + } + + if ((i > 0) && (i < tbl_size)) { + cap = interpolate(voltage, + tbl[i].voltage, + tbl[i].capacity * 10, + tbl[i-1].voltage, + tbl[i-1].capacity * 10); + } else if (i == 0) { + cap = 1000; + } else { + cap = 0; + } + + dev_dbg(di->dev, "%s Vbat: %d, Cap: %d per mille", + __func__, voltage, cap); + + return cap; +} + +/** + * ab5500_fg_uncomp_volt_to_capacity() - Uncompensated voltage based capacity + * @di: pointer to the ab5500_fg structure + * + * Returns battery capacity based on battery voltage that is not compensated + * for the voltage drop due to the load + */ +static int ab5500_fg_uncomp_volt_to_capacity(struct ab5500_fg *di) +{ + di->vbat = ab5500_fg_bat_voltage(di); + return ab5500_fg_volt_to_capacity(di, di->vbat); +} + +/** + * ab5500_fg_load_comp_volt_to_capacity() - Load compensated voltage based capacity + * @di: pointer to the ab5500_fg structure + * + * Returns battery capacity based on battery voltage that is load compensated + * for the voltage drop + */ +static int ab5500_fg_load_comp_volt_to_capacity(struct ab5500_fg *di) +{ + int vbat_comp; + + di->inst_curr = ab5500_fg_inst_curr(di); + di->vbat = ab5500_fg_bat_voltage(di); + + /* Use Ohms law to get the load compensated voltage */ + vbat_comp = di->vbat - (di->inst_curr * + di->bat->bat_type[di->bat->batt_id].battery_resistance) / 1000; + + dev_dbg(di->dev, "%s Measured Vbat: %dmV,Compensated Vbat %dmV, " + "R: %dmOhm, Current: %dmA\n", + __func__, + di->vbat, + vbat_comp, + di->bat->bat_type[di->bat->batt_id].battery_resistance, + di->inst_curr); + + return ab5500_fg_volt_to_capacity(di, vbat_comp); +} + +/** + * ab5500_fg_convert_mah_to_permille() - Capacity in mAh to permille + * @di: pointer to the ab5500_fg structure + * @cap_mah: capacity in mAh + * + * Converts capacity in mAh to capacity in permille + */ +static int ab5500_fg_convert_mah_to_permille(struct ab5500_fg *di, int cap_mah) +{ + return (cap_mah * 1000) / di->bat_cap.max_mah_design; +} + +/** + * ab5500_fg_convert_permille_to_mah() - Capacity in permille to mAh + * @di: pointer to the ab5500_fg structure + * @cap_pm: capacity in permille + * + * Converts capacity in permille to capacity in mAh + */ +static int ab5500_fg_convert_permille_to_mah(struct ab5500_fg *di, int cap_pm) +{ + return cap_pm * di->bat_cap.max_mah_design / 1000; +} + +/** + * ab5500_fg_convert_mah_to_uwh() - Capacity in mAh to uWh + * @di: pointer to the ab5500_fg structure + * @cap_mah: capacity in mAh + * + * Converts capacity in mAh to capacity in uWh + */ +static int ab5500_fg_convert_mah_to_uwh(struct ab5500_fg *di, int cap_mah) +{ + u64 div_res; + u32 div_rem; + + div_res = ((u64) cap_mah) * ((u64) di->vbat_nom); + div_rem = do_div(div_res, 1000); + + /* Make sure to round upwards if necessary */ + if (div_rem >= 1000 / 2) + div_res++; + + return (int) div_res; +} + +/** + * ab5500_fg_calc_cap_charging() - Calculate remaining capacity while charging + * @di: pointer to the ab5500_fg structure + * + * Return the capacity in mAh based on previous calculated capcity and the FG + * accumulator register value. The filter is filled with this capacity + */ +static int ab5500_fg_calc_cap_charging(struct ab5500_fg *di) +{ + dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n", + __func__, + di->bat_cap.mah, + di->accu_charge); + + /* Capacity should not be less than 0 */ + if (di->bat_cap.mah + di->accu_charge > 0) + di->bat_cap.mah += di->accu_charge; + else + di->bat_cap.mah = 0; + + /* + * We force capacity to 100% as long as the algorithm + * reports that it's full. + */ + if (di->bat_cap.mah >= di->bat_cap.max_mah_design || + di->flags.fully_charged) + di->bat_cap.mah = di->bat_cap.max_mah_design; + + ab5500_fg_fill_cap_sample(di, di->bat_cap.mah); + di->bat_cap.permille = + ab5500_fg_convert_mah_to_permille(di, di->bat_cap.mah); + + /* We need to update battery voltage and inst current when charging */ + di->vbat = ab5500_fg_bat_voltage(di); + di->inst_curr = ab5500_fg_inst_curr(di); + + return di->bat_cap.mah; +} + +/** + * ab5500_fg_calc_cap_discharge_voltage() - Capacity in discharge with voltage + * @di: pointer to the ab5500_fg structure + * @comp: if voltage should be load compensated before capacity calc + * + * Return the capacity in mAh based on the battery voltage. The voltage can + * either be load compensated or not. This value is added to the filter and a + * new mean value is calculated and returned. + */ +static int ab5500_fg_calc_cap_discharge_voltage(struct ab5500_fg *di, bool comp) +{ + int permille, mah; + + if (comp) + permille = ab5500_fg_load_comp_volt_to_capacity(di); + else + permille = ab5500_fg_uncomp_volt_to_capacity(di); + + mah = ab5500_fg_convert_permille_to_mah(di, permille); + + di->bat_cap.mah = ab5500_fg_add_cap_sample(di, mah); + di->bat_cap.permille = + ab5500_fg_convert_mah_to_permille(di, di->bat_cap.mah); + + return di->bat_cap.mah; +} + +/** + * ab5500_fg_calc_cap_discharge_fg() - Capacity in discharge with FG + * @di: pointer to the ab5500_fg structure + * + * Return the capacity in mAh based on previous calculated capcity and the FG + * accumulator register value. This value is added to the filter and a + * new mean value is calculated and returned. + */ +static int ab5500_fg_calc_cap_discharge_fg(struct ab5500_fg *di) +{ + int permille_volt, permille; + + dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n", + __func__, + di->bat_cap.mah, + di->accu_charge); + + /* Capacity should not be less than 0 */ + if (di->bat_cap.mah + di->accu_charge > 0) + di->bat_cap.mah += di->accu_charge; + else + di->bat_cap.mah = 0; + + if (di->bat_cap.mah >= di->bat_cap.max_mah_design) + di->bat_cap.mah = di->bat_cap.max_mah_design; + + /* + * Check against voltage based capacity. It can not be lower + * than what the uncompensated voltage says + */ + permille = ab5500_fg_convert_mah_to_permille(di, di->bat_cap.mah); + permille_volt = ab5500_fg_uncomp_volt_to_capacity(di); + + if (permille < permille_volt) { + di->bat_cap.permille = permille_volt; + di->bat_cap.mah = ab5500_fg_convert_permille_to_mah(di, + di->bat_cap.permille); + + dev_dbg(di->dev, "%s voltage based: perm %d perm_volt %d\n", + __func__, + permille, + permille_volt); + + ab5500_fg_fill_cap_sample(di, di->bat_cap.mah); + } else { + ab5500_fg_fill_cap_sample(di, di->bat_cap.mah); + di->bat_cap.permille = + ab5500_fg_convert_mah_to_permille(di, di->bat_cap.mah); + } + + return di->bat_cap.mah; +} + +/** + * ab5500_fg_capacity_level() - Get the battery capacity level + * @di: pointer to the ab5500_fg structure + * + * Get the battery capacity level based on the capacity in percent + */ +static int ab5500_fg_capacity_level(struct ab5500_fg *di) +{ + int ret, percent; + + percent = di->bat_cap.permille / 10; + + if (percent <= di->bat->cap_levels->critical || + di->flags.low_bat) + ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; + else if (percent <= di->bat->cap_levels->low) + ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW; + else if (percent <= di->bat->cap_levels->normal) + ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; + else if (percent <= di->bat->cap_levels->high) + ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; + else + ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL; + + return ret; +} + +/** + * ab5500_fg_check_capacity_limits() - Check if capacity has changed + * @di: pointer to the ab5500_fg structure + * @init: capacity is allowed to go up in init mode + * + * Check if capacity or capacity limit has changed and notify the system + * about it using the power_supply framework + */ +static void ab5500_fg_check_capacity_limits(struct ab5500_fg *di, bool init) +{ + bool changed = false; + + di->bat_cap.level = ab5500_fg_capacity_level(di); + + if (di->bat_cap.level != di->bat_cap.prev_level) { + /* + * We do not allow reported capacity level to go up + * unless we're charging or if we're in init + */ + if (!(!di->flags.charging && di->bat_cap.level > + di->bat_cap.prev_level) || init) { + dev_dbg(di->dev, "level changed from %d to %d\n", + di->bat_cap.prev_level, + di->bat_cap.level); + di->bat_cap.prev_level = di->bat_cap.level; + changed = true; + } else { + dev_dbg(di->dev, "level not allowed to go up " + "since no charger is connected: %d to %d\n", + di->bat_cap.prev_level, + di->bat_cap.level); + } + } + + /* + * If we have received the LOW_BAT IRQ, set capacity to 0 to initiate + * shutdown + */ + if (di->flags.low_bat) { + dev_dbg(di->dev, "Battery low, set capacity to 0\n"); + di->bat_cap.prev_percent = 0; + di->bat_cap.permille = 0; + di->bat_cap.prev_mah = 0; + di->bat_cap.mah = 0; + changed = true; + } else if (di->bat_cap.prev_percent != di->bat_cap.permille / 10) { + if (di->bat_cap.permille / 10 == 0) { + /* + * We will not report 0% unless we've got + * the LOW_BAT IRQ, no matter what the FG + * algorithm says. + */ + di->bat_cap.prev_percent = 1; + di->bat_cap.permille = 1; + di->bat_cap.prev_mah = 1; + di->bat_cap.mah = 1; + + changed = true; + } else if (!(!di->flags.charging && + (di->bat_cap.permille / 10) > + di->bat_cap.prev_percent) || init) { + /* + * We do not allow reported capacity to go up + * unless we're charging or if we're in init + */ + dev_dbg(di->dev, + "capacity changed from %d to %d (%d)\n", + di->bat_cap.prev_percent, + di->bat_cap.permille / 10, + di->bat_cap.permille); + di->bat_cap.prev_percent = di->bat_cap.permille / 10; + di->bat_cap.prev_mah = di->bat_cap.mah; + + changed = true; + } else { + dev_dbg(di->dev, "capacity not allowed to go up since " + "no charger is connected: %d to %d (%d)\n", + di->bat_cap.prev_percent, + di->bat_cap.permille / 10, + di->bat_cap.permille); + } + } + + if (changed) + power_supply_changed(&di->fg_psy); + +} + +static void ab5500_fg_charge_state_to(struct ab5500_fg *di, + enum ab5500_fg_charge_state new_state) +{ + dev_dbg(di->dev, "Charge state from %d [%s] to %d [%s]\n", + di->charge_state, + charge_state[di->charge_state], + new_state, + charge_state[new_state]); + + di->charge_state = new_state; +} + +static void ab5500_fg_discharge_state_to(struct ab5500_fg *di, + enum ab5500_fg_charge_state new_state) +{ + dev_dbg(di->dev, "Disharge state from %d [%s] to %d [%s]\n", + di->discharge_state, + discharge_state[di->discharge_state], + new_state, + discharge_state[new_state]); + + di->discharge_state = new_state; +} + +/** + * ab5500_fg_algorithm_charging() - FG algorithm for when charging + * @di: pointer to the ab5500_fg structure + * + * Battery capacity calculation state machine for when we're charging + */ +static void ab5500_fg_algorithm_charging(struct ab5500_fg *di) +{ + /* + * If we change to discharge mode + * we should start with recovery + */ + if (di->discharge_state != AB5500_FG_DISCHARGE_INIT_RECOVERY) + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_INIT_RECOVERY); + + switch (di->charge_state) { + case AB5500_FG_CHARGE_INIT: + di->fg_samples = SEC_TO_SAMPLE( + di->bat->fg_params->accu_charging); + + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_charge_state_to(di, AB5500_FG_CHARGE_READOUT); + + break; + + case AB5500_FG_CHARGE_READOUT: + /* + * Read the FG and calculate the new capacity + */ + mutex_lock(&di->cc_lock); + if (!di->flags.conv_done) { + /* Wasn't the CC IRQ that got us here */ + mutex_unlock(&di->cc_lock); + dev_dbg(di->dev, "%s CC conv not done\n", + __func__); + + break; + } + di->flags.conv_done = false; + mutex_unlock(&di->cc_lock); + + ab5500_fg_calc_cap_charging(di); + + break; + + default: + break; + } + + /* Check capacity limits */ + ab5500_fg_check_capacity_limits(di, false); +} + +/** + * ab5500_fg_algorithm_discharging() - FG algorithm for when discharging + * @di: pointer to the ab5500_fg structure + * + * Battery capacity calculation state machine for when we're discharging + */ +static void ab5500_fg_algorithm_discharging(struct ab5500_fg *di) +{ + int sleep_time; + + /* If we change to charge mode we should start with init */ + if (di->charge_state != AB5500_FG_CHARGE_INIT) + ab5500_fg_charge_state_to(di, AB5500_FG_CHARGE_INIT); + + switch (di->discharge_state) { + case AB5500_FG_DISCHARGE_INIT: + /* We use the FG IRQ to work on */ + di->init_cnt = 0; + di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_INITMEASURING); + + /* Intentional fallthrough */ + case AB5500_FG_DISCHARGE_INITMEASURING: + /* + * Discard a number of samples during startup. + * After that, use compensated voltage for a few + * samples to get an initial capacity. + * Then go to READOUT + */ + sleep_time = di->bat->fg_params->init_timer; + + /* Discard the first [x] seconds */ + if (di->init_cnt > + di->bat->fg_params->init_discard_time) { + + ab5500_fg_calc_cap_discharge_voltage(di, true); + + ab5500_fg_check_capacity_limits(di, true); + } + + di->init_cnt += sleep_time; + if (di->init_cnt > + di->bat->fg_params->init_total_time) { + di->fg_samples = SEC_TO_SAMPLE( + di->bat->fg_params->accu_high_curr); + + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_READOUT); + } + + break; + + case AB5500_FG_DISCHARGE_INIT_RECOVERY: + di->recovery_cnt = 0; + di->recovery_needed = true; + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_RECOVERY); + + /* Intentional fallthrough */ + + case AB5500_FG_DISCHARGE_RECOVERY: + sleep_time = di->bat->fg_params->recovery_sleep_timer; + + /* + * We should check the power consumption + * If low, go to READOUT (after x min) or + * RECOVERY_SLEEP if time left. + * If high, go to READOUT + */ + di->inst_curr = ab5500_fg_inst_curr(di); + + if (ab5500_fg_is_low_curr(di, di->inst_curr)) { + if (di->recovery_cnt > + di->bat->fg_params->recovery_total_time) { + di->fg_samples = SEC_TO_SAMPLE( + di->bat->fg_params->accu_high_curr); + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_READOUT); + di->recovery_needed = false; + } else { + queue_delayed_work(di->fg_wq, + &di->fg_periodic_work, + sleep_time * HZ); + } + di->recovery_cnt += sleep_time; + } else { + di->fg_samples = SEC_TO_SAMPLE( + di->bat->fg_params->accu_high_curr); + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_READOUT); + } + + break; + + case AB5500_FG_DISCHARGE_READOUT: + di->inst_curr = ab5500_fg_inst_curr(di); + + if (ab5500_fg_is_low_curr(di, di->inst_curr)) { + /* Detect mode change */ + if (di->high_curr_mode) { + di->high_curr_mode = false; + di->high_curr_cnt = 0; + } + + if (di->recovery_needed) { + ab5500_fg_discharge_state_to(di, + AB5500_FG_DISCHARGE_RECOVERY); + + queue_delayed_work(di->fg_wq, + &di->fg_periodic_work, + 0); + + break; + } + + ab5500_fg_calc_cap_discharge_voltage(di, true); + } else { + mutex_lock(&di->cc_lock); + if (!di->flags.conv_done) { + /* Wasn't the CC IRQ that got us here */ + mutex_unlock(&di->cc_lock); + dev_dbg(di->dev, "%s CC conv not done\n", + __func__); + + break; + } + di->flags.conv_done = false; + mutex_unlock(&di->cc_lock); + + /* Detect mode change */ + if (!di->high_curr_mode) { + di->high_curr_mode = true; + di->high_curr_cnt = 0; + } + + di->high_curr_cnt += + di->bat->fg_params->accu_high_curr; + if (di->high_curr_cnt > + di->bat->fg_params->high_curr_time) + di->recovery_needed = true; + + ab5500_fg_calc_cap_discharge_fg(di); + } + + ab5500_fg_check_capacity_limits(di, false); + + break; + + case AB5500_FG_DISCHARGE_WAKEUP: + ab5500_fg_coulomb_counter(di, true); + di->inst_curr = ab5500_fg_inst_curr(di); + + ab5500_fg_calc_cap_discharge_voltage(di, true); + + di->fg_samples = SEC_TO_SAMPLE( + di->bat->fg_params->accu_high_curr); + /* Re-program number of samples set above */ + ab5500_fg_coulomb_counter(di, true); + ab5500_fg_discharge_state_to(di, AB5500_FG_DISCHARGE_READOUT); + + ab5500_fg_check_capacity_limits(di, false); + + break; + + default: + break; + } +} + +/** + * ab5500_fg_algorithm_calibrate() - Internal columb counter offset calibration + * @di: pointer to the ab5500_fg structure + * + */ +static void ab5500_fg_algorithm_calibrate(struct ab5500_fg *di) +{ + int ret; + + switch (di->calib_state) { + case AB5500_FG_CALIB_INIT: + dev_dbg(di->dev, "Calibration ongoing...\n"); + /* TODO: For Cut 1.1 no calibration */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + FG_ACC_RESET_ON_READ_MASK, FG_ACC_RESET_ON_READ); + if (ret) + goto err; + di->calib_state = AB5500_FG_CALIB_WAIT; + break; + case AB5500_FG_CALIB_END: + di->flags.calibrate = false; + dev_dbg(di->dev, "Calibration done...\n"); + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + break; + case AB5500_FG_CALIB_WAIT: + dev_dbg(di->dev, "Calibration WFI\n"); + default: + break; + } + return; +err: + /* Something went wrong, don't calibrate then */ + dev_err(di->dev, "failed to calibrate the CC\n"); + di->flags.calibrate = false; + di->calib_state = AB5500_FG_CALIB_INIT; + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); +} + +/** + * ab5500_fg_algorithm() - Entry point for the FG algorithm + * @di: pointer to the ab5500_fg structure + * + * Entry point for the battery capacity calculation state machine + */ +static void ab5500_fg_algorithm(struct ab5500_fg *di) +{ + if (di->flags.calibrate) + ab5500_fg_algorithm_calibrate(di); + else { + if (di->flags.charging) + ab5500_fg_algorithm_charging(di); + else + ab5500_fg_algorithm_discharging(di); + } + + dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d\n", + di->bat_cap.max_mah_design, + di->bat_cap.mah, + di->bat_cap.permille, + di->bat_cap.level, + di->bat_cap.prev_mah, + di->bat_cap.prev_percent, + di->bat_cap.prev_level, + di->vbat, + di->inst_curr, + di->avg_curr, + di->accu_charge, + di->flags.charging, + di->charge_state, + di->discharge_state, + di->high_curr_mode, + di->recovery_needed); +} + +/** + * ab5500_fg_periodic_work() - Run the FG state machine periodically + * @work: pointer to the work_struct structure + * + * Work queue function for periodic work + */ +static void ab5500_fg_periodic_work(struct work_struct *work) +{ + struct ab5500_fg *di = container_of(work, struct ab5500_fg, + fg_periodic_work.work); + + if (di->init_capacity) { + /* A dummy read that will return 0 */ + di->inst_curr = ab5500_fg_inst_curr(di); + /* Get an initial capacity calculation */ + ab5500_fg_calc_cap_discharge_voltage(di, true); + ab5500_fg_check_capacity_limits(di, true); + di->init_capacity = false; + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + } else + ab5500_fg_algorithm(di); +} + +/** + * ab5500_fg_low_bat_work() - Check LOW_BAT condition + * @work: pointer to the work_struct structure + * + * Work queue function for checking the LOW_BAT condition + */ +static void ab5500_fg_low_bat_work(struct work_struct *work) +{ + int vbat; + + struct ab5500_fg *di = container_of(work, struct ab5500_fg, + fg_low_bat_work.work); + + vbat = ab5500_fg_bat_voltage(di); + + /* Check if LOW_BAT still fulfilled */ + if (vbat < di->bat->fg_params->lowbat_threshold) { + di->flags.low_bat = true; + dev_warn(di->dev, "Battery voltage still LOW\n"); + + /* + * We need to re-schedule this check to be able to detect + * if the voltage increases again during charging + */ + queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, + round_jiffies(LOW_BAT_CHECK_INTERVAL)); + } else { + di->flags.low_bat = false; + dev_warn(di->dev, "Battery voltage OK again\n"); + } + + /* This is needed to dispatch LOW_BAT */ + ab5500_fg_check_capacity_limits(di, false); + + /* Set this flag to check if LOW_BAT IRQ still occurs */ + di->flags.low_bat_delay = false; +} + +/** + * ab5500_fg_instant_work() - Run the FG state machine instantly + * @work: pointer to the work_struct structure + * + * Work queue function for instant work + */ +static void ab5500_fg_instant_work(struct work_struct *work) +{ + struct ab5500_fg *di = container_of(work, struct ab5500_fg, fg_work); + + ab5500_fg_algorithm(di); +} + +/** + * ab5500_fg_get_property() - get the fg properties + * @psy: pointer to the power_supply structure + * @psp: pointer to the power_supply_property structure + * @val: pointer to the power_supply_propval union + * + * This function gets called when an application tries to get the + * fg properties by reading the sysfs files. + * voltage_now: battery voltage + * current_now: battery instant current + * current_avg: battery average current + * charge_full_design: capacity where battery is considered full + * charge_now: battery capacity in nAh + * capacity: capacity in percent + * capacity_level: capacity level + * + * Returns error code in case of failure else 0 on success + */ +static int ab5500_fg_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ab5500_fg *di; + int i, tbl_size; + struct abx500_v_to_cap *tbl; + + di = to_ab5500_fg_device_info(psy); + + /* + * If battery is identified as unknown and charging of unknown + * batteries is disabled, we always report 100% capacity and + * capacity level UNKNOWN, since we can't calculate + * remaining capacity + */ + + switch (psp) { + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + if (di->flags.bat_ovv) + val->intval = 47500000; + else + val->intval = ab5500_gpadc_convert + (di->gpadc, MAIN_BAT_V) * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + di->inst_curr = ab5500_fg_inst_curr(di); + val->intval = di->inst_curr * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = di->avg_curr * 1000; + break; + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + val->intval = ab5500_fg_convert_mah_to_uwh(di, + di->bat_cap.max_mah_design); + break; + case POWER_SUPPLY_PROP_ENERGY_FULL: + val->intval = ab5500_fg_convert_mah_to_uwh(di, + di->bat_cap.max_mah); + break; + case POWER_SUPPLY_PROP_ENERGY_NOW: + if (di->flags.batt_unknown && !di->bat->chg_unknown_bat) + val->intval = ab5500_fg_convert_mah_to_uwh(di, + di->bat_cap.max_mah); + else + val->intval = ab5500_fg_convert_mah_to_uwh(di, + di->bat_cap.prev_mah); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + val->intval = di->bat_cap.max_mah_design; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = di->bat_cap.max_mah; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + if (di->flags.batt_unknown && !di->bat->chg_unknown_bat) + val->intval = di->bat_cap.max_mah; + else + val->intval = di->bat_cap.prev_mah; + break; + case POWER_SUPPLY_PROP_CAPACITY: + if (di->flags.batt_unknown && !di->bat->chg_unknown_bat) + val->intval = 100; + else if (di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl) { + tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, + tbl_size = di->bat->bat_type[ + di->bat->batt_id].n_v_cap_tbl_elements; + + for (i = 0; i < tbl_size; ++i) { + if (di->vbat < tbl[i].voltage && + di->vbat > tbl[i+1].voltage) { + di->v_to_cap = tbl[i].capacity; + break; + } + } + val->intval = di->v_to_cap; + } else + val->intval = di->bat_cap.prev_percent; + break; + case POWER_SUPPLY_PROP_CAPACITY_LEVEL: + if (di->flags.batt_unknown && !di->bat->chg_unknown_bat) + val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; + else + val->intval = di->bat_cap.prev_level; + break; + default: + return -EINVAL; + } + return 0; +} + +static int ab5500_fg_get_ext_psy_data(struct device *dev, void *data) +{ + struct power_supply *psy; + struct power_supply *ext; + struct ab5500_fg *di; + union power_supply_propval ret; + int i, j; + bool psy_found = false; + + psy = (struct power_supply *)data; + ext = dev_get_drvdata(dev); + di = to_ab5500_fg_device_info(psy); + + /* + * For all psy where the name of your driver + * appears in any supplied_to + */ + for (i = 0; i < ext->num_supplicants; i++) { + if (!strcmp(ext->supplied_to[i], psy->name)) + psy_found = true; + } + + if (!psy_found) + return 0; + + /* Go through all properties for the psy */ + for (j = 0; j < ext->num_properties; j++) { + enum power_supply_property prop; + prop = ext->properties[j]; + + if (ext->get_property(ext, prop, &ret)) + continue; + + switch (prop) { + case POWER_SUPPLY_PROP_STATUS: + switch (ext->type) { + case POWER_SUPPLY_TYPE_BATTERY: + switch (ret.intval) { + case POWER_SUPPLY_STATUS_UNKNOWN: + case POWER_SUPPLY_STATUS_DISCHARGING: + case POWER_SUPPLY_STATUS_NOT_CHARGING: + if (!di->flags.charging) + break; + di->flags.charging = false; + di->flags.fully_charged = false; + queue_work(di->fg_wq, &di->fg_work); + break; + case POWER_SUPPLY_STATUS_FULL: + if (di->flags.fully_charged) + break; + di->flags.fully_charged = true; + /* Save current capacity as maximum */ + di->bat_cap.max_mah = di->bat_cap.mah; + queue_work(di->fg_wq, &di->fg_work); + break; + case POWER_SUPPLY_STATUS_CHARGING: + if (di->flags.charging) + break; + di->flags.charging = true; + di->flags.fully_charged = false; + queue_work(di->fg_wq, &di->fg_work); + break; + }; + default: + break; + }; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + switch (ext->type) { + case POWER_SUPPLY_TYPE_BATTERY: + if (ret.intval) + di->flags.batt_unknown = false; + else + di->flags.batt_unknown = true; + break; + default: + break; + } + break; + default: + break; + } + } + return 0; +} + +static int ab5500_fg_bat_v_trig(int mux) +{ + struct ab5500_fg *di = ab5500_fg_get(); + + /* check if the battery voltage is below low threshold */ + if (di->vbat < 2700) { + dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); + di->flags.low_bat_delay = true; + /* + * Start a timer to check LOW_BAT again after some time + * This is done to avoid shutdown on single voltage dips + */ + queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, + round_jiffies(LOW_BAT_CHECK_INTERVAL)); + } + /* check if battery votlage is above OVV */ + else if (di->vbat > 4200) { + dev_dbg(di->dev, "Battery OVV\n"); + di->flags.bat_ovv = true; + + power_supply_changed(&di->fg_psy); + } else + return -EINVAL; + + return 0; +} + +/** + * ab5500_fg_init_hw_registers() - Set up FG related registers + * @di: pointer to the ab5500_fg structure + * + * Set up battery OVV, low battery voltage registers + */ +static int ab5500_fg_init_hw_registers(struct ab5500_fg *di) +{ + int ret; + struct adc_auto_input *auto_ip; + + auto_ip = kzalloc(sizeof(struct adc_auto_input), GFP_KERNEL); + if (!auto_ip) { + dev_err(di->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + auto_ip->mux = MAIN_BAT_V; + auto_ip->freq = MS500; + auto_ip->min = 2700; + auto_ip->max = 4200; + auto_ip->auto_adc_callback = ab5500_fg_bat_v_trig; + di->gpadc_auto = auto_ip; + ret = ab5500_gpadc_convert_auto(di->gpadc, di->gpadc_auto); + if (ret) + dev_err(di->dev, + "failed to set auto trigger for battery votlage\n"); + /* set End Of Charge current to 247mA */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_EOC, EOC_52_mA); + return ret; +} + +/** + * ab5500_fg_external_power_changed() - callback for power supply changes + * @psy: pointer to the structure power_supply + * + * This function is the entry point of the pointer external_power_changed + * of the structure power_supply. + * This function gets executed when there is a change in any external power + * supply that this driver needs to be notified of. + */ +static void ab5500_fg_external_power_changed(struct power_supply *psy) +{ + struct ab5500_fg *di = to_ab5500_fg_device_info(psy); + + class_for_each_device(power_supply_class, NULL, + &di->fg_psy, ab5500_fg_get_ext_psy_data); +} + +#if defined(CONFIG_PM) +static int ab5500_fg_resume(struct platform_device *pdev) +{ + struct ab5500_fg *di = platform_get_drvdata(pdev); + + /* + * Change state if we're not charging. If we're charging we will wake + * up on the FG IRQ + */ + if (!di->flags.charging) { + ab5500_fg_discharge_state_to(di, AB5500_FG_DISCHARGE_WAKEUP); + queue_work(di->fg_wq, &di->fg_work); + } + + return 0; +} + +static int ab5500_fg_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct ab5500_fg *di = platform_get_drvdata(pdev); + + flush_delayed_work(&di->fg_periodic_work); + + /* + * If the FG is enabled we will disable it before going to suspend + * only if we're not charging + */ + if (di->flags.fg_enabled && !di->flags.charging) + ab5500_fg_coulomb_counter(di, false); + + return 0; +} +#else +#define ab5500_fg_suspend NULL +#define ab5500_fg_resume NULL +#endif + +static int __devexit ab5500_fg_remove(struct platform_device *pdev) +{ + int ret = 0; + struct ab5500_fg *di = platform_get_drvdata(pdev); + + /* Disable coulomb counter */ + ret = ab5500_fg_coulomb_counter(di, false); + if (ret) + dev_err(di->dev, "failed to disable coulomb counter\n"); + + destroy_workqueue(di->fg_wq); + + flush_scheduled_work(); + power_supply_unregister(&di->fg_psy); + platform_set_drvdata(pdev, NULL); + kfree(di->gpadc_auto); + kfree(di); + return ret; +} + +static int __devinit ab5500_fg_probe(struct platform_device *pdev) +{ + struct abx500_bm_plat_data *plat_data; + int ret = 0; + + struct ab5500_fg *di = + kzalloc(sizeof(struct ab5500_fg), GFP_KERNEL); + if (!di) + return -ENOMEM; + + mutex_init(&di->cc_lock); + + /* get parent data */ + di->dev = &pdev->dev; + di->parent = dev_get_drvdata(pdev->dev.parent); + di->gpadc = ab5500_gpadc_get("ab5500-adc.0"); + + plat_data = pdev->dev.platform_data; + di->pdata = plat_data->fg; + di->bat = plat_data->battery; + + /* get fg specific platform data */ + if (!di->pdata) { + dev_err(di->dev, "no fg platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + + /* get battery specific platform data */ + if (!di->bat) { + dev_err(di->dev, "no battery platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + + di->fg_psy.name = "ab5500_fg"; + di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; + di->fg_psy.properties = ab5500_fg_props; + di->fg_psy.num_properties = ARRAY_SIZE(ab5500_fg_props); + di->fg_psy.get_property = ab5500_fg_get_property; + di->fg_psy.supplied_to = di->pdata->supplied_to; + di->fg_psy.num_supplicants = di->pdata->num_supplicants; + di->fg_psy.external_power_changed = ab5500_fg_external_power_changed; + + di->bat_cap.max_mah_design = MILLI_TO_MICRO * + di->bat->bat_type[di->bat->batt_id].charge_full_design; + + di->bat_cap.max_mah = di->bat_cap.max_mah_design; + + di->vbat_nom = di->bat->bat_type[di->bat->batt_id].nominal_voltage; + + di->init_capacity = true; + + ab5500_fg_charge_state_to(di, AB5500_FG_CHARGE_INIT); + ab5500_fg_discharge_state_to(di, AB5500_FG_DISCHARGE_INIT); + + /* Create a work queue for running the FG algorithm */ + di->fg_wq = create_singlethread_workqueue("ab5500_fg_wq"); + if (di->fg_wq == NULL) { + dev_err(di->dev, "failed to create work queue\n"); + goto free_device_info; + } + + /* Init work for running the fg algorithm instantly */ + INIT_WORK(&di->fg_work, ab5500_fg_instant_work); + + /* Init work for getting the battery accumulated current */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_acc_cur_work, + ab5500_fg_acc_cur_work); + + /* Work delayed Queue to run the state machine */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_periodic_work, + ab5500_fg_periodic_work); + + /* Work to check low battery condition */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_low_bat_work, + ab5500_fg_low_bat_work); + + list_add_tail(&di->node, &ab5500_fg_list); + + /* Initialize OVV, and other registers */ + ret = ab5500_fg_init_hw_registers(di); + if (ret) { + dev_err(di->dev, "failed to initialize registers\n"); + goto free_fg_wq; + } + + /* Consider battery unknown until we're informed otherwise */ + di->flags.batt_unknown = true; + + /* Register FG power supply class */ + ret = power_supply_register(di->dev, &di->fg_psy); + if (ret) { + dev_err(di->dev, "failed to register FG psy\n"); + goto free_fg_wq; + } + + di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); + ab5500_fg_coulomb_counter(di, true); + + /* Initilialize avg current timer */ + init_timer(&di->avg_current_timer); + di->avg_current_timer.function = ab5500_fg_acc_cur_timer_expired; + di->avg_current_timer.data = (unsigned long) di; + di->avg_current_timer.expires = 60 * HZ;; + if (!timer_pending(&di->avg_current_timer)) + add_timer(&di->avg_current_timer); + else + mod_timer(&di->avg_current_timer, 60 * HZ); + + platform_set_drvdata(pdev, di); + + /* Calibrate the fg first time */ + di->flags.calibrate = true; + di->calib_state = AB5500_FG_CALIB_INIT; + /* Run the FG algorithm */ + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); + + dev_info(di->dev, "probe success\n"); + return ret; + +free_fg_wq: + destroy_workqueue(di->fg_wq); +free_device_info: + kfree(di); + + return ret; +} + +static struct platform_driver ab5500_fg_driver = { + .probe = ab5500_fg_probe, + .remove = __devexit_p(ab5500_fg_remove), + .suspend = ab5500_fg_suspend, + .resume = ab5500_fg_resume, + .driver = { + .name = "ab5500-fg", + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_fg_init(void) +{ + return platform_driver_register(&ab5500_fg_driver); +} + +static void __exit ab5500_fg_exit(void) +{ + platform_driver_unregister(&ab5500_fg_driver); +} + +subsys_initcall_sync(ab5500_fg_init); +module_exit(ab5500_fg_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); +MODULE_ALIAS("platform:ab5500-fg"); +MODULE_DESCRIPTION("AB5500 Fuel Gauge driver"); -- cgit v1.2.3 From 36f1f791ccc9284e4ab8290ef89c0ca49d1e7497 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:50:32 +0530 Subject: power: ab5500-btemp: temperature monitoring driver Temperature monitoring driver for ab5500. Since temperature is the most important aspect of a battery, this driver monitors the battery temperature and takes precautionary measurements even in case of hardware failure. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Idd0a4a7f220ffa9693516757aba395ab7f75cfc2 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23152 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_btemp.c | 870 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 870 insertions(+) create mode 100644 drivers/power/ab5500_btemp.c diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c new file mode 100644 index 00000000000..57241c96f60 --- /dev/null +++ b/drivers/power/ab5500_btemp.c @@ -0,0 +1,870 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Battery temperature driver for ab5500 + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson + * Karl Komierowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BTEMP_THERMAL_LOW_LIMIT -10 +#define BTEMP_THERMAL_MED_LIMIT 0 +#define BTEMP_THERMAL_HIGH_LIMIT_62 62 + +#define BTEMP_BATCTRL_CURR_SRC_7UA 7 +#define BTEMP_BATCTRL_CURR_SRC_15UA 15 +#define BTEMP_BATCTRL_CURR_SRC_20UA 20 + +#define UART_MODE 0x0F +#define BAT_CUR_SRC 0x1F +#define RESIS_ID_MODE 0x03 +#define RESET 0x00 +#define ADOUT_10K_PULL_UP 0x07 + +#define to_ab5500_btemp_device_info(x) container_of((x), \ + struct ab5500_btemp, btemp_psy); + +/** + * struct ab5500_btemp_interrupts - ab5500 interrupts + * @name: name of the interrupt + * @isr function pointer to the isr + */ +struct ab5500_btemp_interrupts { + char *name; + irqreturn_t (*isr)(int irq, void *data); +}; + +struct ab5500_btemp_events { + bool batt_rem; + bool usb_conn; +}; + +/** + * struct ab5500_btemp - ab5500 BTEMP device information + * @dev: Pointer to the structure device + * @chip_id: Chip-Id of the AB5500 + * @curr_source: What current source we use, in uA + * @bat_temp: Battery temperature in degree Celcius + * @prev_bat_temp Last dispatched battery temperature + * @node: struct of type list_head + * @parent: Pointer to the struct ab5500 + * @gpadc: Pointer to the struct gpadc + * @gpadc-auto: Pointer to the struct adc_auto_input + * @pdata: Pointer to the ab5500_btemp platform data + * @bat: Pointer to the ab5500_bm platform data + * @btemp_psy: Structure for BTEMP specific battery properties + * @events: Structure for information about events triggered + * @btemp_wq: Work queue for measuring the temperature periodically + * @btemp_periodic_work: Work for measuring the temperature periodically + */ +struct ab5500_btemp { + struct device *dev; + u8 chip_id; + int curr_source; + int bat_temp; + int prev_bat_temp; + struct list_head node; + struct ab5500 *parent; + struct ab5500_gpadc *gpadc; + struct adc_auto_input *gpadc_auto; + struct abx500_btemp_platform_data *pdata; + struct abx500_bm_data *bat; + struct power_supply btemp_psy; + struct ab5500_btemp_events events; + struct workqueue_struct *btemp_wq; + struct delayed_work btemp_periodic_work; +}; + +/* BTEMP power supply properties */ +static enum power_supply_property ab5500_btemp_props[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_TEMP, +}; + +static LIST_HEAD(ab5500_btemp_list); + +struct ab5500_btemp *ab5500_btemp_get(void) +{ + struct ab5500_btemp *di; + di = list_first_entry(&ab5500_btemp_list, struct ab5500_btemp, node); + + return di; +} + +/** + * ab5500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance + * @di: pointer to the ab5500_btemp structure + * @v_batctrl: measured batctrl voltage + * + * This function returns the battery resistance that is + * derived from the BATCTRL voltage. + * Returns value in Ohms. + */ +static int ab5500_btemp_batctrl_volt_to_res(struct ab5500_btemp *di, + int v_batctrl) +{ + int rbs; + + if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { + /* + * If the battery has internal NTC, we use the current + * source to calculate the resistance, 7uA or 20uA + */ + rbs = v_batctrl * 1000 / di->curr_source; + } else { + /* + * BAT_CTRL is internally + * connected to 1.8V through a 10k resistor + */ + rbs = (10000 * (v_batctrl)) / (1800 - v_batctrl); + } + return rbs; +} + +/** + * ab5500_btemp_read_batctrl_voltage() - measure batctrl voltage + * @di: pointer to the ab5500_btemp structure + * + * This function returns the voltage on BATCTRL. Returns value in mV. + */ +static int ab5500_btemp_read_batctrl_voltage(struct ab5500_btemp *di) +{ + int vbtemp; + static int prev; + + vbtemp = ab5500_gpadc_convert(di->gpadc, BAT_CTRL); + if (vbtemp < 0) { + dev_err(di->dev, + "%s gpadc conversion failed, using previous value", + __func__); + return prev; + } + prev = vbtemp; + return vbtemp; +} + +/** + * ab5500_btemp_curr_source_enable() - enable/disable batctrl current source + * @di: pointer to the ab5500_btemp structure + * @enable: enable or disable the current source + * + * Enable or disable the current sources for the BatCtrl AD channel + */ +static int ab5500_btemp_curr_source_enable(struct ab5500_btemp *di, + bool enable) +{ + int ret = 0; + + /* Only do this for batteries with internal NTC */ + if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { + + dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source); + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_UART, + UART_MODE, RESIS_ID_MODE); + if (ret) { + dev_err(di->dev, + "%s failed setting resistance identification mode\n", + __func__); + return ret; + } + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_URI, + BAT_CUR_SRC, BAT_CTRL_15U_ENA); + if (ret) { + dev_err(di->dev, "%s failed enabling current source\n", + __func__); + goto disable_curr_source; + } + } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { + dev_dbg(di->dev, "Disable BATCTRL curr source\n"); + + /* Write 0 to the curr bits */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_URI, + BAT_CUR_SRC, RESET); + if (ret) { + dev_err(di->dev, "%s failed disabling current source\n", + __func__); + goto disable_curr_source; + } + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_UART, + UART_MODE, RESET); + if (ret) { + dev_err(di->dev, "%s failed disabling force comp\n", + __func__); + } + } + return ret; +disable_curr_source: + /* Write 0 to the curr bits */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_URI, + BAT_CUR_SRC, RESET); + if (ret) { + dev_err(di->dev, "%s failed disabling current source\n", + __func__); + } + return ret; +} + +/** + * ab5500_btemp_get_batctrl_res() - get battery resistance + * @di: pointer to the ab5500_btemp structure + * + * This function returns the battery pack identification resistance. + * Returns value in Ohms. + */ +static int ab5500_btemp_get_batctrl_res(struct ab5500_btemp *di) +{ + int ret; + int batctrl; + int res; + + ret = ab5500_btemp_curr_source_enable(di, true); + /* TODO: This delay has to be optimised */ + mdelay(1000); + if (ret) { + dev_err(di->dev, "%s curr source enable failed\n", __func__); + return ret; + } + + batctrl = ab5500_btemp_read_batctrl_voltage(di); + res = ab5500_btemp_batctrl_volt_to_res(di, batctrl); + + ret = ab5500_btemp_curr_source_enable(di, false); + if (ret) { + dev_err(di->dev, "%s curr source disable failed\n", __func__); + return ret; + } + + dev_dbg(di->dev, "%s batctrl: %d res: %d ", + __func__, batctrl, res); + + return res; +} + +/** + * ab5500_btemp_res_to_temp() - resistance to temperature + * @di: pointer to the ab5500_btemp structure + * @tbl: pointer to the resiatance to temperature table + * @tbl_size: size of the resistance to temperature table + * @res: resistance to calculate the temperature from + * + * This function returns the battery temperature in degrees Celcius + * based on the NTC resistance. + */ +static int ab5500_btemp_res_to_temp(struct ab5500_btemp *di, + const struct abx500_res_to_temp *tbl, int tbl_size, int res) +{ + int i, temp; + /* + * Calculate the formula for the straight line + * Simple interpolation if we are within + * the resistance table limits, extrapolate + * if resistance is outside the limits. + */ + if (res > tbl[0].resist) + i = 0; + else if (res <= tbl[tbl_size - 1].resist) + i = tbl_size - 2; + else { + i = 0; + while (!(res <= tbl[i].resist && + res > tbl[i + 1].resist)) + i++; + } + + temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) * + (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist); + return temp; +} + +/** + * ab5500_btemp_measure_temp() - measure battery temperature + * @di: pointer to the ab5500_btemp structure + * + * Returns battery temperature (on success) else the previous temperature + */ +static int ab5500_btemp_measure_temp(struct ab5500_btemp *di) +{ + int temp, ret; + static int prev; + int rbat, vntc; + int rntc = 0; + u8 id; + + id = di->bat->batt_id; + if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && + id != BATTERY_UNKNOWN) { + rbat = ab5500_btemp_get_batctrl_res(di); + if (rbat < 0) { + dev_err(di->dev, "%s get batctrl res failed\n", + __func__); + /* + * Return out-of-range temperature so that + * charging is stopped + */ + return BTEMP_THERMAL_LOW_LIMIT; + } + + temp = ab5500_btemp_res_to_temp(di, + di->bat->bat_type[id].r_to_t_tbl, + di->bat->bat_type[id].n_temp_tbl_elements, rbat); + } else { + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_UART, + UART_MODE, ADOUT_10K_PULL_UP); + if (ret) { + dev_err(di->dev, + "failed to enable 10k pull up to Vadout\n"); + } + vntc = ab5500_gpadc_convert(di->gpadc, BTEMP_BALL); + if (vntc < 0) { + dev_err(di->dev, + "%s gpadc conversion failed," + " using previous value\n", __func__); + return prev; + } + /* + * The PCB NTC is sourced from 2.75v via a 10kOhm + * resistor. + */ + rntc = 10000 * vntc / (27500 - vntc); + + temp = ab5500_btemp_res_to_temp(di, + di->bat->bat_type[id].r_to_t_tbl, + di->bat->bat_type[id].n_temp_tbl_elements, rntc); + prev = temp; + } + dev_dbg(di->dev, "Battery temperature is %d\n", temp); + return temp; +} + +/** + * ab5500_btemp_id() - Identify the connected battery + * @di: pointer to the ab5500_btemp structure + * + * This function will try to identify the battery by reading the ID + * resistor. Some brands use a combined ID resistor with a NTC resistor to + * both be able to identify and to read the temperature of it. + */ +static int ab5500_btemp_id(struct ab5500_btemp *di) +{ + int res; + u8 i; + + di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; + di->bat->batt_id = BATTERY_UNKNOWN; + + res = ab5500_btemp_get_batctrl_res(di); + if (res < 0) { + dev_err(di->dev, "%s get batctrl res failed\n", __func__); + return -ENXIO; + } + + /* BATTERY_UNKNOWN is defined on position 0, skip it! */ + for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) { + if ((res <= di->bat->bat_type[i].resis_high) && + (res >= di->bat->bat_type[i].resis_low)) { + dev_dbg(di->dev, "Battery detected on %s" + " low %d < res %d < high: %d" + " index: %d\n", + di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ? + "BATCTRL" : "BATTEMP", + di->bat->bat_type[i].resis_low, res, + di->bat->bat_type[i].resis_high, i); + + di->bat->batt_id = i; + break; + } + } + + if (di->bat->batt_id == BATTERY_UNKNOWN) { + dev_warn(di->dev, "Battery identified as unknown" + ", resistance %d Ohm\n", res); + return -ENXIO; + } + + /* + * We only have to change current source if the + * detected type is Type 1, else we use the 7uA source + */ + if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && + di->bat->batt_id == 1) { + dev_dbg(di->dev, "Set BATCTRL current source to 15uA\n"); + di->curr_source = BTEMP_BATCTRL_CURR_SRC_15UA; + } + + return di->bat->batt_id; +} + +/** + * ab5500_btemp_periodic_work() - Measuring the temperature periodically + * @work: pointer to the work_struct structure + * + * Work function for measuring the temperature periodically + */ +static void ab5500_btemp_periodic_work(struct work_struct *work) +{ + struct ab5500_btemp *di = container_of(work, + struct ab5500_btemp, btemp_periodic_work.work); + + di->bat_temp = ab5500_btemp_measure_temp(di); + + if (di->bat_temp != di->prev_bat_temp) { + di->prev_bat_temp = di->bat_temp; + power_supply_changed(&di->btemp_psy); + } + di->bat->temp_now = di->bat_temp; + + /* Schedule a new measurement */ + queue_delayed_work(di->btemp_wq, + &di->btemp_periodic_work, + round_jiffies(20 * HZ)); +} + +/** + * ab5500_btemp_batt_removal_handler() - battery removal detected + * @irq: interrupt number + * @_di: void pointer that has to address of ab5500_btemp + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_btemp_batt_removal_handler(int irq, void *_di) +{ + struct ab5500_btemp *di = _di; + dev_err(di->dev, "Battery removal detected!\n"); + + di->events.batt_rem = true; + power_supply_changed(&di->btemp_psy); + + return IRQ_HANDLED; +} + +/** + * ab5500_btemp_batt_attach_handler() - battery insertion detected + * @irq: interrupt number + * @_di: void pointer that has to address of ab5500_btemp + * + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab5500_btemp_batt_attach_handler(int irq, void *_di) +{ + struct ab5500_btemp *di = _di; + dev_err(di->dev, "Battery attached!\n"); + + di->events.batt_rem = false; + power_supply_changed(&di->btemp_psy); + + return IRQ_HANDLED; +} + +/** + * ab5500_btemp_periodic() - Periodic temperature measurements + * @di: pointer to the ab5500_btemp structure + * @enable: enable or disable periodic temperature measurements + * + * Starts of stops periodic temperature measurements. Periodic measurements + * should only be done when a charger is connected. + */ +static void ab5500_btemp_periodic(struct ab5500_btemp *di, + bool enable) +{ + dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n", + enable); + + if (enable) + queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); + else + cancel_delayed_work_sync(&di->btemp_periodic_work); +} + +/** + * ab5500_btemp_get_property() - get the btemp properties + * @psy: pointer to the power_supply structure + * @psp: pointer to the power_supply_property structure + * @val: pointer to the power_supply_propval union + * + * This function gets called when an application tries to get the btemp + * properties by reading the sysfs files. + * online: presence of the battery + * present: presence of the battery + * technology: battery technology + * temp: battery temperature + * Returns error code in case of failure else 0(on success) + */ +static int ab5500_btemp_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ab5500_btemp *di; + + di = to_ab5500_btemp_device_info(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_PRESENT: + case POWER_SUPPLY_PROP_ONLINE: + if (di->events.batt_rem) + val->intval = 0; + else + val->intval = 1; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = di->bat->bat_type[di->bat->batt_id].name; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = di->bat_temp * 10; + break; + default: + return -EINVAL; + } + return 0; +} + +static int ab5500_btemp_get_ext_psy_data(struct device *dev, void *data) +{ + struct power_supply *psy; + struct power_supply *ext; + struct ab5500_btemp *di; + union power_supply_propval ret; + int i, j; + bool psy_found = false; + + psy = (struct power_supply *)data; + ext = dev_get_drvdata(dev); + di = to_ab5500_btemp_device_info(psy); + + /* + * For all psy where the name of your driver + * appears in any supplied_to + */ + for (i = 0; i < ext->num_supplicants; i++) { + if (!strcmp(ext->supplied_to[i], psy->name)) + psy_found = true; + } + + if (!psy_found) + return 0; + + /* Go through all properties for the psy */ + for (j = 0; j < ext->num_properties; j++) { + enum power_supply_property prop; + prop = ext->properties[j]; + + if (ext->get_property(ext, prop, &ret)) + continue; + + switch (prop) { + case POWER_SUPPLY_PROP_PRESENT: + switch (ext->type) { + case POWER_SUPPLY_TYPE_USB: + /* USB disconnected */ + if (!ret.intval && di->events.usb_conn) { + di->events.usb_conn = false; + ab5500_btemp_periodic(di, + false); + } + /* USB connected */ + else if (ret.intval && !di->events.usb_conn) { + di->events.usb_conn = true; + ab5500_btemp_periodic(di, true); + } + break; + default: + break; + } + break; + default: + break; + } + } + return 0; +} + +/** + * ab5500_btemp_external_power_changed() - callback for power supply changes + * @psy: pointer to the structure power_supply + * + * This function is pointing to the function pointer external_power_changed + * of the structure power_supply. + * This function gets executed when there is a change in the external power + * supply to the btemp. + */ +static void ab5500_btemp_external_power_changed(struct power_supply *psy) +{ + struct ab5500_btemp *di = to_ab5500_btemp_device_info(psy); + + class_for_each_device(power_supply_class, NULL, + &di->btemp_psy, ab5500_btemp_get_ext_psy_data); +} + +/* ab5500 btemp driver interrupts and their respective isr */ +static struct ab5500_btemp_interrupts ab5500_btemp_irq[] = { + {"BATT_REMOVAL", ab5500_btemp_batt_removal_handler}, + {"BATT_ATTACH", ab5500_btemp_batt_attach_handler}, +}; +static int ab5500_btemp_bat_temp_trig(int mux) +{ + struct ab5500_btemp *di = ab5500_btemp_get(); + + if (di->bat_temp < BTEMP_THERMAL_LOW_LIMIT) { + dev_err(di->dev, + "battery temp less than lower threshold (-10 deg cel)\n"); + power_supply_changed(&di->btemp_psy); + } else if (di->bat_temp > BTEMP_THERMAL_HIGH_LIMIT_62) { + dev_err(di->dev, "battery temp greater them max threshold\n"); + power_supply_changed(&di->btemp_psy); + } + return 0;; +} + +static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) +{ + struct adc_auto_input *auto_ip; + int ret = 0; + + auto_ip = kzalloc(sizeof(struct adc_auto_input), GFP_KERNEL); + if (!auto_ip) { + dev_err(di->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + auto_ip->mux = BTEMP_BALL; + auto_ip->freq = MS500; + auto_ip->min = BTEMP_THERMAL_LOW_LIMIT; + auto_ip->max = BTEMP_THERMAL_HIGH_LIMIT_62; + auto_ip->auto_adc_callback = ab5500_btemp_bat_temp_trig; + di->gpadc_auto = auto_ip; + ret = ab5500_gpadc_convert_auto(di->gpadc, di->gpadc_auto); + if (ret) + dev_err(di->dev, + "failed to set auto trigger for battery temp\n"); + return ret; +} + +#if defined(CONFIG_PM) +static int ab5500_btemp_resume(struct platform_device *pdev) +{ + struct ab5500_btemp *di = platform_get_drvdata(pdev); + + if (di->events.usb_conn) + ab5500_btemp_periodic(di, true); + + return 0; +} + +static int ab5500_btemp_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct ab5500_btemp *di = platform_get_drvdata(pdev); + + if (di->events.usb_conn) + ab5500_btemp_periodic(di, false); + + return 0; +} +#else +#define ab5500_btemp_suspend NULL +#define ab5500_btemp_resume NULL +#endif + +static int __devexit ab5500_btemp_remove(struct platform_device *pdev) +{ + struct ab5500_btemp *di = platform_get_drvdata(pdev); + int i, irq; + + /* Disable interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_btemp_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_btemp_irq[i].name); + free_irq(irq, di); + } + + /* Delete the work queue */ + destroy_workqueue(di->btemp_wq); + + flush_scheduled_work(); + power_supply_unregister(&di->btemp_psy); + platform_set_drvdata(pdev, NULL); + kfree(di->gpadc_auto); + kfree(di); + + return 0; +} + +static int __devinit ab5500_btemp_probe(struct platform_device *pdev) +{ + int irq, i, ret = 0; + struct abx500_bm_plat_data *plat_data; + + struct ab5500_btemp *di = + kzalloc(sizeof(struct ab5500_btemp), GFP_KERNEL); + if (!di) + return -ENOMEM; + + /* get parent data */ + di->dev = &pdev->dev; + di->parent = dev_get_drvdata(pdev->dev.parent); + di->gpadc = ab5500_gpadc_get("ab5500-adc.0"); + + plat_data = pdev->dev.platform_data; + di->pdata = plat_data->btemp; + di->bat = plat_data->battery; + + /* get btemp specific platform data */ + if (!di->pdata) { + dev_err(di->dev, "no btemp platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + + /* get battery specific platform data */ + if (!di->bat) { + dev_err(di->dev, "no battery platform data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + + /* BTEMP supply */ + di->btemp_psy.name = "ab5500_btemp"; + di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; + di->btemp_psy.properties = ab5500_btemp_props; + di->btemp_psy.num_properties = ARRAY_SIZE(ab5500_btemp_props); + di->btemp_psy.get_property = ab5500_btemp_get_property; + di->btemp_psy.supplied_to = di->pdata->supplied_to; + di->btemp_psy.num_supplicants = di->pdata->num_supplicants; + di->btemp_psy.external_power_changed = + ab5500_btemp_external_power_changed; + + + /* Create a work queue for the btemp */ + di->btemp_wq = + create_singlethread_workqueue("ab5500_btemp_wq"); + if (di->btemp_wq == NULL) { + dev_err(di->dev, "failed to create work queue\n"); + goto free_device_info; + } + + /* Init work for measuring temperature periodically */ + INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work, + ab5500_btemp_periodic_work); + + /* Get Chip ID of the ABB ASIC */ + ret = abx500_get_chip_id(di->dev); + if (ret < 0) { + dev_err(di->dev, "failed to get chip ID\n"); + goto free_btemp_wq; + } + di->chip_id = ret; + dev_dbg(di->dev, "ab5500 CID is: 0x%02x\n", + di->chip_id); + + /* Identify the battery */ + if (ab5500_btemp_id(di) < 0) + dev_warn(di->dev, "failed to identify the battery\n"); + + /* Measure temperature once initially */ + di->bat_temp = ab5500_btemp_measure_temp(di); + di->bat->temp_now = di->bat_temp; + + /* Register BTEMP power supply class */ + ret = power_supply_register(di->dev, &di->btemp_psy); + if (ret) { + dev_err(di->dev, "failed to register BTEMP psy\n"); + goto free_btemp_wq; + } + + /* Register interrupts */ + for (i = 0; i < ARRAY_SIZE(ab5500_btemp_irq); i++) { + irq = platform_get_irq_byname(pdev, ab5500_btemp_irq[i].name); + ret = request_threaded_irq(irq, NULL, ab5500_btemp_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND, + ab5500_btemp_irq[i].name, di); + + if (ret) { + dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + , ab5500_btemp_irq[i].name, irq, ret); + goto free_irq; + } + dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + ab5500_btemp_irq[i].name, irq, ret); + } + ret = ab5500_btemp_auto_temp(di); + if (ret) { + dev_err(di->dev, + "failed to register auto trigger for battery temp\n"); + goto free_irq; + } + + platform_set_drvdata(pdev, di); + + dev_info(di->dev, "probe success\n"); + return ret; + +free_irq: + power_supply_unregister(&di->btemp_psy); + + /* We also have to free all successfully registered irqs */ + for (i = i - 1; i >= 0; i--) { + irq = platform_get_irq_byname(pdev, ab5500_btemp_irq[i].name); + free_irq(irq, di); + } +free_btemp_wq: + destroy_workqueue(di->btemp_wq); +free_device_info: + kfree(di); + + return ret; +} + +static struct platform_driver ab5500_btemp_driver = { + .probe = ab5500_btemp_probe, + .remove = __devexit_p(ab5500_btemp_remove), + .suspend = ab5500_btemp_suspend, + .resume = ab5500_btemp_resume, + .driver = { + .name = "ab5500-btemp", + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_btemp_init(void) +{ + return platform_driver_register(&ab5500_btemp_driver); +} + +static void __exit ab5500_btemp_exit(void) +{ + platform_driver_unregister(&ab5500_btemp_driver); +} + +subsys_initcall_sync(ab5500_btemp_init); +module_exit(ab5500_btemp_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); +MODULE_ALIAS("platform:ab5500-btemp"); +MODULE_DESCRIPTION("AB5500 battery temperature driver"); -- cgit v1.2.3 From e7b13c7bf44de5fcfa0420d2256a18daa3fe9031 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:51:49 +0530 Subject: mach-ux500: platform data for ab5500 battery driver ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP256401 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I81619ad06bc6f89962b2cfd4404e911cc77082ec Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23153 Reviewed-by: Johan PALSSON Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-bm.c | 496 +++++++++++++++++++++++++++++++++++ arch/arm/mach-ux500/board-u5500-bm.h | 26 ++ 2 files changed, 522 insertions(+) create mode 100644 arch/arm/mach-ux500/board-u5500-bm.c create mode 100644 arch/arm/mach-ux500/board-u5500-bm.h diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c new file mode 100644 index 00000000000..2616d7fa517 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U5500 board specific charger and battery initialization parameters. + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson + * Karl Komierowski + */ + +#include +#include +#include +#include +#include "board-u5500-bm.h" + +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL +/* + * These are the defined batteries that uses a NTC and ID resistor placed + * inside of the battery pack. + * Note that the abx500_res_to_temp table must be strictly sorted by falling resistance + * values to work. + */ +static struct abx500_res_to_temp temp_tbl_type1[] = { + {-20, 67400}, + { 0, 49200}, + { 5, 44200}, + { 10, 39400}, + { 15, 35000}, + { 20, 31000}, + { 25, 27400}, + { 30, 24300}, + { 35, 21700}, + { 40, 19400}, + { 45, 17500}, + { 50, 15900}, + { 55, 14600}, + { 60, 13500}, + { 65, 12500}, + { 70, 11800}, + {100, 9200}, +}; + +static struct abx500_res_to_temp temp_tbl_type2[] = { + {-20, 180700}, + { 0, 160000}, + { 5, 152700}, + { 10, 144900}, + { 15, 136800}, + { 20, 128700}, + { 25, 121000}, + { 30, 113800}, + { 35, 107300}, + { 40, 101500}, + { 45, 96500}, + { 50, 92200}, + { 55, 88600}, + { 60, 85600}, + { 65, 83000}, + { 70, 80900}, + {100, 73900}, +}; + +static struct abx500_res_to_temp temp_tbl_A[] = { + {-5, 53407}, + { 0, 48594}, + { 5, 43804}, + {10, 39188}, + {15, 34870}, + {20, 30933}, + {25, 27422}, + {30, 24347}, + {35, 21694}, + {40, 19431}, + {45, 17517}, + {50, 15908}, + {55, 14561}, + {60, 13437}, + {65, 12500}, +}; + +static struct abx500_res_to_temp temp_tbl_B[] = { + {-5, 165418}, + { 0, 159024}, + { 5, 151921}, + {10, 144300}, + {15, 136424}, + {20, 128565}, + {25, 120978}, + {30, 113875}, + {35, 107397}, + {40, 101629}, + {45, 96592}, + {50, 92253}, + {55, 88569}, + {60, 85461}, + {65, 82869}, +}; + +static struct abx500_v_to_cap cap_tbl_type1[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; + +static struct abx500_v_to_cap cap_tbl_A[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; +static struct abx500_v_to_cap cap_tbl_B[] = { + {4161, 100}, + {4124, 98}, + {4044, 90}, + {4003, 85}, + {3966, 80}, + {3933, 75}, + {3888, 67}, + {3849, 60}, + {3813, 55}, + {3787, 47}, + {3772, 30}, + {3751, 25}, + {3718, 20}, + {3681, 16}, + {3660, 14}, + {3589, 10}, + {3546, 7}, + {3495, 4}, + {3404, 2}, + {3250, 0}, +}; +#endif +static struct abx500_v_to_cap cap_tbl[] = { + {4186, 100}, + {4163, 99}, + {4114, 95}, + {4068, 90}, + {3990, 80}, + {3926, 70}, + {3898, 65}, + {3866, 60}, + {3833, 55}, + {3812, 50}, + {3787, 40}, + {3768, 30}, + {3747, 25}, + {3730, 20}, + {3705, 15}, + {3699, 14}, + {3684, 12}, + {3672, 9}, + {3657, 7}, + {3638, 6}, + {3556, 4}, + {3424, 2}, + {3317, 1}, + {3094, 0}, +}; + +/* + * Note that the abx500_res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct abx500_res_to_temp temp_tbl[] = { + {-5, 214834}, + { 0, 162943}, + { 5, 124820}, + {10, 96520}, + {15, 75306}, + {20, 59254}, + {25, 47000}, + {30, 37566}, + {35, 30245}, + {40, 24520}, + {45, 20010}, + {50, 16432}, + {55, 13576}, + {60, 11280}, + {65, 9425}, +}; + +static const struct abx500_battery_type bat_type[] = { + [BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, + .charge_full_design = 612, + .nominal_voltage = 3700, + .termination_vol = 4050, + .termination_curr = 200, + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 70000, + .resis_low = 8200, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_type1), + .r_to_t_tbl = temp_tbl_type1, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_type1), + .v_to_cap_tbl = cap_tbl_type1, + + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 165418, + .resis_low = 82869, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B), + .r_to_t_tbl = temp_tbl_B, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B), + .v_to_cap_tbl = cap_tbl_B, + }, +#else +/* + * These are the batteries that doesn't have an internal NTC resistor to measure + * its temperature. The temperature in this case is measure with a NTC placed + * near the battery but on the PCB. + */ + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 76000, + .resis_low = 53000, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 30000, + .resis_low = 10000, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 95000, + .resis_low = 76001, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, +#endif +}; + +static char *ab5500_charger_supplied_to[] = { + "abx500_chargalg", + "ab5500_fg", + "ab5500_btemp", +}; + +static char *ab5500_btemp_supplied_to[] = { + "abx500_chargalg", + "ab5500_fg", +}; + +static char *ab5500_fg_supplied_to[] = { + "abx500_chargalg", +}; + +static char *abx500_chargalg_supplied_to[] = { + "ab5500_fg", +}; + +struct abx500_charger_platform_data ab5500_charger_plat_data = { + .supplied_to = ab5500_charger_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_charger_supplied_to), +}; + +struct abx500_btemp_platform_data ab5500_btemp_plat_data = { + .supplied_to = ab5500_btemp_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_btemp_supplied_to), +}; + +struct abx500_fg_platform_data ab5500_fg_plat_data = { + .supplied_to = ab5500_fg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_fg_supplied_to), +}; + +struct abx500_chargalg_platform_data abx500_chargalg_plat_data = { + .supplied_to = abx500_chargalg_supplied_to, + .num_supplicants = ARRAY_SIZE(abx500_chargalg_supplied_to), +}; + +static const struct abx500_bm_capacity_levels cap_levels = { + .critical = 2, + .low = 10, + .normal = 70, + .high = 95, + .full = 100, +}; + +static const struct abx500_fg_parameters fg = { + .recovery_sleep_timer = 10, + .recovery_total_time = 100, + .init_timer = 1, + .init_discard_time = 5, + .init_total_time = 40, + .high_curr_time = 60, + .accu_charging = 30, + .accu_high_curr = 30, + .high_curr_threshold = 50, + .lowbat_threshold = 3100, +}; + +static const struct abx500_maxim_parameters maxi_params = { + .ena_maxi = true, + .chg_curr = 910, + .wait_cycles = 10, + .charger_curr_step = 100, +}; + +static const struct abx500_bm_charger_parameters chg = { + .usb_volt_max = 5500, + .usb_curr_max = 1500, + .ac_volt_max = 7500, + .ac_curr_max = 1500, +}; + +struct abx500_bm_data ab5500_bm_data = { + .temp_under = 3, + .temp_low = 8, + /* TODO: Need to verify the temp values */ + .temp_high = 155, + .temp_over = 160, + .main_safety_tmr_h = 4, + .usb_safety_tmr_h = 4, + .bkup_bat_v = 0x00, + .bkup_bat_i = 0x00, + .no_maintenance = true, +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL + .adc_therm = ABx500_ADC_THERM_BATCTRL, +#else + .adc_therm = ABx500_ADC_THERM_BATTEMP, +#endif + .chg_unknown_bat = false, + .enable_overshoot = false, + .fg_res = 20, + .cap_levels = &cap_levels, + .bat_type = bat_type, + .n_btypes = ARRAY_SIZE(bat_type), + .batt_id = 0, + .interval_charging = 5, + .interval_not_charging = 120, + .temp_hysteresis = 3, + .maxi = &maxi_params, + .chg_params = &chg, + .fg_params = &fg, +}; + +/* ab5500 energy management platform data */ +struct abx500_bm_plat_data abx500_bm_pt_data = { + .battery = &ab5500_bm_data, + .charger = &ab5500_charger_plat_data, + .btemp = &ab5500_btemp_plat_data, + .fg = &ab5500_fg_plat_data, + .chargalg = &abx500_chargalg_plat_data, +}; diff --git a/arch/arm/mach-ux500/board-u5500-bm.h b/arch/arm/mach-ux500/board-u5500-bm.h new file mode 100644 index 00000000000..a6346905911 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-bm.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U5500 board specific charger and battery initialization parameters. + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson + * Karl Komierowski + */ + +#ifndef __BOARD_U5500_BM_H +#define __BOARD_U5500_BM_H + +#include + +extern struct abx500_charger_platform_data ab5500_charger_plat_data; +extern struct abx500_btemp_platform_data ab5500_btemp_plat_data; +extern struct abx500_fg_platform_data ab5500_fg_plat_data; +extern struct abx500_chargalg_platform_data abx500_chargalg_plat_data; +extern struct abx500_bm_data ab5500_bm_data; +extern struct abx500_bm_plat_data abx500_bm_pt_data; + +#endif -- cgit v1.2.3 From 2eb0d026857b7d25df11be5bbf764ffa5f195d53 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:52:33 +0530 Subject: power: Add ab5500 battery, temp, fg, driver Enable compilation of ab5500 energy management driver. It depends on ab5500 mfd and ab5500 gpadc driver. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP256401 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I072f6bfc643897d3a43ad478f05d78ef2fdbffd8 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23154 Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/Kconfig | 13 +++++++++++++ drivers/power/Makefile | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 99dc29f2f2f..c46388840a3 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -307,4 +307,17 @@ config AB8500_BATTERY_THERM_ON_BATCTRL help Say Y to enable battery temperature measurements using thermistor connected on BATCTRL ADC. + +config AB5500_BM + bool "AB5500 Battery Management Driver" + depends on AB5500_CORE && MACH_B5500 + help + Say Y to include support for AB5500 battery management. + +config AB5500_BATTERY_THERM_ON_BATCTRL + bool "Thermistor connected on BATCTRL ADC" + depends on AB5500_BM + help + Say Y to enable battery temperature measurements using + thermistor connected on BATCTRL ADC. endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b6b243416c0..5fcd08d9df4 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o +obj-$(CONFIG_AB5500_BM) += ab5500_charger.o abx500_chargalg.o ab5500_fg.o ab5500_btemp.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o -- cgit v1.2.3 From 02f4452494af00b4c9941cb056b19213486bcf69 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 27 Jun 2011 11:35:42 +0200 Subject: power: u5500: Fix and activate Battery Management for U5500 Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-u5500-bm.c | 1 - drivers/power/Kconfig | 2 +- drivers/power/ab5500_btemp.c | 1 - drivers/power/ab5500_charger.c | 1 - drivers/power/ab5500_fg.c | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index 2616d7fa517..7cfc6386b35 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -13,7 +13,6 @@ #include #include -#include #include #include "board-u5500-bm.h" diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index c46388840a3..f3d5a7a95c3 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -310,7 +310,7 @@ config AB8500_BATTERY_THERM_ON_BATCTRL config AB5500_BM bool "AB5500 Battery Management Driver" - depends on AB5500_CORE && MACH_B5500 + depends on AB5500_CORE && AB8500_GPADC && ARCH_U8500 help Say Y to include support for AB5500 battery management. diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 57241c96f60..8b6ff82a86b 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 1b6bfa21d00..2fd7888ad9d 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 1c866e8fec5..919af5faadf 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -25,7 +25,6 @@ #include #include #include -#include #include static LIST_HEAD(ab5500_fg_list); -- cgit v1.2.3 From 888d1a715c85c3fcedfc078ea23469c36ea103f4 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 26 May 2011 16:57:32 +0530 Subject: mfd: ab5500-gpadc: Discard adc converted value if < 5 ADC Convertion made on BDATA, using resistance mode, sometimes provides a null value or a value < 5. Discard susch values and provide the previous converted value ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib0eaaed520789b91ea77b2a90c640d33a6c913f6 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23607 Reviewed-by: Johan PALSSON Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/ab5500-gpadc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index e90bd9a3aaa..dbfc9c30e38 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -47,7 +47,7 @@ #define AB5500_GPADC_AUTO_TRIG_ADOUT0_CTRL 0x34 #define AB5500_GPADC_AUTO_TRIG_ADOUT1_CTRL 0x35 #define AB5500_GPADC_AUTO_TRIG0_MUX_CTRL 0x37 -#define AB5500_GPADC_AUTO_XALTEMP_CTRL 0x57 +#define AB5500_GPADC_AUTO_XTALTEMP_CTRL 0x57 #define AB5500_GPADC_KELVIN_CTRL 0xFE /* gpadc constants */ @@ -194,6 +194,7 @@ struct ab5500_gpadc { struct mutex ab5500_gpadc_lock; struct regulator *regu; int irq; + int prev_bdata; spinlock_t gpadc_auto_lock; struct adc_auto_trigger adc_trig[N_AUTO_TRIGGER]; struct workqueue_struct *gpadc_wq; @@ -358,7 +359,7 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) break; case XTAL_TEMP: ret = abx500_mask_and_set_register_interruptible(gpadc->dev, - AB5500_BANK_ADC, AB5500_GPADC_AUTO_XALTEMP_CTRL, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_XTALTEMP_CTRL, ADC_XTAL_FORCE_MASK, ADC_XTAL_FORCE_EN); if (ret < 0) { dev_err(gpadc->dev, "gpadc: fail to set xtaltemp\n"); @@ -454,7 +455,7 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) */ if (input == XTAL_TEMP) { ret = abx500_mask_and_set_register_interruptible(gpadc->dev, - AB5500_BANK_ADC, AB5500_GPADC_AUTO_XALTEMP_CTRL, + AB5500_BANK_ADC, AB5500_GPADC_AUTO_XTALTEMP_CTRL, ADC_XTAL_FORCE_MASK, ADC_XTAL_FORCE_DI); if (ret < 0) { dev_err(gpadc->dev, @@ -478,6 +479,17 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) } data = (high_data << 2) | (low_data >> 6); + if (input == BAT_CTRL || input == BTEMP_BALL) { + /* + * TODO: Re-check with h/w team + * discard null or value < 5, as there is some error + * in conversion + */ + if (data < 5) + data = gpadc->prev_bdata; + else + gpadc->prev_bdata = data; + } result = ab5500_gpadc_ad_to_voltage(gpadc, input, data); mutex_unlock(&gpadc->ab5500_gpadc_lock); -- cgit v1.2.3 From da43309107d9b9fab2ece43fa2bdb3a6d1a4c11c Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 14 Jun 2011 11:56:20 +0200 Subject: drivers: watchdog: Add ux500-watchdog driver This driver kicks a watchdog that is located in the prcmu firmware. ST-Ericsson Linux next: Not tested, ask SSM for ER ST-Ericsson ID: 339924 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5fcabc0a409f18914129f6a5c8e17f4267974c61 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25029 Reviewed-by: QATEST Reviewed-by: Linus WALLEIJ --- drivers/watchdog/Kconfig | 16 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/ux500_wdt.c | 410 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 427 insertions(+) create mode 100644 drivers/watchdog/ux500_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37096246c93..a2eb7474ebd 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -294,6 +294,22 @@ config COH901327_WATCHDOG This watchdog is used to reset the system and thus cannot be compiled as a module. +config UX500_WATCHDOG + bool "ST-Ericsson UX500 watchdog" + depends on ARCH_U8500 + default y if MACH_U8500 + help + Say Y here to include Watchdog timer support for the + watchdog existing in the prcmu of ST-Ericsson UX500 series platforms. + This watchdog is used to reset the system and thus cannot be + compiled as a module. + +config UX500_WATCHDOG_DEBUG + bool "ST-Ericsson UX500 watchdog DEBUG" + depends on ARCH_U8500 && DEBUG_FS + help + Say Y here to add various debugfs entries in wdog/ + config TWL4030_WATCHDOG tristate "TWL4030 Watchdog" depends on TWL4030_CORE diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e8f479a1640..746492e2249 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o +obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c new file mode 100644 index 00000000000..fd343197681 --- /dev/null +++ b/drivers/watchdog/ux500_wdt.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Jonas Aaberg for ST-Ericsson + * + * Heavily based upon geodewdt.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define WATCHDOG_TIMEOUT 600 /* 10 minutes */ + +#define WDT_FLAGS_OPEN 1 +#define WDT_FLAGS_ORPHAN 2 + +static unsigned long wdt_flags; + +static int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=131, default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +static u8 wdog_id; +static bool wdt_en; +static bool wdt_auto_off = true; +static bool safe_close; + +static int ux500_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) + return -EBUSY; + + if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) + __module_get(THIS_MODULE); + + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + + return nonseekable_open(inode, file); +} + +static int ux500_wdt_release(struct inode *inode, struct file *file) +{ + if (safe_close) { + prcmu_disable_a9wdog(wdog_id); + module_put(THIS_MODULE); + } else { + pr_crit("Unexpected close - watchdog is not stopping.\n"); + prcmu_kick_a9wdog(wdog_id); + + set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); + } + + clear_bit(WDT_FLAGS_OPEN, &wdt_flags); + safe_close = false; + return 0; +} + +static ssize_t ux500_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + if (!len) + return len; + + if (!nowayout) { + size_t i; + safe_close = false; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + safe_close = true; + } + } + + prcmu_kick_a9wdog(wdog_id); + + return len; +} + +static long ux500_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int interval; + + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "UX500 WDT", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + { + int options; + int ret = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + ret = 0; + } + + return ret; + } + case WDIOC_KEEPALIVE: + return prcmu_kick_a9wdog(wdog_id); + + case WDIOC_SETTIMEOUT: + if (get_user(interval, p)) + return -EFAULT; + + /* 28 bit resolution in ms, becomes 268435455 ms */ + if (interval > 26843 || interval < 0) + return -EINVAL; + timeout = interval; + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + + /* Fall through */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations ux500_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = ux500_wdt_write, + .unlocked_ioctl = ux500_wdt_ioctl, + .open = ux500_wdt_open, + .release = ux500_wdt_release, +}; + +static struct miscdevice ux500_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ux500_wdt_fops, +}; + +#ifdef CONFIG_UX500_WATCHDOG_DEBUG + +enum wdog_dbg { + WDOG_DBG_CONFIG, + WDOG_DBG_LOAD, + WDOG_DBG_KICK, + WDOG_DBG_EN, + WDOG_DBG_DIS, +}; + +static ssize_t wdog_dbg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + unsigned long val; + int err; + enum wdog_dbg v = (enum wdog_dbg)((struct seq_file *) + (file->private_data))->private; + + switch(v) { + case WDOG_DBG_CONFIG: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + wdt_auto_off = val != 0; + (void) prcmu_config_a9wdog(1, + wdt_auto_off); + } + else { + pr_err("ux500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_LOAD: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + timeout = val; + /* Convert seconds to ms */ + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + else { + pr_err("ux500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_KICK: + (void) prcmu_kick_a9wdog(wdog_id); + break; + case WDOG_DBG_EN: + wdt_en = true; + (void) prcmu_enable_a9wdog(wdog_id); + break; + case WDOG_DBG_DIS: + wdt_en = false; + (void) prcmu_disable_a9wdog(wdog_id); + break; + } + + return count; +} + +static int wdog_dbg_read(struct seq_file *s, void *p) +{ + enum wdog_dbg v = (enum wdog_dbg)s->private; + + switch(v) { + case WDOG_DBG_CONFIG: + seq_printf(s,"wdog is on id %d, auto off on sleep: %s\n", + (int)wdog_id, + wdt_auto_off ? "enabled": "disabled"); + break; + case WDOG_DBG_LOAD: + /* In 1s */ + seq_printf(s, "wdog load is: %d s\n", + timeout); + break; + case WDOG_DBG_KICK: + break; + case WDOG_DBG_EN: + case WDOG_DBG_DIS: + seq_printf(s, "wdog is %sabled.\n", + wdt_en ? "en" : "dis"); + break; + } + return 0; +} + +static int wdog_dbg_open(struct inode *inode, + struct file *file) +{ + return single_open(file, wdog_dbg_read, inode->i_private); +} + +static const struct file_operations wdog_dbg_fops = { + .open = wdog_dbg_open, + .write = wdog_dbg_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int __init wdog_dbg_init(void) +{ + struct dentry *wdog_dir; + + wdog_dir = debugfs_create_dir("wdog", NULL); + if (IS_ERR_OR_NULL(wdog_dir)) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_u8("id", + S_IWUGO | S_IRUGO, wdog_dir, + &wdog_id))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("config", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_CONFIG, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("load", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_LOAD, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("kick", + S_IWUGO, wdog_dir, + (void *)WDOG_DBG_KICK, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("enable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_EN, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("disable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_DIS, + &wdog_dbg_fops))) + goto fail; + + return 0; +fail: + pr_err("ux500:wdog: Failed to initialize wdog dbg.\n"); + debugfs_remove_recursive(wdog_dir); + + return -EFAULT; +} + +#else +static inline int __init wdog_dbg_init(void) +{ + return 0; +} +#endif + +static int __init ux500_wdt_probe(struct platform_device *pdev) +{ + int ret; + + /* Number of watch dogs */ + prcmu_config_a9wdog(1, wdt_auto_off); + /* convert to ms */ + prcmu_load_a9wdog(wdog_id, timeout * 1000); + + ret = misc_register(&ux500_wdt_miscdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register misc.\n"); + return ret; + } + + ret = wdog_dbg_init(); + if (ret < 0) + goto fail; + + dev_info(&pdev->dev, "initialized.\n"); + + return 0; +fail: + misc_deregister(&ux500_wdt_miscdev); + return ret; +} + +static int __exit ux500_wdt_remove(struct platform_device *dev) +{ + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + misc_deregister(&ux500_wdt_miscdev); + return 0; +} + +static struct platform_driver ux500_wdt_driver = { + .remove = __exit_p(ux500_wdt_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ux500_wdt", + }, +}; + +static int __init ux500_wdt_init(void) +{ + return platform_driver_probe(&ux500_wdt_driver, ux500_wdt_probe); +} + +static void __exit ux500_wdt_exit(void) +{ + platform_driver_unregister(&ux500_wdt_driver); +} + +module_init(ux500_wdt_init); +module_exit(ux500_wdt_exit); + +MODULE_AUTHOR("Jonas Aaberg "); +MODULE_DESCRIPTION("UX500 Watchdog Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From c49247cb8478bce8563ed9985f694da5b07f7f9e Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Wed, 22 Jun 2011 14:58:53 +0530 Subject: power: ab5500-btemp: do not measure temp if battery is unknown Since the battery is unknown, do not measure the battery temp it might provide some value maybe too high or low leading to system reboot ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP332221 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I70b4cc959bfd2792a25379cc17a25dada4b1c051 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25661 Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_btemp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 8b6ff82a86b..04ad6bbb7ac 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -536,7 +536,15 @@ static int ab5500_btemp_get_property(struct power_supply *psy, val->intval = di->bat->bat_type[di->bat->batt_id].name; break; case POWER_SUPPLY_PROP_TEMP: - val->intval = di->bat_temp * 10; + if (di->bat->batt_id == BATTERY_UNKNOWN) + /* + * In case the battery is not identified, its assumed that + * we are using the power supply and since no monitoring is + * done for the same, a nominal temp is hardocded. + */ + val->intval = 250; + else + val->intval = di->bat_temp * 10; break; default: return -EINVAL; -- cgit v1.2.3 From fbfa47e73de481d6f98da0848fc951abc392ab8b Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 7 Jul 2011 13:28:33 +0200 Subject: ux500: config: Align u8500_defconfig with u5500+u8500 default configs Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c1a041514c2..b78eeed90b0 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -29,6 +29,7 @@ CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_PRCMU_TIMER=y CONFIG_DB8500_MLOADER=y +CONFIG_U5500_MLOADER=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y @@ -36,8 +37,6 @@ CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y -CONFIG_MODEM=y -CONFIG_MODEM_U8500=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -104,9 +103,8 @@ CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y +CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y -CONFIG_U8500_SHRM=y -CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y # CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y @@ -119,7 +117,9 @@ CONFIG_TUN=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y -CONFIG_CAIF_SHM=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -147,6 +147,7 @@ CONFIG_SPI=y # CONFIG_STM_MSP_SPI is not set CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y @@ -156,7 +157,6 @@ CONFIG_SENSORS_DB8500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y -CONFIG_MPCORE_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y @@ -223,6 +223,7 @@ CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y +CONFIG_AB5500_SIM=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_HSEM_U8500=y CONFIG_CG2900=y @@ -233,8 +234,13 @@ CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y CONFIG_U8500_MMIO=y +CONFIG_U5500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y +CONFIG_MODEM=y +CONFIG_MODEM_U8500=y +CONFIG_U8500_SHRM=y +CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -285,7 +291,7 @@ CONFIG_TIMER_STATS=y CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_FTRACE is not set +CONFIG_FUNCTION_TRACER=y CONFIG_DEBUG_USER=y CONFIG_KEYS=y CONFIG_CRYPTO_ECB=y -- cgit v1.2.3 From 1dad971be017d20ee7c66ed3bca22035584a54db Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 22 Jul 2011 11:57:36 +0200 Subject: gpio: nomadik: Rename AB8500_GPIO by GPIO_AB8500 To be compliant with future gpio framework Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b78eeed90b0..b8763283c57 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -149,6 +149,7 @@ CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y +CONFIG_GPIO_AB8500=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y -- cgit v1.2.3 From 26740ac724defecc78a078a4a4e73eedabe24e15 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 12 Aug 2011 11:46:36 +0200 Subject: Doc: Fixing documentation for html generation Change documentation to align with header files and source file renames and move. Change-Id: I8e67e41e90dfb61255db5e2e84ead09972361c1c Signed-off-by: Robert Marklund --- Documentation/DocBook/stylesheet.xsl | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) mode change 100644 => 100755 Documentation/DocBook/stylesheet.xsl diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl old mode 100644 new mode 100755 index 85b25275196..b2769ce5c8f --- a/Documentation/DocBook/stylesheet.xsl +++ b/Documentation/DocBook/stylesheet.xsl @@ -1,10 +1,18 @@ - - -1 -ansi -80 -0 - -2 -1 - + + + + + + + 1 + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 9e145894f31382f02728dd5eb40acf7ff484d592 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 3 Mar 2011 11:26:01 +0100 Subject: RTC: rtc-ab8500: Round alarm time upwards Due to strange android design and the ab8500 hw has a wake up alarm resolution in minutes, we have to add one minute to make sure that we always wake up. ST-Ericsson Linux next: Not tested, ask SSM for ER ST-Ericsson ID: ER324148 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I6a424984cc41757e4d3ba98e8ea48975a85213eb Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17496 Reviewed-by: QATOOLS Reviewed-by: Rickard ANDERSSON --- drivers/rtc/rtc-ab8500.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 4bcf9ca2818..587f593c17e 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -241,8 +241,19 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) */ secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); +#ifndef CONFIG_ANDROID + secs += 30; /* Round to nearest minute */ +#endif + mins = secs / 60; +#ifdef CONFIG_ANDROID + /* + * Needed due to Android believes all hw have a wake-up resolution + * in seconds. + */ + mins++; +#endif buf[2] = mins & 0xFF; buf[1] = (mins >> 8) & 0xFF; buf[0] = (mins >> 16) & 0xFF; -- cgit v1.2.3 From 2183705c3a4c49a0bf04c04c05eaa754a201ccc2 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 12 Jul 2011 13:43:54 +0200 Subject: ux500: Update u8500_defconfig and Add Snowball defconfig for Android Change-Id: I1cef8427a8f931b1be7b60c624a80b05c52d8217 Signed-off-by: Philippe Langlais Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b8763283c57..3455f7c9904 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -43,6 +43,7 @@ CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y +CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y @@ -147,7 +148,6 @@ CONFIG_SPI=y # CONFIG_STM_MSP_SPI is not set CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y CONFIG_GPIO_AB8500=y CONFIG_POWER_SUPPLY=y @@ -198,17 +198,11 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_CDC_COMPOSITE=m -CONFIG_USB_G_MULTI=m -# CONFIG_USB_G_MULTI_RNDIS is not set CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_CLKGATE=y +CONFIG_MMC_PARANOID_SD_INIT=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y @@ -217,6 +211,7 @@ CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y -- cgit v1.2.3 From 2069fe587096c7cdaea8aa6bc6022fd41a9a9d53 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 16 May 2011 10:08:49 +0200 Subject: bh1780gli: Add early suspend/late resume ST-Ericsson Linux next: Not tested, ask SSM for ER. ST-Ericsson ID: ER337907 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I66430fe4369c1320c78b1a8dca5e4abbb3b9abcf Signed-off-by: Marcus Cooper Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23099 Reviewed-by: QATEST Reviewed-by: Martin PERSSON Reviewed-by: Chethan Krishna N Reviewed-by: Jonas ABERG Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28973 Tested-by: Naga RADHESH Y Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/misc/bh1780gli.c | 124 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 30 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 0b9ff5e8825..95aee44e30f 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -26,6 +26,10 @@ #include #include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + #define BH1780_REG_CONTROL 0x80 #define BH1780_REG_PARTID 0x8A #define BH1780_REG_MANFID 0x8B @@ -43,11 +47,19 @@ struct bh1780_data { struct i2c_client *client; struct regulator *regulator; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif int power_state; /* lock for sysfs operations */ struct mutex lock; }; +#ifdef CONFIG_HAS_EARLYSUSPEND +static void bh1780_early_suspend(struct early_suspend *ddata); +static void bh1780_late_resume(struct early_suspend *ddata); +#endif + static int bh1780_write(struct bh1780_data *ddata, u8 reg, u8 val, char *msg) { int ret = i2c_smbus_write_byte_data(ddata->client, reg, val); @@ -192,6 +204,12 @@ static int __devinit bh1780_probe(struct i2c_client *client, dev_err(&client->dev, "failed to read part ID\n"); goto put_regulator; } +#ifdef CONFIG_HAS_EARLYSUSPEND + ddata->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ddata->early_suspend.suspend = bh1780_early_suspend; + ddata->early_suspend.resume = bh1780_late_resume; + register_early_suspend(&ddata->early_suspend); +#endif regulator_disable(ddata->regulator); ddata->power_state = BH1780_POFF; @@ -226,57 +244,101 @@ static int __devexit bh1780_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int bh1780_suspend(struct device *dev) +static int bh1780_do_suspend(struct bh1780_data *ddata) { - struct bh1780_data *ddata; - int state, ret; - struct i2c_client *client = to_i2c_client(dev); + int ret = 0; - ddata = i2c_get_clientdata(client); - state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL"); - if (state < 0) - return state; + mutex_lock(&ddata->lock); - ddata->power_state = state & BH1780_POWMASK; + if (ddata->power_state == BH1780_POFF) + goto unlock; - ret = bh1780_write(ddata, BH1780_REG_CONTROL, BH1780_POFF, - "CONTROL"); + ret = bh1780_write(ddata, BH1780_REG_CONTROL, BH1780_POFF, "CONTROL"); if (ret < 0) - return ret; - - regulator_disable(ddata->regulator); + goto unlock; - return 0; + if (ddata->regulator) + regulator_disable(ddata->regulator); +unlock: + mutex_unlock(&ddata->lock); + return ret; } -static int bh1780_resume(struct device *dev) +static int bh1780_do_resume(struct bh1780_data *ddata) { - struct bh1780_data *ddata; - int state, ret; - struct i2c_client *client = to_i2c_client(dev); + int ret = 0; - ddata = i2c_get_clientdata(client); - state = ddata->power_state; - ret = bh1780_write(ddata, BH1780_REG_CONTROL, state, - "CONTROL"); + mutex_lock(&ddata->lock); - regulator_enable(ddata->regulator); + if (ddata->power_state == BH1780_POFF) + goto unlock; + + if (ddata->regulator) + regulator_enable(ddata->regulator); + + ret = bh1780_write(ddata, BH1780_REG_CONTROL, + ddata->power_state, "CONTROL"); - ret = bh1780_write(ddata, BH1780_REG_CONTROL, ddata->power_state, - "CONTROL"); +unlock: + mutex_unlock(&ddata->lock); + return ret; +} +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) +static int bh1780_suspend(struct device *dev) +{ + struct bh1780_data *ddata = dev_get_drvdata(dev); + int ret = 0; + + ret = bh1780_do_suspend(ddata); if (ret < 0) - return ret; + dev_err(&ddata->client->dev, + "Error while suspending the device\n"); - return 0; + return ret; +} + +static int bh1780_resume(struct device *dev) +{ + struct bh1780_data *ddata = dev_get_drvdata(dev); + int ret = 0; + + ret = bh1780_do_resume(ddata); + if (ret < 0) + dev_err(&ddata->client->dev, + "Error while resuming the device\n"); + + return ret; } static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume); #define BH1780_PMOPS (&bh1780_pm) #else #define BH1780_PMOPS NULL -#endif /* CONFIG_PM */ +static void bh1780_early_suspend(struct early_suspend *data) +{ + struct bh1780_data *ddata = + container_of(data, struct bh1780_data, early_suspend); + int ret; + + ret = bh1780_do_suspend(ddata); + if (ret < 0) + dev_err(&ddata->client->dev, + "Error while suspending the device\n"); +} + +static void bh1780_late_resume(struct early_suspend *data) +{ + struct bh1780_data *ddata = + container_of(data, struct bh1780_data, early_suspend); + int ret; + + ret = bh1780_do_resume(ddata); + if (ret < 0) + dev_err(&ddata->client->dev, + "Error while resuming the device\n"); +} +#endif /*!CONFIG_HAS_EARLYSUSPEND && CONFIG_PM */ static const struct i2c_device_id bh1780_id[] = { { "bh1780", 0 }, @@ -289,7 +351,9 @@ static struct i2c_driver bh1780_driver = { .id_table = bh1780_id, .driver = { .name = "bh1780", +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) .pm = BH1780_PMOPS, +#endif }, }; -- cgit v1.2.3 From 7bc7ab720fbad4393ad7452dcb3ecc1008c3cc37 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 24 May 2011 11:46:28 +0200 Subject: misc: bh1780gli.c: Fix ifdefs ST-Ericsson Linux next: Not tested, ask SSM for ER ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie68a18f1120899167026b8b5116dd14c658d2d1d Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23701 Reviewed-by: Marcus COOPER Reviewed-by: QATEST Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28974 Tested-by: Naga RADHESH Y Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/misc/bh1780gli.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 95aee44e30f..7eb13d1085c 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -244,6 +244,7 @@ static int __devexit bh1780_remove(struct i2c_client *client) return 0; } +#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM) static int bh1780_do_suspend(struct bh1780_data *ddata) { int ret = 0; @@ -284,7 +285,10 @@ unlock: mutex_unlock(&ddata->lock); return ret; } -#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) +#endif + +#ifndef CONFIG_HAS_EARLYSUSPEND +#ifdef CONFIG_PM static int bh1780_suspend(struct device *dev) { struct bh1780_data *ddata = dev_get_drvdata(dev); @@ -313,6 +317,7 @@ static int bh1780_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume); #define BH1780_PMOPS (&bh1780_pm) +#endif /* CONFIG_PM */ #else #define BH1780_PMOPS NULL static void bh1780_early_suspend(struct early_suspend *data) @@ -338,7 +343,7 @@ static void bh1780_late_resume(struct early_suspend *data) dev_err(&ddata->client->dev, "Error while resuming the device\n"); } -#endif /*!CONFIG_HAS_EARLYSUSPEND && CONFIG_PM */ +#endif /*!CONFIG_HAS_EARLYSUSPEND */ static const struct i2c_device_id bh1780_id[] = { { "bh1780", 0 }, -- cgit v1.2.3 From 867bc5c547924edeb53376015cab859f623fcb83 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Fri, 24 Jun 2011 11:28:58 +0530 Subject: power: ab5500-charger - usb line status interrupt correction After getting usb rising edge interrupt, usb chip select should be enabled in order to get the usb line status interrupt. This sequence is done in the usb driver, in battery driver, usb charger detect was enabled. This was conflicting with the sequence followed in the usb driver and hence usb line status interrupt was not triggered. Hence reverted the usb detection enable in battery driver. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: ER349171 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iaa055cdbe59699fe0442489586fd5c7e21c1ed5b Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25822 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 61 ++++++------------------------------------ 1 file changed, 8 insertions(+), 53 deletions(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 2fd7888ad9d..736be487e14 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -37,8 +37,6 @@ /* AB5500 Charger constants */ #define AB5500_USB_LINK_STATUS 0x78 -#define USB_CHARG_DET_ENA_MASK 0x01 -#define USB_CHARG_DET_ENA 0x01 #define CHARGER_REV_SUP 0x10 #define SW_EOC 0x40 #define USB_CHAR_DET 0x02 @@ -396,12 +394,6 @@ static int ab5500_charger_read_usb_type(struct ab5500_charger *di) int ret; u8 val; - ret = abx500_get_register_interruptible(di->dev, - AB5500_BANK_IT, AB5500_IT_SOURCE22_REG, &val); - if (ret < 0) { - dev_err(di->dev, "%s ab5500 read failed\n", __func__); - return ret; - } ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_USB, AB5500_USB_LINE_STATUS, &val); if (ret < 0) { @@ -426,45 +418,17 @@ static int ab5500_charger_read_usb_type(struct ab5500_charger *di) */ static int ab5500_charger_detect_usb_type(struct ab5500_charger *di) { - int i, ret; + int ret; u8 val; - /* - * On getting the VBUS rising edge detect interrupt there - * is a 250ms delay after which the register UsbLineStatus - * is filled with valid data. - */ - for (i = 0; i < 10; i++) { - msleep(250); - ret = abx500_get_register_interruptible(di->dev, - AB5500_BANK_IT, AB5500_IT_SOURCE22_REG, - &val); - if (ret < 0) { - dev_err(di->dev, "%s ab5500 read failed\n", __func__); - return ret; - } - if (!(val & USB_LINK_UPDATE)) - continue; - - ret = abx500_get_register_interruptible(di->dev, - AB5500_BANK_USB, AB5500_USB_LINE_STATUS, &val); - if (ret < 0) { - dev_err(di->dev, "%s ab5500 read failed\n", __func__); - return ret; - } - /* - * Until the IT source register is read the UsbLineStatus - * register is not updated, hence doing the same - * Revisit this: - */ - - /* get the USB type */ - val = (val & AB5500_USB_LINK_STATUS) >> 3; - if (val) { - dev_dbg(di->dev, "values = %d\n", val); - break; - } + ret = abx500_get_register_interruptible(di->dev, + AB5500_BANK_USB, AB5500_USB_LINE_STATUS, &val); + if (ret < 0) { + dev_err(di->dev, "%s ab5500 read failed\n", __func__); + return ret; } + /* get the USB type */ + val = (val & AB5500_USB_LINK_STATUS) >> 3; ret = ab5500_charger_max_usb_curr(di, (enum ab5500_charger_link_status) val); @@ -1533,15 +1497,6 @@ static int ab5500_charger_init_hw_registers(struct ab5500_charger *di) goto out; } - /* Enable USB Charger Detection */ - ret = abx500_mask_and_set_register_interruptible(di->dev, - AB5500_BANK_USB, AB5500_USB_LINE_CTRL2, - USB_CHARG_DET_ENA_MASK, USB_CHARG_DET_ENA); - if (ret) { - dev_err(di->dev, "failed to enable usb charger detection\n"); - goto out; - } - /* Over current protection for reverse supply */ ret = abx500_mask_and_set_register_interruptible(di->dev, AB5500_BANK_CHG, AB5500_CREVS, CHARGER_REV_SUP, -- cgit v1.2.3 From ab810544e4bc75077c4438b29dc07590f1ad3d3b Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Tue, 28 Jun 2011 10:10:11 +0530 Subject: power: ab5500-fg: update battery capacity Battery capacity is updated at boot time and thereafter not updated. Battery capacity is based on the lookup table provided by the battery vendors. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: ER349552 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9cb7b01bccf2dc76e5d68c374fbb1d95120baa06 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25933 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Linus WALLEIJ --- drivers/power/ab5500_fg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 919af5faadf..95f31cb84cb 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -359,7 +359,7 @@ cc_err: */ static int ab5500_fg_inst_curr(struct ab5500_fg *di) { - u8 low, high, value; + u8 low, high; static int val; int ret = 0; bool fg_off = false; @@ -1378,9 +1378,11 @@ static int ab5500_fg_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: if (di->flags.bat_ovv) val->intval = 47500000; - else - val->intval = ab5500_gpadc_convert - (di->gpadc, MAIN_BAT_V) * 1000; + else { + di->vbat = ab5500_gpadc_convert + (di->gpadc, MAIN_BAT_V); + val->intval = di->vbat * 1000; + } break; case POWER_SUPPLY_PROP_CURRENT_NOW: di->inst_curr = ab5500_fg_inst_curr(di); -- cgit v1.2.3 From a26ba5d2293ef23625a6516b2432101de5cf1d7c Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 7 Jul 2011 11:11:34 +0530 Subject: power: ab5500-charger: update the usb presence status When usb is removed, since there are no status registers, verify the same by reading the interrupt source register and send an uevent. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: ER351099 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ife573551319e91e3651c19e40601bb850c186a14 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26703 Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 736be487e14..1eee43a5c8f 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -40,8 +40,8 @@ #define CHARGER_REV_SUP 0x10 #define SW_EOC 0x40 #define USB_CHAR_DET 0x02 -#define USB_CHAR_DET_DONE 0x02 #define VBUS_RISING 0x20 +#define VBUS_FALLING 0x40 #define USB_LINK_UPDATE 0x02 #define USB_CH_TH_PROT_LOW 0x02 #define USB_CH_TH_PROT_HIGH 0x01 @@ -285,16 +285,8 @@ static int ab5500_charger_detect_chargers(struct ab5500_charger *di) if (val & VBUS_RISING) result |= USB_PW_CONN; - - ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_IT, - AB5500_IT_SOURCE9, &val); - if (ret < 0) { - dev_err(di->dev, "%s ab5500 read failed\n", __func__); - return ret; - } - - if (val & USB_CHAR_DET_DONE) - result |= USB_PW_CONN; + else if (val & VBUS_FALLING) + result = NO_PW_CONN; return result; } -- cgit v1.2.3 From 5243b0070163a7bf388d29abc918ca6a67f3a7a6 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 7 Jul 2011 12:26:58 +0530 Subject: power: ab5500-power: usb type detection usb type can be detected based on the usb line status register. USB line status register gets updated on receiving usb line status interrupt. This usb line status interrupt is obtained after doing a chip select in usb rising edge interrupt handler and this is done by the usb driver. Now on getting usb rising edge interrupt, if the usb line status register is read, it ends up with unknown device connected. USB line status register must be read only after getting the usb line status interrupt, else will not be updated. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: ER350732 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ibca3a8e8032e23fb2b52ac45f9172269f868ae42 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26709 Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 1eee43a5c8f..69b808f06d7 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -401,32 +401,6 @@ static int ab5500_charger_read_usb_type(struct ab5500_charger *di) return ret; } -/** - * ab5500_charger_detect_usb_type() - get the type of usb connected - * @di: pointer to the ab5500_charger structure - * - * Detect the type of the plugged USB - * Returns error code in case of failure else 0 on success - */ -static int ab5500_charger_detect_usb_type(struct ab5500_charger *di) -{ - int ret; - u8 val; - - ret = abx500_get_register_interruptible(di->dev, - AB5500_BANK_USB, AB5500_USB_LINE_STATUS, &val); - if (ret < 0) { - dev_err(di->dev, "%s ab5500 read failed\n", __func__); - return ret; - } - /* get the USB type */ - val = (val & AB5500_USB_LINK_STATUS) >> 3; - ret = ab5500_charger_max_usb_curr(di, - (enum ab5500_charger_link_status) val); - - return ret; -} - static int ab5500_charger_voltage_map[] = { 3500 , 3525 , @@ -1075,13 +1049,6 @@ void ab5500_charger_detect_usb_type_work(struct work_struct *work) power_supply_changed(&di->usb_chg.psy); } else { di->vbus_detected = 1; - - ret = ab5500_charger_detect_usb_type(di); - if (!ret) { - di->usb.charger_connected = 1; - power_supply_changed(&di->usb_chg.psy); - } - } } @@ -1713,7 +1680,7 @@ static int __devinit ab5500_charger_probe(struct platform_device *pdev) di->vbus_detected = true; di->vbus_detected_start = true; queue_work(di->charger_wq, - &di->detect_usb_type_work); + &di->usb_link_status_work); } /* Register interrupts */ -- cgit v1.2.3 From e38c284c9045f938474dcd4a0585d42dc087888e Mon Sep 17 00:00:00 2001 From: Johan Palsson Date: Thu, 25 Aug 2011 12:27:06 +0530 Subject: hwmon: ab8500: Add support to monitor battery temp ST-Ericsson ID: CR339643 ST-Ericsson Linux next: ER282986 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib6ad58e7a702fe976a1d66fef0ce9d1782a1f8d2 Signed-off-by: Huan DUAN Signed-off-by: Johan Palsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25108 Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- drivers/hwmon/ab8500.c | 107 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 28 deletions(-) diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index 3167d9adf84..f90423be49e 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -38,6 +38,7 @@ #include #include #include +#include #include /* @@ -50,13 +51,17 @@ #define NUM_SENSORS 5 -/* The driver monitors GPADC - ADC_AUX1 and ADC_AUX2 */ -#define NUM_MONITORED_SENSORS 2 +/* + * The driver monitors GPADC - ADC_AUX1, ADC_AUX2, BTEMP_BALL + * and BAT_CTRL. + */ +#define NUM_MONITORED_SENSORS 4 struct ab8500_temp { struct platform_device *pdev; struct device *hwmon_dev; struct ab8500_gpadc *gpadc; + struct ab8500_btemp *btemp; u8 gpadc_addr[NUM_SENSORS]; unsigned long min[NUM_SENSORS]; unsigned long max[NUM_SENSORS]; @@ -131,10 +136,21 @@ static void gpadc_monitor(struct work_struct *work) && data->min[i] == 0) continue; - val = ab8500_gpadc_convert(data->gpadc, data->gpadc_addr[i]); - if (val < 0) { - dev_err(&data->pdev->dev, "GPADC read failed\n"); - continue; + /* + * Special treatment for the BAT_CTRL node, since this + * temperature measurement is more complex than just + * an ADC readout + */ + if (data->gpadc_addr[i] == BAT_CTRL) { + val = ab8500_btemp_get_batctrl_temp(data->btemp); + } else { + val = ab8500_gpadc_convert(data->gpadc, + data->gpadc_addr[i]); + if (val < 0) { + dev_err(&data->pdev->dev, + "GPADC read failed\n"); + continue; + } } mutex_lock(&data->lock); @@ -322,11 +338,11 @@ static ssize_t show_label(struct device *dev, name = "bat_temp"; break; case 4: - name = "ab8500"; - break; - case 5: name = "bat_ctrl"; break; + case 5: + name = "ab8500"; + break; default: return -EINVAL; } @@ -342,9 +358,18 @@ static ssize_t show_input(struct device *dev, /* hwmon attr index starts at 1, thus "attr->index-1" below */ u8 gpadc_addr = data->gpadc_addr[attr->index - 1]; - val = ab8500_gpadc_convert(data->gpadc, gpadc_addr); - if (val < 0) - dev_err(&data->pdev->dev, "GPADC read failed\n"); + /* + * Special treatment for the BAT_CTRL node, since this + * temperature measurement is more complex than just + * an ADC readout + */ + if (gpadc_addr == BAT_CTRL) { + val = ab8500_btemp_get_batctrl_temp(data->btemp); + } else { + val = ab8500_gpadc_convert(data->gpadc, gpadc_addr); + if (val < 0) + dev_err(&data->pdev->dev, "GPADC read failed\n"); + } return sprintf(buf, "%d\n", val); } @@ -546,15 +571,31 @@ static SENSOR_DEVICE_ATTR(temp2_max_hyst_alarm, S_IRUGO, /* GPADC - BTEMP_BALL */ static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 3); static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, 3); +static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, 3); +static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 3); +static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_min_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_max_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 3); -/* AB8500 */ +/* GPADC - BAT_CTRL */ static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, - show_crit_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_input, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_min, set_min, 4); +static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_max, set_max, 4); +static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 4); +static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 4); -/* GPADC - BAT_CTRL */ +/* AB8500 */ static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, + show_crit_alarm, NULL, 5); static struct attribute *ab8500_temp_attributes[] = { &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, @@ -581,12 +622,24 @@ static struct attribute *ab8500_temp_attributes[] = { /* GPADC - BTEMP_BALL */ &sensor_dev_attr_temp3_label.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, - /* AB8500 */ - &sensor_dev_attr_temp4_label.dev_attr.attr, - &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst_alarm.dev_attr.attr, /* GPADC - BAT_CTRL */ + &sensor_dev_attr_temp4_label.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_max_hyst_alarm.dev_attr.attr, + /* AB8500 */ &sensor_dev_attr_temp5_label.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, NULL }; @@ -605,9 +658,9 @@ static irqreturn_t ab8500_temp_irq_handler(int irq, void *irq_data) * used for AB8500 thermal warning from HW. */ mutex_lock(&data->lock); - data->crit_alarm[3] = 1; + data->crit_alarm[4] = 1; mutex_unlock(&data->lock); - sysfs_notify(&pdev->dev.kobj, NULL, "temp4_crit_alarm"); + sysfs_notify(&pdev->dev.kobj, NULL, "temp5_crit_alarm"); dev_info(&pdev->dev, "AB8500 thermal warning, power off in %lu s\n", data->power_off_delay); delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); @@ -645,6 +698,7 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) goto exit; data->gpadc = ab8500_gpadc_get(); + data->btemp = ab8500_btemp_get(); data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { @@ -665,21 +719,18 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) * GPADC - ADC_AUX2, connected to NTC R2150 near DB8500 on HREF * Hence, temp#_min/max/max_hyst refer to millivolts and not * millidegrees + * This is not the case for BAT_CTRL where millidegrees is used * * HREF HW does not support reading AB8500 temperature. BUT an * AB8500 IRQ will be launched if die crit temp limit is reached. * - * Also: - * Battery temperature (BatTemp and BatCtrl) thresholds will - * not be exposed via hwmon. - * * Make sure indexes correspond to the attribute indexes * used when calling SENSOR_DEVICE_ATRR */ data->gpadc_addr[0] = ADC_AUX1; data->gpadc_addr[1] = ADC_AUX2; data->gpadc_addr[2] = BTEMP_BALL; - data->gpadc_addr[4] = BAT_CTRL; + data->gpadc_addr[3] = BAT_CTRL; mutex_init(&data->lock); data->pdev = pdev; data->power_off_delay = DEFAULT_POWER_OFF_DELAY; -- cgit v1.2.3 From 388022b6b95cba8732eec6d2f622919d9769a33a Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 25 Aug 2011 13:20:04 +0530 Subject: abx500: hwmon: generalize AB8500 temperature monitor driver Generalize ab8500 hwmon driver to support other abx500 variants. Source code is split into generic and variant specific files. ST-Ericsson Linux next: NA ST-Ericsson ID: WP257616 ST-Ericsson FOSS-OUT ID: NA Change-Id: Ia39feaac455160149d49a5982374da3729ea5301 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28138 Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/Makefile | 2 +- drivers/hwmon/ab8500.c | 714 +++------------------------------------------- drivers/hwmon/abx500.c | 667 +++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/abx500.h | 84 ++++++ drivers/mfd/ab8500-core.c | 4 +- 6 files changed, 801 insertions(+), 672 deletions(-) create mode 100644 drivers/hwmon/abx500.c create mode 100644 drivers/hwmon/abx500.h diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 95a4a2f878b..0d0f033852d 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -41,7 +41,7 @@ comment "Native drivers" config SENSORS_AB8500 tristate "AB8500 thermal monitoring" - depends on AB8500_CORE + depends on AB8500_GPADC default n help If you say yes here you get support for the thermal sensor part diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6d6bf2564e6..1a2412487a6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_SENSORS_W83795) += w83795.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o -obj-$(CONFIG_SENSORS_AB8500) += ab8500.o +obj-$(CONFIG_SENSORS_AB8500) += abx500.o ab8500.o obj-$(CONFIG_SENSORS_DB8500) += db8500.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index f90423be49e..45a8ef675b3 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -6,16 +6,6 @@ * * Note: * - * AB8500 does not provide auto ADC, so to monitor the required - * temperatures, a periodic work is used. It is more important - * to not wake up the CPU than to perform this job, hence the use - * of a deferred delay. - * - * A deferred delay for thermal monitor is considered safe because: - * If the chip gets too hot during a sleep state it's most likely - * due to external factors, such as the surrounding temperature. - * I.e. no SW decisions will make any difference. - * * If/when the AB8500 thermal warning temperature is reached (threshold * cannot be changed by SW), an interrupt is set and the driver * notifies user space via a sysfs event. If a shut down is not @@ -26,30 +16,17 @@ * shutdown of the AB8500 will occur. */ -#include #include +#include #include #include #include -#include #include -#include -#include -#include -#include #include #include -#include +#include "abx500.h" -/* - * If AB8500 warm interrupt is set, user space will be notified. - * If user space doesn't shut down the platform within this time - * frame, this driver will. Time unit is ms. - */ #define DEFAULT_POWER_OFF_DELAY 10000 -#define DEFAULT_MONITOR_DELAY 1000 - -#define NUM_SENSORS 5 /* * The driver monitors GPADC - ADC_AUX1, ADC_AUX2, BTEMP_BALL @@ -57,265 +34,46 @@ */ #define NUM_MONITORED_SENSORS 4 -struct ab8500_temp { - struct platform_device *pdev; - struct device *hwmon_dev; - struct ab8500_gpadc *gpadc; - struct ab8500_btemp *btemp; - u8 gpadc_addr[NUM_SENSORS]; - unsigned long min[NUM_SENSORS]; - unsigned long max[NUM_SENSORS]; - unsigned long max_hyst[NUM_SENSORS]; - unsigned long crit[NUM_SENSORS]; - unsigned long min_alarm[NUM_SENSORS]; - unsigned long max_alarm[NUM_SENSORS]; - unsigned long max_hyst_alarm[NUM_SENSORS]; - unsigned long crit_alarm[NUM_SENSORS]; - struct delayed_work work; - struct delayed_work power_off_work; - struct mutex lock; - /* Delay (ms) between temperature readings */ - unsigned long gpadc_monitor_delay; - /* Delay (ms) before power off */ - unsigned long power_off_delay; -}; - -/* - * Thresholds are considered inactive if set to 0. - * To avoid confusion for user space applications, - * the temp monitor delay is set to 0 if all thresholds - * are 0. - */ -static bool find_active_thresholds(struct ab8500_temp *data) +static int ab8500_read_sensor(struct abx500_temp *data, u8 sensor) { - int i; - for (i = 0; i < NUM_MONITORED_SENSORS; i++) - if (data->max[i] != 0 || data->max_hyst[i] != 0 - || data->min[i] != 0) - return true; - - dev_dbg(&data->pdev->dev, "No active thresholds," - "cancel deferred job (if it exists)" - "and reset temp monitor delay\n"); - cancel_delayed_work_sync(&data->work); - return false; -} - + int val; + /* + * Special treatment for the BAT_CTRL node, since this + * temperature measurement is more complex than just + * an ADC readout + * + * DIE_TEMP input temperature reading is not supported + * in AB8500 + */ + if (sensor == DIE_TEMP) + val = 0; + else if (sensor == BAT_CTRL) + val = ab8500_btemp_get_batctrl_temp(data->ab8500_btemp); + else + val = ab8500_gpadc_convert(data->ab8500_gpadc, sensor); -static inline void schedule_monitor(struct ab8500_temp *data) { - unsigned long delay_in_jiffies; - delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); - schedule_delayed_work(&data->work, delay_in_jiffies); + return val; } -static void thermal_power_off(struct work_struct *work) +static void ab8500_thermal_power_off(struct work_struct *work) { - struct ab8500_temp *data = container_of(work, struct ab8500_temp, + struct abx500_temp *data = container_of(work, struct abx500_temp, power_off_work.work); dev_warn(&data->pdev->dev, "Power off due to AB8500 thermal warning\n"); pm_power_off(); } -static void gpadc_monitor(struct work_struct *work) -{ - unsigned long delay_in_jiffies; - int val, i, ret; - /* Container for alarm node name */ - char alarm_node[30]; - - bool updated_min_alarm = false; - bool updated_max_alarm = false; - bool updated_max_hyst_alarm = false; - struct ab8500_temp *data = container_of(work, struct ab8500_temp, - work.work); - - for (i = 0; i < NUM_MONITORED_SENSORS; i++) { - /* Thresholds are considered inactive if set to 0 */ - if (data->max[i] == 0 && data->max_hyst[i] == 0 - && data->min[i] == 0) - continue; - - /* - * Special treatment for the BAT_CTRL node, since this - * temperature measurement is more complex than just - * an ADC readout - */ - if (data->gpadc_addr[i] == BAT_CTRL) { - val = ab8500_btemp_get_batctrl_temp(data->btemp); - } else { - val = ab8500_gpadc_convert(data->gpadc, - data->gpadc_addr[i]); - if (val < 0) { - dev_err(&data->pdev->dev, - "GPADC read failed\n"); - continue; - } - } - - mutex_lock(&data->lock); - if (data->min[i] != 0) { - if (val < data->min[i]) { - if (data->min_alarm[i] == 0) { - data->min_alarm[i] = 1; - updated_min_alarm = true; - } - } else { - if (data->min_alarm[i] == 1) { - data->min_alarm[i] = 0; - updated_min_alarm = true; - } - } - - } - if (data->max[i] != 0) { - if (val > data->max[i]) { - if (data->max_alarm[i] == 0) { - data->max_alarm[i] = 1; - updated_max_alarm = true; - } - } else { - if (data->max_alarm[i] == 1) { - data->max_alarm[i] = 0; - updated_max_alarm = true; - } - } - - } - if (data->max_hyst[i] != 0) { - if (val > data->max_hyst[i]) { - if (data->max_hyst_alarm[i] == 0) { - data->max_hyst_alarm[i] = 1; - updated_max_hyst_alarm = true; - } - } else { - if (data->max_hyst_alarm[i] == 1) { - data->max_hyst_alarm[i] = 0; - updated_max_hyst_alarm = true; - } - } - } - mutex_unlock(&data->lock); - - /* hwmon attr index starts at 1, thus "i+1" below */ - if (updated_min_alarm) { - ret = snprintf(alarm_node, 16, "temp%d_min_alarm", - (i + 1)); - if (ret < 0) { - dev_err(&data->pdev->dev, - "Unable to update alarm node (%d)", - ret); - break; - } - sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); - } - if (updated_max_alarm) { - ret = snprintf(alarm_node, 16, "temp%d_max_alarm", - (i + 1)); - if (ret < 0) { - dev_err(&data->pdev->dev, - "Unable to update alarm node (%d)", - ret); - break; - } - sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); - } - if (updated_max_hyst_alarm) { - ret = snprintf(alarm_node, 21, "temp%d_max_hyst_alarm", - (i + 1)); - if (ret < 0) { - dev_err(&data->pdev->dev, - "Unable to update alarm node (%d)", - ret); - break; - } - sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); - } - } - delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); - schedule_delayed_work(&data->work, delay_in_jiffies); -} - -static inline void gpadc_monitor_exit(struct platform_device *pdev) -{ - struct ab8500_temp *data = platform_get_drvdata(pdev); - cancel_delayed_work_sync(&data->work); -} - -static ssize_t set_temp_monitor_delay(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int res; - unsigned long delay_in_s; - struct ab8500_temp *data = dev_get_drvdata(dev); - - res = strict_strtoul(buf, 10, &delay_in_s); - if (res < 0) - return res; - - mutex_lock(&data->lock); - data->gpadc_monitor_delay = delay_in_s * 1000; - - if (find_active_thresholds(data)) { - schedule_monitor(data); - } - - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t set_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int res; - unsigned long delay_in_s; - struct ab8500_temp *data = dev_get_drvdata(dev); - - res = strict_strtoul(buf, 10, &delay_in_s); - if (res < 0) - return res; - - mutex_lock(&data->lock); - data->power_off_delay = delay_in_s * 1000; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_monitor_delay(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - /* return time in s, not ms */ - return sprintf(buf, "%lu\n", (data->gpadc_monitor_delay) / 1000); -} - -static ssize_t show_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - char *buf) +static ssize_t ab8500_show_name(struct device *dev, + struct device_attribute *devattr, + char *buf) { - struct ab8500_temp *data = dev_get_drvdata(dev); - /* return time in s, not ms */ - return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); -} - -/* HWMON sysfs interface */ -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - /* - * To avoid confusion between sensor label and chip name, the function - * "show_label" is not used to return the chip name. - */ return sprintf(buf, "ab8500\n"); } -static ssize_t show_label(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t ab8500_show_label(struct device *dev, + struct device_attribute *devattr, + char *buf) { char *name; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -349,310 +107,9 @@ static ssize_t show_label(struct device *dev, return sprintf(buf, "%s\n", name); } -static ssize_t show_input(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int val; - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - u8 gpadc_addr = data->gpadc_addr[attr->index - 1]; - - /* - * Special treatment for the BAT_CTRL node, since this - * temperature measurement is more complex than just - * an ADC readout - */ - if (gpadc_addr == BAT_CTRL) { - val = ab8500_btemp_get_batctrl_temp(data->btemp); - } else { - val = ab8500_gpadc_convert(data->gpadc, gpadc_addr); - if (val < 0) - dev_err(&data->pdev->dev, "GPADC read failed\n"); - } - - return sprintf(buf, "%d\n", val); -} - -/* set functions (RW nodes) */ -static ssize_t set_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - /* - * Threshold is considered inactive if set to 0 - * hwmon attr index starts at 1, thus "attr->index-1" below - */ - if (val == 0) - data->min_alarm[attr->index - 1] = 0; - - data->min[attr->index - 1] = val; - - if (val == 0) - (void) find_active_thresholds(data); - else - schedule_monitor(data); - - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t set_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - /* - * Threshold is considered inactive if set to 0 - * hwmon attr index starts at 1, thus "attr->index-1" below - */ - if (val == 0) - data->max_alarm[attr->index - 1] = 0; - - data->max[attr->index - 1] = val; - - if (val == 0) - (void) find_active_thresholds(data); - else - schedule_monitor(data); - - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t set_max_hyst(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - /* - * Threshold is considered inactive if set to 0 - * hwmon attr index starts at 1, thus "attr->index-1" below - */ - if (val == 0) - data->max_hyst_alarm[attr->index - 1] = 0; - - data->max_hyst[attr->index - 1] = val; - - if (val == 0) - (void) find_active_thresholds(data); - else - schedule_monitor(data); - - mutex_unlock(&data->lock); - - return count; -} - -/* - * show functions (RO nodes) - * Notice that min/max/max_hyst refer to millivolts and not millidegrees - */ -static ssize_t show_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->min[attr->index - 1]); -} - -static ssize_t show_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->max[attr->index - 1]); -} - -static ssize_t show_max_hyst(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->max_hyst[attr->index - 1]); -} - -/* Alarms */ -static ssize_t show_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->min_alarm[attr->index - 1]); -} - -static ssize_t show_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->max_alarm[attr->index - 1]); -} - -static ssize_t show_max_hyst_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->max_hyst_alarm[attr->index - 1]); -} - -static ssize_t show_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct ab8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%ld\n", data->crit_alarm[attr->index - 1]); -} - -/*These node are not included in the kernel hwmon sysfs interface */ -static SENSOR_DEVICE_ATTR(temp_monitor_delay, S_IRUGO | S_IWUSR, - show_temp_monitor_delay, set_temp_monitor_delay, 0); -static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, - show_temp_power_off_delay, - set_temp_power_off_delay, 0); - -/* Chip name, required by hwmon*/ -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -/* GPADC - ADC_AUX1 */ -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, - show_max_hyst, set_max_hyst, 1); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst_alarm, S_IRUGO, - show_max_hyst_alarm, NULL, 1); - -/* GPADC - ADC_AUX2 */ -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, 2); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, 2); -static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IWUSR | S_IRUGO, - show_max_hyst, set_max_hyst, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_min_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_max_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_max_hyst_alarm, S_IRUGO, - show_max_hyst_alarm, NULL, 2); - -/* GPADC - BTEMP_BALL */ -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, 3); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, 3); -static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IWUSR | S_IRUGO, - show_max_hyst, set_max_hyst, 3); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_min_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_max_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_max_hyst_alarm, S_IRUGO, - show_max_hyst_alarm, NULL, 3); - -/* GPADC - BAT_CTRL */ -static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_input, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_min, set_min, 4); -static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_max, set_max, 4); -static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO, - show_max_hyst, set_max_hyst, 4); -static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO, - show_max_hyst_alarm, NULL, 4); - -/* AB8500 */ -static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); -static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, - show_crit_alarm, NULL, 5); - -static struct attribute *ab8500_temp_attributes[] = { - &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, - &sensor_dev_attr_temp_monitor_delay.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, - /* GPADC - ADC_AUX1 */ - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst_alarm.dev_attr.attr, - /* GPADC - ADC_AUX2 */ - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst_alarm.dev_attr.attr, - /* GPADC - BTEMP_BALL */ - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst_alarm.dev_attr.attr, - /* GPADC - BAT_CTRL */ - &sensor_dev_attr_temp4_label.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_max_hyst_alarm.dev_attr.attr, - /* AB8500 */ - &sensor_dev_attr_temp5_label.dev_attr.attr, - &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group ab8500_temp_group = { - .attrs = ab8500_temp_attributes, -}; - -static irqreturn_t ab8500_temp_irq_handler(int irq, void *irq_data) +static int ab8500_temp_irq_handler(int irq, struct abx500_temp *data) { unsigned long delay_in_jiffies; - struct platform_device *pdev = irq_data; - struct ab8500_temp *data = platform_get_drvdata(pdev); - /* * Make sure the magic numbers below corresponds to the node * used for AB8500 thermal warning from HW. @@ -660,55 +117,25 @@ static irqreturn_t ab8500_temp_irq_handler(int irq, void *irq_data) mutex_lock(&data->lock); data->crit_alarm[4] = 1; mutex_unlock(&data->lock); - sysfs_notify(&pdev->dev.kobj, NULL, "temp5_crit_alarm"); - dev_info(&pdev->dev, "AB8500 thermal warning, power off in %lu s\n", - data->power_off_delay); + sysfs_notify(&data->pdev->dev.kobj, NULL, "temp5_crit_alarm"); + dev_info(&data->pdev->dev, "AB8500 thermal warning," + " power off in %lu s\n", data->power_off_delay); delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); schedule_delayed_work(&data->power_off_work, delay_in_jiffies); - return IRQ_HANDLED; -} - -static int setup_irqs(struct platform_device *pdev) -{ - int ret; - int irq = platform_get_irq_byname(pdev, "AB8500_TEMP_WARM"); - - if (irq < 0) - dev_err(&pdev->dev, "Get irq by name failed\n"); - - ret = request_threaded_irq(irq, NULL, ab8500_temp_irq_handler, - IRQF_NO_SUSPEND, "ab8500-temp", pdev); - if (ret < 0) - dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); - - return ret; + return 0; } -static int __devinit ab8500_temp_probe(struct platform_device *pdev) +int __init abx500_hwmon_init(struct abx500_temp *data) { - struct ab8500_temp *data; - int err; - - data = kzalloc(sizeof(struct ab8500_temp), GFP_KERNEL); - if (!data) - return -ENOMEM; + data->ab8500_gpadc = ab8500_gpadc_get(); + if (IS_ERR(data->ab8500_gpadc)) + return PTR_ERR(data->ab8500_gpadc); - err = setup_irqs(pdev); - if (err < 0) - goto exit; - - data->gpadc = ab8500_gpadc_get(); - data->btemp = ab8500_btemp_get(); - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", err); - goto exit; - } + data->ab8500_btemp = ab8500_btemp_get(); + if (IS_ERR(data->ab8500_btemp)) + return PTR_ERR(data->ab8500_btemp); - INIT_DELAYED_WORK_DEFERRABLE(&data->work, gpadc_monitor); - INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); + INIT_DELAYED_WORK(&data->power_off_work, ab8500_thermal_power_off); /* * Setup HW defined data. @@ -731,63 +158,14 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev) data->gpadc_addr[1] = ADC_AUX2; data->gpadc_addr[2] = BTEMP_BALL; data->gpadc_addr[3] = BAT_CTRL; - mutex_init(&data->lock); - data->pdev = pdev; + data->gpadc_addr[4] = DIE_TEMP; data->power_off_delay = DEFAULT_POWER_OFF_DELAY; - data->gpadc_monitor_delay = DEFAULT_MONITOR_DELAY; + data->monitored_sensors = NUM_MONITORED_SENSORS; - platform_set_drvdata(pdev, data); - - err = sysfs_create_group(&pdev->dev.kobj, &ab8500_temp_group); - if (err < 0) { - dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); - goto exit_platform_data; - } + data->ops.read_sensor = ab8500_read_sensor; + data->ops.irq_handler = ab8500_temp_irq_handler; + data->ops.show_name = ab8500_show_name; + data->ops.show_label = ab8500_show_label; return 0; - -exit_platform_data: - platform_set_drvdata(pdev, NULL); -exit: - kfree(data); - return err; } - -static int __devexit ab8500_temp_remove(struct platform_device *pdev) -{ - struct ab8500_temp *data = platform_get_drvdata(pdev); - - gpadc_monitor_exit(pdev); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &ab8500_temp_group); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; -} - -/* No action required in suspend/resume, thus the lack of functions */ -static struct platform_driver ab8500_temp_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "ab8500-temp", - }, - .probe = ab8500_temp_probe, - .remove = __devexit_p(ab8500_temp_remove), -}; - -static int __init ab8500_temp_init(void) -{ - return platform_driver_register(&ab8500_temp_driver); -} - -static void __exit ab8500_temp_exit(void) -{ - platform_driver_unregister(&ab8500_temp_driver); -} - -MODULE_AUTHOR("Martin Persson "); -MODULE_DESCRIPTION("AB8500 temperature driver"); -MODULE_LICENSE("GPL"); - -module_init(ab8500_temp_init) -module_exit(ab8500_temp_exit) diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c new file mode 100644 index 00000000000..9d522ef6f62 --- /dev/null +++ b/drivers/hwmon/abx500.c @@ -0,0 +1,667 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Martin Persson for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + * Note: + * + * ABX500 does not provide auto ADC, so to monitor the required + * temperatures, a periodic work is used. It is more important + * to not wake up the CPU than to perform this job, hence the use + * of a deferred delay. + * + * A deferred delay for thermal monitor is considered safe because: + * If the chip gets too hot during a sleep state it's most likely + * due to external factors, such as the surrounding temperature. + * I.e. no SW decisions will make any difference. + * + * If/when the ABX500 thermal warning temperature is reached (threshold + * cannot be changed by SW), an interrupt is set and the driver + * notifies user space via a sysfs event. + * + * If/when ABX500 thermal shutdown temperature is reached a hardware + * shutdown of the ABX500 will occur. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "abx500.h" + +#define DEFAULT_MONITOR_DELAY 1000 + +/* + * Thresholds are considered inactive if set to 0. + * To avoid confusion for user space applications, + * the temp monitor delay is set to 0 if all thresholds + * are 0. + */ +static bool find_active_thresholds(struct abx500_temp *data) +{ + int i; + for (i = 0; i < data->monitored_sensors; i++) + if (data->max[i] != 0 || data->max_hyst[i] != 0 + || data->min[i] != 0) + return true; + + dev_dbg(&data->pdev->dev, "No active thresholds," + "cancel deferred job (if it exists)" + "and reset temp monitor delay\n"); + cancel_delayed_work_sync(&data->work); + return false; +} + +static inline void schedule_monitor(struct abx500_temp *data) +{ + unsigned long delay_in_jiffies; + delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); + schedule_delayed_work(&data->work, delay_in_jiffies); +} + +static inline void gpadc_monitor_exit(struct abx500_temp *data) +{ + cancel_delayed_work_sync(&data->work); +} + +static void gpadc_monitor(struct work_struct *work) +{ + unsigned long delay_in_jiffies; + int val, i, ret; + /* Container for alarm node name */ + char alarm_node[30]; + + bool updated_min_alarm = false; + bool updated_max_alarm = false; + bool updated_max_hyst_alarm = false; + struct abx500_temp *data = container_of(work, struct abx500_temp, + work.work); + + for (i = 0; i < data->monitored_sensors; i++) { + /* Thresholds are considered inactive if set to 0 */ + if (data->max[i] == 0 && data->max_hyst[i] == 0 + && data->min[i] == 0) + continue; + + val = data->ops.read_sensor(data, data->gpadc_addr[i]); + if (val < 0) { + dev_err(&data->pdev->dev, "GPADC read failed\n"); + continue; + } + + mutex_lock(&data->lock); + if (data->min[i] != 0) { + if (val < data->min[i]) { + if (data->min_alarm[i] == 0) { + data->min_alarm[i] = 1; + updated_min_alarm = true; + } + } else { + if (data->min_alarm[i] == 1) { + data->min_alarm[i] = 0; + updated_min_alarm = true; + } + } + + } + if (data->max[i] != 0) { + if (val > data->max[i]) { + if (data->max_alarm[i] == 0) { + data->max_alarm[i] = 1; + updated_max_alarm = true; + } + } else { + if (data->max_alarm[i] == 1) { + data->max_alarm[i] = 0; + updated_max_alarm = true; + } + } + + } + if (data->max_hyst[i] != 0) { + if (val > data->max_hyst[i]) { + if (data->max_hyst_alarm[i] == 0) { + data->max_hyst_alarm[i] = 1; + updated_max_hyst_alarm = true; + } + } else { + if (data->max_hyst_alarm[i] == 1) { + data->max_hyst_alarm[i] = 0; + updated_max_hyst_alarm = true; + } + } + } + mutex_unlock(&data->lock); + + /* hwmon attr index starts at 1, thus "i+1" below */ + if (updated_min_alarm) { + ret = snprintf(alarm_node, 16, "temp%d_min_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + if (updated_max_alarm) { + ret = snprintf(alarm_node, 16, "temp%d_max_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + if (updated_max_hyst_alarm) { + ret = snprintf(alarm_node, 21, "temp%d_max_hyst_alarm", + (i + 1)); + if (ret < 0) { + dev_err(&data->pdev->dev, + "Unable to update alarm node (%d)", + ret); + break; + } + sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); + } + } + delay_in_jiffies = msecs_to_jiffies(data->gpadc_monitor_delay); + schedule_delayed_work(&data->work, delay_in_jiffies); +} + +static ssize_t set_temp_monitor_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_s; + struct abx500_temp *data = dev_get_drvdata(dev); + + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->gpadc_monitor_delay = delay_in_s * 1000; + + if (find_active_thresholds(data)) + schedule_monitor(data); + + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_s; + struct abx500_temp *data = dev_get_drvdata(dev); + + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->power_off_delay = delay_in_s * 1000; + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp_monitor_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->gpadc_monitor_delay) / 1000); +} + +static ssize_t show_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); +} + +/* HWMON sysfs interface */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + /* + * To avoid confusion between sensor label and chip name, the function + * "show_label" is not used to return the chip name. + */ + struct abx500_temp *data = dev_get_drvdata(dev); + return data->ops.show_name(dev, devattr, buf); +} + +static ssize_t show_label(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + return data->ops.show_label(dev, devattr, buf); +} + +static ssize_t show_input(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int val; + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + u8 gpadc_addr = data->gpadc_addr[attr->index - 1]; + + val = data->ops.read_sensor(data, gpadc_addr); + if (val < 0) + dev_err(&data->pdev->dev, "GPADC read failed\n"); + + return sprintf(buf, "%d\n", val); +} + +/* set functions (RW nodes) */ +static ssize_t set_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->min_alarm[attr->index - 1] = 0; + + data->min[attr->index - 1] = val; + + if (val == 0) + (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->max_alarm[attr->index - 1] = 0; + + data->max[attr->index - 1] = val; + + if (val == 0) + (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_max_hyst(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + /* + * Threshold is considered inactive if set to 0 + * hwmon attr index starts at 1, thus "attr->index-1" below + */ + if (val == 0) + data->max_hyst_alarm[attr->index - 1] = 0; + + data->max_hyst[attr->index - 1] = val; + + if (val == 0) + (void) find_active_thresholds(data); + else + schedule_monitor(data); + + mutex_unlock(&data->lock); + + return count; +} + +/* + * show functions (RO nodes) + */ +static ssize_t show_min(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->min[attr->index - 1]); +} + +static ssize_t show_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max[attr->index - 1]); +} + +static ssize_t show_max_hyst(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_hyst[attr->index - 1]); +} + +/* Alarms */ +static ssize_t show_min_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->min_alarm[attr->index - 1]); +} + +static ssize_t show_max_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_alarm[attr->index - 1]); +} + +static ssize_t show_max_hyst_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->max_hyst_alarm[attr->index - 1]); +} + +static ssize_t show_crit_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct abx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%ld\n", data->crit_alarm[attr->index - 1]); +} + +static SENSOR_DEVICE_ATTR(temp_monitor_delay, S_IRUGO | S_IWUSR, + show_temp_monitor_delay, set_temp_monitor_delay, 0); +static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, + show_temp_power_off_delay, + set_temp_power_off_delay, 0); + +/* Chip name, required by hwmon*/ +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +/* GPADC - SENSOR1 */ +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 1); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 1); + +/* GPADC - SENSOR2 */ +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, 2); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, 2); +static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 2); +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_min_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_max_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 2); + +/* GPADC - SENSOR3 */ +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, 3); +static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, 3); +static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 3); +static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_min_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_max_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 3); + +/* GPADC - SENSOR4 */ +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_input, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_min, set_min, 4); +static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_max, set_max, 4); +static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 4); +static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 4); + +/* GPADC - SENSOR4 */ +static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, + show_crit_alarm, NULL, 5); + +struct attribute *abx500_temp_attributes[] = { + &sensor_dev_attr_name.dev_attr.attr, + &sensor_dev_attr_temp_monitor_delay.dev_attr.attr, + &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, + /* GPADC SENSOR1 */ + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst_alarm.dev_attr.attr, + /* GPADC SENSOR2 */ + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst_alarm.dev_attr.attr, + /* GPADC SENSOR3 */ + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst_alarm.dev_attr.attr, + /* GPADC SENSOR4 */ + &sensor_dev_attr_temp4_label.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_max_hyst_alarm.dev_attr.attr, + /* GPADC SENSOR5*/ + &sensor_dev_attr_temp5_label.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group abx500_temp_group = { + .attrs = abx500_temp_attributes, +}; + +static irqreturn_t abx500_temp_irq_handler(int irq, void *irq_data) +{ + struct platform_device *pdev = irq_data; + struct abx500_temp *data = platform_get_drvdata(pdev); + data->ops.irq_handler(irq, data); + return IRQ_HANDLED; +} + +static int setup_irqs(struct platform_device *pdev) +{ + int ret; + int irq = platform_get_irq_byname(pdev, "ABX500_TEMP_WARM"); + + if (irq < 0) + dev_err(&pdev->dev, "Get irq by name failed\n"); + + ret = request_threaded_irq(irq, NULL, abx500_temp_irq_handler, + IRQF_NO_SUSPEND, "abx500-temp", pdev); + if (ret < 0) + dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); + + return ret; +} + +static int __devinit abx500_temp_probe(struct platform_device *pdev) +{ + struct abx500_temp *data; + int err; + + data = kzalloc(sizeof(struct abx500_temp), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->pdev = pdev; + mutex_init(&data->lock); + + /* Chip specific initialization */ + err = abx500_hwmon_init(data); + if (err < 0) { + dev_err(&pdev->dev, "abx500 init failed"); + goto exit; + } + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + dev_err(&pdev->dev, "Class registration failed (%d)\n", err); + goto exit; + } + + INIT_DELAYED_WORK_DEFERRABLE(&data->work, gpadc_monitor); + data->gpadc_monitor_delay = DEFAULT_MONITOR_DELAY; + + platform_set_drvdata(pdev, data); + + err = sysfs_create_group(&pdev->dev.kobj, &abx500_temp_group); + if (err < 0) { + dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); + goto exit_platform_data; + } + + err = setup_irqs(pdev); + if (err < 0) { + dev_err(&pdev->dev, "irq setup failed (%d)\n", err); + goto exit_sysfs_group; + } + return 0; + +exit_sysfs_group: + sysfs_remove_group(&pdev->dev.kobj, &abx500_temp_group); +exit_platform_data: + hwmon_device_unregister(data->hwmon_dev); + platform_set_drvdata(pdev, NULL); +exit: + kfree(data); + return err; +} + +static int __devexit abx500_temp_remove(struct platform_device *pdev) +{ + struct abx500_temp *data = platform_get_drvdata(pdev); + + gpadc_monitor_exit(data); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &abx500_temp_group); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +/* No action required in suspend/resume, thus the lack of functions */ +static struct platform_driver abx500_temp_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "abx500-temp", + }, + .probe = abx500_temp_probe, + .remove = __devexit_p(abx500_temp_remove), +}; + +static int __init abx500_temp_init(void) +{ + return platform_driver_register(&abx500_temp_driver); +} + +static void __exit abx500_temp_exit(void) +{ + platform_driver_unregister(&abx500_temp_driver); +} + +MODULE_AUTHOR("Martin Persson "); +MODULE_DESCRIPTION("ABX500 temperature driver"); +MODULE_LICENSE("GPL"); + +module_init(abx500_temp_init) +module_exit(abx500_temp_exit) diff --git a/drivers/hwmon/abx500.h b/drivers/hwmon/abx500.h new file mode 100644 index 00000000000..a089a63939d --- /dev/null +++ b/drivers/hwmon/abx500.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * License terms: GNU General Public License v2 + * Author: Martin Persson + */ + +#ifndef _ABX500_H +#define _ABX500_H + +#define NUM_SENSORS 5 + +struct ab8500_gpadc; +struct ab8500_btemp; +struct abx500_temp; + +/** + * struct abx500_temp_ops - abx500 chip specific ops + * @read_sensor: reads gpadc output + * @irq_handler: irq handler + * @show_name: hwmon device name + * @show_label: hwmon attribute label + */ +struct abx500_temp_ops { + int (*read_sensor)(struct abx500_temp *, u8); + int (*irq_handler)(int, struct abx500_temp *); + ssize_t (*show_name)(struct device *, + struct device_attribute *, char *); + ssize_t (*show_label) (struct device *, + struct device_attribute *, char *); +}; + +/** + * struct abx500_temp - representation of temp mon device + * @pdev: platform device + * @hwmon_dev: hwmon device + * @ab8500_gpadc: gpadc interface for ab8500 + * @btemp: battery temperature interface for ab8500 + * @gpadc_addr: gpadc channel address + * @temp: sensor temperature input value + * @min: sensor temperature min value + * @max: sensor temperature max value + * @max_hyst: sensor temperature hysteresis value for max limit + * @crit: sensor temperature critical value + * @min_alarm: sensor temperature min alarm + * @max_alarm: sensor temperature max alarm + * @max_hyst_alarm: sensor temperature hysteresis alarm + * @crit_alarm: sensor temperature critical value alarm + * @work: delayed work scheduled to monitor temperature periodically + * @power_off_work: delayed work scheduled to power off the system + when critical temperature is reached + * @lock: mutex + * @gpadc_monitor_delay: delay between temperature readings in ms + * @power_off_delay: delay before power off in ms + * @monitored_sensors: number of monitored sensors + */ +struct abx500_temp { + struct platform_device *pdev; + struct device *hwmon_dev; + struct ab8500_gpadc *ab8500_gpadc; + struct ab8500_btemp *ab8500_btemp; + struct abx500_temp_ops ops; + u8 gpadc_addr[NUM_SENSORS]; + unsigned long temp[NUM_SENSORS]; + unsigned long min[NUM_SENSORS]; + unsigned long max[NUM_SENSORS]; + unsigned long max_hyst[NUM_SENSORS]; + unsigned long crit[NUM_SENSORS]; + unsigned long min_alarm[NUM_SENSORS]; + unsigned long max_alarm[NUM_SENSORS]; + unsigned long max_hyst_alarm[NUM_SENSORS]; + unsigned long crit_alarm[NUM_SENSORS]; + struct delayed_work work; + struct delayed_work power_off_work; + struct mutex lock; + /* Delay (ms) between temperature readings */ + unsigned long gpadc_monitor_delay; + /* Delay (ms) before power off */ + unsigned long power_off_delay; + int monitored_sensors; +}; + +int abx500_hwmon_init(struct abx500_temp *data) __init; + +#endif /* _ABX500_H */ diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 35114f86a9e..63c52edf5cc 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -746,7 +746,7 @@ static struct resource __devinitdata ab8500_usb_resources[] = { static struct resource __devinitdata ab8500_temp_resources[] = { { - .name = "AB8500_TEMP_WARM", + .name = "ABX500_TEMP_WARM", .start = AB8500_INT_TEMP_WARM, .end = AB8500_INT_TEMP_WARM, .flags = IORESOURCE_IRQ, @@ -831,7 +831,7 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { .name = "ab8500-denc", }, { - .name = "ab8500-temp", + .name = "abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, }, -- cgit v1.2.3 From c671d5c9c8303a965e97635d97384f2a7880ed7a Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 25 Aug 2011 13:27:42 +0530 Subject: abx500: hwmon: temperature monitor support for AB5500 Includes support for xtal temp, pcb temp and die temp monitoring ST-Ericsson Linux next: NA ST-Ericsson ID: WP257616 & WP351655 ST-Ericsson FOSS-OUT ID: NA Change-Id: I7668fb36df957b66929bfd13a4b6ad0386036aa1 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28139 Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/hwmon/Kconfig | 14 +++- drivers/hwmon/Makefile | 1 + drivers/hwmon/ab5500.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/abx500.c | 2 + drivers/hwmon/abx500.h | 6 ++ drivers/mfd/ab5500-core.c | 13 ++++ 6 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 drivers/hwmon/ab5500.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0d0f033852d..ecb19ff1a40 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -50,7 +50,19 @@ config SENSORS_AB8500 used to access sensors outside the AB8500 chip. This driver can also be built as a module. If so, the module - will be called ab8500-temp. + will be called abx500-temp. + +config SENSORS_AB5500 + tristate "AB5500 thermal monitoring" + depends on AB5500_GPADC + default n + help + If you say yes here you get support for the thermal sensor part + of the AB5500 chip. The driver includes thermal management for + AB5500 die, pcb and RF XTAL temperature. + + This driver can also be built as a module. If so, the module + will be called abx500-temp. config SENSORS_DB8500 tristate "DB8500 thermal monitoring" diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 1a2412487a6..39bdd768b24 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o obj-$(CONFIG_SENSORS_AB8500) += abx500.o ab8500.o +obj-$(CONFIG_SENSORS_AB5500) += abx500.o ab5500.o obj-$(CONFIG_SENSORS_DB8500) += db8500.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o diff --git a/drivers/hwmon/ab5500.c b/drivers/hwmon/ab5500.c new file mode 100644 index 00000000000..f229d103ec1 --- /dev/null +++ b/drivers/hwmon/ab5500.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Martin Persson for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + * Note: + * + * If/when the AB5500 thermal warning temperature is reached (threshold + * 125C cannot be changed by SW), an interrupt is set and the driver + * notifies user space via a sysfs event. If a shut down is not + * triggered by user space and temperature reaches beyond critical + * limit(130C) pm_power off is called. + * + * If/when AB5500 thermal shutdown temperature is reached a hardware + * shutdown of the AB5500 will occur. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "abx500.h" + +/* AB5500 driver monitors GPADC - XTAL_TEMP, PCB_TEMP, + * BTEMP_BALL, BAT_CTRL and DIE_TEMP + */ +#define NUM_MONITORED_SENSORS 5 + +#define SHUTDOWN_AUTO_MIN_LIMIT -25 +#define SHUTDOWN_AUTO_MAX_LIMIT 130 + +static int ab5500_output_convert(int val, u8 sensor) +{ + int res = val; + /* GPADC returns die temperature in Celsius + * convert it to millidegree celsius + */ + if (sensor == DIE_TEMP) + res = val * 1000; + + return res; +} + +static int ab5500_read_sensor(struct abx500_temp *data, u8 sensor) +{ + /* + * TODO: Add support for BAT_CTRL node, since this + * temperature measurement is more complex than just + * an ADC readout + */ + int val = ab5500_gpadc_convert(data->ab5500_gpadc, sensor); + if (val < 0) + return val; + else + return ab5500_output_convert(val, sensor); +} + +static ssize_t ab5500_show_name(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "ab5500\n"); +} + +static ssize_t ab5500_show_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + char *name; + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = attr->index; + + /* + * Make sure these labels correspond to the attribute indexes + * used when calling SENSOR_DEVICE_ATRR. + * Temperature sensors outside ab8500 (read via GPADC) are marked + * with prefix ext_ + */ + switch (index) { + case 1: + name = "xtal_temp"; + break; + case 2: + name = "pcb_temp"; + break; + case 3: + name = "bat_temp"; + break; + case 4: + name = "bat_ctrl"; + break; + case 5: + name = "ab5500"; + break; + default: + return -EINVAL; + } + return sprintf(buf, "%s\n", name); +} + +static int temp_shutdown_trig(int mux) +{ + pm_power_off(); + return 0; +} + +static int ab5500_temp_shutdown_auto(struct abx500_temp *data) +{ + int ret; + struct adc_auto_input *auto_ip; + + auto_ip = kzalloc(sizeof(struct adc_auto_input), GFP_KERNEL); + if (!auto_ip) { + dev_err(&data->pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + auto_ip->mux = DIE_TEMP; + auto_ip->freq = MS500; + auto_ip->min = SHUTDOWN_AUTO_MIN_LIMIT; + auto_ip->max = SHUTDOWN_AUTO_MAX_LIMIT; + auto_ip->auto_adc_callback = temp_shutdown_trig; + data->gpadc_auto = auto_ip; + ret = ab5500_gpadc_convert_auto(data->ab5500_gpadc, + data->gpadc_auto); + if (ret < 0) + kfree(auto_ip); + + return ret; +} + +static int ab5500_temp_irq_handler(int irq, struct abx500_temp *data) +{ + /* + * Make sure the magic numbers below corresponds to the node + * used for AB5500 thermal warning from HW. + */ + mutex_lock(&data->lock); + data->crit_alarm[4] = 1; + mutex_unlock(&data->lock); + sysfs_notify(&data->pdev->dev.kobj, NULL, "temp5_crit_alarm"); + dev_info(&data->pdev->dev, "ABX500 thermal warning," + " power off system now!\n"); + return 0; +} + +int __init abx500_hwmon_init(struct abx500_temp *data) +{ + int err; + + data->ab5500_gpadc = ab5500_gpadc_get("ab5500-adc.0"); + if (IS_ERR(data->ab5500_gpadc)) + return PTR_ERR(data->ab5500_gpadc); + + err = ab5500_temp_shutdown_auto(data); + if (err < 0) { + dev_err(&data->pdev->dev, "Failed to register" + " auto trigger(%d)\n", err); + return err; + } + + /* + * Setup HW defined data. + * + * Reference hardware (HREF): + * + * XTAL_TEMP, PCB_TEMP, BTEMP_BALL refer to millivolts and + * BAT_CTRL and DIE_TEMP refer to millidegrees + * + * Make sure indexes correspond to the attribute indexes + * used when calling SENSOR_DEVICE_ATRR + */ + data->gpadc_addr[0] = XTAL_TEMP; + data->gpadc_addr[1] = PCB_TEMP; + data->gpadc_addr[2] = BTEMP_BALL; + data->gpadc_addr[3] = BAT_CTRL; + data->gpadc_addr[4] = DIE_TEMP; + data->monitored_sensors = NUM_MONITORED_SENSORS; + + data->ops.read_sensor = ab5500_read_sensor; + data->ops.irq_handler = ab5500_temp_irq_handler; + data->ops.show_name = ab5500_show_name; + data->ops.show_label = ab5500_show_label; + + return 0; +} diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index 9d522ef6f62..6666dc27065 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -623,6 +623,7 @@ exit_platform_data: hwmon_device_unregister(data->hwmon_dev); platform_set_drvdata(pdev, NULL); exit: + kfree(data->gpadc_auto); kfree(data); return err; } @@ -635,6 +636,7 @@ static int __devexit abx500_temp_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &abx500_temp_group); platform_set_drvdata(pdev, NULL); + kfree(data->gpadc_auto); kfree(data); return 0; } diff --git a/drivers/hwmon/abx500.h b/drivers/hwmon/abx500.h index a089a63939d..1d41aa191fe 100644 --- a/drivers/hwmon/abx500.h +++ b/drivers/hwmon/abx500.h @@ -10,7 +10,9 @@ #define NUM_SENSORS 5 struct ab8500_gpadc; +struct ab5500_gpadc; struct ab8500_btemp; +struct adc_auto_input; struct abx500_temp; /** @@ -34,7 +36,9 @@ struct abx500_temp_ops { * @pdev: platform device * @hwmon_dev: hwmon device * @ab8500_gpadc: gpadc interface for ab8500 + * @ab5500_gpadc: gpadc interface for ab5500 * @btemp: battery temperature interface for ab8500 + * @adc_auto_input: gpadc auto trigger * @gpadc_addr: gpadc channel address * @temp: sensor temperature input value * @min: sensor temperature min value @@ -57,7 +61,9 @@ struct abx500_temp { struct platform_device *pdev; struct device *hwmon_dev; struct ab8500_gpadc *ab8500_gpadc; + struct ab5500_gpadc *ab5500_gpadc; struct ab8500_btemp *ab8500_btemp; + struct adc_auto_input *gpadc_auto; struct abx500_temp_ops ops; u8 gpadc_addr[NUM_SENSORS]; unsigned long temp[NUM_SENSORS]; diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c index 54d0fe40845..75a4b05ad2e 100644 --- a/drivers/mfd/ab5500-core.c +++ b/drivers/mfd/ab5500-core.c @@ -991,6 +991,19 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { }, }, }, + [AB5500_DEVID_TEMPMON] = { + .name = "abx500-temp", + .id = AB5500_DEVID_TEMPMON, + .num_resources = 1, + .resources = (struct resource[]) { + { + .name = "ABX500_TEMP_WARM", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(2, 2), + .end = AB5500_IRQ(2, 2), + }, + }, + }, }; /* -- cgit v1.2.3 From 185086eac879aecc2604621a092c1795f37acab5 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 25 Aug 2011 13:31:50 +0530 Subject: hwmon: ab5500: support for battery temp monitor add support for battery temperature monitor ST-Ericsson Linux next: NA ST-Ericsson ID: WP257616 ST-Ericsson FOSS-OUT ID: NA Change-Id: I344947ed41b4dd0a49abcb28e57b7b3c697dc57d Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28233 Reviewed-by: Arun MURTHY Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/hwmon/ab5500.c | 14 ++++++++++++-- drivers/hwmon/abx500.h | 2 ++ drivers/power/ab5500_btemp.c | 11 +++++++++++ include/linux/mfd/abx500/ab5500-bm.h | 10 ++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/ab5500.c b/drivers/hwmon/ab5500.c index f229d103ec1..79540c9a79b 100644 --- a/drivers/hwmon/ab5500.c +++ b/drivers/hwmon/ab5500.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "abx500.h" /* AB5500 driver monitors GPADC - XTAL_TEMP, PCB_TEMP, @@ -47,12 +48,17 @@ static int ab5500_output_convert(int val, u8 sensor) static int ab5500_read_sensor(struct abx500_temp *data, u8 sensor) { + int val; /* - * TODO: Add support for BAT_CTRL node, since this + * Special treatment for BAT_CTRL node, since this * temperature measurement is more complex than just * an ADC readout */ - int val = ab5500_gpadc_convert(data->ab5500_gpadc, sensor); + if (sensor == BAT_CTRL) + val = ab5500_btemp_get_batctrl_temp(data->ab5500_btemp); + else + val = ab5500_gpadc_convert(data->ab5500_gpadc, sensor); + if (val < 0) return val; else @@ -156,6 +162,10 @@ int __init abx500_hwmon_init(struct abx500_temp *data) if (IS_ERR(data->ab5500_gpadc)) return PTR_ERR(data->ab5500_gpadc); + data->ab5500_btemp = ab5500_btemp_get(); + if (IS_ERR(data->ab5500_btemp)) + return PTR_ERR(data->ab5500_btemp); + err = ab5500_temp_shutdown_auto(data); if (err < 0) { dev_err(&data->pdev->dev, "Failed to register" diff --git a/drivers/hwmon/abx500.h b/drivers/hwmon/abx500.h index 1d41aa191fe..77ae7cbd5c1 100644 --- a/drivers/hwmon/abx500.h +++ b/drivers/hwmon/abx500.h @@ -12,6 +12,7 @@ struct ab8500_gpadc; struct ab5500_gpadc; struct ab8500_btemp; +struct ab5500_btemp; struct adc_auto_input; struct abx500_temp; @@ -63,6 +64,7 @@ struct abx500_temp { struct ab8500_gpadc *ab8500_gpadc; struct ab5500_gpadc *ab5500_gpadc; struct ab8500_btemp *ab8500_btemp; + struct ab5500_btemp *ab5500_btemp; struct adc_auto_input *gpadc_auto; struct abx500_temp_ops ops; u8 gpadc_addr[NUM_SENSORS]; diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 04ad6bbb7ac..2e2a5054a58 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -109,6 +109,17 @@ struct ab5500_btemp *ab5500_btemp_get(void) return di; } +/** + * ab5500_btemp_get_batctrl_temp() - get the temperature + * @di: pointer to the ab5500_btemp structure + * + * Returns the batctrl temperature in millidegrees + */ +int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *di) +{ + return di->bat_temp * 1000; +} + /** * ab5500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance * @di: pointer to the ab5500_btemp structure diff --git a/include/linux/mfd/abx500/ab5500-bm.h b/include/linux/mfd/abx500/ab5500-bm.h index b9800cd8c19..1bb22614b27 100644 --- a/include/linux/mfd/abx500/ab5500-bm.h +++ b/include/linux/mfd/abx500/ab5500-bm.h @@ -100,9 +100,19 @@ #ifdef CONFIG_AB5500_BM void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA); +struct ab5500_btemp *ab5500_btemp_get(void); +int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp); #else static void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) { } +inline struct ab5500_btemp *ab5500_btemp_get(void) +{ + return 0; +} +inline int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp) +{ + return 0; +} #endif #endif /* _AB5500_BM_H */ -- cgit v1.2.3 From 5ab858840f671a26a2c3ca11f71774ac80eed541 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Tue, 16 Aug 2011 11:35:23 +0530 Subject: power: ab5500-fg: Proper registering of power supply During boot if the battery voltage exceed the max voltage, then an interrupt is triggered to the GPADC for auto control. This in turn will call the fg registered callback handler. But this happens before the power supply class of fg is registered. Thereby calling power_supply_changed() will lead to BUG since it used the wake lock which has not yet been initializes. Hence register power supply class for fg first followed by initializing the hardware registers, which includes registering for a gpadc auto convert for battery voltage. ST-Ericsson Linux next: NA ST-Ericsson ID: 355236 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iaa291c5ebbd8c2ba3fcee579de3605805a306ebd Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28777 Reviewed-by: QATEST Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_fg.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 95f31cb84cb..bb2bfb9e840 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -1751,13 +1751,6 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) list_add_tail(&di->node, &ab5500_fg_list); - /* Initialize OVV, and other registers */ - ret = ab5500_fg_init_hw_registers(di); - if (ret) { - dev_err(di->dev, "failed to initialize registers\n"); - goto free_fg_wq; - } - /* Consider battery unknown until we're informed otherwise */ di->flags.batt_unknown = true; @@ -1768,6 +1761,13 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) goto free_fg_wq; } + /* Initialize OVV, and other registers */ + ret = ab5500_fg_init_hw_registers(di); + if (ret) { + dev_err(di->dev, "failed to initialize registers\n"); + goto pow_unreg; + } + di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); ab5500_fg_coulomb_counter(di, true); @@ -1793,6 +1793,8 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) dev_info(di->dev, "probe success\n"); return ret; +pow_unreg: + power_supply_unregister(&di->fg_psy); free_fg_wq: destroy_workqueue(di->fg_wq); free_device_info: -- cgit v1.2.3 From c25da77db899f604b36be3d43c229e2dcb1fcafb Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Fri, 15 Jul 2011 12:57:40 +0530 Subject: power: ab5500-charger: update the watchdog rekick seq In AB5500 there exist no charger watchdog, instead all the charging registers that are written during enabling charging are to be re-written which acts as a watchdog re-kick. Even though its usb charging DCIOCURRENT register has to be written in order to kick charging, else charging is not started. ST-Ericsson Linux next: Not Tested ST-Ericsson ID: WP257120 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iad283349e21027908df8aec560c9f44f2861f0ee Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27220 Reviewed-by: Johan PALSSON Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 69b808f06d7..b30f00a57f9 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -825,6 +825,21 @@ static int ab5500_charger_usb_en(struct ux500_charger *charger, __func__, __LINE__); return ret; } + + /* + * Register DCIOCURRENT is one among the charging watchdog + * rekick sequence, hence irrespective of usb charging this + * register will have to be written. + */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_DCIOCURRENT, + RESET); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", + __func__, __LINE__); + return ret; + } + di->usb.charger_online = 1; } else { /* ChVoltLevel: max voltage upto which battery can be charged */ @@ -946,6 +961,19 @@ static int ab5500_charger_watchdog_kick(struct ux500_charger *charger) dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); return ret; } + /* + * Register DCIOCURRENT is one among the charging watchdog + * rekick sequence, hence irrespective of usb charging this + * register will have to be written. + */ + ret = abx500_set_register_interruptible(di->dev, + AB5500_BANK_CHG, AB5500_DCIOCURRENT, + RESET); + if (ret) { + dev_err(di->dev, "%s write failed %d\n", __func__, __LINE__); + return ret; + } + return ret; } -- cgit v1.2.3 From d1f851958180507bc1829c92cb90f7ae958757cd Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 23 Jun 2011 17:36:41 +0530 Subject: ab5500: identify AB5500v2 ST-Ericsson Linux next: - ST-Ericsson ID: 349062 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I0df95338d14b45167c5be811d8b74d6d48bd78e2 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25781 Reviewed-by: Bibek BASU Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/ab5500-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c index 75a4b05ad2e..3d7a9a282c2 100644 --- a/drivers/mfd/ab5500-core.c +++ b/drivers/mfd/ab5500-core.c @@ -1314,6 +1314,10 @@ static const struct ab_family_id ids[] __initdata = { .id = AB5500_1_1, .name = "1.1" }, + { + .id = AB5500_2_0, + .name = "2.0" + }, /* Terminator */ { .id = 0x00, -- cgit v1.2.3 From 8082cdf0d2be872144dba62d19bac818834560e8 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 17 Aug 2011 13:20:21 +0200 Subject: MFD: AB8500: If a charger is present, reboot instead If a changer is present on power off, reboot the system instead of powering it off. ST-Ericsson ID: 354056 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I03a2a91936219db040f55fa7cd833fdbe5a05657 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28933 Reviewed-by: Karl KOMIEROWSKI --- drivers/mfd/ab8500-sysctrl.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 799fb5e696a..01b06694c18 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -19,6 +21,31 @@ void ab8500_power_off(void) { sigset_t old; sigset_t all; + static char *pss[] = {"ab8500_ac", "ab8500_usb"}; + int i; + + /* + * If we have a charger connected and we're powering off, + * reboot into charge-only mode. + */ + + for (i = 0; i < ARRAY_SIZE(pss); i++) { + union power_supply_propval val; + struct power_supply *psy; + int ret; + + psy = power_supply_get_by_name(pss[i]); + if (!psy) + continue; + ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + + if (!ret && val.intval) { + printk(KERN_INFO + "Charger \"%s\" is connected. Rebooting.\n", + pss[i]); + machine_restart(NULL); + } + } sigfillset(&all); -- cgit v1.2.3 From 1504845b986bd479eb68b3d577e38d596cf86d53 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 17 Aug 2011 15:58:52 +0200 Subject: MFD: AB8500: Only reboot into charging if battery type is known Only reboot into charging mode if the battery is of known type. ST-Ericsson ID: 354056 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I8aa0d6f56940fc3b82858534324ab3027c592b21 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28945 Reviewed-by: QATEST Reviewed-by: Karl KOMIEROWSKI --- drivers/mfd/ab8500-sysctrl.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 01b06694c18..26216e7f93b 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -23,6 +23,10 @@ void ab8500_power_off(void) sigset_t all; static char *pss[] = {"ab8500_ac", "ab8500_usb"}; int i; + bool charger_present = false; + union power_supply_propval val; + struct power_supply *psy; + int ret; /* * If we have a charger connected and we're powering off, @@ -30,23 +34,36 @@ void ab8500_power_off(void) */ for (i = 0; i < ARRAY_SIZE(pss); i++) { - union power_supply_propval val; - struct power_supply *psy; - int ret; - psy = power_supply_get_by_name(pss[i]); if (!psy) continue; + ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); if (!ret && val.intval) { + charger_present = true; + break; + } + } + + if (!charger_present) + goto shutdown; + + /* Check if battery is known */ + psy = power_supply_get_by_name("ab8500_btemp"); + if (psy) { + ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY, + &val); + if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) { printk(KERN_INFO - "Charger \"%s\" is connected. Rebooting.\n", + "Charger \"%s\" is connected with known battery." + " Rebooting.\n", pss[i]); machine_restart(NULL); } } +shutdown: sigfillset(&all); if (!sigprocmask(SIG_BLOCK, &all, &old)) { -- cgit v1.2.3 From 3e14585136e98dfe62218fb6a188331a1909f07a Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 18 Aug 2011 10:14:38 +0200 Subject: MFD: AB8500: Provide charging as reset reason Provide charging as reset reason when proper ST-Ericsson ID: 354056 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5c6dd0e0a4bce63dbf43a138b132f27e2e42b1b1 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28982 Reviewed-by: QATEST Reviewed-by: Karl KOMIEROWSKI --- drivers/mfd/ab8500-sysctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 26216e7f93b..cf58f694539 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -59,7 +59,7 @@ void ab8500_power_off(void) "Charger \"%s\" is connected with known battery." " Rebooting.\n", pss[i]); - machine_restart(NULL); + machine_restart("charging"); } } -- cgit v1.2.3 From cce6492e4219706b13f8d35068b711915b85259d Mon Sep 17 00:00:00 2001 From: David Paris Date: Tue, 2 Aug 2011 11:55:16 +0530 Subject: MFD: tc3589x: Optimize power save settings for suspend Compared to HSI GPIO V3.1, register 0x82 is set with a different value 0x82 = 0xE (HSI GPIO V3.1) 0x82 = 0xF (on android) In case of android, it seems that GPIO reset should be applied to reach 13uA of consumption on TC3589x when AP in DeepSleep Change-Id: I64eaa4304fcd9f71546cadba0aa703c91b6075df Signed-off-by: David Paris Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17640 --- drivers/mfd/tc3589x.c | 127 +++++++++++++++++++++++++++++++++++++++++--- include/linux/mfd/tc3589x.h | 61 ++++++++++++--------- 2 files changed, 155 insertions(+), 33 deletions(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index de979742c6f..6059be67bb2 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -358,16 +358,112 @@ static int __devexit tc3589x_remove(struct i2c_client *client) } #ifdef CONFIG_PM + +static u32 sleep_regs[] = { + TC3589x_IOPC0_L, + TC3589x_IOPC0_H, + TC3589x_IOPC1_L, + TC3589x_IOPC1_H, + TC3589x_IOPC2_L, + TC3589x_IOPC2_H, + TC3589x_DRIVE0_L, + TC3589x_DRIVE0_H, + TC3589x_DRIVE1_L, + TC3589x_DRIVE1_H, + TC3589x_DRIVE2_L, + TC3589x_DRIVE2_H, + TC3589x_DRIVE3, + TC3589x_GPIODATA0, + TC3589x_GPIOMASK0, + TC3589x_GPIODATA1, + TC3589x_GPIOMASK1, + TC3589x_GPIODATA2, + TC3589x_GPIOMASK2, + TC3589x_GPIODIR0, + TC3589x_GPIODIR1, + TC3589x_GPIODIR2, + TC3589x_GPIOIE0, + TC3589x_GPIOIE1, + TC3589x_GPIOIE2, + TC3589x_RSTCTRL, + TC3589x_CLKCFG, +}; + +static u8 sleep_regs_val[] = { + 0x00, /* TC3589x_IOPC0_L */ + 0x00, /* TC3589x_IOPC0_H */ + 0x00, /* TC3589x_IOPC1_L */ + 0x00, /* TC3589x_IOPC1_H */ + 0x00, /* TC3589x_IOPC2_L */ + 0x00, /* TC3589x_IOPC2_H */ + 0xff, /* TC3589x_DRIVE0_L */ + 0xff, /* TC3589x_DRIVE0_H */ + 0xff, /* TC3589x_DRIVE1_L */ + 0xff, /* TC3589x_DRIVE1_H */ + 0xff, /* TC3589x_DRIVE2_L */ + 0xff, /* TC3589x_DRIVE2_H */ + 0x0f, /* TC3589x_DRIVE3 */ + 0x80, /* TC3589x_GPIODATA0 */ + 0x80, /* TC3589x_GPIOMASK0 */ + 0x80, /* TC3589x_GPIODATA1 */ + 0x80, /* TC3589x_GPIOMASK1 */ + 0x06, /* TC3589x_GPIODATA2 */ + 0x06, /* TC3589x_GPIOMASK2 */ + 0xf0, /* TC3589x_GPIODIR0 */ + 0xe0, /* TC3589x_GPIODIR1 */ + 0xee, /* TC3589x_GPIODIR2 */ + 0x0f, /* TC3589x_GPIOIE0 */ + 0x1f, /* TC3589x_GPIOIE1 */ + 0x11, /* TC3589x_GPIOIE2 */ + 0x0f, /* TC3589x_RSTCTRL */ + 0xb0 /* TC3589x_CLKCFG */ + +}; + +static u8 sleep_regs_backup[ARRAY_SIZE(sleep_regs)]; + static int tc3589x_suspend(struct device *dev) { struct tc3589x *tc3589x = dev_get_drvdata(dev); struct i2c_client *client = tc3589x->i2c; int ret = 0; + int i, j; + int val; + + /* Put the system to sleep mode */ + if (!device_may_wakeup(&client->dev)) { + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + val = tc3589x_reg_read(tc3589x, + sleep_regs[i]); + if (val < 0) + goto out; + + sleep_regs_backup[i] = (u8) (val & 0xff); + } - /* put the system to sleep mode */ - if (!device_may_wakeup(&client->dev)) - ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, - TC3589x_CLKMODE_MODCTL_SLEEP); + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + ret = tc3589x_reg_write(tc3589x, + sleep_regs[i], + sleep_regs_val[i]); + if (ret < 0) + goto fail; + + } + + ret = tc3589x_reg_write(tc3589x, + TC3589x_CLKMODE, + TC3589x_CLKMODE_MODCTL_SLEEP); + } +out: + return ret; +fail: + for (j = 0; j <= i; j++) { + ret = tc3589x_reg_write(tc3589x, + sleep_regs[i], + sleep_regs_backup[i]); + if (ret < 0) + break; + } return ret; } @@ -377,12 +473,27 @@ static int tc3589x_resume(struct device *dev) struct tc3589x *tc3589x = dev_get_drvdata(dev); struct i2c_client *client = tc3589x->i2c; int ret = 0; + int i; - /* enable the system into operation */ + /* Enable the system into operation */ if (!device_may_wakeup(&client->dev)) - ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, - TC3589x_CLKMODE_MODCTL_OPERATION); - + { + ret = tc3589x_reg_write(tc3589x, + TC3589x_CLKMODE, + TC3589x_CLKMODE_MODCTL_OPERATION); + if (ret < 0) + goto out; + + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + ret = tc3589x_reg_write(tc3589x, + sleep_regs[i], + sleep_regs_backup[i]); + /* Not much to do here if we fail */ + if (ret < 0) + break; + } + } +out: return ret; } diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index 3acb3a8e3af..5c5f37d2e95 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -31,20 +31,43 @@ enum tx3589x_block { #define TC3589x_EVTCODE_FIFO 0x10 #define TC3589x_KBDMFS 0x8F -#define TC3589x_IRQST 0x91 - -#define TC3589x_MANFCODE_MAGIC 0x03 #define TC3589x_MANFCODE 0x80 +#define TC3589x_MANFCODE_MAGIC 0x03 #define TC3589x_VERSION 0x81 -#define TC3589x_IOCFG 0xA7 +#define TC3589x_RSTCTRL 0x82 +#define TC3589x_EXTRSTN 0x83 +#define TC3589x_RSTINTCLR 0x84 #define TC3589x_CLKMODE 0x88 #define TC3589x_CLKCFG 0x89 #define TC3589x_CLKEN 0x8A +#define TC3589x_IRQST 0x91 -#define TC3589x_RSTCTRL 0x82 -#define TC3589x_EXTRSTN 0x83 -#define TC3589x_RSTINTCLR 0x84 +#define TC3589x_DRIVE0_L 0xA0 +#define TC3589x_DRIVE0_H 0xA1 +#define TC3589x_DRIVE1_L 0xA2 +#define TC3589x_DRIVE1_H 0xA3 +#define TC3589x_DRIVE2_L 0xA4 +#define TC3589x_DRIVE2_H 0XA5 +#define TC3589x_DRIVE3 0xA6 +#define TC3589x_IOCFG 0xA7 + +#define TC3589x_IOPC0_L 0xAA +#define TC3589x_IOPC0_H 0xAB +#define TC3589x_IOPC1_L 0xAC +#define TC3589x_IOPC1_H 0xAD +#define TC3589x_IOPC2_L 0xAE +#define TC3589x_IOPC2_H 0xAF + +#define TC3589x_GPIODATA0 0xC0 +#define TC3589x_GPIOMASK0 0xC1 +#define TC3589x_GPIODATA1 0xC2 +#define TC3589x_GPIOMASK1 0xC3 +#define TC3589x_GPIODATA2 0xC4 +#define TC3589x_GPIOMASK2 0xC5 +#define TC3589x_GPIODIR0 0xC6 +#define TC3589x_GPIODIR1 0xC7 +#define TC3589x_GPIODIR2 0xC8 /* Pull up/down configuration registers */ #define TC3589x_IOCFG 0xA7 @@ -75,17 +98,12 @@ enum tx3589x_block { #define TC3589x_GPIOIC0 0xDC #define TC3589x_GPIOIC1 0xDD #define TC3589x_GPIOIC2 0xDE - -#define TC3589x_GPIODATA0 0xC0 -#define TC3589x_GPIOMASK0 0xc1 -#define TC3589x_GPIODATA1 0xC2 -#define TC3589x_GPIOMASK1 0xc3 -#define TC3589x_GPIODATA2 0xC4 -#define TC3589x_GPIOMASK2 0xC5 - -#define TC3589x_GPIODIR0 0xC6 -#define TC3589x_GPIODIR1 0xC7 -#define TC3589x_GPIODIR2 0xC8 +#define TC3589x_GPIOODM0 0xE0 +#define TC3589x_GPIOODE0 0xE1 +#define TC3589x_GPIOODM1 0xE2 +#define TC3589x_GPIOODE1 0xE3 +#define TC3589x_GPIOODM2 0xE4 +#define TC3589x_GPIOODE2 0xE5 #define TC3589x_GPIOSYNC0 0xE6 #define TC3589x_GPIOSYNC1 0xE7 @@ -95,13 +113,6 @@ enum tx3589x_block { #define TC3589x_GPIOWAKE1 0xEA #define TC3589x_GPIOWAKE2 0xEB -#define TC3589x_GPIOODM0 0xE0 -#define TC3589x_GPIOODE0 0xE1 -#define TC3589x_GPIOODM1 0xE2 -#define TC3589x_GPIOODE1 0xE3 -#define TC3589x_GPIOODM2 0xE4 -#define TC3589x_GPIOODE2 0xE5 - #define TC3589x_INT_GPIIRQ 0 #define TC3589x_INT_TI0IRQ 1 #define TC3589x_INT_TI1IRQ 2 -- cgit v1.2.3 From 14edacde3cb93e98147ddaef7f3905e4d38a50e6 Mon Sep 17 00:00:00 2001 From: Martin Persson Date: Tue, 2 Aug 2011 12:04:49 +0530 Subject: MFD: tc35892: Correct optimized power settings Change-Id: I83fd9379c037fe3c949aa5d01a99423d2fc555b4 Signed-off-by: Martin Persson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19261 Reviewed-by: Jonas ABERG --- drivers/mfd/tc3589x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 6059be67bb2..8c58389f695 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -484,7 +484,7 @@ static int tc3589x_resume(struct device *dev) if (ret < 0) goto out; - for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + for (i = ARRAY_SIZE(sleep_regs) - 1; i >= 0; i--) { ret = tc3589x_reg_write(tc3589x, sleep_regs[i], sleep_regs_backup[i]); -- cgit v1.2.3 From afa646b3ba6bfc5ab4a507e1ee7854184b310b17 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Wed, 22 Dec 2010 14:52:44 +0530 Subject: amba-pl022: Clear SSE once the transfer is completed Clear SSE after the xfer completion and remove the not needed default register restoration in suspend. ST-Ericsson ID: ER 316546 Change-Id: I73368e18bd55abdff6b1909239bcf5b64583b452 Signed-off-by: Virupax Sadashivpetimath --- drivers/spi/spi-pl022.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 97351afc7c8..8bf53a76a33 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -489,6 +489,13 @@ static void giveback(struct pl022 *pl022) pl022->cur_transfer = NULL; pl022->cur_chip = NULL; spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + + /* This message is completed, so let's turn off the clocks & power */ + pm_runtime_put(&pl022->adev->dev); } /** -- cgit v1.2.3 From 77709a77eebd29363690cef397233bd93a5a53ec Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 17 Aug 2011 14:05:43 +0530 Subject: mfd: Add Toshiba's TC35892 MFD core The TC35892 I/O Expander provides 24 GPIOs, a keypad controller, timers, and a rotator wheel interface. This patch adds the MFD core. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Samuel Ortiz Change-Id: Ib9fe0f306c241284be763e8c65ce1bee44d22d5a Signed-off-by: Virupax Sadashivpetimath --- drivers/mfd/Kconfig | 11 ++ drivers/mfd/Makefile | 1 + drivers/mfd/tc35892.c | 345 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/tc35892.h | 132 +++++++++++++++++ 4 files changed, 489 insertions(+) create mode 100644 drivers/mfd/tc35892.c create mode 100644 include/linux/mfd/tc35892.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 41a3e482cb5..d3879b9c469 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -331,6 +331,17 @@ config MFD_TC3589X additional drivers must be enabled in order to use the functionality of the device. +config MFD_TC35892 + bool "Support Toshiba TC35892" + depends on I2C=y && GENERIC_HARDIRQS + select MFD_CORE + help + Support for the Toshiba TC35892 I/O Expander. + + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. + config MFD_TMIO bool default n diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e1f64f9403a..cfed0402931 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_MFD_STMPE) += stmpe.o obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o obj-$(CONFIG_MFD_TC3589X) += tc3589x.o +obj-$(CONFIG_MFD_TC35892) += tc35892.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c new file mode 100644 index 00000000000..e619e2a5599 --- /dev/null +++ b/drivers/mfd/tc35892.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License, version 2 + * Author: Hanumath Prasad for ST-Ericsson + * Author: Rabin Vincent for ST-Ericsson + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * tc35892_reg_read() - read a single TC35892 register + * @tc35892: Device to read from + * @reg: Register to read + */ +int tc35892_reg_read(struct tc35892 *tc35892, u8 reg) +{ + int ret; + + ret = i2c_smbus_read_byte_data(tc35892->i2c, reg); + if (ret < 0) + dev_err(tc35892->dev, "failed to read reg %#x: %d\n", + reg, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(tc35892_reg_read); + +/** + * tc35892_reg_read() - write a single TC35892 register + * @tc35892: Device to write to + * @reg: Register to read + * @data: Value to write + */ +int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data) +{ + int ret; + + ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data); + if (ret < 0) + dev_err(tc35892->dev, "failed to write reg %#x: %d\n", + reg, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(tc35892_reg_write); + +/** + * tc35892_block_read() - read multiple TC35892 registers + * @tc35892: Device to read from + * @reg: First register + * @length: Number of registers + * @values: Buffer to write to + */ +int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values) +{ + int ret; + + ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values); + if (ret < 0) + dev_err(tc35892->dev, "failed to read regs %#x: %d\n", + reg, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(tc35892_block_read); + +/** + * tc35892_block_write() - write multiple TC35892 registers + * @tc35892: Device to write to + * @reg: First register + * @length: Number of registers + * @values: Values to write + */ +int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, + const u8 *values) +{ + int ret; + + ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length, + values); + if (ret < 0) + dev_err(tc35892->dev, "failed to write regs %#x: %d\n", + reg, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(tc35892_block_write); + +/** + * tc35892_set_bits() - set the value of a bitfield in a TC35892 register + * @tc35892: Device to write to + * @reg: Register to write + * @mask: Mask of bits to set + * @values: Value to set + */ +int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val) +{ + int ret; + + mutex_lock(&tc35892->lock); + + ret = tc35892_reg_read(tc35892, reg); + if (ret < 0) + goto out; + + ret &= ~mask; + ret |= val; + + ret = tc35892_reg_write(tc35892, reg, ret); + +out: + mutex_unlock(&tc35892->lock); + return ret; +} +EXPORT_SYMBOL_GPL(tc35892_set_bits); + +static struct resource gpio_resources[] = { + { + .start = TC35892_INT_GPIIRQ, + .end = TC35892_INT_GPIIRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell tc35892_devs[] = { + { + .name = "tc35892-gpio", + .num_resources = ARRAY_SIZE(gpio_resources), + .resources = &gpio_resources[0], + }, +}; + +static irqreturn_t tc35892_irq(int irq, void *data) +{ + struct tc35892 *tc35892 = data; + int status; + + status = tc35892_reg_read(tc35892, TC35892_IRQST); + if (status < 0) + return IRQ_NONE; + + while (status) { + int bit = __ffs(status); + + handle_nested_irq(tc35892->irq_base + bit); + status &= ~(1 << bit); + } + + /* + * A dummy read or write (to any register) appears to be necessary to + * have the last interrupt clear (for example, GPIO IC write) take + * effect. + */ + tc35892_reg_read(tc35892, TC35892_IRQST); + + return IRQ_HANDLED; +} + +static void tc35892_irq_dummy(unsigned int irq) +{ + /* No mask/unmask at this level */ +} + +static struct irq_chip tc35892_irq_chip = { + .name = "tc35892", + .mask = tc35892_irq_dummy, + .unmask = tc35892_irq_dummy, +}; + +static int tc35892_irq_init(struct tc35892 *tc35892) +{ + int base = tc35892->irq_base; + int irq; + + for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { + set_irq_chip_data(irq, tc35892); + set_irq_chip_and_handler(irq, &tc35892_irq_chip, + handle_edge_irq); + set_irq_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + set_irq_noprobe(irq); +#endif + } + + return 0; +} + +static void tc35892_irq_remove(struct tc35892 *tc35892) +{ + int base = tc35892->irq_base; + int irq; + + for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { +#ifdef CONFIG_ARM + set_irq_flags(irq, 0); +#endif + set_irq_chip_and_handler(irq, NULL, NULL); + set_irq_chip_data(irq, NULL); + } +} + +static int tc35892_chip_init(struct tc35892 *tc35892) +{ + int manf, ver, ret; + + manf = tc35892_reg_read(tc35892, TC35892_MANFCODE); + if (manf < 0) + return manf; + + ver = tc35892_reg_read(tc35892, TC35892_VERSION); + if (ver < 0) + return ver; + + if (manf != TC35892_MANFCODE_MAGIC) { + dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf); + return -EINVAL; + } + + dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); + + /* Put everything except the IRQ module into reset */ + ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, + TC35892_RSTCTRL_TIMRST + | TC35892_RSTCTRL_ROTRST + | TC35892_RSTCTRL_KBDRST + | TC35892_RSTCTRL_GPIRST); + if (ret < 0) + return ret; + + /* Clear the reset interrupt. */ + return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1); +} + +static int __devinit tc35892_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct tc35892_platform_data *pdata = i2c->dev.platform_data; + struct tc35892 *tc35892; + int ret; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_I2C_BLOCK)) + return -EIO; + + tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL); + if (!tc35892) + return -ENOMEM; + + mutex_init(&tc35892->lock); + + tc35892->dev = &i2c->dev; + tc35892->i2c = i2c; + tc35892->pdata = pdata; + tc35892->irq_base = pdata->irq_base; + tc35892->num_gpio = id->driver_data; + + i2c_set_clientdata(i2c, tc35892); + + ret = tc35892_chip_init(tc35892); + if (ret) + goto out_free; + + ret = tc35892_irq_init(tc35892); + if (ret) + goto out_free; + + ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "tc35892", tc35892); + if (ret) { + dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret); + goto out_removeirq; + } + + ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs, + ARRAY_SIZE(tc35892_devs), NULL, + tc35892->irq_base); + if (ret) { + dev_err(tc35892->dev, "failed to add children\n"); + goto out_freeirq; + } + + return 0; + +out_freeirq: + free_irq(tc35892->i2c->irq, tc35892); +out_removeirq: + tc35892_irq_remove(tc35892); +out_free: + kfree(tc35892); + return ret; +} + +static int __devexit tc35892_remove(struct i2c_client *client) +{ + struct tc35892 *tc35892 = i2c_get_clientdata(client); + + mfd_remove_devices(tc35892->dev); + + free_irq(tc35892->i2c->irq, tc35892); + tc35892_irq_remove(tc35892); + + kfree(tc35892); + + return 0; +} + +static const struct i2c_device_id tc35892_id[] = { + { "tc35892", 24 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tc35892_id); + +static struct i2c_driver tc35892_driver = { + .driver.name = "tc35892", + .driver.owner = THIS_MODULE, + .probe = tc35892_probe, + .remove = __devexit_p(tc35892_remove), + .id_table = tc35892_id, +}; + +static int __init tc35892_init(void) +{ + return i2c_add_driver(&tc35892_driver); +} +subsys_initcall(tc35892_init); + +static void __exit tc35892_exit(void) +{ + i2c_del_driver(&tc35892_driver); +} +module_exit(tc35892_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("TC35892 MFD core driver"); +MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h new file mode 100644 index 00000000000..e47f770d306 --- /dev/null +++ b/include/linux/mfd/tc35892.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License, version 2 + */ + +#ifndef __LINUX_MFD_TC35892_H +#define __LINUX_MFD_TC35892_H + +#include + +#define TC35892_RSTCTRL_IRQRST (1 << 4) +#define TC35892_RSTCTRL_TIMRST (1 << 3) +#define TC35892_RSTCTRL_ROTRST (1 << 2) +#define TC35892_RSTCTRL_KBDRST (1 << 1) +#define TC35892_RSTCTRL_GPIRST (1 << 0) + +#define TC35892_IRQST 0x91 + +#define TC35892_MANFCODE_MAGIC 0x03 +#define TC35892_MANFCODE 0x80 +#define TC35892_VERSION 0x81 +#define TC35892_IOCFG 0xA7 + +#define TC35892_CLKMODE 0x88 +#define TC35892_CLKCFG 0x89 +#define TC35892_CLKEN 0x8A + +#define TC35892_RSTCTRL 0x82 +#define TC35892_EXTRSTN 0x83 +#define TC35892_RSTINTCLR 0x84 + +#define TC35892_GPIOIS0 0xC9 +#define TC35892_GPIOIS1 0xCA +#define TC35892_GPIOIS2 0xCB +#define TC35892_GPIOIBE0 0xCC +#define TC35892_GPIOIBE1 0xCD +#define TC35892_GPIOIBE2 0xCE +#define TC35892_GPIOIEV0 0xCF +#define TC35892_GPIOIEV1 0xD0 +#define TC35892_GPIOIEV2 0xD1 +#define TC35892_GPIOIE0 0xD2 +#define TC35892_GPIOIE1 0xD3 +#define TC35892_GPIOIE2 0xD4 +#define TC35892_GPIORIS0 0xD6 +#define TC35892_GPIORIS1 0xD7 +#define TC35892_GPIORIS2 0xD8 +#define TC35892_GPIOMIS0 0xD9 +#define TC35892_GPIOMIS1 0xDA +#define TC35892_GPIOMIS2 0xDB +#define TC35892_GPIOIC0 0xDC +#define TC35892_GPIOIC1 0xDD +#define TC35892_GPIOIC2 0xDE + +#define TC35892_GPIODATA0 0xC0 +#define TC35892_GPIOMASK0 0xc1 +#define TC35892_GPIODATA1 0xC2 +#define TC35892_GPIOMASK1 0xc3 +#define TC35892_GPIODATA2 0xC4 +#define TC35892_GPIOMASK2 0xC5 + +#define TC35892_GPIODIR0 0xC6 +#define TC35892_GPIODIR1 0xC7 +#define TC35892_GPIODIR2 0xC8 + +#define TC35892_GPIOSYNC0 0xE6 +#define TC35892_GPIOSYNC1 0xE7 +#define TC35892_GPIOSYNC2 0xE8 + +#define TC35892_GPIOWAKE0 0xE9 +#define TC35892_GPIOWAKE1 0xEA +#define TC35892_GPIOWAKE2 0xEB + +#define TC35892_GPIOODM0 0xE0 +#define TC35892_GPIOODE0 0xE1 +#define TC35892_GPIOODM1 0xE2 +#define TC35892_GPIOODE1 0xE3 +#define TC35892_GPIOODM2 0xE4 +#define TC35892_GPIOODE2 0xE5 + +#define TC35892_INT_GPIIRQ 0 +#define TC35892_INT_TI0IRQ 1 +#define TC35892_INT_TI1IRQ 2 +#define TC35892_INT_TI2IRQ 3 +#define TC35892_INT_ROTIRQ 5 +#define TC35892_INT_KBDIRQ 6 +#define TC35892_INT_PORIRQ 7 + +#define TC35892_NR_INTERNAL_IRQS 8 +#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) + +struct tc35892 { + struct mutex lock; + struct device *dev; + struct i2c_client *i2c; + + int irq_base; + int num_gpio; + struct tc35892_platform_data *pdata; +}; + +extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data); +extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg); +extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, + u8 *values); +extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, + const u8 *values); +extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val); + +/** + * struct tc35892_gpio_platform_data - TC35892 GPIO platform data + * @gpio_base: first gpio number assigned to TC35892. A maximum of + * %TC35892_NR_GPIOS GPIOs will be allocated. + */ +struct tc35892_gpio_platform_data { + int gpio_base; +}; + +/** + * struct tc35892_platform_data - TC35892 platform data + * @irq_base: base IRQ number. %TC35892_NR_IRQS irqs will be used. + * @gpio: GPIO-specific platform data + */ +struct tc35892_platform_data { + int irq_base; + struct tc35892_gpio_platform_data *gpio; +}; + +#define TC35892_NR_GPIOS 24 +#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) + +#endif -- cgit v1.2.3 From 25c9628f826b4564625eebb5eaed12b7f7f64ddb Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Wed, 17 Aug 2011 21:04:48 +0530 Subject: mfd: Convert tc35892 to new irq_ methods Change-Id: I841eff44f2939b5e718050039a0a2ccb87477461 Signed-off-by: Virupax Sadashivpetimath --- drivers/mfd/tc35892.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index e619e2a5599..3f3a5d8d435 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -170,8 +170,8 @@ static void tc35892_irq_dummy(unsigned int irq) static struct irq_chip tc35892_irq_chip = { .name = "tc35892", - .mask = tc35892_irq_dummy, - .unmask = tc35892_irq_dummy, + .irq_mask = tc35892_irq_dummy, + .irq_unmask = tc35892_irq_dummy, }; static int tc35892_irq_init(struct tc35892 *tc35892) @@ -180,10 +180,10 @@ static int tc35892_irq_init(struct tc35892 *tc35892) int irq; for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { - set_irq_chip_data(irq, tc35892); - set_irq_chip_and_handler(irq, &tc35892_irq_chip, + irq_set_chip_data(irq, tc35892); + irq_set_chip_and_handler(irq, &tc35892_irq_chip, handle_edge_irq); - set_irq_nested_thread(irq, 1); + irq_set_nested_thread(irq, 1); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else @@ -203,8 +203,8 @@ static void tc35892_irq_remove(struct tc35892 *tc35892) #ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif - set_irq_chip_and_handler(irq, NULL, NULL); - set_irq_chip_data(irq, NULL); + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); } } -- cgit v1.2.3 From 7a6fd327eba6b3875d9738b67e958b0c59cada1d Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Sat, 30 Oct 2010 11:39:08 +0530 Subject: mfd/tc35892: add suspend/resume support ST-Ericcson ID: TASK_ER170555 Change-Id: I6e36b7430ad1ece88600ab4e17f81d08878b34b4 Signed-off-by: Sundar Iyer --- drivers/mfd/tc35892.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index 3f3a5d8d435..9fd67e1e9a7 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -14,6 +14,9 @@ #include #include +#define TC35892_CLKMODE_MODCTL_SLEEP 0x0 +#define TC35892_CLKMODE_MODCTL_OPERATION (1 << 0) + /** * tc35892_reg_read() - read a single TC35892 register * @tc35892: Device to read from @@ -314,6 +317,42 @@ static int __devexit tc35892_remove(struct i2c_client *client) return 0; } +#if CONFIG_PM +static int tc35892_suspend(struct device *dev) +{ + struct tc35892 *tc35892 = dev_get_drvdata(dev); + struct i2c_client *client = tc35892->i2c; + int ret = 0; + + /* put the system to sleep mode */ + if (!device_may_wakeup(&client->dev)) + ret = tc35892_reg_write(tc35892, TC35892_CLKMODE, + TC35892_CLKMODE_MODCTL_SLEEP); + + return ret; +} + +static int tc35892_resume(struct device *dev) +{ + struct tc35892 *tc35892 = dev_get_drvdata(dev); + struct i2c_client *client = tc35892->i2c; + int ret = 0; + + /* enable the system into operation */ + if (!device_may_wakeup(&client->dev)) + ret = tc35892_reg_write(tc35892, TC35892_CLKMODE, + TC35892_CLKMODE_MODCTL_OPERATION); + + return ret; +} + + +static const struct dev_pm_ops tc35892_dev_pm_ops = { + .suspend = tc35892_suspend, + .resume = tc35892_resume, +}; +#endif + static const struct i2c_device_id tc35892_id[] = { { "tc35892", 24 }, { } @@ -323,6 +362,9 @@ MODULE_DEVICE_TABLE(i2c, tc35892_id); static struct i2c_driver tc35892_driver = { .driver.name = "tc35892", .driver.owner = THIS_MODULE, +#if CONFIG_PM + .driver.pm = &tc35892_dev_pm_ops, +#endif .probe = tc35892_probe, .remove = __devexit_p(tc35892_remove), .id_table = tc35892_id, -- cgit v1.2.3 From cb8acc7d5b863e8f30bae557d189d4c4cc32ee66 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 15 Nov 2010 11:19:20 +0100 Subject: MFD: Correct a few #if to #ifdef Signed-off-by: Jonas Aaberg --- drivers/mfd/tc35892.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index 9fd67e1e9a7..a149e7f62ea 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -317,7 +317,7 @@ static int __devexit tc35892_remove(struct i2c_client *client) return 0; } -#if CONFIG_PM +#ifdef CONFIG_PM static int tc35892_suspend(struct device *dev) { struct tc35892 *tc35892 = dev_get_drvdata(dev); @@ -362,7 +362,7 @@ MODULE_DEVICE_TABLE(i2c, tc35892_id); static struct i2c_driver tc35892_driver = { .driver.name = "tc35892", .driver.owner = THIS_MODULE, -#if CONFIG_PM +#ifdef CONFIG_PM .driver.pm = &tc35892_dev_pm_ops, #endif .probe = tc35892_probe, -- cgit v1.2.3 From 66e3f449d104dd7a432ede36ac16fdcaf2fdf5c1 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Tue, 16 Nov 2010 18:18:34 +0530 Subject: mfd/tc35892: fix random interrupt misses On the TC35892, a random delayed interrupt clear (GPIO IC) write locks up the child interrupts. In such a case, the original interrupt is active and not yet acknowledged. Re-check the IRQST bit for any pending interrupts and handle those. ST-Ericsson ID: 277560 Change-Id: Idce53fd1214f9ffc255b5662abb8eb030d43f0f5 Signed-off-by: Sundar Iyer --- drivers/mfd/tc35892.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index a149e7f62ea..c470917e288 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -145,6 +145,7 @@ static irqreturn_t tc35892_irq(int irq, void *data) struct tc35892 *tc35892 = data; int status; +again: status = tc35892_reg_read(tc35892, TC35892_IRQST); if (status < 0) return IRQ_NONE; @@ -159,9 +160,12 @@ static irqreturn_t tc35892_irq(int irq, void *data) /* * A dummy read or write (to any register) appears to be necessary to * have the last interrupt clear (for example, GPIO IC write) take - * effect. + * effect. In such a case, recheck for any interrupt which is still + * pending. */ - tc35892_reg_read(tc35892, TC35892_IRQST); + status = tc35892_reg_read(tc35892, TC35892_IRQST); + if (status) + goto again; return IRQ_HANDLED; } -- cgit v1.2.3 From ba133989bb85a49900862b7851b11f0680a967e9 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Wed, 24 Nov 2010 12:31:55 +0530 Subject: mfd/tc35892: undo gpio module reset during chip init Skip putting the GPIO module into a reset during the chip init. This makes sure to preserve any existing GPIO configurations done by pre-kernel boot code. ST-Ericsson ID: ER277334 Change-Id: Ia6727a1f268db0576f5eb40b5dc5c30f6abecba7 Signed-off-by: Sundar Iyer --- drivers/mfd/tc35892.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index c470917e288..33d44bbc731 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -234,12 +234,15 @@ static int tc35892_chip_init(struct tc35892 *tc35892) dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); - /* Put everything except the IRQ module into reset */ + /* + * Put everything except the IRQ module into reset; + * also spare the GPIO module for any pin initialization + * done during pre-kernel boot + */ ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, TC35892_RSTCTRL_TIMRST | TC35892_RSTCTRL_ROTRST - | TC35892_RSTCTRL_KBDRST - | TC35892_RSTCTRL_GPIRST); + | TC35892_RSTCTRL_KBDRST); if (ret < 0) return ret; -- cgit v1.2.3 From 2cfecece99f1f7b737663f778069d907a75b6063 Mon Sep 17 00:00:00 2001 From: David Paris Date: Fri, 4 Mar 2011 14:57:08 +0100 Subject: MFD: tc35892: Optimize power save settings for suspend Compared to HSI GPIO V3.1, register 0x82 is set with a different value 0x82 = 0xE (HSI GPIO V3.1) 0x82 = 0xF (on android) In case of android, it seems that GPIO reset should be applied to reach 13uA of consumption on TC35892 when AP in DeepSleep Change-Id: I64eaa4304fcd9f71546cadba0aa703c91b6075df Signed-off-by: David Paris Signed-off-by: Jonas Aaberg --- drivers/mfd/tc35892.c | 131 ++++++++++++++++++++++++++++++++++++++++---- include/linux/mfd/tc35892.h | 60 +++++++++++--------- 2 files changed, 155 insertions(+), 36 deletions(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index 33d44bbc731..c997a4b67aa 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -325,17 +325,112 @@ static int __devexit tc35892_remove(struct i2c_client *client) } #ifdef CONFIG_PM + +static u32 sleep_regs[] = { + TC35892_IOPC0_L, + TC35892_IOPC0_H, + TC35892_IOPC1_L, + TC35892_IOPC1_H, + TC35892_IOPC2_L, + TC35892_IOPC2_H, + TC35892_DRIVE0_L, + TC35892_DRIVE0_H, + TC35892_DRIVE1_L, + TC35892_DRIVE1_H, + TC35892_DRIVE2_L, + TC35892_DRIVE2_H, + TC35892_DRIVE3, + TC35892_GPIODATA0, + TC35892_GPIOMASK0, + TC35892_GPIODATA1, + TC35892_GPIOMASK1, + TC35892_GPIODATA2, + TC35892_GPIOMASK2, + TC35892_GPIODIR0, + TC35892_GPIODIR1, + TC35892_GPIODIR2, + TC35892_GPIOIE0, + TC35892_GPIOIE1, + TC35892_GPIOIE2, + TC35892_RSTCTRL, + TC35892_CLKCFG, +}; + +static u8 sleep_regs_val[] = { + 0x00, /* TC35892_IOPC0_L */ + 0x00, /* TC35892_IOPC0_H */ + 0x00, /* TC35892_IOPC1_L */ + 0x00, /* TC35892_IOPC1_H */ + 0x00, /* TC35892_IOPC2_L */ + 0x00, /* TC35892_IOPC2_H */ + 0xff, /* TC35892_DRIVE0_L */ + 0xff, /* TC35892_DRIVE0_H */ + 0xff, /* TC35892_DRIVE1_L */ + 0xff, /* TC35892_DRIVE1_H */ + 0xff, /* TC35892_DRIVE2_L */ + 0xff, /* TC35892_DRIVE2_H */ + 0x0f, /* TC35892_DRIVE3 */ + 0x80, /* TC35892_GPIODATA0 */ + 0x80, /* TC35892_GPIOMASK0 */ + 0x80, /* TC35892_GPIODATA1 */ + 0x80, /* TC35892_GPIOMASK1 */ + 0x06, /* TC35892_GPIODATA2 */ + 0x06, /* TC35892_GPIOMASK2 */ + 0xf0, /* TC35892_GPIODIR0 */ + 0xe0, /* TC35892_GPIODIR1 */ + 0xee, /* TC35892_GPIODIR2 */ + 0x0f, /* TC35892_GPIOIE0 */ + 0x1f, /* TC35892_GPIOIE1 */ + 0x11, /* TC35892_GPIOIE2 */ + 0x0f, /* TC35892_RSTCTRL */ + 0xb0 /* TC35892_CLKCFG */ + +}; + +static u8 sleep_regs_backup[ARRAY_SIZE(sleep_regs)]; + static int tc35892_suspend(struct device *dev) { struct tc35892 *tc35892 = dev_get_drvdata(dev); struct i2c_client *client = tc35892->i2c; int ret = 0; - - /* put the system to sleep mode */ - if (!device_may_wakeup(&client->dev)) - ret = tc35892_reg_write(tc35892, TC35892_CLKMODE, - TC35892_CLKMODE_MODCTL_SLEEP); - + int i, j; + int val; + + /* Put the system to sleep mode */ + if (!device_may_wakeup(&client->dev)) { + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + val = tc35892_reg_read(tc35892, + sleep_regs[i]); + if (val < 0) + goto out; + + sleep_regs_backup[i] = (u8) (val & 0xff); + } + + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + ret = tc35892_reg_write(tc35892, + sleep_regs[i], + sleep_regs_val[i]); + if (ret < 0) + goto fail; + + } + + ret = tc35892_reg_write(tc35892, + TC35892_CLKMODE, + TC35892_CLKMODE_MODCTL_SLEEP); + } +out: + return ret; +fail: + for (j = 0; j <= i; j++) { + ret = tc35892_reg_write(tc35892, + sleep_regs[i], + sleep_regs_backup[i]); + if (ret < 0) + break; + } return ret; } @@ -344,16 +439,30 @@ static int tc35892_resume(struct device *dev) struct tc35892 *tc35892 = dev_get_drvdata(dev); struct i2c_client *client = tc35892->i2c; int ret = 0; + int i; - /* enable the system into operation */ + /* Enable the system into operation */ if (!device_may_wakeup(&client->dev)) - ret = tc35892_reg_write(tc35892, TC35892_CLKMODE, - TC35892_CLKMODE_MODCTL_OPERATION); - + { + ret = tc35892_reg_write(tc35892, + TC35892_CLKMODE, + TC35892_CLKMODE_MODCTL_OPERATION); + if (ret < 0) + goto out; + + for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + ret = tc35892_reg_write(tc35892, + sleep_regs[i], + sleep_regs_backup[i]); + /* Not much to do here if we fail */ + if (ret < 0) + break; + } + } +out: return ret; } - static const struct dev_pm_ops tc35892_dev_pm_ops = { .suspend = tc35892_suspend, .resume = tc35892_resume, diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h index e47f770d306..41b572c1f8e 100644 --- a/include/linux/mfd/tc35892.h +++ b/include/linux/mfd/tc35892.h @@ -15,21 +15,43 @@ #define TC35892_RSTCTRL_KBDRST (1 << 1) #define TC35892_RSTCTRL_GPIRST (1 << 0) -#define TC35892_IRQST 0x91 -#define TC35892_MANFCODE_MAGIC 0x03 #define TC35892_MANFCODE 0x80 +#define TC35892_MANFCODE_MAGIC 0x03 #define TC35892_VERSION 0x81 -#define TC35892_IOCFG 0xA7 - +#define TC35892_RSTCTRL 0x82 +#define TC35892_EXTRSTN 0x83 +#define TC35892_RSTINTCLR 0x84 #define TC35892_CLKMODE 0x88 #define TC35892_CLKCFG 0x89 #define TC35892_CLKEN 0x8A +#define TC35892_IRQST 0x91 -#define TC35892_RSTCTRL 0x82 -#define TC35892_EXTRSTN 0x83 -#define TC35892_RSTINTCLR 0x84 +#define TC35892_DRIVE0_L 0xA0 +#define TC35892_DRIVE0_H 0xA1 +#define TC35892_DRIVE1_L 0xA2 +#define TC35892_DRIVE1_H 0xA3 +#define TC35892_DRIVE2_L 0xA4 +#define TC35892_DRIVE2_H 0XA5 +#define TC35892_DRIVE3 0xA6 +#define TC35892_IOCFG 0xA7 + +#define TC35892_IOPC0_L 0xAA +#define TC35892_IOPC0_H 0xAB +#define TC35892_IOPC1_L 0xAC +#define TC35892_IOPC1_H 0xAD +#define TC35892_IOPC2_L 0xAE +#define TC35892_IOPC2_H 0xAF +#define TC35892_GPIODATA0 0xC0 +#define TC35892_GPIOMASK0 0xC1 +#define TC35892_GPIODATA1 0xC2 +#define TC35892_GPIOMASK1 0xC3 +#define TC35892_GPIODATA2 0xC4 +#define TC35892_GPIOMASK2 0xC5 +#define TC35892_GPIODIR0 0xC6 +#define TC35892_GPIODIR1 0xC7 +#define TC35892_GPIODIR2 0xC8 #define TC35892_GPIOIS0 0xC9 #define TC35892_GPIOIS1 0xCA #define TC35892_GPIOIS2 0xCB @@ -51,17 +73,12 @@ #define TC35892_GPIOIC0 0xDC #define TC35892_GPIOIC1 0xDD #define TC35892_GPIOIC2 0xDE - -#define TC35892_GPIODATA0 0xC0 -#define TC35892_GPIOMASK0 0xc1 -#define TC35892_GPIODATA1 0xC2 -#define TC35892_GPIOMASK1 0xc3 -#define TC35892_GPIODATA2 0xC4 -#define TC35892_GPIOMASK2 0xC5 - -#define TC35892_GPIODIR0 0xC6 -#define TC35892_GPIODIR1 0xC7 -#define TC35892_GPIODIR2 0xC8 +#define TC35892_GPIOODM0 0xE0 +#define TC35892_GPIOODE0 0xE1 +#define TC35892_GPIOODM1 0xE2 +#define TC35892_GPIOODE1 0xE3 +#define TC35892_GPIOODM2 0xE4 +#define TC35892_GPIOODE2 0xE5 #define TC35892_GPIOSYNC0 0xE6 #define TC35892_GPIOSYNC1 0xE7 @@ -71,13 +88,6 @@ #define TC35892_GPIOWAKE1 0xEA #define TC35892_GPIOWAKE2 0xEB -#define TC35892_GPIOODM0 0xE0 -#define TC35892_GPIOODE0 0xE1 -#define TC35892_GPIOODM1 0xE2 -#define TC35892_GPIOODE1 0xE3 -#define TC35892_GPIOODM2 0xE4 -#define TC35892_GPIOODE2 0xE5 - #define TC35892_INT_GPIIRQ 0 #define TC35892_INT_TI0IRQ 1 #define TC35892_INT_TI1IRQ 2 -- cgit v1.2.3 From c9e3dcc6075ed26d4762a0bb3913483a7c67a809 Mon Sep 17 00:00:00 2001 From: Martin Persson Date: Mon, 28 Mar 2011 11:50:24 +0200 Subject: MFD: tc35892: Correct optimized power settings Change-Id: I83fd9379c037fe3c949aa5d01a99423d2fc555b4 Signed-off-by: Martin Persson --- drivers/mfd/tc35892.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index c997a4b67aa..91211f29623 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -450,7 +450,7 @@ static int tc35892_resume(struct device *dev) if (ret < 0) goto out; - for (i = 0; i < ARRAY_SIZE(sleep_regs); i++) { + for (i = ARRAY_SIZE(sleep_regs) - 1; i >= 0; i--) { ret = tc35892_reg_write(tc35892, sleep_regs[i], sleep_regs_backup[i]); -- cgit v1.2.3 From 518d244f27fa37638af038e80bbadbe0c17905c0 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 17 Aug 2011 21:29:59 +0530 Subject: ARM: 6373/1: tc35892-gpio: add setup/remove callbacks For board-specific initialization. Change-Id: I8a13382bf91608b9edf2e712cff157b14e20848a Cc: Samuel Ortiz Cc: linux-kernel@vger.kernel.org Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King Signed-off-by: Virupax Sadashivpetimath --- include/linux/mfd/tc35892.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h index 41b572c1f8e..8c5385c2191 100644 --- a/include/linux/mfd/tc35892.h +++ b/include/linux/mfd/tc35892.h @@ -121,9 +121,13 @@ extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val); * struct tc35892_gpio_platform_data - TC35892 GPIO platform data * @gpio_base: first gpio number assigned to TC35892. A maximum of * %TC35892_NR_GPIOS GPIOs will be allocated. + * @setup: callback for board-specific initialization + * @remove: callback for board-specific teardown */ struct tc35892_gpio_platform_data { int gpio_base; + void (*setup)(struct tc35892 *tc35892, unsigned gpio_base); + void (*remove)(struct tc35892 *tc35892, unsigned gpio_base); }; /** -- cgit v1.2.3 From 8cd41cfd5bd2cc90974294484331ea51fa4ed869 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 26 Aug 2011 16:19:48 +0530 Subject: u8500: enable PRCMU and disable 5500 in defconfig Change-Id: Ieffe86726e7efb682c58b00dbc7796875e2dfd44 --- arch/arm/configs/u8500_defconfig | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3455f7c9904..466ec299e55 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -20,7 +20,6 @@ CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y -CONFIG_UX500_SOC_DB5500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y @@ -28,15 +27,20 @@ CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_PRCMU_TIMER=y +CONFIG_U8500_PRCMU=y +CONFIG_UX500_PRCMU_DEBUG=y +CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y -CONFIG_U5500_MLOADER=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y +CONFIG_U8500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -230,7 +234,6 @@ CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y CONFIG_U8500_MMIO=y -CONFIG_U5500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y CONFIG_MODEM=y @@ -290,10 +293,8 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_FUNCTION_TRACER=y CONFIG_DEBUG_USER=y CONFIG_KEYS=y -CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ARC4=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -- cgit v1.2.3 From 06450a4cc88d65f4e1467382f6587e780942d4aa Mon Sep 17 00:00:00 2001 From: Fredrik Allansson Date: Fri, 15 Oct 2010 16:07:53 +0200 Subject: misc: dispdev: Migrate to kernel 3.0 apply below mcde mach-ux500 patches for kernel3.0 migration ce479ee [ANDROID] misc: dispdev: Add dispdev driver f499637 misc: dispdev: Enable dispdev in U5500 b07b4c [ANDROID] misc: dispdev: Disable UI overlay ST-Ericsson ID: 352334 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Signed-off-by: Rajagopala V Change-Id: I4afae8f61b28754cb0380d44c9b2273c958572a9 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29655 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 466ec299e55..2e995c31a46 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -110,6 +110,7 @@ CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y +CONFIG_DISPDEV=y # CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y -- cgit v1.2.3 From a67df1f9bf1e46df8f0d0537f7d3d3d400d40dd3 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Fri, 5 Aug 2011 16:52:41 +0530 Subject: hwmon: dbx500: Migrate to kernel3.0 Patch includes following commits u5500: prcmu: add irqs for db5500 temperature sensor dbx500: hwmon: temperature monitor support for DB5500 ST-Ericsson ID: 352334 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Signed-off-by: Rajagopala V Change-Id: I4df816759c0f8d039b88788e35372c05990c11ce Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29681 --- arch/arm/configs/u8500_defconfig | 2 +- drivers/hwmon/Kconfig | 12 +- drivers/hwmon/Makefile | 2 +- drivers/hwmon/db8500.c | 450 -------------------------------------- drivers/hwmon/dbx500.c | 455 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 463 insertions(+), 458 deletions(-) delete mode 100755 drivers/hwmon/db8500.c create mode 100644 drivers/hwmon/dbx500.c diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 2e995c31a46..c2bfd0829b1 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -159,7 +159,7 @@ CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y CONFIG_SENSORS_AB8500=y -CONFIG_SENSORS_DB8500=y +CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index ecb19ff1a40..297ad8e3b28 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -64,17 +64,17 @@ config SENSORS_AB5500 This driver can also be built as a module. If so, the module will be called abx500-temp. -config SENSORS_DB8500 - tristate "DB8500 thermal monitoring" - depends on UX500_SOC_DB8500 +config SENSORS_DBX500 + tristate "DBX500 thermal monitoring" + depends on U8500_PRCMU || U5500_PRCMU default n help If you say yes here you get support for the thermal sensor part - of the DB8500 chip. The driver includes thermal management for - DB8500 die. + of the DBX500 chip. The driver includes thermal management for + DBX500 die. This driver can also be built as a module. If so, the module - will be called db8500_temp. + will be called dbx500_temp. config SENSORS_ABITUGURU diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 39bdd768b24..1e893cbdb83 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o obj-$(CONFIG_SENSORS_AB8500) += abx500.o ab8500.o obj-$(CONFIG_SENSORS_AB5500) += abx500.o ab5500.o -obj-$(CONFIG_SENSORS_DB8500) += db8500.o +obj-$(CONFIG_SENSORS_DBX500) += dbx500.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o obj-$(CONFIG_SENSORS_AD7314) += ad7314.o diff --git a/drivers/hwmon/db8500.c b/drivers/hwmon/db8500.c deleted file mode 100755 index c08ab033ada..00000000000 --- a/drivers/hwmon/db8500.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - * - * Author: WenHai Fang for - * ST-Ericsson. - * License terms: GNU Gereral Public License (GPL) version 2 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * If DB8500 warm interrupt is set, user space will be notified. - * If user space doesn't shut down the platform within this time - * frame, this driver will. Time unit is ms. - */ -#define DEFAULT_POWER_OFF_DELAY 10000 - -/* - * Default measure period to 0xFF x cycle32k - */ -#define DEFAULT_MEASURE_TIME 0xFF - -/* This driver monitors DB thermal*/ -#define NUM_SENSORS 1 - -struct db8500_temp { - struct platform_device *pdev; - struct device *hwmon_dev; - unsigned char min[NUM_SENSORS]; - unsigned char max[NUM_SENSORS]; - unsigned char crit[NUM_SENSORS]; - unsigned char min_alarm[NUM_SENSORS]; - unsigned char max_alarm[NUM_SENSORS]; - unsigned short measure_time; - struct delayed_work power_off_work; - struct mutex lock; - /* Delay (ms) before power off */ - unsigned long power_off_delay; -}; - -static void thermal_power_off(struct work_struct *work) -{ - struct db8500_temp *data = container_of(work, struct db8500_temp, - power_off_work.work); - - dev_warn(&data->pdev->dev, "Power off due to DB8500 thermal warning\n"); - pm_power_off(); -} - -static ssize_t set_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int res; - unsigned long delay_in_s; - struct db8500_temp *data = dev_get_drvdata(dev); - - res = strict_strtoul(buf, 10, &delay_in_s); - if (res < 0) { - dev_warn(&data->pdev->dev, "Set power_off_delay wrong\n"); - return res; - } - - mutex_lock(&data->lock); - data->power_off_delay = delay_in_s * 1000; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - /* return time in s, not ms */ - return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); -} - -/* HWMON sysfs interface */ -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "db8500\n"); -} - -static ssize_t show_label(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "db8500\n"); -} - -/* set functions (RW nodes) */ -static ssize_t set_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - val &= 0xFF; - if (val > data->max[attr->index - 1]) - val = data->max[attr->index - 1]; - - data->min[attr->index - 1] = val; - - (void)prcmu_config_hotmon(data->min[attr->index - 1], - data->max[attr->index - 1]); - mutex_unlock(&data->lock); - return count; -} - -static ssize_t set_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - val &= 0xFF; - if (val < data->min[attr->index - 1]) - val = data->min[attr->index - 1]; - - data->max[attr->index - 1] = val; - - (void)prcmu_config_hotmon(data->min[attr->index - 1], - data->max[attr->index - 1]); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t set_crit(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - val &= 0xFF; - data->crit[attr->index - 1] = val; - (void)prcmu_config_hotdog(data->crit[attr->index - 1]); - mutex_unlock(&data->lock); - - return count; -} - -/* start/stop temperature measurement */ -static ssize_t start_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - data->measure_time = val & 0xFFFF; - data->min_alarm[attr->index - 1] = 0; - data->max_alarm[attr->index - 1] = 0; - mutex_unlock(&data->lock); - - (void)prcmu_start_temp_sense(data->measure_time); - dev_dbg(&data->pdev->dev, "DB8500 thermal start measurement\n"); - return count; -} - -static ssize_t stop_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct db8500_temp *data = dev_get_drvdata(dev); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - (void)prcmu_stop_temp_sense(); - dev_dbg(&data->pdev->dev, "DB8500 thermal stop measurement\n"); - - return count; -} - -/* - * show functions (RO nodes) - * Notice that min/max/crit refer to degrees - */ -static ssize_t show_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%d\n", data->min[attr->index - 1]); -} - -static ssize_t show_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%d\n", data->max[attr->index - 1]); -} - -static ssize_t show_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%d\n", data->crit[attr->index - 1]); -} - -/* Alarms */ -static ssize_t show_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%d\n", data->min_alarm[attr->index - 1]); -} - -static ssize_t show_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct db8500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - /* hwmon attr index starts at 1, thus "attr->index-1" below */ - return sprintf(buf, "%d\n", data->max_alarm[attr->index - 1]); -} - -/*These node are not included in the kernel hwmon sysfs interface */ -static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, - show_temp_power_off_delay, - set_temp_power_off_delay, 0); - -/* Chip name, required by hwmon*/ -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, - show_crit, set_crit, 1); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); - -static struct attribute *db8500_temp_attributes[] = { - &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, - &sensor_dev_attr_temp1_start.dev_attr.attr, - &sensor_dev_attr_temp1_stop.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group db8500_temp_group = { - .attrs = db8500_temp_attributes, -}; - -static irqreturn_t prcmu_hotmon_low_irq_handler(int irq, void *irq_data) -{ - struct platform_device *pdev = irq_data; - struct db8500_temp *data = platform_get_drvdata(pdev); - - mutex_lock(&data->lock); - data->min_alarm[0] = 1; - mutex_unlock(&data->lock); - - sysfs_notify(&pdev->dev.kobj, NULL, "temp1_min_alarm"); - dev_dbg(&pdev->dev, "DB8500 thermal low warning\n"); - return IRQ_HANDLED; -} - -static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) -{ - unsigned long delay_in_jiffies; - struct platform_device *pdev = irq_data; - struct db8500_temp *data = platform_get_drvdata(pdev); - - mutex_lock(&data->lock); - data->max_alarm[0] = 1; - mutex_unlock(&data->lock); - - sysfs_notify(&pdev->dev.kobj, NULL, "temp1_max_alarm"); - dev_dbg(&pdev->dev, "DB8500 thermal warning, power off in %lu s\n", - (data->power_off_delay) / 1000); - delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); - schedule_delayed_work(&data->power_off_work, delay_in_jiffies); - return IRQ_HANDLED; -} - -static int __devinit db8500_temp_probe(struct platform_device *pdev) -{ - struct db8500_temp *data; - int err = 0, i; - int irq; - - dev_dbg(&pdev->dev, "db8500_temp: Function db8500_temp_probe.\n"); - - data = kzalloc(sizeof(struct db8500_temp), GFP_KERNEL); - if (!data) - return -ENOMEM; - - irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW"); - if (irq < 0) { - dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed\n"); - goto exit; - } - - err = request_threaded_irq(irq, NULL, prcmu_hotmon_low_irq_handler, - IRQF_NO_SUSPEND, "db8500_temp_low", pdev); - if (err < 0) { - dev_err(&pdev->dev, "db8500: Failed allocate HOTMON_LOW.\n"); - goto exit; - } else { - dev_dbg(&pdev->dev, "db8500: Succeed allocate HOTMON_LOW.\n"); - } - - irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH"); - if (irq < 0) { - dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed\n"); - goto exit; - } - - err = request_threaded_irq(irq, NULL, prcmu_hotmon_high_irq_handler, - IRQF_NO_SUSPEND, "db8500_temp_high", pdev); - if (err < 0) { - dev_err(&pdev->dev, "db8500: Failed allocate HOTMON_HIGH.\n"); - goto exit; - } else { - dev_dbg(&pdev->dev, "db8500: Succeed allocate HOTMON_HIGH.\n"); - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", err); - goto exit; - } - - for (i = 0; i < NUM_SENSORS; i++) { - data->min[i] = 0; - data->max[i] = 0xFF; - data->crit[i] = 0xFF; - data->min_alarm[i] = 0; - data->max_alarm[i] = 0; - } - - mutex_init(&data->lock); - INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); - - data->pdev = pdev; - data->power_off_delay = DEFAULT_POWER_OFF_DELAY; - data->measure_time = DEFAULT_MEASURE_TIME; - - platform_set_drvdata(pdev, data); - - err = sysfs_create_group(&pdev->dev.kobj, &db8500_temp_group); - if (err < 0) { - dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); - goto exit_platform_data; - } - - return 0; - -exit_platform_data: - platform_set_drvdata(pdev, NULL); -exit: - kfree(data); - return err; -} - -static int __devexit db8500_temp_remove(struct platform_device *pdev) -{ - struct db8500_temp *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &db8500_temp_group); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; -} - -/* No action required in suspend/resume, thus the lack of functions */ -static struct platform_driver db8500_temp_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "db8500_temp", - }, - .probe = db8500_temp_probe, - .remove = __devexit_p(db8500_temp_remove), -}; - -static int __init db8500_temp_init(void) -{ - return platform_driver_register(&db8500_temp_driver); -} - -static void __exit db8500_temp_exit(void) -{ - platform_driver_unregister(&db8500_temp_driver); -} - -MODULE_AUTHOR("WenHai Fang "); -MODULE_DESCRIPTION("DB8500 temperature driver"); -MODULE_LICENSE("GPL"); - -module_init(db8500_temp_init) -module_exit(db8500_temp_exit) diff --git a/drivers/hwmon/dbx500.c b/drivers/hwmon/dbx500.c new file mode 100644 index 00000000000..a26e08b3707 --- /dev/null +++ b/drivers/hwmon/dbx500.c @@ -0,0 +1,455 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + * + * Author: WenHai Fang for + * ST-Ericsson. + * License terms: GNU Gereral Public License (GPL) version 2 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * If DBX500 warm interrupt is set, user space will be notified. + * If user space doesn't shut down the platform within this time + * frame, this driver will. Time unit is ms. + */ +#define DEFAULT_POWER_OFF_DELAY 10000 + +/* + * Default measure period to 0xFF x cycle32k + */ +#define DEFAULT_MEASURE_TIME 0xFF + +/* This driver monitors DB thermal*/ +#define NUM_SENSORS 1 + +struct dbx500_temp { + struct platform_device *pdev; + struct device *hwmon_dev; + unsigned char min[NUM_SENSORS]; + unsigned char max[NUM_SENSORS]; + unsigned char crit[NUM_SENSORS]; + unsigned char min_alarm[NUM_SENSORS]; + unsigned char max_alarm[NUM_SENSORS]; + unsigned short measure_time; + struct delayed_work power_off_work; + struct mutex lock; + /* Delay (ms) before power off */ + unsigned long power_off_delay; +}; + +static void thermal_power_off(struct work_struct *work) +{ + struct dbx500_temp *data = container_of(work, struct dbx500_temp, + power_off_work.work); + + dev_warn(&data->pdev->dev, "Power off due to DBX500 thermal warning\n"); + pm_power_off(); +} + +static ssize_t set_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int res; + unsigned long delay_in_s; + struct dbx500_temp *data = dev_get_drvdata(dev); + + res = strict_strtoul(buf, 10, &delay_in_s); + if (res < 0) { + dev_warn(&data->pdev->dev, "Set power_off_delay wrong\n"); + return res; + } + + mutex_lock(&data->lock); + data->power_off_delay = delay_in_s * 1000; + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp_power_off_delay(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + /* return time in s, not ms */ + return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); +} + +/* HWMON sysfs interface */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "dbx500\n"); +} + +static ssize_t show_label(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return show_name(dev, devattr, buf); +} + +/* set functions (RW nodes) */ +static ssize_t set_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val &= 0xFF; + if (val > data->max[attr->index - 1]) + val = data->max[attr->index - 1]; + + data->min[attr->index - 1] = val; + + (void)prcmu_config_hotmon(data->min[attr->index - 1], + data->max[attr->index - 1]); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t set_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val &= 0xFF; + if (val < data->min[attr->index - 1]) + val = data->min[attr->index - 1]; + + data->max[attr->index - 1] = val; + + (void)prcmu_config_hotmon(data->min[attr->index - 1], + data->max[attr->index - 1]); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_crit(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + val &= 0xFF; + data->crit[attr->index - 1] = val; + (void)prcmu_config_hotdog(data->crit[attr->index - 1]); + mutex_unlock(&data->lock); + + return count; +} + +/* start/stop temperature measurement */ +static ssize_t start_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + mutex_lock(&data->lock); + data->measure_time = val & 0xFFFF; + data->min_alarm[attr->index - 1] = 0; + data->max_alarm[attr->index - 1] = 0; + mutex_unlock(&data->lock); + + (void)prcmu_start_temp_sense(data->measure_time); + dev_dbg(&data->pdev->dev, "DBX500 thermal start measurement\n"); + + return count; +} + +static ssize_t stop_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long val; + struct dbx500_temp *data = dev_get_drvdata(dev); + int res = strict_strtoul(buf, 10, &val); + if (res < 0) + return res; + + (void)prcmu_stop_temp_sense(); + dev_dbg(&data->pdev->dev, "DBX500 thermal stop measurement\n"); + + return count; +} + +/* + * show functions (RO nodes) + * Notice that min/max/crit refer to degrees + */ +static ssize_t show_min(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->min[attr->index - 1]); +} + +static ssize_t show_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->max[attr->index - 1]); +} + +static ssize_t show_crit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->crit[attr->index - 1]); +} + +/* Alarms */ +static ssize_t show_min_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->min_alarm[attr->index - 1]); +} + +static ssize_t show_max_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct dbx500_temp *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + /* hwmon attr index starts at 1, thus "attr->index-1" below */ + return sprintf(buf, "%d\n", data->max_alarm[attr->index - 1]); +} + +/*These node are not included in the kernel hwmon sysfs interface */ +static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, + show_temp_power_off_delay, + set_temp_power_off_delay, 0); + +/* Chip name, required by hwmon*/ +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, + show_crit, set_crit, 1); +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); + +static struct attribute *dbx500_temp_attributes[] = { + &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, + &sensor_dev_attr_name.dev_attr.attr, + &sensor_dev_attr_temp1_start.dev_attr.attr, + &sensor_dev_attr_temp1_stop.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group dbx500_temp_group = { + .attrs = dbx500_temp_attributes, +}; + +static irqreturn_t prcmu_hotmon_low_irq_handler(int irq, void *irq_data) +{ + struct platform_device *pdev = irq_data; + struct dbx500_temp *data = platform_get_drvdata(pdev); + + mutex_lock(&data->lock); + data->min_alarm[0] = 1; + mutex_unlock(&data->lock); + + sysfs_notify(&pdev->dev.kobj, NULL, "temp1_min_alarm"); + dev_dbg(&pdev->dev, "DBX500 thermal low warning\n"); + return IRQ_HANDLED; +} + +static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) +{ + unsigned long delay_in_jiffies; + struct platform_device *pdev = irq_data; + struct dbx500_temp *data = platform_get_drvdata(pdev); + + mutex_lock(&data->lock); + data->max_alarm[0] = 1; + mutex_unlock(&data->lock); + + sysfs_notify(&pdev->dev.kobj, NULL, "temp1_max_alarm"); + dev_dbg(&pdev->dev, "DBX500 thermal warning, power off in %lu s\n", + (data->power_off_delay) / 1000); + delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); + schedule_delayed_work(&data->power_off_work, delay_in_jiffies); + return IRQ_HANDLED; +} + +static int __devinit dbx500_temp_probe(struct platform_device *pdev) +{ + struct dbx500_temp *data; + int err = 0, i; + int irq; + + dev_dbg(&pdev->dev, "dbx500_temp: Function dbx500_temp_probe.\n"); + + data = kzalloc(sizeof(struct dbx500_temp), GFP_KERNEL); + if (!data) + return -ENOMEM; + + irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW"); + if (irq < 0) { + dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed\n"); + goto exit; + } + + err = request_threaded_irq(irq, NULL, + prcmu_hotmon_low_irq_handler, + IRQF_NO_SUSPEND, + "dbx500_temp_low", pdev); + if (err < 0) { + dev_err(&pdev->dev, "dbx500: Failed allocate HOTMON_LOW.\n"); + goto exit; + } else { + dev_dbg(&pdev->dev, "dbx500: Succeed allocate HOTMON_LOW.\n"); + } + + irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH"); + if (irq < 0) { + dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed\n"); + goto exit; + } + + err = request_threaded_irq(irq, NULL, + prcmu_hotmon_high_irq_handler, + IRQF_NO_SUSPEND, + "dbx500_temp_high", pdev); + if (err < 0) { + dev_err(&pdev->dev, "dbx500: Failed allocate HOTMON_HIGH.\n"); + goto exit; + } else { + dev_dbg(&pdev->dev, "dbx500: Succeed allocate HOTMON_HIGH.\n"); + } + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + dev_err(&pdev->dev, "Class registration failed (%d)\n", err); + goto exit; + } + + for (i = 0; i < NUM_SENSORS; i++) { + data->min[i] = 0; + data->max[i] = 0xFF; + data->crit[i] = 0xFF; + data->min_alarm[i] = 0; + data->max_alarm[i] = 0; + } + + mutex_init(&data->lock); + INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); + + data->pdev = pdev; + data->power_off_delay = DEFAULT_POWER_OFF_DELAY; + data->measure_time = DEFAULT_MEASURE_TIME; + + platform_set_drvdata(pdev, data); + + err = sysfs_create_group(&pdev->dev.kobj, &dbx500_temp_group); + if (err < 0) { + dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err); + goto exit_platform_data; + } + + return 0; + +exit_platform_data: + platform_set_drvdata(pdev, NULL); +exit: + kfree(data); + return err; +} + +static int __devexit dbx500_temp_remove(struct platform_device *pdev) +{ + struct dbx500_temp *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &dbx500_temp_group); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +/* No action required in suspend/resume, thus the lack of functions */ +static struct platform_driver dbx500_temp_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "dbx500_temp", + }, + .probe = dbx500_temp_probe, + .remove = __devexit_p(dbx500_temp_remove), +}; + +static int __init dbx500_temp_init(void) +{ + return platform_driver_register(&dbx500_temp_driver); +} + +static void __exit dbx500_temp_exit(void) +{ + platform_driver_unregister(&dbx500_temp_driver); +} + +MODULE_AUTHOR("WenHai Fang "); +MODULE_DESCRIPTION("DBX500 temperature driver"); +MODULE_LICENSE("GPL"); + +module_init(dbx500_temp_init) +module_exit(dbx500_temp_exit) -- cgit v1.2.3 From 6ab6831fef18468b1626785d112ae500b5358abb Mon Sep 17 00:00:00 2001 From: Magnus Wendt Date: Thu, 19 May 2011 16:59:12 +0200 Subject: ux500: configs/: Include mali in ux500_defconfigs Include mali device driver support in the ux500_defconfigs. If the mali400ko git is not checked out in the drivers/gpu/imali/mali400ko folder the mali driver will be excluded from the build. ST-Ericsson ID: CR335265, CR341392 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5ad86540ba0516d0564b8bf95a66d479a61d1882 Signed-off-by: Magnus Wendt Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29946 Reviewed-by: Robert FEKETE Tested-by: Robert FEKETE Reviewed-by: Ushit KUMAR Tested-by: Ushit KUMAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c2bfd0829b1..44db8af014f 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -179,6 +179,7 @@ CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y +CONFIG_GPU_MALI=y CONFIG_B2R2_PLUG_CONF=y CONFIG_SOUND=y CONFIG_SND=y -- cgit v1.2.3 From 9e88c12b8853e9d0db699e44f3befee0d6a181af Mon Sep 17 00:00:00 2001 From: Naveen Kumar Gaddipati Date: Mon, 5 Sep 2011 19:09:29 +0530 Subject: mach-ux500:Video default config kernel 3.0 migration Video default config kernel 3.0 migrate for MCDE, B2R2 and av8100 drivers. ST-Ericsson ID: 352334 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Signed-off-by: Naveen Kumar Gaddipati Change-Id: I67e7466b79cfeb593ba9113fd75e60bdaf3cdfbb Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30129 --- arch/arm/configs/u8500_defconfig | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 44db8af014f..4d368f98783 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -31,7 +31,11 @@ CONFIG_U8500_PRCMU=y CONFIG_UX500_PRCMU_DEBUG=y CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y +CONFIG_DISPLAY_GENERIC_PRIMARY=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_90=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y @@ -175,12 +179,28 @@ CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set # CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_GPU_MALI=y +CONFIG_GPU_MALI_DEBUG=y CONFIG_FB=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +CONFIG_FB_SYS_FOPS=y CONFIG_FB_MCDE=y -CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_MCDE_DISPLAY_GENERIC_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE=y CONFIG_FB_B2R2=y -CONFIG_GPU_MALI=y CONFIG_B2R2_PLUG_CONF=y +CONFIG_B2R2_OPSIZE_64=y +CONFIG_B2R2_CHSIZE_128=y +CONFIG_B2R2_MGSIZE_128=y +CONFIG_B2R2_PGSIZE_256=y +CONFIG_B2R2_GENERIC=y +CONFIG_B2R2_GENERIC_FALLBACK=y +CONFIG_AV8100=y +CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_DUMMY_CONSOLE=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y -- cgit v1.2.3 From d0581ae9f00986231647496a55c0ae7f0dcbbf1a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 6 Sep 2011 09:26:47 +0530 Subject: ab5500: move to separate header Use new include/linux/mfd/abx500/ab5500.h instead of upstream include/linux/mfd/ab5500/ab5500.h file Change-Id: I11dd2a23323229096b6e0ee2d4dc68cab8919bff --- drivers/leds/leds-ab5500.c | 1 + drivers/mfd/ab5500-gpadc.c | 1 + drivers/mfd/ab5500-power.c | 1 + drivers/power/ab5500_btemp.c | 1 + drivers/power/ab5500_charger.c | 1 + drivers/power/ab5500_fg.c | 1 + drivers/rtc/rtc-ab.c | 1 + include/linux/mfd/abx500/ab5500-bm.h | 4 ++-- include/linux/mfd/abx500/ab5500.h | 24 +++++++++++++++++++++++- 9 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/leds/leds-ab5500.c b/drivers/leds/leds-ab5500.c index e4376d1b59b..94db3a6feea 100644 --- a/drivers/leds/leds-ab5500.c +++ b/drivers/leds/leds-ab5500.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index dbfc9c30e38..6756d3cf37a 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* diff --git a/drivers/mfd/ab5500-power.c b/drivers/mfd/ab5500-power.c index d23960bc976..a549b3e7538 100644 --- a/drivers/mfd/ab5500-power.c +++ b/drivers/mfd/ab5500-power.c @@ -10,6 +10,7 @@ #include #include +#include static struct device *dev; diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 2e2a5054a58..7867455f493 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index b30f00a57f9..8b5b081fe34 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index bb2bfb9e840..0975c7417a4 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -26,6 +26,7 @@ #include #include #include +#include static LIST_HEAD(ab5500_fg_list); diff --git a/drivers/rtc/rtc-ab.c b/drivers/rtc/rtc-ab.c index 8e595e05d99..db1992632fa 100644 --- a/drivers/rtc/rtc-ab.c +++ b/drivers/rtc/rtc-ab.c @@ -13,6 +13,7 @@ #include #include #include +#include #define AB5500_RTC_CLOCK_RATE 32768 #define AB5500_RTC 0x00 diff --git a/include/linux/mfd/abx500/ab5500-bm.h b/include/linux/mfd/abx500/ab5500-bm.h index 1bb22614b27..f62137a6e9d 100644 --- a/include/linux/mfd/abx500/ab5500-bm.h +++ b/include/linux/mfd/abx500/ab5500-bm.h @@ -106,11 +106,11 @@ int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp); static void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) { } -inline struct ab5500_btemp *ab5500_btemp_get(void) +static inline struct ab5500_btemp *ab5500_btemp_get(void) { return 0; } -inline int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp) +static inline int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp) { return 0; } diff --git a/include/linux/mfd/abx500/ab5500.h b/include/linux/mfd/abx500/ab5500.h index 54f820ed73b..13ef9bcf30e 100644 --- a/include/linux/mfd/abx500/ab5500.h +++ b/include/linux/mfd/abx500/ab5500.h @@ -24,6 +24,9 @@ enum ab5500_devid { AB5500_DEVID_VIDEO, AB5500_DEVID_DBIECI, AB5500_DEVID_ONSWA, + AB5500_DEVID_CHARGALG, + AB5500_DEVID_BTEMP, + AB5500_DEVID_TEMPMON, AB5500_NUM_DEVICES, }; @@ -92,8 +95,9 @@ enum ab5500_banks_addr { #define AB5500_IT_SOURCE21_REG 0x35 #define AB5500_IT_SOURCE22_REG 0x36 #define AB5500_IT_SOURCE23_REG 0x37 +#define AB5500_IT_SOURCE24_REG 0x38 -#define AB5500_NUM_IRQ_REGS 23 +#define AB5500_NUM_IRQ_REGS 25 /** * struct ab5500 @@ -118,6 +122,7 @@ struct ab5500 { char chip_name[32]; u8 chip_id; struct mutex irq_lock; + u32 num_event_reg; u32 abb_events; u8 mask[AB5500_NUM_IRQ_REGS]; u8 oldmask[AB5500_NUM_IRQ_REGS]; @@ -129,12 +134,29 @@ struct ab5500 { #endif }; +#ifndef CONFIG_AB5500_CORE +static inline int ab5500_clock_rtc_enable(int num, bool enable) +{ + return -ENOSYS; +} +#else +extern int ab5500_clock_rtc_enable(int num, bool enable); +#endif + +/* Forward Declaration */ +struct ab5500_regulator_platform_data; + struct ab5500_platform_data { struct {unsigned int base; unsigned int count; } irq; void *dev_data[AB5500_NUM_DEVICES]; + size_t dev_data_sz[AB5500_NUM_DEVICES]; struct abx500_init_settings *init_settings; unsigned int init_settings_sz; bool pm_power_off; + struct ab5500_regulator_platform_data *regulator; }; +struct ab5500_ponkey_platform_data { + u8 shutdown_secs; +}; #endif /* MFD_AB5500_H */ -- cgit v1.2.3 From 427decffed2adc79289efdbfaaa24e877f44c5b9 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Thu, 1 Sep 2011 08:33:09 +0200 Subject: WLAN: Add compat-wireless settings to u8500_defconfig ST-Ericsson ID: 352334 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Bartosz Markowski Change-Id: I77ff7475f13e94337af48eab0c1f3c67644f8dc8 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30003 --- arch/arm/configs/u8500_defconfig | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4d368f98783..8190834a32c 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -97,10 +97,38 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_CFG80211=m -CONFIG_MAC80211=m + +#WIRELESS +CONFIG_WIRELESS=y +CONFIG_COMPAT_WIRELESS=y +CONFIG_COMPAT_WIRELESS_MODULES=y +CONFIG_CFG80211=y +CONFIG_COMPAT_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_COMPAT_RFKILL=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_MESH=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_MAC80211_HAS_RC is not set +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +# CONFIG_MAC80211_RC_DEFAULT is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y CONFIG_NET_9P=y CONFIG_CAIF=y -- cgit v1.2.3 From 2866c3c46937e45368e3a2c6fc66e255e5ac6546 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Fri, 2 Sep 2011 08:02:39 +0200 Subject: u8500: Enable AVERAGE and LED_TRIGGERS * reqired by WLAN (compat-wireless) ST-Ericsson ID: 352334 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Bartosz Markowski Change-Id: I8a7ac523ce05549d31f968a00d32ca01de26d891 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30007 --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) mode change 100644 => 100755 arch/arm/configs/u8500_defconfig diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig old mode 100644 new mode 100755 index 8190834a32c..434f0a48f4d --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -98,6 +98,8 @@ CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y +CONFIG_AVERAGE=y + #WIRELESS CONFIG_WIRELESS=y CONFIG_COMPAT_WIRELESS=y @@ -264,6 +266,7 @@ CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_SWITCH=y CONFIG_RTC_CLASS=y -- cgit v1.2.3 From fb358f9d14838e233cb219589eed99595da76e99 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 6 Jul 2011 08:24:42 +0200 Subject: drivers:watchdog:ux500: Only use auto kick on suspend Configure the watchdog to get automatically kicked only during suspend. Previous it was automatically kicked during cpuidle sleep stages as well. ST-Ericsson Linux next: Not tested, ask SSM for ER ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Jonas Aaberg Change-Id: Ifb42c4eac7cf36581dec4d8646af0b51f0a24483 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26648 Reviewed-by: Rickard ANDERSSON Reviewed-by: QATEST Reviewed-by: Per-Inge TALLBERG --- drivers/watchdog/ux500_wdt.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index fd343197681..b620200ea3e 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -40,7 +40,7 @@ MODULE_PARM_DESC(nowayout, __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); static u8 wdog_id; static bool wdt_en; -static bool wdt_auto_off = true; +static bool wdt_auto_off = false; static bool safe_close; static int ux500_wdt_open(struct inode *inode, struct file *file) @@ -382,13 +382,44 @@ static int __exit ux500_wdt_remove(struct platform_device *dev) misc_deregister(&ux500_wdt_miscdev); return 0; } +#ifdef CONFIG_PM +static int ux500_wdt_suspend(struct platform_device *pdev, + pm_message_t state) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, true); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} +static int ux500_wdt_resume(struct platform_device *pdev) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, wdt_auto_off); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} + +#else +#define ux500_wdt_suspend NULL +#define ux500_wdt_resume NULL +#endif static struct platform_driver ux500_wdt_driver = { .remove = __exit_p(ux500_wdt_remove), .driver = { .owner = THIS_MODULE, .name = "ux500_wdt", }, + .suspend = ux500_wdt_suspend, + .resume = ux500_wdt_resume, }; static int __init ux500_wdt_init(void) -- cgit v1.2.3 From 2c7b054ab58d3cafcaba3c5d360585aa0237bdf6 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 09:48:55 +0200 Subject: ab8500 mfd: USB: Set the charging cur to 300mA for ABV3 In case of AB-V3, the eye diagram related issues are resolved. So, set the device charging current to 300mA when connected to standard host. Also, add the USB PHY tuning values to improve the USB eye diagram Signed-off-by: --- drivers/mfd/ab8500-debugfs.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index f36390c0d3d..9521d738fd0 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -144,7 +144,7 @@ static struct hwreg_cfg hwreg_cfg = { #define AB8500_NAME_STRING "ab8500" #define AB8500_ADC_NAME_STRING "gpadc" -#define AB8500_NUM_BANKS 22 +#define AB8500_NUM_BANKS 24 #define AB8500_REV_REG 0x80 @@ -316,7 +316,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { }, }, [AB8500_CHARGER] = { - .num_ranges = 8, + .num_ranges = 9, .range = (struct ab8500_reg_range[]) { { .first = 0x00, @@ -350,6 +350,10 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { .first = 0xC0, .last = 0xC2, }, + { + .first = 0xf5, + .last = 0xf6, + }, }, }, [AB8500_GAS_GAUGE] = { @@ -369,6 +373,24 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { }, }, }, + [AB8500_DEVELOPMENT] = { + .num_ranges = 1, + .range = (struct ab8500_reg_range[]) { + { + .first = 0x00, + .last = 0x00, + }, + }, + }, + [AB8500_DEBUG] = { + .num_ranges = 1, + .range = (struct ab8500_reg_range[]) { + { + .first = 0x05, + .last = 0x07, + }, + }, + }, [AB8500_AUDIO] = { .num_ranges = 1, .range = (struct ab8500_reg_range[]) { -- cgit v1.2.3 From c03cd4e6ffe661108ab97eae9b245702ad8e5cf5 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 7 Sep 2011 11:45:28 +0200 Subject: Update kernelrelease target in kernel Makefile setlocalversion script has input parameter which should be passed when calling kernelrelease target. Add kernelrelease to no-dot-config-targets. We should not run oldconfig when calling kernelrelease target. ST-Ericsson ID: 352334 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Bartosz Markowski Change-Id: I10ab7bf7963685887bbb97b7f8dfa5ea9a43c29d Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30296 Reviewed-by: Axel FAGERSTEDT Tested-by: Said BAGHERI Reviewed-by: Ushit KUMAR Reviewed-by: Srinidhi KASAGAR --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cd2916d5c8f..f75dfdba153 100644 --- a/Makefile +++ b/Makefile @@ -443,7 +443,7 @@ asm-generic: no-dot-config-targets := clean mrproper distclean \ cscope gtags TAGS tags help %docs check% coccicheck \ include/linux/version.h headers_% archheaders archscripts \ - kernelversion %src-pkg + kernelrelease kernelversion %src-pkg config-targets := 0 mixed-targets := 0 @@ -1466,7 +1466,7 @@ checkstack: $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH) kernelrelease: - @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" + @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion -s $(srctree) -t v$(KERNELVERSION))" kernelversion: @echo $(KERNELVERSION) -- cgit v1.2.3 From 1232e887f97a3e9ea82b6193cda5e58ba7605736 Mon Sep 17 00:00:00 2001 From: Daniel Willerud Date: Fri, 26 Aug 2011 10:49:11 +0200 Subject: hwmon: Adding notifiers to hwmon ST-Ericsson ID: 354533 ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I068a3c801405b6f7ca2b78df7cd9f7461ed8738b Signed-off-by: Daniel Willerud Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29502 Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/hwmon/hwmon.c | 21 +++++++++++++++++++++ include/linux/hwmon.h | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index c3c471ca202..8957bbac7a7 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -21,6 +21,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" @@ -29,6 +30,8 @@ static struct class *hwmon_class; static DEFINE_IDA(hwmon_ida); +static BLOCKING_NOTIFIER_HEAD(hwmon_notifier_list); + /** * hwmon_device_register - register w/ hwmon * @dev: the device to register @@ -75,6 +78,24 @@ void hwmon_device_unregister(struct device *dev) } EXPORT_SYMBOL_GPL(hwmon_device_unregister); +int hwmon_notifier_register(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&hwmon_notifier_list, nb); +} +EXPORT_SYMBOL(hwmon_notifier_register); + +int hwmon_notifier_unregister(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&hwmon_notifier_list, nb); +} +EXPORT_SYMBOL(hwmon_notifier_unregister); + +void hwmon_notify(unsigned long val, void *v) +{ + blocking_notifier_call_chain(&hwmon_notifier_list, val, v); +} +EXPORT_SYMBOL(hwmon_notify); + static void __init hwmon_pci_quirks(void) { #if defined CONFIG_X86 && defined CONFIG_PCI diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h index 82b29ae6ebb..6cb4d26bf60 100644 --- a/include/linux/hwmon.h +++ b/include/linux/hwmon.h @@ -14,12 +14,18 @@ #ifndef _HWMON_H_ #define _HWMON_H_ +#include + struct device; struct device *hwmon_device_register(struct device *dev); void hwmon_device_unregister(struct device *dev); +int hwmon_notifier_register(struct notifier_block *nb); +int hwmon_notifier_unregister(struct notifier_block *nb); +void hwmon_notify(unsigned long val, void *v); + /* Scale user input to sensible values */ static inline int SENSORS_LIMIT(long value, long low, long high) { -- cgit v1.2.3 From d8e4caf56945aed91c1610b6adeb2f23df02cbc4 Mon Sep 17 00:00:00 2001 From: Daniel Willerud Date: Thu, 25 Aug 2011 17:39:18 +0200 Subject: ux500: Thermal power off To determine whether the system had a thermal power off or a regular software power off upon the next boot, the system must utilize the thermal power off bit, ThDB8500SWoff, in AB8500 register STw4500Ctrl1. ST-Ericsson ID: 354533 ST-Ericsson Linux next: N/A ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I07440dcdc39a86cb72aa95d86411a1f020b05cae Signed-off-by: Daniel Willerud Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28515 Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/hwmon/ab8500.c | 2 ++ drivers/hwmon/abx500.c | 1 + drivers/hwmon/dbx500.c | 1 + drivers/mfd/ab8500-sysctrl.c | 50 +++++++++++++++++++++++++++++++++++---- include/linux/mfd/abx500/ab8500.h | 7 ++++++ 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index 45a8ef675b3..db601e3158d 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -117,6 +117,8 @@ static int ab8500_temp_irq_handler(int irq, struct abx500_temp *data) mutex_lock(&data->lock); data->crit_alarm[4] = 1; mutex_unlock(&data->lock); + + hwmon_notify(data->crit_alarm[4], NULL); sysfs_notify(&data->pdev->dev.kobj, NULL, "temp5_crit_alarm"); dev_info(&data->pdev->dev, "AB8500 thermal warning," " power off in %lu s\n", data->power_off_delay); diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index 6666dc27065..68da2d03dbd 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -163,6 +163,7 @@ static void gpadc_monitor(struct work_struct *work) ret); break; } + hwmon_notify(data->max_alarm[i], NULL); sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node); } if (updated_max_hyst_alarm) { diff --git a/drivers/hwmon/dbx500.c b/drivers/hwmon/dbx500.c index a26e08b3707..cd44e78030c 100644 --- a/drivers/hwmon/dbx500.c +++ b/drivers/hwmon/dbx500.c @@ -323,6 +323,7 @@ static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) data->max_alarm[0] = 1; mutex_unlock(&data->lock); + hwmon_notify(data->max_alarm[0], NULL); sysfs_notify(&pdev->dev.kobj, NULL, "temp1_max_alarm"); dev_dbg(&pdev->dev, "DBX500 thermal warning, power off in %lu s\n", (data->power_off_delay) / 1000); diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index cf58f694539..2a328cfaf43 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -14,11 +14,15 @@ #include #include #include +#include +#include static struct device *sysctrl_dev; void ab8500_power_off(void) { + struct ab8500_platform_data *plat; + struct timespec ts; sigset_t old; sigset_t all; static char *pss[] = {"ab8500_ac", "ab8500_usb"}; @@ -66,14 +70,51 @@ void ab8500_power_off(void) shutdown: sigfillset(&all); + plat = dev_get_platdata(sysctrl_dev->parent); + getnstimeofday(&ts); if (!sigprocmask(SIG_BLOCK, &all, &old)) { - (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, - AB8500_STW4500CTRL1_SWOFF | - AB8500_STW4500CTRL1_SWRESET4500N); - (void)sigprocmask(SIG_SETMASK, &old, NULL); + if (ts.tv_sec == 0 || + (ts.tv_sec - plat->thermal_set_time_sec > + plat->thermal_time_out)) + plat->thermal_power_off_pending = false; + if (!plat->thermal_power_off_pending) { + (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, + AB8500_STW4500CTRL1_SWOFF | + AB8500_STW4500CTRL1_SWRESET4500N); + (void)sigprocmask(SIG_SETMASK, &old, NULL); + } else { + (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, + AB8500_STW4500CTRL1_THDB8500SWOFF | + AB8500_STW4500CTRL1_SWRESET4500N); + (void)sigprocmask(SIG_SETMASK, &old, NULL); + } } } +static int ab8500_notifier_call(struct notifier_block *this, + unsigned long val, void *data) +{ + struct ab8500_platform_data *plat; + static struct timespec ts; + if (sysctrl_dev == NULL) + return -EAGAIN; + + plat = dev_get_platdata(sysctrl_dev->parent); + if (val) { + getnstimeofday(&ts); + plat->thermal_set_time_sec = ts.tv_sec; + plat->thermal_power_off_pending = true; + } else { + plat->thermal_set_time_sec = 0; + plat->thermal_power_off_pending = false; + } + return 0; +} + +static struct notifier_block ab8500_notifier = { + .notifier_call = ab8500_notifier_call, +}; + static inline bool valid_bank(u8 bank) { return ((bank == AB8500_SYS_CTRL1_BLOCK) || @@ -118,6 +159,7 @@ static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev) plat = dev_get_platdata(pdev->dev.parent); if (plat->pm_power_off) pm_power_off = ab8500_power_off; + hwmon_notifier_register(&ab8500_notifier); return 0; } diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index c1016272ab2..f746cf3ca34 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -266,6 +266,10 @@ struct ab8500_gpio_platform_data; /** * struct ab8500_platform_data - AB8500 platform data + * @pm_power_off: Should machine pm power off hook be registered or not + * @thermal_power_off_pending: Set if there was a thermal alarm + * @thermal_set_time_sec: Time of the thermal alarm + * @thermal_time_out: Time out before the thermal alarm should be ignored * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used * @init: board-specific initialization after detection of ab8500 * @num_regulator_reg_init: number of regulator init registers @@ -279,6 +283,9 @@ struct ab8500_gpio_platform_data; struct ab8500_platform_data { int irq_base; bool pm_power_off; + bool thermal_power_off_pending; + long thermal_set_time_sec; + long thermal_time_out; void (*init) (struct ab8500 *); int num_regulator_reg_init; struct ab8500_regulator_reg_init *regulator_reg_init; -- cgit v1.2.3 From fadb8d09cbdd0a96c3f9a6f75a0b0e5fd9dfa4d5 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 9 Sep 2011 17:50:48 +0530 Subject: u8500: set cpuidle deepest state to 2 Some drivers such as MMC and UART do not yet managed the v-ape regulator on 3.0. Change-Id: Ifc3d989542eb44476f711d46e8c7dd27852998a7 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 434f0a48f4d..3d5dba1ed11 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -39,6 +39,7 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_U8500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y -- cgit v1.2.3 From 91bd390ed518c8b6562fc3a403426735bb70cbe8 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 12 Sep 2011 10:45:15 +0530 Subject: u5500: enable PRCMU QoS and PRCMU debug Change-Id: I8985a0224cea4854f4b733c9294e4096516ac5a4 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3d5dba1ed11..2f7749a1d25 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -29,6 +29,7 @@ CONFIG_MACH_UX500_DT=y CONFIG_UX500_PRCMU_TIMER=y CONFIG_U8500_PRCMU=y CONFIG_UX500_PRCMU_DEBUG=y +CONFIG_UX500_DEBUG_UART=0 CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_DISPLAY_GENERIC_PRIMARY=y -- cgit v1.2.3 From d276a1ca7e56871a8190aef5ea1b78243ab096da Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 18 Oct 2011 13:25:14 +0200 Subject: pl011: migrate pl011 changes from 2.3v3.2 Ref: ARM: ux500: uart: context save/restore uses relaxed pl011: add ifdef pl011: don't touch registers when clock is off ux500: pl011: Workaround for UART registers lockup Migrated Changes from: e1f512c, 852b78d, c2195fa, ac87c0e --- drivers/tty/serial/amba-pl011.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 59d48f8b0c5..9cb09ae7a56 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1253,7 +1253,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) do { writew(status & ~(UART011_TXIS|UART011_RTIS| UART011_RXIS), - uap->port.membase + UART011_ICR); + uap->port.membase + UART011_ICR); if (status & (UART011_RTIS|UART011_RXIS)) { if (pl011_dma_rx_running(uap)) @@ -1760,8 +1760,6 @@ static struct uart_ops amba_pl011_pops = { #endif }; -static struct uart_amba_port *amba_ports[UART_NR]; - #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE static void pl011_console_putchar(struct uart_port *port, int ch) @@ -2022,7 +2020,12 @@ static int pl011_suspend(struct amba_device *dev, pm_message_t state) if (!uap) return -EINVAL; +#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL + cancel_delayed_work_sync(&uap->clk_off_work); + if (uap->clk_state == PL011_CLK_OFF) + return 0; +#endif return uart_suspend_port(&amba_reg, &uap->port); } @@ -2032,6 +2035,10 @@ static int pl011_resume(struct amba_device *dev) if (!uap) return -EINVAL; +#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL + if (uap->clk_state == PL011_CLK_OFF) + return 0; +#endif return uart_resume_port(&amba_reg, &uap->port); } -- cgit v1.2.3 From 9d4e615519b0ca1d233247e885bebf0cd387f8c7 Mon Sep 17 00:00:00 2001 From: "Rajanikanth H.V" Date: Mon, 12 Sep 2011 11:37:20 +0530 Subject: UART:pl011: migrate pl011 support to 3.0 pl011 changes from the following commits have been manually merged. ef45647, d57a627, 588c0bb, 9b4ecf9, 913afa0, 13aa593, e7d5dcb, 5115d25, 19fcf44 ST-Ericsson ID: NA ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Change-Id: I1759c825add127867cf6edc688b860e82743ce6f Signed-off-by: Rajanikanth H.V --- arch/arm/configs/u8500_defconfig | 1 + drivers/tty/serial/Kconfig | 8 + drivers/tty/serial/amba-pl011.c | 366 +++++++++++++++++++++++++++++++++++---- 3 files changed, 345 insertions(+), 30 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 2f7749a1d25..0cf7de03993 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -181,6 +181,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_DEVKMEM is not set CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_NOMADIK=y CONFIG_I2C_CHARDEV=y diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 070b442c1f8..b2831ed01bb 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -63,6 +63,14 @@ config SERIAL_AMBA_PL011_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_AMBA_PL011_CLOCK_CONTROL + bool "Support for clock control on AMBA serial port" + depends on SERIAL_AMBA_PL011 + select CONSOLE_POLL + ---help--- + Say Y here if you wish to use amba set_termios function to control + the pl011 clock. Any positive baudrate passed enables clock, + config SERIAL_SB1250_DUART tristate "BCM1xxx on-chip DUART serial support" depends on SIBYTE_SB1xxx_SOC=y diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 9cb09ae7a56..3618278df03 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,37 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) +/* + * The console UART is handled differently for power management (it doesn't + * take the regulator, in order to allow the system to go to sleep even if the + * console is open). This should be removed once cable detect is in place. + */ +#ifdef CONFIG_SERIAL_CORE_CONSOLE +#define uart_console(port) ((port)->cons \ + && (port)->cons->index == (port)->line) +#else +#define uart_console(port) (0) +#endif + +/* Available amba pl011 port clock states */ +enum pl011_clk_states { + PL011_CLK_OFF = 0, /* clock disabled */ + PL011_CLK_REQUEST_OFF, /* disable after TX flushed */ + PL011_CLK_ON, /* clock enabled */ + PL011_PORT_OFF, /* port disabled */ +}; + +/* + * Backup registers to be used during regulator startup/shutdown + */ +static const u32 backup_regs[] = { + UART011_IBRD, + UART011_FBRD, + ST_UART011_LCRH_RX, + ST_UART011_LCRH_TX, + UART011_CR, + UART011_IMSC, +}; #define UART_WA_SAVE_NR 14 @@ -158,10 +190,18 @@ struct uart_amba_port { unsigned int im; /* interrupt mask */ unsigned int old_status; unsigned int fifosize; /* vendor-specific */ + unsigned int ifls; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */ unsigned int old_cr; /* state during shutdown */ bool autorts; +#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL + enum pl011_clk_states clk_state; /* actual clock state */ + struct delayed_work clk_off_work; /* work used for clock off */ + unsigned int clk_off_delay; /* clock off delay */ +#endif + struct regulator *regulator; + u32 backup[ARRAY_SIZE(backup_regs)]; char type[12]; bool interrupt_may_hang; /* vendor-specific */ #ifdef CONFIG_DMA_ENGINE @@ -1117,6 +1157,246 @@ static void pl011_lockup_wa(unsigned long data) tty->hw_stopped = 0; } +static void __pl011_startup(struct uart_amba_port *uap) +{ + unsigned int cr; + + writew(uap->ifls, uap->port.membase + UART011_IFLS); + + /* + * Provoke TX FIFO interrupt into asserting. + */ + cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; + writew(cr, uap->port.membase + UART011_CR); + writew(0, uap->port.membase + UART011_FBRD); + writew(1, uap->port.membase + UART011_IBRD); + writew(0, uap->port.membase + uap->lcrh_rx); + if (uap->lcrh_tx != uap->lcrh_rx) { + int i; + /* + * Wait 10 PCLKs before writing LCRH_TX register, + * to get this delay write read only register 10 times + */ + for (i = 0; i < 10; ++i) + writew(0xff, uap->port.membase + UART011_MIS); + writew(0, uap->port.membase + uap->lcrh_tx); + } + writew(0, uap->port.membase + UART01x_DR); + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) + barrier(); +} + +/* Backup the registers during regulator startup/shutdown */ +#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL +static int pl011_backup(struct uart_amba_port *uap, bool suspend) +{ + int i, cnt; + + if (!suspend) { + __pl011_startup(uap); + writew(0, uap->port.membase + UART011_CR); + } + + for (i = 0; i < ARRAY_SIZE(backup_regs); i++) { + if (suspend) + uap->backup[i] = readw(uap->port.membase + + backup_regs[i]); + else { + if (backup_regs[i] == ST_UART011_LCRH_TX) { + /* + * Wait 10 PCLKs before writing LCRH_TX + * register, to get this delay write read + * only register 10 times + */ + for (cnt = 0; cnt < 10; ++cnt) + writew(0xff, uap->port.membase + + UART011_MIS); + } + + writew(uap->backup[i], + uap->port.membase + backup_regs[i]); + } + } + return 0; +} +#endif + +#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL +/* Turn clock off if TX buffer is empty, otherwise reschedule */ +static void pl011_clock_off(struct work_struct *work) +{ + struct uart_amba_port *uap = container_of(work, struct uart_amba_port, + clk_off_work.work); + struct uart_port *port = &uap->port; + struct circ_buf *xmit = &port->state->xmit; + unsigned long flags; + bool disable_regulator = false; + unsigned int busy, interrupt_status; + + spin_lock_irqsave(&port->lock, flags); + + interrupt_status = readw(uap->port.membase + UART011_MIS); + busy = readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY; + + if (uap->clk_state == PL011_CLK_REQUEST_OFF) { + if (uart_circ_empty(xmit) && !interrupt_status && !busy) { + if (!uart_console(&uap->port) && uap->regulator) { + pl011_backup(uap, true); + disable_regulator = true; + } + uap->clk_state = PL011_CLK_OFF; + clk_disable(uap->clk); + } else + schedule_delayed_work(&uap->clk_off_work, + uap->clk_off_delay); + } + + spin_unlock_irqrestore(&port->lock, flags); + + if (disable_regulator) + regulator_disable(uap->regulator); +} + +/* Request to turn off uart clock once pending TX is flushed */ +static void pl011_clock_request_off(struct uart_port *port) +{ + unsigned long flags; + struct uart_amba_port *uap = (struct uart_amba_port *)(port); + + spin_lock_irqsave(&port->lock, flags); + + if (uap->clk_state == PL011_CLK_ON) { + uap->clk_state = PL011_CLK_REQUEST_OFF; + /* Turn off later */ + schedule_delayed_work(&uap->clk_off_work, + uap->clk_off_delay); + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* Request to immediately turn on uart clock */ +static void pl011_clock_on(struct uart_port *port) +{ + unsigned long flags; + struct uart_amba_port *uap = (struct uart_amba_port *)(port); + + spin_lock_irqsave(&port->lock, flags); + + switch (uap->clk_state) { + case PL011_CLK_OFF: + clk_enable(uap->clk); + if (!uart_console(&uap->port) && uap->regulator) { + spin_unlock_irqrestore(&port->lock, flags); + regulator_enable(uap->regulator); + spin_lock_irqsave(&port->lock, flags); + pl011_backup(uap, false); + } + /* fallthrough */ + case PL011_CLK_REQUEST_OFF: + cancel_delayed_work(&uap->clk_off_work); + uap->clk_state = PL011_CLK_ON; + break; + default: + break; + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +static void pl011_clock_check(struct uart_amba_port *uap) +{ + /* Reshedule work during off request */ + if (uap->clk_state == PL011_CLK_REQUEST_OFF) + /* New TX - restart work */ + if (cancel_delayed_work(&uap->clk_off_work)) + schedule_delayed_work(&uap->clk_off_work, + uap->clk_off_delay); +} + +static int pl011_power_startup(struct uart_amba_port *uap) +{ + int retval = 0; + + if (uap->clk_state == PL011_PORT_OFF) { + if (!uart_console(&uap->port) && uap->regulator) + regulator_enable(uap->regulator); + retval = clk_enable(uap->clk); + if (!retval) + uap->clk_state = PL011_CLK_ON; + else + uap->clk_state = PL011_PORT_OFF; + } + + return retval; +} + +static void pl011_power_shutdown(struct uart_amba_port *uap) +{ + bool disable_regulator = false; + + cancel_delayed_work_sync(&uap->clk_off_work); + + spin_lock_irq(&uap->port.lock); + if (uap->clk_state == PL011_CLK_ON || + uap->clk_state == PL011_CLK_REQUEST_OFF) { + clk_disable(uap->clk); + if (!uart_console(&uap->port) && uap->regulator) + disable_regulator = true; + } + uap->clk_state = PL011_PORT_OFF; + spin_unlock_irq(&uap->port.lock); + + if (disable_regulator) + regulator_disable(uap->regulator); +} + +static void +pl011_clock_control(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + speed_t new_baud = tty_termios_baud_rate(termios); + + if (new_baud == 0) + pl011_clock_request_off(port); + else + pl011_clock_on(port); +} + +static void pl011_clock_control_init(struct uart_amba_port *uap) +{ + uap->clk_state = PL011_PORT_OFF; + INIT_DELAYED_WORK(&uap->clk_off_work, pl011_clock_off); + uap->clk_off_delay = HZ / 10; /* 100 ms */ +} + +#else +/* Blank functions for clock control */ +static inline void pl011_clock_check(struct uart_amba_port *uap) +{ +} + +static inline int pl011_power_startup(struct uart_amba_port *uap) +{ + return clk_enable(uap->clk); +} + +static inline void pl011_power_shutdown(struct uart_amba_port *uap) +{ + clk_disable(uap->clk); +} + +static inline void +pl011_clock_control(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ +} + +static inline void pl011_clock_control_init(struct uart_amba_port *uap) +{ +} +#endif + static void pl011_stop_tx(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1208,6 +1488,9 @@ static void pl011_tx_chars(struct uart_amba_port *uap) break; } while (--count > 0); + if (count) + pl011_clock_check(uap); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); @@ -1389,9 +1672,9 @@ static int pl011_startup(struct uart_port *port) goto out; /* - * Try to enable the clock producer. + * Try to enable the clock producer and the regulator. */ - retval = clk_enable(uap->clk); + retval = pl011_power_startup(uap); if (retval) goto clk_unprep; @@ -1408,29 +1691,7 @@ static int pl011_startup(struct uart_port *port) if (retval) goto clk_dis; - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); - - /* - * Provoke TX FIFO interrupt into asserting. - */ - cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; - writew(cr, uap->port.membase + UART011_CR); - writew(0, uap->port.membase + UART011_FBRD); - writew(1, uap->port.membase + UART011_IBRD); - writew(0, uap->port.membase + uap->lcrh_rx); - if (uap->lcrh_tx != uap->lcrh_rx) { - int i; - /* - * Wait 10 PCLKs before writing LCRH_TX register, - * to get this delay write read only register 10 times - */ - for (i = 0; i < 10; ++i) - writew(0xff, uap->port.membase + UART011_MIS); - writew(0, uap->port.membase + uap->lcrh_tx); - } - writew(0, uap->port.membase + UART01x_DR); - while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) - barrier(); + __pl011_startup(uap); /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); @@ -1471,7 +1732,7 @@ static int pl011_startup(struct uart_port *port) return 0; clk_dis: - clk_disable(uap->clk); + pl011_power_shutdown(uap); clk_unprep: clk_unprepare(uap->clk); out: @@ -1538,9 +1799,9 @@ static void pl011_shutdown(struct uart_port *port) } /* - * Shut down the clock producer + * Shut down the clock producer and the producer */ - clk_disable(uap->clk); + pl011_power_shutdown(uap); clk_unprepare(uap->clk); if (uap->port.dev->platform_data) { @@ -1553,6 +1814,32 @@ static void pl011_shutdown(struct uart_port *port) } +/* Power/Clock management. */ +static void pl011_serial_pm(struct uart_port *port, unsigned int state, +unsigned int oldstate) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + + switch (state) { + case 0: /*fully on */ + /* + * Enable the peripheral clock for this serial port. + * This is called on uart_open() or a resume event. + */ + pl011_power_startup(uap); + break; + case 3: /* powered down */ + /* + * Disable the peripheral clock for this serial port. + * This is called on uart_close() or a suspend event. + */ + pl011_power_shutdown(uap); + break; + default: + printk(KERN_ERR "pl011_serial: unknown pm %d\n", state); + } +} + static void pl011_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) @@ -1566,7 +1853,12 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, clkdiv = 8; else clkdiv = 16; - + /* + * Must be before uart_get_baud_rate() call, because + * this function changes baudrate to default in case of 0 + * B0 hangup !!! + */ + pl011_clock_control(port, termios, old); /* * Ask the core to calculate the divisor for us. */ @@ -1754,6 +2046,7 @@ static struct uart_ops amba_pl011_pops = { .request_port = pl010_request_port, .config_port = pl010_config_port, .verify_port = pl010_verify_port, + .pm = pl011_serial_pm, #ifdef CONFIG_CONSOLE_POLL .poll_get_char = pl010_get_poll_char, .poll_put_char = pl010_put_poll_char, @@ -1917,7 +2210,6 @@ static struct uart_driver amba_reg = { .nr = UART_NR, .cons = AMBA_CONSOLE, }; - static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; @@ -1946,6 +2238,12 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto free; } + uap->regulator = regulator_get(&dev->dev, "v-uart"); + if (IS_ERR(uap->regulator)) { + dev_warn(&dev->dev, "could not get uart regulator\n"); + uap->regulator = NULL; + } + uap->clk = clk_get(&dev->dev, NULL); if (IS_ERR(uap->clk)) { ret = PTR_ERR(uap->clk); @@ -1953,6 +2251,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) } uap->vendor = vendor; + uap->ifls = vendor->ifls; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; uap->old_cr = 0; @@ -1978,6 +2277,9 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) amba_ports[i] = uap; amba_set_drvdata(dev, uap); + + pl011_clock_control_init(uap); + ret = uart_add_one_port(&amba_reg, &uap->port); if (ret) { amba_set_drvdata(dev, NULL); @@ -1985,6 +2287,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) pl011_dma_remove(uap); clk_put(uap->clk); unmap: + if (uap->regulator) + regulator_put(uap->regulator); iounmap(base); free: kfree(uap); @@ -2008,6 +2312,8 @@ static int pl011_remove(struct amba_device *dev) pl011_dma_remove(uap); iounmap(uap->port.membase); + if (uap->regulator) + regulator_put(uap->regulator); clk_put(uap->clk); kfree(uap); return 0; -- cgit v1.2.3 From f3ea5d7bba1b35e4f257d4f845bcddf2e55dacbd Mon Sep 17 00:00:00 2001 From: Johan Palmaeus Date: Tue, 13 Sep 2011 13:43:19 +0200 Subject: CG2900 FM Radio: Enable CG2900 FM Radio Several modules needed for CG2900 FM Radio was missing in u5500/u8500 defconfig files. This patch adds them. ST-Ericsson ID: 352334 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I720d40f0596c906bf4d2f52cddad098912ad4824 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30832 Tested-by: Johan PALMAEUS Reviewed-by: Virupax SADASHIVPETIMATH --- arch/arm/configs/u8500_defconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0cf7de03993..058dd6305c6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -210,8 +210,17 @@ CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_MEDIA=y +CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_V4L1=y # CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_CG2900=y CONFIG_GPU_MALI=y CONFIG_GPU_MALI_DEBUG=y CONFIG_FB=y -- cgit v1.2.3 From 8d958ac99214d99c51338a3ea0ef9dd4cf637ccc Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 15 Sep 2011 12:54:09 +0530 Subject: power: ab5500: wrong dependancy in kconfig Correct the dependancy for enabling ab5500 battery charging driver. Change-Id: Ia2f0ba7d2631f19424c01efcf07ea6e088d8b784 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31012 --- drivers/power/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f3d5a7a95c3..0626dfa9ff6 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -310,7 +310,7 @@ config AB8500_BATTERY_THERM_ON_BATCTRL config AB5500_BM bool "AB5500 Battery Management Driver" - depends on AB5500_CORE && AB8500_GPADC && ARCH_U8500 + depends on AB5500_CORE && AB5500_GPADC && MACH_U5500 help Say Y to include support for AB5500 battery management. -- cgit v1.2.3 From db0bfb0422f075fa14374adc0005d3678bc21382 Mon Sep 17 00:00:00 2001 From: psen Date: Fri, 16 Sep 2011 15:50:39 +0530 Subject: u8500: Change FORCE_MAX_ZONEORDER NMF Component Manager driver module uses for the time being dma_alloc_coherent to allocate contiguous SDRAM memory to store MMDSP's code and data: 8M for SIA and SVA data + 2M for SIA code + 2M for SVA code Change-Id: I2994bfaa522cdd49767940ae0488e88f90a291e7 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31251 Reviewed-by: Pankaj SEN Tested-by: Pankaj SEN Reviewed-by: Srinidhi KASAGAR --- arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9324e33e531..46cf36a5114 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1762,7 +1762,9 @@ source "mm/Kconfig" config FORCE_MAX_ZONEORDER int "Maximum zone order" if ARCH_SHMOBILE range 11 64 if ARCH_SHMOBILE + depends on SA1111 || UX500_SOC_DB8500 default "9" if SA1111 + default "12" if UX500_SOC_DB8500 default "11" help The kernel memory allocator divides physically contiguous memory -- cgit v1.2.3 From a3fff4bcb7518e1ff733f2ea761924b10079338b Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 10:45:15 +0200 Subject: ab5500 mfd: usb:Migrate the patches to kernel 3.0 Following patches for usb driver are manually merged to kernel 3.0 d11e52a ux500: usb: add usb device mode support on u5500 1fecc55 ux500: usb: enabling adb and ACM functionality in u5500_defconfig 2847bf4 ux500: usb: error handling in musb for u5500 37f22da ux500: usb: U5500 v2 update e1b079d ux500: usb: Fix for enumeration when ON with cable 181701a ux500: usb: Fix for V2 emmc2 boot USB device issue 3a60721 mach-ux500: Handle the LinkStatus register. 086a83e usb: ux500: usb gpio enable/disable in pair Signed-off-by: Avinash Kumar --- include/linux/mfd/abx500/ab5500.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mfd/abx500/ab5500.h b/include/linux/mfd/abx500/ab5500.h index 13ef9bcf30e..ad8ffa65132 100644 --- a/include/linux/mfd/abx500/ab5500.h +++ b/include/linux/mfd/abx500/ab5500.h @@ -154,6 +154,7 @@ struct ab5500_platform_data { unsigned int init_settings_sz; bool pm_power_off; struct ab5500_regulator_platform_data *regulator; + struct ab5500_usbgpio_platform_data *usb; }; struct ab5500_ponkey_platform_data { -- cgit v1.2.3 From 5a501bbc449b721a61181a7871ae3e8b7f0a6836 Mon Sep 17 00:00:00 2001 From: om prakash Date: Fri, 16 Sep 2011 17:50:17 +0530 Subject: Disable STM_TRACE : Disable this for kernel3.0 Disabled CONFIG_STM_TRACE of u8500 for kernel3.0 Change-Id: I0c5c5b1f43d1fbb35c71a48445d71f10a893073b Signed-off-by: om prakash Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31266 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 058dd6305c6..e340276ca14 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -145,7 +145,7 @@ CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y CONFIG_U8500_SIM_DETECT=y -CONFIG_STM_TRACE=y +# CONFIG_STM_TRACE=y CONFIG_DISPDEV=y # CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y -- cgit v1.2.3 From 0c39da75fc4ea5f8b0c5f13c65c36161ae8ea57d Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 21 Sep 2011 15:24:48 +0200 Subject: Align u9500_defconfig on 8500 Change-Id: I288ea800be0a6acf7b31a4e247a0dd703ab97277 Change-Id: Iae584f8558f571952c6805ba3788f7241db70636 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31536 Reviewed-by: Yann GAUTIER Tested-by: Yann GAUTIER Reviewed-by: Christopher BLAIR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index e340276ca14..b1a93e8a45f 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -80,6 +80,7 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set +# CONFIG_ANDROID_PARANOID_NETWORK is not set CONFIG_NETFILTER=y CONFIG_NF_CONNTRACK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -- cgit v1.2.3 From f9c1042a8ca7c190545f14aec43285e38277fd84 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Wed, 21 Sep 2011 11:22:59 +0530 Subject: power: ab5500-bm: update usb state change interface to otg notifier Remove usb_state_changed() exported function. Replace it with otg notifier call. This makes static_di redundant so it is removed. Moreover, there is no need to protect usb_state.usb_changed with usb_lock. So usb_lock is removed as well. Usb state is fabricated based on the reported mA. State is not as accurate as reading it directly from the usb controller. This should not matter as battery- manager driver should care more about mA than the state anyway. Change-Id: I180062a87ca773b5c215aee3ef1c60315d309d42 Signed-off-by: Arun Murthy Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31577 Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_charger.c | 71 +++++++++++++++++++++++++++--------- include/linux/mfd/abx500/ab5500-bm.h | 4 -- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 8b5b081fe34..b4ac1ac6bb7 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -27,6 +27,7 @@ #include #include #include +#include /* Charger constants */ #define NO_PW_CONN 0 @@ -168,6 +169,11 @@ struct ab5500_charger_usb_state { * Work for checking Main thermal status * @check_usb_thermal_prot_work: * Work for checking USB thermal status + * @ otg: pointer to struct otg_transceiver, used to + * notify the current during a standard host + * charger. + * @nb: structture of type notifier_block, which has + * a function pointer referenced by usb driver. */ struct ab5500_charger { struct device *dev; @@ -190,15 +196,10 @@ struct ab5500_charger { struct work_struct usb_link_status_work; struct work_struct usb_state_changed_work; struct work_struct check_usb_thermal_prot_work; + struct otg_transceiver *otg; + struct notifier_block nb; }; -/* - * TODO: This variable is static in order to get information - * about maximum current and USB state from the USB driver - * This should be solved in a better way - */ -static struct ab5500_charger *static_di; - /* USB properties */ static enum power_supply_property ab5500_charger_usb_props[] = { POWER_SUPPLY_PROP_HEALTH, @@ -1130,15 +1131,16 @@ static void ab5500_charger_usb_link_status_work(struct work_struct *work) static void ab5500_charger_usb_state_changed_work(struct work_struct *work) { int ret; + unsigned long flags; struct ab5500_charger *di = container_of(work, struct ab5500_charger, usb_state_changed_work); if (!di->vbus_detected) return; - spin_lock(&di->usb_state.usb_lock); + spin_lock_irqsave(&di->usb_state.usb_lock, flags); di->usb_state.usb_changed = false; - spin_unlock(&di->usb_state.usb_lock); + spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); /* * wait for some time until you get updates from the usb stack @@ -1521,25 +1523,41 @@ static struct ab5500_charger_interrupts ab5500_charger_irq[] = { /*{"CHG_SW_TIMER_OUT", ab5500_charger_chwdexp_handler},*/ }; -void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) +static int ab5500_charger_usb_notifier_call(struct notifier_block *nb, + unsigned long event, void *power) { - struct ab5500_charger *di = static_di; + struct ab5500_charger *di = + container_of(nb, struct ab5500_charger, nb); + enum ab5500_usb_state bm_usb_state; + unsigned mA = *((unsigned *)power); + + /* TODO: State is fabricate here. See if charger really needs USB + * state or if mA is enough + */ + if ((di->usb_state.usb_current == 2) && (mA > 2)) + bm_usb_state = AB5500_BM_USB_STATE_RESUME; + else if (mA == 0) + bm_usb_state = AB5500_BM_USB_STATE_RESET_HS; + else if (mA == 2) + bm_usb_state = AB5500_BM_USB_STATE_SUSPEND; + else if (mA >= 8) /* 8, 100, 500 */ + bm_usb_state = AB5500_BM_USB_STATE_CONFIGURED; + else /* Should never occur */ + bm_usb_state = AB5500_BM_USB_STATE_RESET_FS; dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", __func__, bm_usb_state, mA); spin_lock(&di->usb_state.usb_lock); di->usb_state.usb_changed = true; - spin_unlock(&di->usb_state.usb_lock); - di->usb_state.state = bm_usb_state; di->usb_state.usb_current = mA; + spin_unlock(&di->usb_state.usb_lock); queue_work(di->charger_wq, &di->usb_state_changed_work); - return; + return NOTIFY_OK; } -EXPORT_SYMBOL(ab5500_charger_usb_state_changed); #if defined(CONFIG_PM) static int ab5500_charger_resume(struct platform_device *pdev) @@ -1585,6 +1603,9 @@ static int __devexit ab5500_charger_remove(struct platform_device *pdev) free_irq(irq, di); } + otg_unregister_notifier(di->otg, &di->nb); + otg_put_transceiver(di->otg); + /* Delete the work queue */ destroy_workqueue(di->charger_wq); @@ -1606,8 +1627,6 @@ static int __devinit ab5500_charger_probe(struct platform_device *pdev) if (!di) return -ENOMEM; - static_di = di; - /* get parent data */ di->dev = &pdev->dev; di->parent = dev_get_drvdata(pdev->dev.parent); @@ -1702,6 +1721,18 @@ static int __devinit ab5500_charger_probe(struct platform_device *pdev) goto free_device_info; } + di->otg = otg_get_transceiver(); + if (!di->otg) { + dev_err(di->dev, "failed to get otg transceiver\n"); + goto free_usb; + } + di->nb.notifier_call = ab5500_charger_usb_notifier_call; + ret = otg_register_notifier(di->otg, &di->nb); + if (ret) { + dev_err(di->dev, "failed to register otg notifier\n"); + goto put_otg_transceiver; + } + /* Identify the connected charger types during startup */ charger_status = ab5500_charger_detect_chargers(di); if (charger_status & USB_PW_CONN) { @@ -1734,13 +1765,17 @@ static int __devinit ab5500_charger_probe(struct platform_device *pdev) return ret; free_irq: - power_supply_unregister(&di->usb_chg.psy); + otg_unregister_notifier(di->otg, &di->nb); /* We also have to free all successfully registered irqs */ for (i = i - 1; i >= 0; i--) { irq = platform_get_irq_byname(pdev, ab5500_charger_irq[i].name); free_irq(irq, di); } +put_otg_transceiver: + otg_put_transceiver(di->otg); +free_usb: + power_supply_unregister(&di->usb_chg.psy); free_charger_wq: destroy_workqueue(di->charger_wq); free_device_info: diff --git a/include/linux/mfd/abx500/ab5500-bm.h b/include/linux/mfd/abx500/ab5500-bm.h index f62137a6e9d..cfad11c530c 100644 --- a/include/linux/mfd/abx500/ab5500-bm.h +++ b/include/linux/mfd/abx500/ab5500-bm.h @@ -99,13 +99,9 @@ #define BATTERY_UNKNOWN 0 #ifdef CONFIG_AB5500_BM -void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA); struct ab5500_btemp *ab5500_btemp_get(void); int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp); #else -static void ab5500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) -{ -} static inline struct ab5500_btemp *ab5500_btemp_get(void) { return 0; -- cgit v1.2.3 From 729be001c355df1c52c2309b1d2b20efcc028b9f Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 29 Aug 2011 08:32:36 +0200 Subject: mfd: ab8500-gpadc: Change to mdelay The resolution of msleep is related to HZ, so with HZ set to 100 any msleep of less than 10ms will become ~10ms. ST-Ericsson ID: - ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Jonas Aaberg Change-Id: I3b70c983f332605eea5826ca76bb2a8995de9d3b Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31735 Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/mfd/ab8500-gpadc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 4b16f50dd1c..515e360fb09 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -340,7 +340,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) * Delay might be needed for ABB8500 cut 3.0, if not, remove * when hardware will be availible */ - msleep(1); + mdelay(1); break; } /* Intentional fallthrough */ -- cgit v1.2.3 From cd574d44e9ff564c2602b45a65dcd07301c103f5 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 11:02:18 +0200 Subject: ab5500 mfd:input:misc: Add accessory driver Add driver for the accessory detection block of the ab5500 PMIC. The common functions from the 8500 accessory driver are moved to abx500-accdet generic driver. This generic driver uses callbacks registerd from the 8500 and 5500 specific driver to work as a accessory driver for a perticluar platform. Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Robert Marklund --- drivers/mfd/ab5500-core.c | 67 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab5500.h | 2 ++ 2 files changed, 69 insertions(+) diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c index 3d7a9a282c2..493b8cb5871 100644 --- a/drivers/mfd/ab5500-core.c +++ b/drivers/mfd/ab5500-core.c @@ -1004,6 +1004,73 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { }, }, }, + [AB5500_DEVID_ACCDET] = { + .name = "ab5500-acc-det", + .id = AB5500_DEVID_ACCDET, + .num_resources = 10, + .resources = (struct resource[]) { + { + .name = "acc_detedt22db_rising", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(2, 7), + .end = AB5500_IRQ(2, 7), + }, + { + .name = "acc_detedt21db_falling", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(2, 6), + .end = AB5500_IRQ(2, 6), + }, + { + .name = "acc_detedt21db_rising", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(2, 5), + .end = AB5500_IRQ(2, 5), + }, + { + .name = "acc_detedt3db_falling", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(3, 4), + .end = AB5500_IRQ(3, 4), + }, + { + .name = "acc_detedt3db_rising", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(3, 3), + .end = AB5500_IRQ(3, 3), + }, + { + .name = "acc_detedt1db_falling", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(3, 2), + .end = AB5500_IRQ(3, 2), + }, + { + .name = "acc_detedt1db_rising", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(3, 1), + .end = AB5500_IRQ(3, 1), + }, + { + .name = "acc_detedt22db_falling", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(3, 0), + .end = AB5500_IRQ(3, 0), + }, + { + .name = "plugTVdet", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(13, 7), + .end = AB5500_IRQ(13, 7), + }, + { + .name = "plugTVdet_removal", + .flags = IORESOURCE_IRQ, + .start = AB5500_IRQ(23, 2), + .end = AB5500_IRQ(23, 2), + }, + }, + }, }; /* diff --git a/include/linux/mfd/abx500/ab5500.h b/include/linux/mfd/abx500/ab5500.h index ad8ffa65132..bf990010048 100644 --- a/include/linux/mfd/abx500/ab5500.h +++ b/include/linux/mfd/abx500/ab5500.h @@ -27,6 +27,7 @@ enum ab5500_devid { AB5500_DEVID_CHARGALG, AB5500_DEVID_BTEMP, AB5500_DEVID_TEMPMON, + AB5500_DEVID_ACCDET, AB5500_NUM_DEVICES, }; @@ -155,6 +156,7 @@ struct ab5500_platform_data { bool pm_power_off; struct ab5500_regulator_platform_data *regulator; struct ab5500_usbgpio_platform_data *usb; + struct abx500_accdet_platform_data *accdet; }; struct ab5500_ponkey_platform_data { -- cgit v1.2.3 From 87212d5239fc22d88e94fd7904cf04fd4c5eeb31 Mon Sep 17 00:00:00 2001 From: Joakim Bech Date: Thu, 22 Sep 2011 16:11:07 +0200 Subject: ux500 cryp: Disable u8500 crypto hardware This patch disable the crypto hardware in u8500. ST-Ericsson ID: 363148 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I20da80897c88e7e1ff3b53e8c549dd4bd3b4e84a Signed-off-by: Joakim Bech Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31788 Reviewed-by: Berne HEBARK --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b1a93e8a45f..ec87f7ad895 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -365,6 +365,6 @@ CONFIG_CRYPTO_ARC4=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_UX500=y -CONFIG_CRYPTO_DEV_UX500_CRYP=y +# CONFIG_CRYPTO_DEV_UX500_CRYP is not set CONFIG_CRC7=y CONFIG_LIBCRC32C=m -- cgit v1.2.3 From 144a38103457c81d79f457d4179a3b743388a464 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Mon, 26 Sep 2011 18:22:53 +0530 Subject: u5500_defconfig: Refresh the defconfig file make ARCH=arm u5500_defconfig make ARCH=arm savedefconfig cp defconfig arch/arm/configs/u5500_defconfig git add arch/arm/configs/u5500_defconfig Change-Id: Icc525eaf6c6eb1a205be5f74e9a4881a5c20f9de Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31983 Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index ec87f7ad895..76ff948e7c6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -80,7 +80,6 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set -# CONFIG_ANDROID_PARANOID_NETWORK is not set CONFIG_NETFILTER=y CONFIG_NF_CONNTRACK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y @@ -92,6 +91,7 @@ CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y CONFIG_NET_SCHED=y +# CONFIG_IPV6 is not set CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y @@ -100,7 +100,6 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y - CONFIG_AVERAGE=y #WIRELESS @@ -207,20 +206,14 @@ CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_DUMMY=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -CONFIG_VIDEO_ALLOW_V4L1=y -CONFIG_VIDEO_V4L1_COMPAT=y -CONFIG_VIDEO_MEDIA=y -CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEO_V4L1=y # CONFIG_VIDEO_CAPTURE_DRIVERS is not set -CONFIG_RADIO_ADAPTERS=y CONFIG_RADIO_CG2900=y CONFIG_GPU_MALI=y CONFIG_GPU_MALI_DEBUG=y @@ -258,13 +251,20 @@ CONFIG_USB=y CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_U5500=y +CONFIG_SND_SOC_UX500_AB5500=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_UX500=y -CONFIG_USB_MUSB_OTG=y CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y +CONFIG_MUSB_PIO_ONLY=y +CONFIG_USB_MUSB_DEBUG=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 CONFIG_AB8500_USB=y @@ -306,6 +306,7 @@ CONFIG_MODEM=y CONFIG_MODEM_U8500=y CONFIG_U8500_SHRM=y CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y +CONFIG_U5500_MMIO=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -358,6 +359,8 @@ CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_FUNCTION_TRACER=y CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y CONFIG_KEYS=y CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m -- cgit v1.2.3 From 07deafc45dd4addafbd4528a5858a980d3086fed Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 11:29:08 +0200 Subject: ARM: u8500: config: Not every u8500 has a TPS6105 Do not always select TPS6105X, but enable it via defconfig Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31951 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 76ff948e7c6..fc73208b2c6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -202,6 +202,7 @@ CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y +CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y -- cgit v1.2.3 From 5b1715283ca5ed88398a426ca0ca10c5489afae1 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Mon, 26 Sep 2011 18:05:36 +0530 Subject: abx500: support for ab5500 die temp monitoring add support for ab5500 die temperature monitoring as hardware supports reading input temperature ST-Ericsson Linux next: NA ST-Ericsson ID: 339643 ST-Ericsson FOSS-OUT ID: NA Change-Id: I26db88645c4e627829211366bdc1df22ad8ac067 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31981 Reviewed-by: Srinidhi KASAGAR --- drivers/hwmon/ab5500.c | 6 ++++++ drivers/hwmon/ab8500.c | 22 ++++++++++++++++------ drivers/hwmon/abx500.c | 25 ++++++++++++++++++++++++- drivers/hwmon/abx500.h | 2 ++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/ab5500.c b/drivers/hwmon/ab5500.c index 79540c9a79b..7352e07ffde 100644 --- a/drivers/hwmon/ab5500.c +++ b/drivers/hwmon/ab5500.c @@ -139,6 +139,11 @@ static int ab5500_temp_shutdown_auto(struct abx500_temp *data) return ret; } +static int ab5500_is_visible(struct attribute *attr, int n) +{ + return attr->mode; +} + static int ab5500_temp_irq_handler(int irq, struct abx500_temp *data) { /* @@ -195,6 +200,7 @@ int __init abx500_hwmon_init(struct abx500_temp *data) data->ops.irq_handler = ab5500_temp_irq_handler; data->ops.show_name = ab5500_show_name; data->ops.show_label = ab5500_show_label; + data->ops.is_visible = ab5500_is_visible; return 0; } diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index db601e3158d..00647240137 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -41,13 +41,8 @@ static int ab8500_read_sensor(struct abx500_temp *data, u8 sensor) * Special treatment for the BAT_CTRL node, since this * temperature measurement is more complex than just * an ADC readout - * - * DIE_TEMP input temperature reading is not supported - * in AB8500 */ - if (sensor == DIE_TEMP) - val = 0; - else if (sensor == BAT_CTRL) + if (sensor == BAT_CTRL) val = ab8500_btemp_get_batctrl_temp(data->ab8500_btemp); else val = ab8500_gpadc_convert(data->ab8500_gpadc, sensor); @@ -107,6 +102,20 @@ static ssize_t ab8500_show_label(struct device *dev, return sprintf(buf, "%s\n", name); } +static int ab8500_is_visible(struct attribute *attr, int n) +{ + if (!strcmp(attr->name, "temp5_input") || + !strcmp(attr->name, "temp5_min") || + !strcmp(attr->name, "temp5_max") || + !strcmp(attr->name, "temp5_max_hyst") || + !strcmp(attr->name, "temp5_min_alarm") || + !strcmp(attr->name, "temp5_max_alarm") || + !strcmp(attr->name, "temp5_max_hyst_alarm")) + return 0; + + return attr->mode; +} + static int ab8500_temp_irq_handler(int irq, struct abx500_temp *data) { unsigned long delay_in_jiffies; @@ -168,6 +177,7 @@ int __init abx500_hwmon_init(struct abx500_temp *data) data->ops.irq_handler = ab8500_temp_irq_handler; data->ops.show_name = ab8500_show_name; data->ops.show_label = ab8500_show_label; + data->ops.is_visible = ab8500_is_visible; return 0; } diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index 68da2d03dbd..b26a13e8438 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -436,6 +436,14 @@ static ssize_t show_crit_alarm(struct device *dev, return sprintf(buf, "%ld\n", data->crit_alarm[attr->index - 1]); } +static mode_t abx500_attrs_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct abx500_temp *data = dev_get_drvdata(dev); + return data->ops.is_visible(a, n); +} + static SENSOR_DEVICE_ATTR(temp_monitor_delay, S_IRUGO | S_IWUSR, show_temp_monitor_delay, set_temp_monitor_delay, 0); static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, @@ -493,9 +501,17 @@ static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO, show_max_hyst_alarm, NULL, 4); -/* GPADC - SENSOR4 */ +/* GPADC - SENSOR5 */ static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_min, S_IWUSR | S_IRUGO, show_min, set_min, 4); +static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_max, set_max, 4); +static SENSOR_DEVICE_ATTR(temp5_max_hyst, S_IWUSR | S_IRUGO, + show_max_hyst, set_max_hyst, 4); +static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_min_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp5_max_hyst_alarm, S_IRUGO, + show_max_hyst_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_crit_alarm, NULL, 5); @@ -542,12 +558,19 @@ struct attribute *abx500_temp_attributes[] = { /* GPADC SENSOR5*/ &sensor_dev_attr_temp5_label.dev_attr.attr, &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp5_min.dev_attr.attr, + &sensor_dev_attr_temp5_max.dev_attr.attr, + &sensor_dev_attr_temp5_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp5_max_hyst_alarm.dev_attr.attr, &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, NULL }; static const struct attribute_group abx500_temp_group = { .attrs = abx500_temp_attributes, + .is_visible = abx500_attrs_visible, }; static irqreturn_t abx500_temp_irq_handler(int irq, void *irq_data) diff --git a/drivers/hwmon/abx500.h b/drivers/hwmon/abx500.h index 77ae7cbd5c1..65a9a8238ba 100644 --- a/drivers/hwmon/abx500.h +++ b/drivers/hwmon/abx500.h @@ -22,6 +22,7 @@ struct abx500_temp; * @irq_handler: irq handler * @show_name: hwmon device name * @show_label: hwmon attribute label + * @is_visible: is attribute visible */ struct abx500_temp_ops { int (*read_sensor)(struct abx500_temp *, u8); @@ -30,6 +31,7 @@ struct abx500_temp_ops { struct device_attribute *, char *); ssize_t (*show_label) (struct device *, struct device_attribute *, char *); + int (*is_visible)(struct attribute *, int); }; /** -- cgit v1.2.3 From e40581759d8ebc8c8fca2f4241c64a2423c94302 Mon Sep 17 00:00:00 2001 From: Per Persson Date: Tue, 27 Sep 2011 12:50:47 +0200 Subject: arm: u8500: Disable HDMI fb auto creation In order to support dynamic frame buffer creation when HDMI cable is plugged, the Auto creation config flag is default disabled. ST-Ericsson ID: 364125 ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I4098a7640a91c7f2695748a7a7ddf96f16e7981b Signed-off-by: Per Persson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32171 Reviewed-by: Jimmy RUBIN --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index fc73208b2c6..343975ec71e 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -226,7 +226,7 @@ CONFIG_FB_SYS_FOPS=y CONFIG_FB_MCDE=y CONFIG_MCDE_DISPLAY_GENERIC_DSI=y CONFIG_MCDE_DISPLAY_AV8100=y -CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE=y +# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y CONFIG_B2R2_OPSIZE_64=y -- cgit v1.2.3 From d3990f196e91132d0c64b7feec0f1093d73d0ffb Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 12:05:43 +0200 Subject: ARM: ux500: Remove powersave Since we don't know really the status of powersave related feature on this development track, let's remove everything, except: - prcmu driver: New location, which is the same as linux-next - cpufreq: new location, same as linux-next - regulator: keep as is for the moment, needed for the system to work. - clocks: same as for regulator. - pm-runtime: keep it as is. Later patches will re-add powersave, based upon what exists on SI u8500-android-2.3_v3.15 MTU from plat-nomadik is now used instead of own copy in mach. Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32048 --- arch/arm/configs/u8500_defconfig | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 343975ec71e..8bef0eee3aa 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -26,10 +26,7 @@ CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y -CONFIG_UX500_PRCMU_TIMER=y CONFIG_U8500_PRCMU=y -CONFIG_UX500_PRCMU_DEBUG=y -CONFIG_UX500_DEBUG_UART=0 CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_DISPLAY_GENERIC_PRIMARY=y @@ -40,13 +37,6 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 -CONFIG_U8500_CPUIDLE_DEBUG=y -CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_STANDBY=y -CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -57,13 +47,6 @@ CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_IDLE=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y -- cgit v1.2.3 From 013df391764044b68cbd26b283f6a7a9be58aee9 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:04:22 +0200 Subject: ARM: ux500: core: Replace mach prcmu driver with mainlined version The prcmu driver now exists in drivers/mfd Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32057 --- arch/arm/configs/u8500_defconfig | 2 +- drivers/watchdog/ux500_wdt.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 8bef0eee3aa..362fadbb628 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -26,7 +26,6 @@ CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y -CONFIG_U8500_PRCMU=y CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_DISPLAY_GENERIC_PRIMARY=y @@ -185,6 +184,7 @@ CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y +CONFIG_MFD_DB8500_PRCMU=y CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index b620200ea3e..ccfb3788930 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -17,8 +17,7 @@ #include #include #include - -#include +#include #define WATCHDOG_TIMEOUT 600 /* 10 minutes */ -- cgit v1.2.3 From 43574b4ec3d4940c65d52e0c50cf1ee5d51ad565 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:20:37 +0200 Subject: ARM: ux500: config: Add prcmu qos power Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32060 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 362fadbb628..3bdf760d124 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -36,6 +36,7 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y +CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From 149bb9c93598f84655fac516c67d14d78522be1c Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:27:03 +0200 Subject: ARM: ux500: config: Add prcmu-debug Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32061 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3bdf760d124..b6c7b6227f0 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -37,6 +37,7 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y +CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From 4859c4f4ca3c9afddbbd10a9c40c8c22eb86c5d2 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:32:28 +0200 Subject: ARM: ux500: pm: config: Added context and pm These files are primarily needed by suspend and cpuidle. Signed-off-by: Rickard Andersson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32068 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b6c7b6227f0..16c24924356 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -38,6 +38,8 @@ CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y +# CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set +CONFIG_UX500_CONTEXT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From 1ee50668d6535b111ae21922495238d7046e9ada Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 20 Sep 2011 09:16:36 +0200 Subject: ARM: u8500: config: Enable cpufreq Change-Id: I6d29a32251144e3ff33841516ea265ea9964f46e Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32071 --- arch/arm/configs/u8500_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 16c24924356..d02ae0fdb0b 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -40,6 +40,12 @@ CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_UX500_CONTEXT=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From 291896b1411e641a8eb9b8c60cf1d0441820a753 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:35:52 +0200 Subject: ARM: ux500: config Add suspend support Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32074 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index d02ae0fdb0b..4b3172a60e8 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -39,6 +39,7 @@ CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set +CONFIG_UX500_SUSPEND=y CONFIG_UX500_CONTEXT=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y -- cgit v1.2.3 From d7c3a84fd9a215f3914a123a88c169ac61c47c30 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:36:59 +0200 Subject: ARM: ux500: config: suspend: Add wake on uart Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32077 --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4b3172a60e8..1e2928e4b79 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -40,6 +40,8 @@ CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_UX500_SUSPEND=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_UX500_CONTEXT=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y -- cgit v1.2.3 From 8e1714fba25c10e4dbfa5a7f76e56f23f434f2b6 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:38:18 +0200 Subject: ARM: ux500: config: suspend_dbg: Add debug information Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32081 --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 1e2928e4b79..8416d298e5e 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -42,6 +42,8 @@ CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y +CONFIG_UX500_SUSPEND_STANDBY=y +CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_CONTEXT=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y -- cgit v1.2.3 From c0918d13d1297dbf973c9d2a98259374aea890a0 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:44:22 +0200 Subject: drivers:cpuidle:config U8500 support cpuidle driver Signed-off-by: Rickard Andersson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32084 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 8416d298e5e..e2aee993c24 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -38,7 +38,11 @@ CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_CPU_IDLE=y +CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 +CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y -- cgit v1.2.3 From ac8465f8f96ae7d565a8fb0a1dd2895706ffcf36 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Tue, 20 Sep 2011 17:33:17 +0200 Subject: cpuidle: only go to ApIdle Until all drivers can handle ApSleep properly we only go to sleep state ApIdle Change-Id: I952f7521284a41af56698cd8fc72b833210ea30e Signed-off-by: Rickard Andersson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32086 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index e2aee993c24..d0944bf1a1a 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -41,7 +41,7 @@ CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_CPU_IDLE=y CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=3 +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_DBG=y -- cgit v1.2.3 From 6044b6e7d6a6d04e0e570c860fe6d49dbcf1b75a Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 21 Sep 2011 10:02:50 +0200 Subject: u8500: watchdog: Reset to mainline status Change-Id: I14fd6f9990e3fe58671ff256baa8e6dfa0376b1f Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32087 --- arch/arm/configs/u8500_defconfig | 1 - drivers/watchdog/Kconfig | 16 -- drivers/watchdog/Makefile | 1 - drivers/watchdog/ux500_wdt.c | 440 --------------------------------------- 4 files changed, 458 deletions(-) delete mode 100644 drivers/watchdog/ux500_wdt.c diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index d0944bf1a1a..ee9cc394992 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -200,7 +200,6 @@ CONFIG_SENSORS_AB8500=y CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_L3G4200D=y -CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_MFD_DB8500_PRCMU=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a2eb7474ebd..37096246c93 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -294,22 +294,6 @@ config COH901327_WATCHDOG This watchdog is used to reset the system and thus cannot be compiled as a module. -config UX500_WATCHDOG - bool "ST-Ericsson UX500 watchdog" - depends on ARCH_U8500 - default y if MACH_U8500 - help - Say Y here to include Watchdog timer support for the - watchdog existing in the prcmu of ST-Ericsson UX500 series platforms. - This watchdog is used to reset the system and thus cannot be - compiled as a module. - -config UX500_WATCHDOG_DEBUG - bool "ST-Ericsson UX500 watchdog DEBUG" - depends on ARCH_U8500 && DEBUG_FS - help - Say Y here to add various debugfs entries in wdog/ - config TWL4030_WATCHDOG tristate "TWL4030 Watchdog" depends on TWL4030_CORE diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 746492e2249..e8f479a1640 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -49,7 +49,6 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o -obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c deleted file mode 100644 index ccfb3788930..00000000000 --- a/drivers/watchdog/ux500_wdt.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * - * Author: Jonas Aaberg for ST-Ericsson - * - * Heavily based upon geodewdt.c - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WATCHDOG_TIMEOUT 600 /* 10 minutes */ - -#define WDT_FLAGS_OPEN 1 -#define WDT_FLAGS_ORPHAN 2 - -static unsigned long wdt_flags; - -static int timeout = WATCHDOG_TIMEOUT; -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, - "Watchdog timeout in seconds. 1<= timeout <=131, default=" - __MODULE_STRING(WATCHDOG_TIMEOUT) "."); - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static u8 wdog_id; -static bool wdt_en; -static bool wdt_auto_off = false; -static bool safe_close; - -static int ux500_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) - return -EBUSY; - - if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) - __module_get(THIS_MODULE); - - prcmu_enable_a9wdog(wdog_id); - wdt_en = true; - - return nonseekable_open(inode, file); -} - -static int ux500_wdt_release(struct inode *inode, struct file *file) -{ - if (safe_close) { - prcmu_disable_a9wdog(wdog_id); - module_put(THIS_MODULE); - } else { - pr_crit("Unexpected close - watchdog is not stopping.\n"); - prcmu_kick_a9wdog(wdog_id); - - set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); - } - - clear_bit(WDT_FLAGS_OPEN, &wdt_flags); - safe_close = false; - return 0; -} - -static ssize_t ux500_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - if (!len) - return len; - - if (!nowayout) { - size_t i; - safe_close = false; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - - if (c == 'V') - safe_close = true; - } - } - - prcmu_kick_a9wdog(wdog_id); - - return len; -} - -static long ux500_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int interval; - - static const struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 1, - .identity = "UX500 WDT", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &ident, - sizeof(ident)) ? -EFAULT : 0; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - - case WDIOC_SETOPTIONS: - { - int options; - int ret = -EINVAL; - - if (get_user(options, p)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) { - prcmu_disable_a9wdog(wdog_id); - wdt_en = false; - ret = 0; - } - - if (options & WDIOS_ENABLECARD) { - prcmu_enable_a9wdog(wdog_id); - wdt_en = true; - ret = 0; - } - - return ret; - } - case WDIOC_KEEPALIVE: - return prcmu_kick_a9wdog(wdog_id); - - case WDIOC_SETTIMEOUT: - if (get_user(interval, p)) - return -EFAULT; - - /* 28 bit resolution in ms, becomes 268435455 ms */ - if (interval > 26843 || interval < 0) - return -EINVAL; - timeout = interval; - prcmu_disable_a9wdog(wdog_id); - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - - /* Fall through */ - case WDIOC_GETTIMEOUT: - return put_user(timeout, p); - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations ux500_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = ux500_wdt_write, - .unlocked_ioctl = ux500_wdt_ioctl, - .open = ux500_wdt_open, - .release = ux500_wdt_release, -}; - -static struct miscdevice ux500_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &ux500_wdt_fops, -}; - -#ifdef CONFIG_UX500_WATCHDOG_DEBUG - -enum wdog_dbg { - WDOG_DBG_CONFIG, - WDOG_DBG_LOAD, - WDOG_DBG_KICK, - WDOG_DBG_EN, - WDOG_DBG_DIS, -}; - -static ssize_t wdog_dbg_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - unsigned long val; - int err; - enum wdog_dbg v = (enum wdog_dbg)((struct seq_file *) - (file->private_data))->private; - - switch(v) { - case WDOG_DBG_CONFIG: - err = kstrtoul_from_user(user_buf, count, 0, &val); - - if (!err) { - wdt_auto_off = val != 0; - (void) prcmu_config_a9wdog(1, - wdt_auto_off); - } - else { - pr_err("ux500_wdt:dbg: unknown value\n"); - } - break; - case WDOG_DBG_LOAD: - err = kstrtoul_from_user(user_buf, count, 0, &val); - - if (!err) { - timeout = val; - /* Convert seconds to ms */ - prcmu_disable_a9wdog(wdog_id); - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - else { - pr_err("ux500_wdt:dbg: unknown value\n"); - } - break; - case WDOG_DBG_KICK: - (void) prcmu_kick_a9wdog(wdog_id); - break; - case WDOG_DBG_EN: - wdt_en = true; - (void) prcmu_enable_a9wdog(wdog_id); - break; - case WDOG_DBG_DIS: - wdt_en = false; - (void) prcmu_disable_a9wdog(wdog_id); - break; - } - - return count; -} - -static int wdog_dbg_read(struct seq_file *s, void *p) -{ - enum wdog_dbg v = (enum wdog_dbg)s->private; - - switch(v) { - case WDOG_DBG_CONFIG: - seq_printf(s,"wdog is on id %d, auto off on sleep: %s\n", - (int)wdog_id, - wdt_auto_off ? "enabled": "disabled"); - break; - case WDOG_DBG_LOAD: - /* In 1s */ - seq_printf(s, "wdog load is: %d s\n", - timeout); - break; - case WDOG_DBG_KICK: - break; - case WDOG_DBG_EN: - case WDOG_DBG_DIS: - seq_printf(s, "wdog is %sabled.\n", - wdt_en ? "en" : "dis"); - break; - } - return 0; -} - -static int wdog_dbg_open(struct inode *inode, - struct file *file) -{ - return single_open(file, wdog_dbg_read, inode->i_private); -} - -static const struct file_operations wdog_dbg_fops = { - .open = wdog_dbg_open, - .write = wdog_dbg_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int __init wdog_dbg_init(void) -{ - struct dentry *wdog_dir; - - wdog_dir = debugfs_create_dir("wdog", NULL); - if (IS_ERR_OR_NULL(wdog_dir)) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_u8("id", - S_IWUGO | S_IRUGO, wdog_dir, - &wdog_id))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("config", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_CONFIG, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("load", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_LOAD, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("kick", - S_IWUGO, wdog_dir, - (void *)WDOG_DBG_KICK, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("enable", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_EN, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("disable", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_DIS, - &wdog_dbg_fops))) - goto fail; - - return 0; -fail: - pr_err("ux500:wdog: Failed to initialize wdog dbg.\n"); - debugfs_remove_recursive(wdog_dir); - - return -EFAULT; -} - -#else -static inline int __init wdog_dbg_init(void) -{ - return 0; -} -#endif - -static int __init ux500_wdt_probe(struct platform_device *pdev) -{ - int ret; - - /* Number of watch dogs */ - prcmu_config_a9wdog(1, wdt_auto_off); - /* convert to ms */ - prcmu_load_a9wdog(wdog_id, timeout * 1000); - - ret = misc_register(&ux500_wdt_miscdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register misc.\n"); - return ret; - } - - ret = wdog_dbg_init(); - if (ret < 0) - goto fail; - - dev_info(&pdev->dev, "initialized.\n"); - - return 0; -fail: - misc_deregister(&ux500_wdt_miscdev); - return ret; -} - -static int __exit ux500_wdt_remove(struct platform_device *dev) -{ - prcmu_disable_a9wdog(wdog_id); - wdt_en = false; - misc_deregister(&ux500_wdt_miscdev); - return 0; -} -#ifdef CONFIG_PM -static int ux500_wdt_suspend(struct platform_device *pdev, - pm_message_t state) -{ - if (wdt_en && !wdt_auto_off) { - prcmu_disable_a9wdog(wdog_id); - prcmu_config_a9wdog(1, true); - - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - return 0; -} - -static int ux500_wdt_resume(struct platform_device *pdev) -{ - if (wdt_en && !wdt_auto_off) { - prcmu_disable_a9wdog(wdog_id); - prcmu_config_a9wdog(1, wdt_auto_off); - - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - return 0; -} - -#else -#define ux500_wdt_suspend NULL -#define ux500_wdt_resume NULL -#endif -static struct platform_driver ux500_wdt_driver = { - .remove = __exit_p(ux500_wdt_remove), - .driver = { - .owner = THIS_MODULE, - .name = "ux500_wdt", - }, - .suspend = ux500_wdt_suspend, - .resume = ux500_wdt_resume, -}; - -static int __init ux500_wdt_init(void) -{ - return platform_driver_probe(&ux500_wdt_driver, ux500_wdt_probe); -} - -static void __exit ux500_wdt_exit(void) -{ - platform_driver_unregister(&ux500_wdt_driver); -} - -module_init(ux500_wdt_init); -module_exit(ux500_wdt_exit); - -MODULE_AUTHOR("Jonas Aaberg "); -MODULE_DESCRIPTION("UX500 Watchdog Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From 188f7b8d729e67541b3732a4b8b3ac45162dfef7 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 21 Sep 2011 08:35:08 +0200 Subject: drivers: watchdog: Add watchdog for u8500 Watchdog driver for ST-Ericsson's u8500 platform Change-Id: I9154a96b85493db8c94e52ed84f6e25119f0847c Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32088 --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/u8500_wdt.c | 265 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 drivers/watchdog/u8500_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37096246c93..620994f0c1b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -349,6 +349,16 @@ config IMX2_WDT To compile this driver as a module, choose M here: the module will be called imx2_wdt. +config U8500_WATCHDOG + bool "ST-Ericsson U8500 watchdog" + depends on UX500_SOC_DB8500 + default y + help + Say Y here to include Watchdog timer support for the + watchdog existing in the prcmu of ST-Ericsson U8500 series platforms. + This watchdog is used to reset the system and thus cannot be + compiled as a module. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e8f479a1640..7e77ba49897 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o +obj-$(CONFIG_U8500_WATCHDOG) += u8500_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/u8500_wdt.c b/drivers/watchdog/u8500_wdt.c new file mode 100644 index 00000000000..6433e798916 --- /dev/null +++ b/drivers/watchdog/u8500_wdt.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Jonas Aaberg for ST-Ericsson + * + * Heavily based upon geodewdt.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WATCHDOG_TIMEOUT 600 /* 10 minutes */ + +#define WDT_FLAGS_OPEN 1 +#define WDT_FLAGS_ORPHAN 2 + +static unsigned long wdt_flags; + +static int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +static u8 wdog_id; +static bool wdt_en; +static bool wdt_auto_off = false; +static bool safe_close; + +static int u8500_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) + return -EBUSY; + + if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) + __module_get(THIS_MODULE); + + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + + return nonseekable_open(inode, file); +} + +static int u8500_wdt_release(struct inode *inode, struct file *file) +{ + if (safe_close) { + prcmu_disable_a9wdog(wdog_id); + module_put(THIS_MODULE); + } else { + pr_crit("Unexpected close - watchdog is not stopping.\n"); + prcmu_kick_a9wdog(wdog_id); + + set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); + } + + clear_bit(WDT_FLAGS_OPEN, &wdt_flags); + safe_close = false; + return 0; +} + +static ssize_t u8500_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + if (!len) + return len; + + if (!nowayout) { + size_t i; + safe_close = false; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + safe_close = true; + } + } + + prcmu_kick_a9wdog(wdog_id); + + return len; +} + +static long u8500_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int interval; + + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "U8500 WDT", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + { + int options; + int ret = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + ret = 0; + } + + return ret; + } + case WDIOC_KEEPALIVE: + return prcmu_kick_a9wdog(wdog_id); + + case WDIOC_SETTIMEOUT: + if (get_user(interval, p)) + return -EFAULT; + + /* 28 bit resolution in ms, becomes 268435.455 s */ + if (interval > 268435 || interval < 0) + return -EINVAL; + timeout = interval; + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + + /* Fall through */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations u8500_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = u8500_wdt_write, + .unlocked_ioctl = u8500_wdt_ioctl, + .open = u8500_wdt_open, + .release = u8500_wdt_release, +}; + +static struct miscdevice u8500_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &u8500_wdt_fops, +}; + +static int __init u8500_wdt_probe(struct platform_device *pdev) +{ + int ret; + + /* Number of watch dogs */ + prcmu_config_a9wdog(1, wdt_auto_off); + /* convert to ms */ + prcmu_load_a9wdog(wdog_id, timeout * 1000); + + ret = misc_register(&u8500_wdt_miscdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register misc\n"); + return ret; + } + + dev_info(&pdev->dev, "initialized\n"); + + return 0; +} + +static int __exit u8500_wdt_remove(struct platform_device *dev) +{ + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + misc_deregister(&u8500_wdt_miscdev); + return 0; +} +#ifdef CONFIG_PM +static int u8500_wdt_suspend(struct platform_device *pdev, + pm_message_t state) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, true); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} + +static int u8500_wdt_resume(struct platform_device *pdev) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, wdt_auto_off); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} + +#else +#define u8500_wdt_suspend NULL +#define u8500_wdt_resume NULL +#endif +static struct platform_driver u8500_wdt_driver = { + .remove = __exit_p(u8500_wdt_remove), + .driver = { + .owner = THIS_MODULE, + .name = "u8500_wdt", + }, + .suspend = u8500_wdt_suspend, + .resume = u8500_wdt_resume, +}; + +static int __init u8500_wdt_init(void) +{ + return platform_driver_probe(&u8500_wdt_driver, u8500_wdt_probe); +} +module_init(u8500_wdt_init); + +MODULE_AUTHOR("Jonas Aaberg "); +MODULE_DESCRIPTION("U8500 Watchdog Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From 8ce8442c499bec4e62ef4214b9328cfedbcb7a7a Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 21 Sep 2011 09:30:42 +0200 Subject: drivers: watchdog: u8500: Add debugfs interface Change-Id: I0c2da769eea8ff3d89ded8253482d805d4913f00 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32089 --- drivers/watchdog/Kconfig | 6 ++ drivers/watchdog/u8500_wdt.c | 168 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 620994f0c1b..57386b4feaa 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -359,6 +359,12 @@ config U8500_WATCHDOG This watchdog is used to reset the system and thus cannot be compiled as a module. +config U8500_WATCHDOG_DEBUG + bool "ST-Ericsson U8500 watchdog DEBUG" + depends on UX500_SOC_DB8500 && DEBUG_FS + help + Say Y here to add various debugfs entries in wdog/ + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/u8500_wdt.c b/drivers/watchdog/u8500_wdt.c index 6433e798916..3ac23ab05f3 100644 --- a/drivers/watchdog/u8500_wdt.c +++ b/drivers/watchdog/u8500_wdt.c @@ -186,6 +186,167 @@ static struct miscdevice u8500_wdt_miscdev = { .fops = &u8500_wdt_fops, }; +#ifdef CONFIG_U8500_WATCHDOG_DEBUG + +enum wdog_dbg { + WDOG_DBG_CONFIG, + WDOG_DBG_LOAD, + WDOG_DBG_KICK, + WDOG_DBG_EN, + WDOG_DBG_DIS, +}; + +static ssize_t wdog_dbg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + unsigned long val; + int err; + enum wdog_dbg v = (enum wdog_dbg)((struct seq_file *) + (file->private_data))->private; + + switch(v) { + case WDOG_DBG_CONFIG: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + wdt_auto_off = val != 0; + (void) prcmu_config_a9wdog(1, + wdt_auto_off); + } + else { + pr_err("u8500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_LOAD: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + timeout = val; + /* Convert seconds to ms */ + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + else { + pr_err("u8500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_KICK: + (void) prcmu_kick_a9wdog(wdog_id); + break; + case WDOG_DBG_EN: + wdt_en = true; + (void) prcmu_enable_a9wdog(wdog_id); + break; + case WDOG_DBG_DIS: + wdt_en = false; + (void) prcmu_disable_a9wdog(wdog_id); + break; + } + + return count; +} + +static int wdog_dbg_read(struct seq_file *s, void *p) +{ + enum wdog_dbg v = (enum wdog_dbg)s->private; + + switch(v) { + case WDOG_DBG_CONFIG: + seq_printf(s,"wdog is on id %d, auto off on sleep: %s\n", + (int)wdog_id, + wdt_auto_off ? "enabled": "disabled"); + break; + case WDOG_DBG_LOAD: + /* In 1s */ + seq_printf(s, "wdog load is: %d s\n", + timeout); + break; + case WDOG_DBG_KICK: + break; + case WDOG_DBG_EN: + case WDOG_DBG_DIS: + seq_printf(s, "wdog is %sabled\n", + wdt_en ? "en" : "dis"); + break; + } + return 0; +} + +static int wdog_dbg_open(struct inode *inode, + struct file *file) +{ + return single_open(file, wdog_dbg_read, inode->i_private); +} + +static const struct file_operations wdog_dbg_fops = { + .open = wdog_dbg_open, + .write = wdog_dbg_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int __init wdog_dbg_init(void) +{ + struct dentry *wdog_dir; + + wdog_dir = debugfs_create_dir("wdog", NULL); + if (IS_ERR_OR_NULL(wdog_dir)) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_u8("id", + S_IWUGO | S_IRUGO, wdog_dir, + &wdog_id))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("config", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_CONFIG, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("load", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_LOAD, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("kick", + S_IWUGO, wdog_dir, + (void *)WDOG_DBG_KICK, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("enable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_EN, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("disable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_DIS, + &wdog_dbg_fops))) + goto fail; + + return 0; +fail: + pr_err("u8500:wdog: Failed to initialize wdog dbg\n"); + debugfs_remove_recursive(wdog_dir); + + return -EFAULT; +} + +#else +static inline int __init wdog_dbg_init(void) +{ + return 0; +} +#endif + static int __init u8500_wdt_probe(struct platform_device *pdev) { int ret; @@ -201,9 +362,16 @@ static int __init u8500_wdt_probe(struct platform_device *pdev) return ret; } + ret = wdog_dbg_init(); + if (ret < 0) + goto fail; + dev_info(&pdev->dev, "initialized\n"); return 0; +fail: + misc_deregister(&u8500_wdt_miscdev); + return ret; } static int __exit u8500_wdt_remove(struct platform_device *dev) -- cgit v1.2.3 From c0fd97c568a0270dbd0bf6f48cbbd8a683748ec5 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:51:49 +0200 Subject: ARM: ux500: config: Use u8500_wdt Enalbe the u8500 watchdog including debug for u8500 builds. Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32090 --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index ee9cc394992..b45723e2730 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -200,6 +200,9 @@ CONFIG_SENSORS_AB8500=y CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_L3G4200D=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +CONFIG_U8500_WATCHDOG_DEBUG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_MFD_DB8500_PRCMU=y -- cgit v1.2.3 From 1441a474e7002e5d8e9c5e04c8164f91534e7495 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Fri, 23 Sep 2011 10:34:33 +0200 Subject: ARM: config: u8500: Enable DB8500 regulators Change-Id: Ieb69b0092465a71e7233cc63bddb149998f96410 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32110 --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b45723e2730..067532174cf 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -215,6 +215,7 @@ CONFIG_REGULATOR_DUMMY=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_DB8500_PRCMU=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set -- cgit v1.2.3 From 5e474534bf1d0c9397d7b751bd1f615237a5b44c Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 21 Sep 2011 11:06:57 +0200 Subject: serial: amba-pl011: delay driver initialization During pl011 probe() On u8500 platform, amba bus driver tries to access regulator driver and fails as the regulator driver is also at arch_init level. Moving serial driver to the next level but still as early as possible. Change-Id: I29d23067df9465b3c25f4010dca8af253fe6d070 Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32121 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- drivers/tty/serial/amba-pl011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3618278df03..1a65c2d1093 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2403,7 +2403,7 @@ static void __exit pl011_exit(void) * While this can be a module, if builtin it's most likely the console * So let's leave module_exit but move module_init to an earlier place */ -arch_initcall(pl011_init); +subsys_initcall(pl011_init); module_exit(pl011_exit); MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); -- cgit v1.2.3 From 7d8e5cdf54d2dac3a8a7bebb56aa9c8bdc8b70d6 Mon Sep 17 00:00:00 2001 From: Christian Nilsson Date: Thu, 29 Sep 2011 07:42:58 +0200 Subject: u8500_defconfig: Enable ip rule support Added support for multiple routing tables used for Dial Up Networking and enabled the usage of ip rule command to configure them. ST-Ericsson ID: 339665 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I3a570cdf0dbdbea2b2279428fa10d8a1fc63f659 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32428 Reviewed-by: Christian NILSSON Tested-by: Christian NILSSON Reviewed-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 067532174cf..a9a9443532b 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -72,7 +72,14 @@ CONFIG_PM_RUNTIME=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set @@ -82,12 +89,17 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y +CONFIG_NF_CT_NETLINK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_ULOG=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y @@ -104,6 +116,7 @@ CONFIG_BT_HIDP=y CONFIG_AVERAGE=y #WIRELESS +CONFIG_FIB_RULES=y CONFIG_WIRELESS=y CONFIG_COMPAT_WIRELESS=y CONFIG_COMPAT_WIRELESS_MODULES=y @@ -163,6 +176,18 @@ CONFIG_SMSC911X=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=y +# CONFIG_PPPOE is not set +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_SLHC=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set -- cgit v1.2.3 From 21b15cc573a83fc5c4886131c810873b3d36ee22 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 30 Sep 2011 23:34:55 +0200 Subject: config: Update the u8500 def config Change-Id: I6f0959ab3d5496d54d35cdf74354b27d616ba8cf Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 118 ++++++--------------------------------- 1 file changed, 17 insertions(+), 101 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index a9a9443532b..41e1b225462 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -24,37 +24,23 @@ CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y -CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y -CONFIG_U8500_REGULATOR_DEBUG=y +CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_DB8500_MLOADER=y -CONFIG_DISPLAY_GENERIC_PRIMARY=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_90=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_CPU_IDLE=y -CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_CONTEXT=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -65,6 +51,15 @@ CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 +CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y @@ -73,13 +68,9 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y -# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IP_FIB_TRIE_STATS is not set CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set @@ -89,7 +80,6 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set CONFIG_NETFILTER=y -CONFIG_NETFILTER_NETLINK=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y @@ -104,7 +94,6 @@ CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y CONFIG_NET_SCHED=y -# CONFIG_IPV6 is not set CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y @@ -113,40 +102,11 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_AVERAGE=y - -#WIRELESS -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_COMPAT_WIRELESS=y -CONFIG_COMPAT_WIRELESS_MODULES=y CONFIG_CFG80211=y -CONFIG_COMPAT_MAC80211_RC_DEFAULT="minstrel_ht" -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_COMPAT_RFKILL=y CONFIG_NL80211_TESTMODE=y -CONFIG_CFG80211_DEFAULT_PS=y CONFIG_CFG80211_REG_DEBUG=y -CONFIG_MAC80211_RC_PID=y -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -CONFIG_MAC80211_LEDS=y -CONFIG_MAC80211_MESH=y -# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set -# CONFIG_CFG80211_DEBUGFS is not set -# CONFIG_CFG80211_INTERNAL_REGDB is not set # CONFIG_CFG80211_WEXT is not set -# CONFIG_LIB80211 is not set -# CONFIG_MAC80211 is not set -# CONFIG_MAC80211_HAS_RC is not set -# CONFIG_MAC80211_RC_DEFAULT_PID is not set -# CONFIG_MAC80211_RC_DEFAULT is not set -# CONFIG_MAC80211_DEBUGFS is not set -# CONFIG_MAC80211_DEBUG_MENU is not set -# CONFIG_WIMAX is not set CONFIG_RFKILL=y -CONFIG_RFKILL_PM=y -CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y CONFIG_NET_9P=y CONFIG_CAIF=y @@ -158,9 +118,8 @@ CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y -CONFIG_U8500_SIM_DETECT=y -# CONFIG_STM_TRACE=y CONFIG_DISPDEV=y +CONFIG_U8500_SIM_DETECT=y # CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y @@ -177,17 +136,8 @@ CONFIG_SMSC911X=y # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set CONFIG_PPP_ASYNC=y -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set CONFIG_PPP_MPPE=y -# CONFIG_PPPOE is not set -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_SLHC=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -226,18 +176,14 @@ CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y CONFIG_U8500_WATCHDOG_DEBUG=y +CONFIG_TPS6105X=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y -CONFIG_MFD_DB8500_PRCMU=y -CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y -CONFIG_REGULATOR_DUMMY=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_DB8500_PRCMU=y @@ -246,28 +192,12 @@ CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_RADIO_CG2900=y -CONFIG_GPU_MALI=y -CONFIG_GPU_MALI_DEBUG=y CONFIG_FB=y -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -CONFIG_FB_SYS_FOPS=y CONFIG_FB_MCDE=y -CONFIG_MCDE_DISPLAY_GENERIC_DSI=y -CONFIG_MCDE_DISPLAY_AV8100=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y -CONFIG_B2R2_OPSIZE_64=y -CONFIG_B2R2_CHSIZE_128=y -CONFIG_B2R2_MGSIZE_128=y -CONFIG_B2R2_PGSIZE_256=y -CONFIG_B2R2_GENERIC=y -CONFIG_B2R2_GENERIC_FALLBACK=y -CONFIG_AV8100=y -CONFIG_AV8100_HWTRIG_I2SDAT3=y -CONFIG_DUMMY_CONSOLE=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_USB_AUDIO=y @@ -282,27 +212,19 @@ CONFIG_USB=y CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -CONFIG_SND_SOC=y -CONFIG_SND_SOC_UX500=y -CONFIG_SND_SOC_U5500=y -CONFIG_SND_SOC_UX500_AB5500=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_UX500=y +CONFIG_USB_MUSB_OTG=y CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y -CONFIG_MUSB_PIO_ONLY=y -CONFIG_USB_MUSB_DEBUG=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_CLKGATE=y -CONFIG_MMC_PARANOID_SD_INIT=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y @@ -312,7 +234,6 @@ CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_SWITCH=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y @@ -337,7 +258,6 @@ CONFIG_MODEM=y CONFIG_MODEM_U8500=y CONFIG_U8500_SHRM=y CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y -CONFIG_U5500_MMIO=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -390,15 +310,11 @@ CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_FUNCTION_TRACER=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y CONFIG_KEYS=y CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_ARC4=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_UX500=y -# CONFIG_CRYPTO_DEV_UX500_CRYP is not set CONFIG_CRC7=y CONFIG_LIBCRC32C=m +CONFIG_AVERAGE=y -- cgit v1.2.3 From 086d306e1f3574d055df43de7384189ef31f03e6 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 28 Sep 2011 09:48:38 +0200 Subject: hwmon: Make all ux500 mach build at once Alter the hwmon driver so we can build both the MACH_U5500 and the U8500 at the same time. Change-Id: I2ff9665427c1c33181552e7e51074c5eca3f1473 Signed-off-by: Robert Marklund --- drivers/hwmon/ab5500.c | 3 ++- drivers/hwmon/ab8500.c | 3 ++- drivers/hwmon/abx500.c | 7 ++++++- drivers/hwmon/abx500.h | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/ab5500.c b/drivers/hwmon/ab5500.c index 7352e07ffde..0122f315ac6 100644 --- a/drivers/hwmon/ab5500.c +++ b/drivers/hwmon/ab5500.c @@ -25,6 +25,7 @@ #include #include #include "abx500.h" +#include /* AB5500 driver monitors GPADC - XTAL_TEMP, PCB_TEMP, * BTEMP_BALL, BAT_CTRL and DIE_TEMP @@ -159,7 +160,7 @@ static int ab5500_temp_irq_handler(int irq, struct abx500_temp *data) return 0; } -int __init abx500_hwmon_init(struct abx500_temp *data) +int __init ab5500_hwmon_init(struct abx500_temp *data) { int err; diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index 00647240137..8204af594a9 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -25,6 +25,7 @@ #include #include #include "abx500.h" +#include #define DEFAULT_POWER_OFF_DELAY 10000 @@ -136,7 +137,7 @@ static int ab8500_temp_irq_handler(int irq, struct abx500_temp *data) return 0; } -int __init abx500_hwmon_init(struct abx500_temp *data) +int __init ab8500_hwmon_init(struct abx500_temp *data) { data->ab8500_gpadc = ab8500_gpadc_get(); if (IS_ERR(data->ab8500_gpadc)) diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index b26a13e8438..de4e6280b4b 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -36,6 +36,8 @@ #include #include #include +#include + #include "abx500.h" #define DEFAULT_MONITOR_DELAY 1000 @@ -610,7 +612,10 @@ static int __devinit abx500_temp_probe(struct platform_device *pdev) mutex_init(&data->lock); /* Chip specific initialization */ - err = abx500_hwmon_init(data); + if (!machine_is_u5500()) + err = ab8500_hwmon_init(data); + else + err = ab5500_hwmon_init(data); if (err < 0) { dev_err(&pdev->dev, "abx500 init failed"); goto exit; diff --git a/drivers/hwmon/abx500.h b/drivers/hwmon/abx500.h index 65a9a8238ba..9fe28dac28f 100644 --- a/drivers/hwmon/abx500.h +++ b/drivers/hwmon/abx500.h @@ -89,6 +89,7 @@ struct abx500_temp { int monitored_sensors; }; -int abx500_hwmon_init(struct abx500_temp *data) __init; +int ab8500_hwmon_init(struct abx500_temp *data) __init; +int ab5500_hwmon_init(struct abx500_temp *data) __init; #endif /* _ABX500_H */ -- cgit v1.2.3 From be7e60d38ef00f59500266b41ff3e61626274626 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 30 Sep 2011 10:27:32 +0200 Subject: smsc911x: Add regulator support Add some regulator support, there can be nessesary to add moreregulators to suite all power save needs. But this is a start. Also add a wait for the chip to be ready after the regulators are enabled, this was a bug in the old implementation. Change-Id: I5ed6732f9f86f0305ac6428bdb984836aac8b1f1 Signed-off-by: Robert Marklund --- drivers/net/ethernet/smsc/smsc911x.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index cd3defb11ff..dbeb806f123 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2343,6 +2343,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) unsigned int intcfg = 0; int res_size, irq_flags; int retval; + int to = 100; pr_info("Driver version %s\n", SMSC_DRV_VERSION); @@ -2419,6 +2420,18 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (pdata->config.shift) pdata->ops = &shifted_smsc911x_ops; + /* poll the READY bit in PMT_CTRL. Any other access to the device is + * forbidden while this bit isn't set. Try for 100ms + */ + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + udelay(1000); + + if (to == 0) { + pr_err("Device not READY in 100ms aborting\n"); + goto out_0; + } + + retval = smsc911x_init(dev); if (retval < 0) goto out_disable_resources; -- cgit v1.2.3 From 9af092b1b5b0b21cbe62c7ea3bf2517424bc5165 Mon Sep 17 00:00:00 2001 From: Dmitry Tarnyagin Date: Mon, 10 Oct 2011 12:28:49 +0200 Subject: u8500: Enable cw1200 in defconfig Change-Id: Ifbc169cdb432cdda7b2efba3550cb703f007e6da Signed-off-by: Dmitry Tarnyagin Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33544 Reviewed-by: Bartosz MARKOWSKI Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 41e1b225462..dfbe20e608b 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -102,10 +102,10 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_CFG80211=y +CONFIG_CFG80211=m CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_REG_DEBUG=y -# CONFIG_CFG80211_WEXT is not set +CONFIG_CFG80211_WEXT=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y CONFIG_NET_9P=y @@ -251,6 +251,11 @@ CONFIG_CG2900_UART=y CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y +CONFIG_CW1200=m +# CONFIG_CW1200_NON_POWER_OF_TWO_BLOCKSIZES is not set +CONFIG_CW1200_USE_GPIO_IRQ=y +CONFIG_CW1200_WOW=y +CONFIG_CW1200_DEBUGFS=y CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y -- cgit v1.2.3 From 499bae90886e71cce9b2ec29f9660f5cb3ee0f26 Mon Sep 17 00:00:00 2001 From: John Fredriksson Date: Wed, 12 Oct 2011 15:15:17 +0200 Subject: u8500_defconfig: Enable support for x11. Make it possible to use x11 window system. Signed-off-by: John Fredriksson Change-Id: I2b916c72ac1a9f337dac8da59a9ca43ee3803bd2 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33812 Reviewed-by: Philippe LANGLAIS Tested-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index dfbe20e608b..0412ef17a7d 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -192,9 +192,11 @@ CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_RADIO_CG2900=y +CONFIG_DRM=y +CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y -# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_MCDE_FB_AVOID_REALLOC=y CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y -- cgit v1.2.3 From 63ae31ae359e31579c701747df419f2bfd329230 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 14 Oct 2011 15:28:36 +0200 Subject: config: enable usb modules Change-Id: I9cefa3c2089df1b0cc70e21f28a7550dae16e8fd Signed-off-by: Robert Marklund Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34109 Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0412ef17a7d..8f0efa642f1 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -102,10 +102,8 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_CFG80211=m CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_REG_DEBUG=y -CONFIG_CFG80211_WEXT=y CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y CONFIG_NET_9P=y @@ -223,6 +221,13 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_MULTI=m +# CONFIG_USB_G_MULTI_RNDIS is not set CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y @@ -254,9 +259,7 @@ CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y CONFIG_CW1200=m -# CONFIG_CW1200_NON_POWER_OF_TWO_BLOCKSIZES is not set CONFIG_CW1200_USE_GPIO_IRQ=y -CONFIG_CW1200_WOW=y CONFIG_CW1200_DEBUGFS=y CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y @@ -324,4 +327,3 @@ CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRC7=y CONFIG_LIBCRC32C=m -CONFIG_AVERAGE=y -- cgit v1.2.3 From cb6248417b6a4a5437ed16d9318cbb70b674fb87 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 14 Oct 2011 15:56:48 +0200 Subject: config: enable dynamic debug Change-Id: I89dc5e064002cf47d0c1b65adec2e58655ace572 Signed-off-by: Robert Marklund Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34117 Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 8f0efa642f1..3bec8e68b2f 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -319,6 +319,7 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_FUNCTION_TRACER=y +CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_USER=y CONFIG_KEYS=y CONFIG_CRYPTO_MD5=m -- cgit v1.2.3 From a84f2e301626a162c2b40468862ad114a63c4d3f Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 14 Oct 2011 18:26:08 +0200 Subject: config: Enable usb HID and FS Change-Id: I6767174545255e89131d159421606ecc1fc082bb Signed-off-by: Robert Marklund Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34134 Reviewed-by: Philippe LANGLAIS --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3bec8e68b2f..7fbcc5c9648 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -223,11 +223,13 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 CONFIG_USB_ZERO=m CONFIG_USB_ETH=m +CONFIG_USB_FILE_STORAGE=m CONFIG_USB_MASS_STORAGE=m CONFIG_USB_G_SERIAL=m CONFIG_USB_CDC_COMPOSITE=m CONFIG_USB_G_MULTI=m # CONFIG_USB_G_MULTI_RNDIS is not set +CONFIG_USB_G_HID=m CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y -- cgit v1.2.3 From e50aca827cde3cd4732326cb6ca99a84e276958b Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 18 Oct 2011 20:49:50 +0100 Subject: DocBook: add input documentations generation Signed-off-by: Philippe Langlais --- Documentation/DocBook/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 3f118e4defb..91f06ffcfdc 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -15,7 +15,10 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml drm.xml media_api.xml \ - stmpe.xml + stmpe.xml \ + touchp.xml tc_keypad.xml \ + synaptics_rmi4_touchp.xml db5500_keypad.xml \ + ste_ff_vibra.xml include $(srctree)/Documentation/DocBook/media/Makefile -- cgit v1.2.3 From f6c6eb796b4b5452e4c8a1478f05e139a1c23575 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 09:40:44 +0200 Subject: stmpe: Fix warning Signed-off-by: Philippe Langlais --- include/linux/mfd/stmpe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index 8516fd1eaab..f8d5b4d5843 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -117,7 +117,7 @@ struct matrix_keymap_data; * @no_autorepeat: disable key autorepeat */ struct stmpe_keypad_platform_data { - struct matrix_keymap_data *keymap_data; + const struct matrix_keymap_data *keymap_data; unsigned int debounce_ms; unsigned int scan_count; bool no_autorepeat; -- cgit v1.2.3 From 906fe6c0b497472cea298194ce2ee77eb9bf53a7 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 11:24:34 +0200 Subject: mach-ux500: add ab8500 bm support Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-mop500-bm.c | 411 ++++++++++++++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500-bm.h | 24 ++ 2 files changed, 435 insertions(+) create mode 100644 arch/arm/mach-ux500/board-mop500-bm.c create mode 100644 arch/arm/mach-ux500/board-mop500-bm.h diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c new file mode 100644 index 00000000000..031d8721f4a --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -0,0 +1,411 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson for ST-Ericsson. + * Author: Johan Gardsmark for ST-Ericsson. + * + */ + +#include +#include +#include "board-mop500-bm.h" + +#ifdef AB8500_BATTERY_THERM_ON_BATCTRL +/* + * These are the defined batteries that uses a NTC and ID resistor placed + * inside of the battery pack. + * Note that the res_to_temp table must be strictly sorted by falling resistance + * values to work. + */ +static struct res_to_temp temp_tbl_A[] = { + {-5, 53407}, + { 0, 48594}, + { 5, 43804}, + {10, 39188}, + {15, 34870}, + {20, 30933}, + {25, 27422}, + {30, 24347}, + {35, 21694}, + {40, 19431}, + {45, 17517}, + {50, 15908}, + {55, 14561}, + {60, 13437}, + {65, 12500}, +}; +static struct res_to_temp temp_tbl_B[] = { + {-5, 165418}, + { 0, 159024}, + { 5, 151921}, + {10, 144300}, + {15, 136424}, + {20, 128565}, + {25, 120978}, + {30, 113875}, + {35, 107397}, + {40, 101629}, + {45, 96592}, + {50, 92253}, + {55, 88569}, + {60, 85461}, + {65, 82869}, +}; +static struct v_to_cap cap_tbl_A[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; +static struct v_to_cap cap_tbl_B[] = { + {4161, 100}, + {4124, 98}, + {4044, 90}, + {4003, 85}, + {3966, 80}, + {3933, 75}, + {3888, 67}, + {3849, 60}, + {3813, 55}, + {3787, 47}, + {3772, 30}, + {3751, 25}, + {3718, 20}, + {3681, 16}, + {3660, 14}, + {3589, 10}, + {3546, 7}, + {3495, 4}, + {3404, 2}, + {3250, 0}, +}; +#endif +static struct v_to_cap cap_tbl[] = { + {4186, 100}, + {4163, 99}, + {4114, 95}, + {4068, 90}, + {3990, 80}, + {3926, 70}, + {3898, 65}, + {3866, 60}, + {3833, 55}, + {3812, 50}, + {3787, 40}, + {3768, 30}, + {3747, 25}, + {3730, 20}, + {3705, 15}, + {3699, 14}, + {3684, 12}, + {3672, 9}, + {3657, 7}, + {3638, 6}, + {3556, 4}, + {3424, 2}, + {3317, 1}, + {3094, 0}, +}; + +/* + * Note that the res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct res_to_temp temp_tbl[] = { + {-5, 214834}, + { 0, 162943}, + { 5, 124820}, + {10, 96520}, + {15, 75306}, + {20, 59254}, + {25, 47000}, + {30, 37566}, + {35, 30245}, + {40, 24520}, + {45, 20010}, + {50, 16432}, + {55, 13576}, + {60, 11280}, + {65, 9425}, +}; + +static const struct battery_type bat_type[] = { + [BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, + .charge_full_design = 612, + .nominal_voltage = 3700, + .termination_vol = 4050, + .termination_curr = 200, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4000, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + +#ifdef AB8500_BATTERY_THERM_ON_BATCTRL + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 53407, + .resis_low = 12500, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A), + .r_to_t_tbl = temp_tbl_A, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A), + .v_to_cap_tbl = cap_tbl_A, + + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 165418, + .resis_low = 82869, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B), + .r_to_t_tbl = temp_tbl_B, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B), + .v_to_cap_tbl = cap_tbl_B, + }, +#else +/* + * These are the batteries that doesn't have an internal NTC resistor to measure + * its temperature. The temperature in this case is measure with a NTC placed + * near the battery but on the PCB. + */ + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 76000, + .resis_low = 53000, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 30000, + .resis_low = 10000, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 95000, + .resis_low = 76001, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, +#endif +}; + +static char *ab8500_charger_supplied_to[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static char *ab8500_btemp_supplied_to[] = { + "ab8500_chargalg", + "ab8500_fg", +}; + +static char *ab8500_fg_supplied_to[] = { + "ab8500_chargalg", +}; + +static char *ab8500_chargalg_supplied_to[] = { + "ab8500_fg", +}; + +struct ab8500_charger_platform_data ab8500_charger_plat_data = { + .supplied_to = ab8500_charger_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to), +}; + +struct ab8500_btemp_platform_data ab8500_btemp_plat_data = { + .supplied_to = ab8500_btemp_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_btemp_supplied_to), +}; + +struct ab8500_fg_platform_data ab8500_fg_plat_data = { + .supplied_to = ab8500_fg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_fg_supplied_to), +}; + +struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data = { + .supplied_to = ab8500_chargalg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to), +}; + +static const struct ab8500_bm_capacity_levels cap_levels = { + .critical = 2, + .low = 10, + .normal = 70, + .high = 95, + .full = 100, +}; + +static const struct ab8500_fg_parameters fg = { + .recovery_sleep_timer = 10, + .recovery_total_time = 100, + .init_timer = 1, + .init_discard_time = 5, + .init_total_time = 40, + .high_curr_time = 60, + .accu_charging = 30, + .accu_high_curr = 30, + .high_curr_threshold = 50, + .lowbat_threshold = 3100, +}; + +static const struct ab8500_maxim_parameters maxi_params = { + .ena_maxi = true, + .chg_curr = 910, + .wait_cycles = 10, + .charger_curr_step = 100, +}; + +static const struct ab8500_bm_charger_parameters chg = { + .usb_volt_max = 5500, + .usb_curr_max = 1500, + .ac_volt_max = 7500, + .ac_curr_max = 1500, +}; + +struct ab8500_bm_data ab8500_bm_data = { + .temp_under = 3, + .temp_low = 8, + .temp_high = 55, + .temp_over = 60, + .main_safety_tmr_h = 4, + .usb_safety_tmr_h = 4, + .bkup_bat_v = BUP_VCH_SEL_2P6V, + .bkup_bat_i = BUP_ICH_SEL_150UA, +#ifdef AB8500_BATTERY_THERM_ON_BATCTRL + .adc_therm = ADC_THERM_BATCTRL, +#else + .adc_therm = ADC_THERM_BATTEMP, +#endif + .chg_unknown_bat = false, + .enable_overshoot = false, + .fg_res = 10, + .cap_levels = &cap_levels, + .bat_type = bat_type, + .n_btypes = ARRAY_SIZE(bat_type), + .batt_id = 0, + .interval_charging = 5, + .interval_not_charging = 120, + .temp_hysteresis = 3, + .maxi = &maxi_params, + .chg_params = &chg, + .fg_params = &fg, +}; diff --git a/arch/arm/mach-ux500/board-mop500-bm.h b/arch/arm/mach-ux500/board-mop500-bm.h new file mode 100644 index 00000000000..74d44529fe6 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson for ST-Ericsson. + * Author: Johan Gardsmark for ST-Ericsson. + * + */ + +#ifndef __BOARD_MOP500_BM_H +#define __BOARD_MOP500_BM_H + +#include + +extern struct ab8500_charger_platform_data ab8500_charger_plat_data; +extern struct ab8500_btemp_platform_data ab8500_btemp_plat_data; +extern struct ab8500_fg_platform_data ab8500_fg_plat_data; +extern struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data; +extern struct ab8500_bm_data ab8500_bm_data; + +#endif -- cgit v1.2.3 From 464d668965c1f2b7d133c76680b3e246ba3d45da Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 11:25:00 +0200 Subject: ux500: Fix CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL configuration Remove the temporary AB8500_BATTERY_THERM_ON_BATCTRL flag and use CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL instead ST-Ericsson Linux next: - ST-Ericsson Change-ID: ER330310 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib4328deaa4fafe887f9082fc8a1e8e0c618e0d61 Signed-off-by: Mikael HEDEN Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19014 Reviewed-by: Johan PALSSON Reviewed-by: Johan GARDSMARK Reviewed-by: QATOOLS Reviewed-by: Jonas ABERG Conflicts: arch/arm/mach-ux500/Makefile --- arch/arm/mach-ux500/board-mop500-bm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 031d8721f4a..945964f3300 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -14,7 +14,7 @@ #include #include "board-mop500-bm.h" -#ifdef AB8500_BATTERY_THERM_ON_BATCTRL +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL /* * These are the defined batteries that uses a NTC and ID resistor placed * inside of the battery pack. @@ -176,7 +176,7 @@ static const struct battery_type bat_type[] = { .v_to_cap_tbl = cap_tbl, }, -#ifdef AB8500_BATTERY_THERM_ON_BATCTRL +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL { .name = POWER_SUPPLY_TECHNOLOGY_LIPO, .resis_high = 53407, @@ -390,7 +390,7 @@ struct ab8500_bm_data ab8500_bm_data = { .usb_safety_tmr_h = 4, .bkup_bat_v = BUP_VCH_SEL_2P6V, .bkup_bat_i = BUP_ICH_SEL_150UA, -#ifdef AB8500_BATTERY_THERM_ON_BATCTRL +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL .adc_therm = ADC_THERM_BATCTRL, #else .adc_therm = ADC_THERM_BATTEMP, -- cgit v1.2.3 From 73f4b28af12990a581b78faf1c4108916ea7351c Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Oct 2011 11:20:48 +0200 Subject: mach-ux500: power: ab8500_bm: Removal of maintenance charging This patch makes it possible to remove the maintenance A and B charging states and replaces them with a state that restarts the charging when the battery voltage level dropped below a certain level. The maintenance charging can now be turned of by setting a flag in the board configuration. ST-Ericsson Linux Next: - ST-Ericsson ID: CR333019 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie5e8ab20a3b57a1028d544371b10ffbb1fd77660 Signed-off-by: Kalle Komierowski Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19916 Reviewed-by: Johan GARDSMARK Reviewed-by: Johan PALSSON Reviewed-by: Jonas ABERG Tested-by: Karl KOMIEROWSKI Conflicts: drivers/power/ab8500_chargalg.c drivers/power/ab8500_fg.c include/linux/mfd/ab8500/bm.h --- arch/arm/mach-ux500/board-mop500-bm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 945964f3300..66ced8e088e 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -160,6 +160,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3700, .termination_vol = 4050, .termination_curr = 200, + .recharge_vol = 3990, .normal_cur_lvl = 400, .normal_vol_lvl = 4100, .maint_a_cur_lvl = 400, @@ -186,6 +187,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3600, .termination_vol = 4150, .termination_curr = 80, + .recharge_vol = 4130, .normal_cur_lvl = 700, .normal_vol_lvl = 4200, .maint_a_cur_lvl = 600, @@ -211,6 +213,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3600, .termination_vol = 4150, .termination_curr = 80, + .recharge_vol = 4130, .normal_cur_lvl = 700, .normal_vol_lvl = 4200, .maint_a_cur_lvl = 600, @@ -241,6 +244,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3700, .termination_vol = 4150, .termination_curr = 100, + .recharge_vol = 4130, .normal_cur_lvl = 700, .normal_vol_lvl = 4200, .maint_a_cur_lvl = 600, @@ -265,6 +269,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3700, .termination_vol = 4150, .termination_curr = 100, + .recharge_vol = 4130, .normal_cur_lvl = 700, .normal_vol_lvl = 4200, .maint_a_cur_lvl = 600, @@ -289,6 +294,7 @@ static const struct battery_type bat_type[] = { .nominal_voltage = 3700, .termination_vol = 4150, .termination_curr = 100, + .recharge_vol = 4130, .normal_cur_lvl = 700, .normal_vol_lvl = 4200, .maint_a_cur_lvl = 600, @@ -390,6 +396,7 @@ struct ab8500_bm_data ab8500_bm_data = { .usb_safety_tmr_h = 4, .bkup_bat_v = BUP_VCH_SEL_2P6V, .bkup_bat_i = BUP_ICH_SEL_150UA, + .no_maintenance = false, #ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL .adc_therm = ADC_THERM_BATCTRL, #else -- cgit v1.2.3 From ef64658d6e151d6163c839a255ee8486641f25ee Mon Sep 17 00:00:00 2001 From: Johan Palsson Date: Thu, 7 Jul 2011 11:45:03 +0200 Subject: power: ab8500_bm: Measure battery temperature when not charging Battery temperature is now measured even when no charger is connected. ST-Ericsson ID: 342846 ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ia861437635bcdcdc32b259aff05d889b449ee682 Signed-off-by: Johan Palsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26608 Reviewed-by: QATEST Reviewed-by: Mattias WALLIN --- arch/arm/mach-ux500/board-mop500-bm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 66ced8e088e..86be12cad3b 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -393,6 +393,8 @@ struct ab8500_bm_data ab8500_bm_data = { .temp_high = 55, .temp_over = 60, .main_safety_tmr_h = 4, + .temp_interval_chg = 20, + .temp_interval_nochg = 120, .usb_safety_tmr_h = 4, .bkup_bat_v = BUP_VCH_SEL_2P6V, .bkup_bat_i = BUP_ICH_SEL_150UA, -- cgit v1.2.3 From d13f54bb53fddff1f32cdb98a15e9fc5d1abaa81 Mon Sep 17 00:00:00 2001 From: Andrew Lynn Date: Thu, 18 Aug 2011 15:08:21 +0100 Subject: ab8500-bm: Ground lift compensation for Tbat Measure Ibat and remove the resulting voltage between Vbat- and Gnd from Vntc readings. ST-Ericsson ID: 350661 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I232b9fc7da3ea69e2062feda98776ded33d6253b Signed-off-by: Andrew Lynn Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27869 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Johan PALSSON Reviewed-by: Jonas ABERG Reviewed-by: Karl KOMIEROWSKI --- arch/arm/mach-ux500/board-mop500-bm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 86be12cad3b..1d8730408fa 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -414,6 +414,7 @@ struct ab8500_bm_data ab8500_bm_data = { .interval_charging = 5, .interval_not_charging = 120, .temp_hysteresis = 3, + .gnd_lift_resistance = 34, .maxi = &maxi_params, .chg_params = &chg, .fg_params = &fg, -- cgit v1.2.3 From 4814b304ef58dfdc0f51b98857fce31e4e8cf36b Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 10:34:46 +0200 Subject: mach-ux500: power: ab8500_charger: Lower VBUS input current when below threshold Due to a bug in AB8500 the input current to the VBUS charger needs to be lowered when the battery voltage is below 3,7 V. Otherwise there is a risk that a higher than allowed current is drawn from the USB host. Signed-off-by: Kalle Komierowski --- arch/arm/mach-ux500/board-mop500-bm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 1d8730408fa..78f20626cab 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -326,6 +326,7 @@ static char *ab8500_btemp_supplied_to[] = { static char *ab8500_fg_supplied_to[] = { "ab8500_chargalg", + "ab8500_usb", }; static char *ab8500_chargalg_supplied_to[] = { -- cgit v1.2.3 From 0cc9ca09d7783a1025641542a0416ded9b293dc6 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 16:04:48 +0200 Subject: mfd: fix dependency problem with PRCMU Signed-off-by: Philippe Langlais --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d3879b9c469..825673af5f3 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -710,7 +710,7 @@ config AB8500_CORE config AB8500_I2C_CORE bool "AB8500 register access via PRCMU I2C" - depends on AB8500_CORE && MFD_DB8500_PRCMU + depends on AB8500_CORE default y help This enables register access to the AB8500 chip via PRCMU I2C. -- cgit v1.2.3 From e8618f949f674fa1b83409f53aabdec35aa7873e Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 10:21:27 +0200 Subject: Documentation: Update DocBook makefile to generate all ux500 specific driver doc Signed-off-by: Philippe Langlais --- Documentation/DocBook/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 91f06ffcfdc..80c42603ff2 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -15,10 +15,11 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml drm.xml media_api.xml \ - stmpe.xml \ - touchp.xml tc_keypad.xml \ + i2s.xml msp.xml shrm.xml stmpe.xml touchp.xml \ + tc_keypad.xml prcmu-fw-api.xml cg2900_fm_radio.xml \ synaptics_rmi4_touchp.xml db5500_keypad.xml \ - ste_ff_vibra.xml + u5500_LogicalMailbox.xml cg2900.xml \ + lsm303dlh.xml ste_ff_vibra.xml ux500_usb.xml include $(srctree)/Documentation/DocBook/media/Makefile -- cgit v1.2.3 From 33069b8c31da5f85aabfdbf1d52537bc2f437fed Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 15:56:07 +0200 Subject: mfd: abx500: input: Add accessory detection driver Add driver for the accessory detection block of abx500 PMIC. Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Philippe Langlais --- include/linux/mfd/abx500/ab8500.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index f746cf3ca34..e7309e5e231 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -260,6 +260,7 @@ struct ab8500 { struct regulator_reg_init; struct regulator_init_data; +struct ab8500_accdet_platform_data; struct ab8500_denc_platform_data; struct ab8500_audio_platform_data; struct ab8500_gpio_platform_data; @@ -276,6 +277,7 @@ struct ab8500_gpio_platform_data; * @regulator_reg_init: regulator init registers * @num_regulator: number of regulators * @regulator: machine-specific constraints for regulators + * @accdet: machine-specific Accessory detection data * @battery: machine-specific battery management data * @charger: machine-specific charger data * @btemp: machine-specific battery temp data @@ -291,6 +293,7 @@ struct ab8500_platform_data { struct ab8500_regulator_reg_init *regulator_reg_init; int num_regulator; struct regulator_init_data *regulator; + struct abx500_accdet_platform_data *accdet; struct ab8500_bm_data *battery; struct ab8500_denc_platform_data *denc; struct ab8500_audio_platform_data *audio; -- cgit v1.2.3 From 09c7643277ffe1b5e13799d27ed6c9e89cbb2e01 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 15:13:35 +0200 Subject: config: Update u8500 defconfig Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 7fbcc5c9648..609d716635c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -246,7 +246,6 @@ CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y -CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y @@ -328,5 +327,6 @@ CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y CONFIG_LIBCRC32C=m -- cgit v1.2.3 From ef2fdd1ddd7646d8bdc84df4e111919409ee6b92 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Mon, 26 Sep 2011 21:19:13 +0530 Subject: input:misc: Remove TVout support in accessory driver The TVout hardware block is not used, so remove the related code. ST-Ericsson ID: 355539 ST-Ericsson Linux next: 344984 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I0f0f39b13f5b48de6096d076b9dd5253a3c14346 Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32003 Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/ab5500-core.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c index 493b8cb5871..e8ae5d945e4 100644 --- a/drivers/mfd/ab5500-core.c +++ b/drivers/mfd/ab5500-core.c @@ -1007,7 +1007,7 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { [AB5500_DEVID_ACCDET] = { .name = "ab5500-acc-det", .id = AB5500_DEVID_ACCDET, - .num_resources = 10, + .num_resources = 8, .resources = (struct resource[]) { { .name = "acc_detedt22db_rising", @@ -1057,18 +1057,6 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { .start = AB5500_IRQ(3, 0), .end = AB5500_IRQ(3, 0), }, - { - .name = "plugTVdet", - .flags = IORESOURCE_IRQ, - .start = AB5500_IRQ(13, 7), - .end = AB5500_IRQ(13, 7), - }, - { - .name = "plugTVdet_removal", - .flags = IORESOURCE_IRQ, - .start = AB5500_IRQ(23, 2), - .end = AB5500_IRQ(23, 2), - }, }, }, }; -- cgit v1.2.3 From 164015931a5b1fa119f353ff76be134b713353ac Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Fri, 30 Sep 2011 09:43:41 +0200 Subject: ARM: u8500: configs: Enable regulator suspend force ST-Ericsson Linux next: - ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I26ba2f655d4fb65708913cdeda632e2ca35fea0a Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32671 Reviewed-by: Bengt JONSSON --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 609d716635c..aa28732a74c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -184,6 +184,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_REGULATOR_DB8500_PRCMU=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y -- cgit v1.2.3 From 8bc040bb8052b5155c8f3a57a6f7c449f3b87ba4 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 30 Sep 2011 10:26:39 +0530 Subject: u5500: enable cpuidle debug ST-Ericsson ID: 361450 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I809d2d8e76532f6930f27764b76748110c7a492c Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32582 --- arch/arm/configs/u8500_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index aa28732a74c..214c22cf7e4 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -58,7 +58,6 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_IDLE=y -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y -- cgit v1.2.3 From 8c35f32920f28d4cb68f7e41d4323f57baba5eae Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 30 Sep 2011 10:26:39 +0530 Subject: u5500: cpuidle: enable ApIdle ST-Ericsson ID: 361450 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I75dc4afafc493412a128071b10da3a8b773b3bf5 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32727 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 214c22cf7e4..aa28732a74c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -58,6 +58,7 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_IDLE=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y -- cgit v1.2.3 From 9bac6a0efe0993a13822a3cf84371d6ff92e1abb Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Fri, 23 Sep 2011 14:11:24 +0200 Subject: ux500: Start crash dump through SW reset When using kexec/kdump without an crash kernel image loaded: * clean the caches and write the crash_notes * perform a restart ST-Ericsson ID: 340331 Change-Id: I1ae34ed2b5e43da4849650a8a7d2f1e453dcbe93 Signed-off-by: Per Fransson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32678 Reviewed-by: Jonas ABERG Reviewed-by: Srinidhi KASAGAR --- arch/arm/Kconfig | 7 +++++++ arch/arm/kernel/machine_kexec.c | 10 ++++++++++ include/linux/kexec.h | 1 + kernel/kexec.c | 10 +++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 46cf36a5114..275ac0dd1e8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2079,6 +2079,13 @@ config KEXEC initially work for you. It may help to enable device hotplugging support. +config CRASH_SWRESET + bool "Perform a software reset at a panic (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on KEXEC + help + If no crash kernel has been loaded, perform a SW reset as plan B. + config ATAGS_PROC bool "Export atags in procfs" depends on KEXEC diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 29b7f3c27b7..7455ca0fc51 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -139,3 +139,13 @@ void machine_kexec(struct kimage *image) soft_restart(reboot_code_buffer_phys); } + +void machine_crash_swreset(void) +{ + printk(KERN_INFO "Software reset on panic!\n"); + + flush_cache_all(); + outer_flush_all(); + outer_disable(); + arm_pm_restart(0, NULL); +} diff --git a/include/linux/kexec.h b/include/linux/kexec.h index ddeb2a9debe..9943c5dd618 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -120,6 +120,7 @@ struct kimage { /* kexec interface functions */ extern void machine_kexec(struct kimage *image); +extern void machine_crash_swreset(void); extern int machine_kexec_prepare(struct kimage *image); extern void machine_kexec_cleanup(struct kimage *image); extern asmlinkage long sys_kexec_load(unsigned long entry, diff --git a/kernel/kexec.c b/kernel/kexec.c index 6146beeeecc..799064323aa 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1082,6 +1082,7 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry, void crash_kexec(struct pt_regs *regs) { + struct pt_regs fixed_regs; /* Take the kexec_mutex here to prevent sys_kexec_load * running on one cpu from replacing the crash kernel * we are using after a panic on a different cpu. @@ -1092,13 +1093,20 @@ void crash_kexec(struct pt_regs *regs) */ if (mutex_trylock(&kexec_mutex)) { if (kexec_crash_image) { - struct pt_regs fixed_regs; crash_setup_regs(&fixed_regs, regs); crash_save_vmcoreinfo(); machine_crash_shutdown(&fixed_regs); machine_kexec(kexec_crash_image); } +#ifdef CONFIG_CRASH_SWRESET + else { + crash_setup_regs(&fixed_regs, regs); + crash_save_vmcoreinfo(); + machine_crash_shutdown(&fixed_regs); + machine_crash_swreset(); + } +#endif mutex_unlock(&kexec_mutex); } } -- cgit v1.2.3 From 2ff7e0ff79b553e7077e456cb9c9e7ec48b887a6 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Wed, 20 Jul 2011 20:58:00 +0530 Subject: u5500: leds: add ab5500v2 HVLED blink feature This patch adds support for AB5500 v2.0 HVLED hardware blink feature in existing driver. ST-Ericsson Linux next: ER 336280 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: ER 364964 Change-Id:I73e1caeac14774b7d3e03d1e7c5e4bd16fc7d06a Signed-off-by: Shreshtha Kumar Sahu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27547 Reviewed-by: Srinidhi KASAGAR Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32746 Reviewed-by: Naga RADHESH Y Tested-by: Naga RADHESH Y --- drivers/leds/leds-ab5500.c | 505 ++++++++++++++++++++++++++++++++++++++------ include/linux/leds-ab5500.h | 14 +- 2 files changed, 451 insertions(+), 68 deletions(-) diff --git a/drivers/leds/leds-ab5500.c b/drivers/leds/leds-ab5500.c index 94db3a6feea..294551b1962 100644 --- a/drivers/leds/leds-ab5500.c +++ b/drivers/leds/leds-ab5500.c @@ -1,13 +1,47 @@ /* + * leds-ab5500.c - driver for High Voltage (HV) LED in ST-Ericsson AB5500 chip + * * Copyright (C) 2011 ST-Ericsson SA. * * License Terms: GNU General Public License v2 * - * Driver for LED in ST-Ericsson AB5500 v1.0 Analog baseband Controller - * * Author: Shreshtha Kumar SAHU */ +/* + * Driver for HVLED in ST-Ericsson AB5500 analog baseband controller + * + * This chip can drive upto 3 leds, of upto 40mA of led sink current. + * These leds can be programmed to blink between two intensities with + * fading delay of half, one or two seconds. + * + * Leds can be controlled via sysfs entries in + * "/sys/class/leds/< red | green | blue >" + * + * For each led, + * + * Modes of operation: + * - manual: echo 0 > fade_auto (default, no auto blinking) + * - auto: echo 1 > fade_auto + * + * Soft scaling delay between two intensities: + * - 1/2 sec: echo 1 > fade_delay + * - 1 sec: echo 2 > fade_delay + * - 2 sec: echo 3 > fade_delay + * + * Possible sequence of operation: + * - continuous glow: set brightness (brt) + * - blink between LED_OFF and LED_FULL: + * set fade delay -> set fade auto + * - blink between previous two brightness (only for LED-1): + * set brt1 -> set brt2 -> set fade auto + * + * Delay can be set in any step, its affect will be seen on switching mode. + * + * Note: Blink/Fade feature is supported in AB5500 v2 onwards + * + */ + #include #include #include @@ -18,45 +52,67 @@ #include #include +#include + #define AB5500LED_NAME "ab5500-leds" +#define AB5500_LED_MAX 0x03 /* Register offsets */ #define AB5500_LED_REG_ENABLE 0x03 -#define AB5500_LED_FADE_CTL 0x0D +#define AB5500_LED_FADE_CTRL 0x0D -/* LED-0 */ +/* LED-0 Register Addr. Offsets */ #define AB5500_LED0_PWM_DUTY 0x01 #define AB5500_LED0_PWMFREQ 0x02 #define AB5500_LED0_SINKCTL 0x0A +#define AB5500_LED0_FADE_HI 0x11 +#define AB5500_LED0_FADE_LO 0x17 -/* LED-1 */ +/* LED-1 Register Addr. Offsets */ #define AB5500_LED1_PWM_DUTY 0x05 #define AB5500_LED1_PWMFREQ 0x06 #define AB5500_LED1_SINKCTL 0x0B +#define AB5500_LED1_FADE_HI 0x13 +#define AB5500_LED1_FADE_LO 0x19 -/* LED-2 */ +/* LED-2 Register Addr. Offsets */ #define AB5500_LED2_PWM_DUTY 0x08 #define AB5500_LED2_PWMFREQ 0x09 #define AB5500_LED2_SINKCTL 0x0C +#define AB5500_LED2_FADE_HI 0x15 +#define AB5500_LED2_FADE_LO 0x1B + +/* led-0/1/2 enable bit */ +#define AB5500_LED_ENABLE_MASK 0x04 -/* pwm duty cycle */ -#define AB5500_LED_PWMDUTY_OFF 0x0 -#define AB5500_LED_PWMDUTY_MAX 0x3FF -#define AB5500_LED_PWMDUTY_STEP (AB5500_LED_PWMDUTY_MAX/LED_FULL) +/* led intensity */ +#define AB5500_LED_INTENSITY_OFF 0x0 +#define AB5500_LED_INTENSITY_MAX 0x3FF +#define AB5500_LED_INTENSITY_STEP (AB5500_LED_INTENSITY_MAX/LED_FULL) /* pwm frequency */ -#define AB5500_LED_PWMFREQ_MAX 0x0F /* 373.39 @sysclk=26MHz */ +#define AB5500_LED_PWMFREQ_MAX 0x0F /* 373.39 @sysclk=26MHz */ #define AB5500_LED_PWMFREQ_SHIFT 4 /* LED sink current control */ -#define AB5500_LED_SINKCURR_MAX 0x0F /* 40mA */ +#define AB5500_LED_SINKCURR_MAX 0x0F /* 40mA MAX */ #define AB5500_LED_SINKCURR_SHIFT 4 +/* fade Control shift and masks */ +#define AB5500_FADE_DELAY_SHIFT 0x00 +#define AB5500_FADE_MODE_MASK 0x80 +#define AB5500_FADE_DELAY_MASK 0x03 +#define AB5500_FADE_START_MASK 0x04 +#define AB5500_FADE_ON_MASK 0x70 +#define AB5500_LED_FADE_ENABLE(ledid) (0x40 >> (ledid)) + struct ab5500_led { u8 id; u8 max_current; u16 brt_val; - enum ab5500_led_status status; + u16 fade_hi; + u16 fade_lo; + bool led_on; struct led_classdev led_cdev; struct work_struct led_work; }; @@ -66,26 +122,41 @@ struct ab5500_hvleds { struct device *dev; struct ab5500_hvleds_platform_data *pdata; struct ab5500_led leds[AB5500_HVLEDS_MAX]; + bool hw_fade; + bool fade_auto; + enum ab5500_fade_delay fade_delay; }; -static u8 ab5500_led_pwmduty_reg[] = { +static u8 ab5500_led_pwmduty_reg[AB5500_LED_MAX] = { AB5500_LED0_PWM_DUTY, AB5500_LED1_PWM_DUTY, AB5500_LED2_PWM_DUTY, }; -static u8 ab5500_led_pwmfreq_reg[] = { +static u8 ab5500_led_pwmfreq_reg[AB5500_LED_MAX] = { AB5500_LED0_PWMFREQ, AB5500_LED1_PWMFREQ, AB5500_LED2_PWMFREQ, }; -static u8 ab5500_led_sinkctl_reg[] = { +static u8 ab5500_led_sinkctl_reg[AB5500_LED_MAX] = { AB5500_LED0_SINKCTL, AB5500_LED1_SINKCTL, AB5500_LED2_SINKCTL }; +static u8 ab5500_led_fade_hi_reg[AB5500_LED_MAX] = { + AB5500_LED0_FADE_HI, + AB5500_LED1_FADE_HI, + AB5500_LED2_FADE_HI, +}; + +static u8 ab5500_led_fade_lo_reg[AB5500_LED_MAX] = { + AB5500_LED0_FADE_LO, + AB5500_LED1_FADE_LO, + AB5500_LED2_FADE_LO, +}; + #define to_led(_x) container_of(_x, struct ab5500_led, _x) static inline struct ab5500_hvleds *led_to_hvleds(struct ab5500_led *led) @@ -93,19 +164,74 @@ static inline struct ab5500_hvleds *led_to_hvleds(struct ab5500_led *led) return container_of(led, struct ab5500_hvleds, leds[led->id]); } +static int ab5500_led_enable(struct ab5500_hvleds *hvleds, + unsigned int led_id) +{ + int ret; + + ret = abx500_mask_and_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmduty_reg[led_id], + AB5500_LED_ENABLE_MASK, + AB5500_LED_ENABLE_MASK); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + ab5500_led_pwmduty_reg[led_id], ret); + + return ret; + +} + +static int ab5500_led_start_manual(struct ab5500_hvleds *hvleds) +{ + int ret; + + mutex_lock(&hvleds->lock); + + ret = abx500_mask_and_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + AB5500_LED_FADE_CTRL, AB5500_FADE_START_MASK, + AB5500_FADE_START_MASK); + if (ret < 0) + dev_err(hvleds->dev, "update reg 0x%x failed - %d\n", + AB5500_LED_FADE_CTRL, ret); + + mutex_unlock(&hvleds->lock); + + return ret; +} + +static int ab5500_led_disable(struct ab5500_hvleds *hvleds, + unsigned int led_id) +{ + int ret; + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmduty_reg[led_id] - 1, 0); + ret |= abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + ab5500_led_pwmduty_reg[led_id], 0); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + ab5500_led_pwmduty_reg[led_id], ret); + + return ret; +} + static int ab5500_led_pwmduty_write(struct ab5500_hvleds *hvleds, unsigned int led_id, u16 val) { int ret; - int val_lsb = val & 0xFF; - int val_msb = (val & 0x300) >> 8; + u8 val_lsb = val & 0xFF; + u8 val_msb = (val & 0x300) >> 8; mutex_lock(&hvleds->lock); dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val = %d\n" - "reg[%d] w val = %d\n", - ab5500_led_pwmduty_reg[led_id] - 1, val_lsb, - ab5500_led_pwmduty_reg[led_id], val_msb); + "reg[%d] w val = %d\n", + ab5500_led_pwmduty_reg[led_id] - 1, val_lsb, + ab5500_led_pwmduty_reg[led_id], val_msb); ret = abx500_set_register_interruptible( hvleds->dev, AB5500_BANK_LED, @@ -116,6 +242,7 @@ static int ab5500_led_pwmduty_write(struct ab5500_hvleds *hvleds, if (ret < 0) dev_err(hvleds->dev, "reg[%d] w failed: %d\n", ab5500_led_pwmduty_reg[led_id], ret); + mutex_unlock(&hvleds->lock); return ret; @@ -139,6 +266,7 @@ static int ab5500_led_pwmfreq_write(struct ab5500_hvleds *hvleds, if (ret < 0) dev_err(hvleds->dev, "reg[%d] w failed: %d\n", ab5500_led_pwmfreq_reg[led_id], ret); + mutex_unlock(&hvleds->lock); return ret; @@ -149,19 +277,58 @@ static int ab5500_led_sinkctl_write(struct ab5500_hvleds *hvleds, { int ret; - val = (val & 0x0F) << AB5500_LED_SINKCURR_SHIFT; + if (val > AB5500_LED_SINKCURR_MAX) + val = AB5500_LED_SINKCURR_MAX; - mutex_lock(&hvleds->lock); + val = (val << AB5500_LED_SINKCURR_SHIFT); dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val=%d\n", ab5500_led_sinkctl_reg[led_id], val); + mutex_lock(&hvleds->lock); + ret = abx500_set_register_interruptible( hvleds->dev, AB5500_BANK_LED, ab5500_led_sinkctl_reg[led_id], val); if (ret < 0) dev_err(hvleds->dev, "reg[%d] w failed: %d\n", ab5500_led_sinkctl_reg[led_id], ret); + + mutex_unlock(&hvleds->lock); + + return ret; +} + +static int ab5500_led_fade_write(struct ab5500_hvleds *hvleds, + unsigned int led_id, bool on, u16 val) +{ + int ret; + int val_lsb = val & 0xFF; + int val_msb = (val & 0x300) >> 8; + u8 *fade_reg; + + if (on) + fade_reg = ab5500_led_fade_hi_reg; + else + fade_reg = ab5500_led_fade_lo_reg; + + dev_dbg(hvleds->dev, "ab5500-leds: reg[%d] w val = %d\n" + "reg[%d] w val = %d\n", + fade_reg[led_id] - 1, val_lsb, + fade_reg[led_id], val_msb); + + mutex_lock(&hvleds->lock); + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + fade_reg[led_id] - 1, val_lsb); + ret |= abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + fade_reg[led_id], val_msb); + if (ret < 0) + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + fade_reg[led_id], ret); + mutex_unlock(&hvleds->lock); return ret; @@ -174,6 +341,7 @@ static int ab5500_led_sinkctl_read(struct ab5500_hvleds *hvleds, u8 val; mutex_lock(&hvleds->lock); + ret = abx500_get_register_interruptible( hvleds->dev, AB5500_BANK_LED, ab5500_led_sinkctl_reg[led_id], &val); @@ -183,7 +351,9 @@ static int ab5500_led_sinkctl_read(struct ab5500_hvleds *hvleds, mutex_unlock(&hvleds->lock); return ret; } + val = (val & 0xF0) >> AB5500_LED_SINKCURR_SHIFT; + mutex_unlock(&hvleds->lock); return val; @@ -196,7 +366,8 @@ static void ab5500_led_brightness_set(struct led_classdev *led_cdev, /* adjust LED_FULL to 10bit range */ brt_val &= LED_FULL; - led->brt_val = brt_val * AB5500_LED_PWMDUTY_STEP; + led->brt_val = brt_val * AB5500_LED_INTENSITY_STEP; + schedule_work(&led->led_work); } @@ -205,8 +376,13 @@ static void ab5500_led_work(struct work_struct *led_work) struct ab5500_led *led = to_led(led_work); struct ab5500_hvleds *hvleds = led_to_hvleds(led); - if (led->status == AB5500_LED_ON) + if (led->led_on == true) { ab5500_led_pwmduty_write(hvleds, led->id, led->brt_val); + if (hvleds->hw_fade && led->brt_val) { + ab5500_led_enable(hvleds, led->id); + ab5500_led_start_manual(hvleds); + } + } } static ssize_t ab5500_led_show_current(struct device *dev, @@ -248,9 +424,122 @@ static ssize_t ab5500_led_store_current(struct device *dev, return len; } +static ssize_t ab5500_led_store_fade_auto(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + int ret; + u8 fade_ctrl = 0; + unsigned long fade_auto; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ab5500_led *led = to_led(led_cdev); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + if (strict_strtoul(buf, 0, &fade_auto)) + return -EINVAL; + + if (fade_auto > 1) { + dev_err(hvleds->dev, "invalid mode\n"); + return -EINVAL; + } + + mutex_lock(&hvleds->lock); + + ret = abx500_get_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + AB5500_LED_FADE_CTRL, &fade_ctrl); + if (ret < 0) { + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + AB5500_LED_FADE_CTRL, ret); + goto unlock_and_return; + } + + /* manual mode */ + if (fade_auto == false) { + fade_ctrl &= ~(AB5500_LED_FADE_ENABLE(led->id)); + if (!(fade_ctrl & AB5500_FADE_ON_MASK)) + fade_ctrl = 0; + + ret = ab5500_led_disable(hvleds, led->id); + if (ret < 0) + goto unlock_and_return; + } else { + /* set led auto enable bit */ + fade_ctrl |= AB5500_FADE_MODE_MASK; + fade_ctrl |= AB5500_LED_FADE_ENABLE(led->id); + + /* set fade delay */ + fade_ctrl &= ~AB5500_FADE_DELAY_MASK; + fade_ctrl |= hvleds->fade_delay << AB5500_FADE_DELAY_SHIFT; + + /* set fade start manual */ + fade_ctrl |= AB5500_FADE_START_MASK; + + /* enble corresponding led */ + ret = ab5500_led_enable(hvleds, led->id); + if (ret < 0) + goto unlock_and_return; + + } + + ret = abx500_set_register_interruptible( + hvleds->dev, AB5500_BANK_LED, + AB5500_LED_FADE_CTRL, fade_ctrl); + if (ret < 0) { + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + AB5500_LED_FADE_CTRL, ret); + goto unlock_and_return; + } + + hvleds->fade_auto = fade_auto; + + ret = len; + +unlock_and_return: + mutex_unlock(&hvleds->lock); + + return ret; +} + +static ssize_t ab5500_led_show_fade_auto(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ab5500_led *led = to_led(led_cdev); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + return sprintf(buf, "%d\n", hvleds->fade_auto); +} + +static ssize_t ab5500_led_store_fade_delay(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + unsigned long fade_delay; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ab5500_led *led = to_led(led_cdev); + struct ab5500_hvleds *hvleds = led_to_hvleds(led); + + if (strict_strtoul(buf, 0, &fade_delay)) + return -EINVAL; + + if (fade_delay > AB5500_FADE_DELAY_TWOSEC) { + dev_err(hvleds->dev, "invalid mode\n"); + return -EINVAL; + } + + hvleds->fade_delay = fade_delay; + + return len; +} + /* led class device attributes */ static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, ab5500_led_show_current, ab5500_led_store_current); +static DEVICE_ATTR(fade_auto, S_IRUGO | S_IWUGO, + ab5500_led_show_fade_auto, ab5500_led_store_fade_auto); +static DEVICE_ATTR(fade_delay, S_IRUGO | S_IWUGO, + NULL, ab5500_led_store_fade_delay); static int ab5500_led_init_registers(struct ab5500_hvleds *hvleds) { @@ -258,30 +547,52 @@ static int ab5500_led_init_registers(struct ab5500_hvleds *hvleds) unsigned int led_id; /* fade - manual : dur mid : pwm duty mid */ - ret = abx500_set_register_interruptible( + if (!hvleds->hw_fade) { + ret = abx500_set_register_interruptible( hvleds->dev, AB5500_BANK_LED, AB5500_LED_REG_ENABLE, true); - if (ret < 0) { - dev_err(hvleds->dev, "reg[%d] w failed: %d\n", - AB5500_LED_REG_ENABLE, ret); - return ret; + if (ret < 0) { + dev_err(hvleds->dev, "reg[%d] w failed: %d\n", + AB5500_LED_REG_ENABLE, ret); + return ret; + } } for (led_id = 0; led_id < AB5500_HVLEDS_MAX; led_id++) { - /* Set pwm freq. and sink current to mid values */ - ret = ab5500_led_pwmfreq_write( - hvleds, led_id, AB5500_LED_PWMFREQ_MAX); - if (ret < 0) - return ret; + if (hvleds->leds[led_id].led_on == false) + continue; ret = ab5500_led_sinkctl_write( - hvleds, led_id, AB5500_LED_SINKCURR_MAX); + hvleds, led_id, + hvleds->leds[led_id].max_current); if (ret < 0) return ret; + if (hvleds->hw_fade) { + ret = ab5500_led_pwmfreq_write( + hvleds, led_id, + AB5500_LED_PWMFREQ_MAX / 2); + if (ret < 0) + return ret; + + /* fade high intensity */ + ret = ab5500_led_fade_write( + hvleds, led_id, true, + hvleds->leds[led_id].fade_hi); + if (ret < 0) + return ret; + + /* fade low intensity */ + ret = ab5500_led_fade_write( + hvleds, led_id, false, + hvleds->leds[led_id].fade_lo); + if (ret < 0) + return ret; + } + /* init led off */ - ret = ab5500_led_pwmduty_write( - hvleds, led_id, AB5500_LED_PWMDUTY_OFF); + ret |= ab5500_led_pwmduty_write( + hvleds, led_id, AB5500_LED_INTENSITY_OFF); if (ret < 0) return ret; } @@ -294,12 +605,18 @@ static int ab5500_led_register_leds(struct device *dev, struct ab5500_hvleds *hvleds) { int i_led; - int err; + int ret = 0; struct ab5500_led_conf *pled; struct ab5500_led *led; hvleds->dev = dev; hvleds->pdata = pdata; + + if (abx500_get_chip_id(dev) == AB5500_2_0) + hvleds->hw_fade = true; + else + hvleds->hw_fade = false; + for (i_led = 0; i_led < AB5500_HVLEDS_MAX; i_led++) { pled = &pdata->leds[i_led]; led = &hvleds->leds[i_led]; @@ -308,84 +625,137 @@ static int ab5500_led_register_leds(struct device *dev, led->id = pled->led_id; led->max_current = pled->max_current; - led->status = pled->status; + led->led_on = pled->led_on; led->led_cdev.name = pled->name; led->led_cdev.brightness_set = ab5500_led_brightness_set; - err = led_classdev_register(dev, &led->led_cdev); - if (err < 0) { - dev_err(dev, "Register led class failed: %d\n", err); + /* Provide interface only for enabled LEDs */ + if (led->led_on == false) + continue; + + if (hvleds->hw_fade) { + led->fade_hi = (pled->fade_hi & LED_FULL); + led->fade_hi *= AB5500_LED_INTENSITY_STEP; + led->fade_lo = (pled->fade_lo & LED_FULL); + led->fade_lo *= AB5500_LED_INTENSITY_STEP; + } + + ret = led_classdev_register(dev, &led->led_cdev); + if (ret < 0) { + dev_err(dev, "Register led class failed: %d\n", ret); goto bailout1; } - err = device_create_file(led->led_cdev.dev, + ret = device_create_file(led->led_cdev.dev, &dev_attr_led_current); - if (err < 0) { - dev_err(dev, "sysfs device creation failed: %d\n", err); + if (ret < 0) { + dev_err(dev, "sysfs device creation failed: %d\n", ret); goto bailout2; } + + if (hvleds->hw_fade) { + ret = device_create_file(led->led_cdev.dev, + &dev_attr_fade_auto); + if (ret < 0) { + dev_err(dev, "sysfs device " + "creation failed: %d\n", ret); + goto bailout3; + } + + ret = device_create_file(led->led_cdev.dev, + &dev_attr_fade_delay); + if (ret < 0) { + dev_err(dev, "sysfs device " + "creation failed: %d\n", ret); + goto bailout4; + } + } } - return err; + return ret; for (; i_led >= 0; i_led--) { - device_remove_file(led->led_cdev.dev, &dev_attr_led_current); + if (hvleds->leds[i_led].led_on == false) + continue; + + if (hvleds->hw_fade) { + device_remove_file(hvleds->leds[i_led].led_cdev.dev, + &dev_attr_fade_delay); +bailout4: + device_remove_file(hvleds->leds[i_led].led_cdev.dev, + &dev_attr_fade_auto); + } +bailout3: + device_remove_file(hvleds->leds[i_led].led_cdev.dev, + &dev_attr_led_current); bailout2: led_classdev_unregister(&hvleds->leds[i_led].led_cdev); bailout1: cancel_work_sync(&hvleds->leds[i_led].led_work); } - return err; + return ret; } static int __devinit ab5500_hvleds_probe(struct platform_device *pdev) { struct ab5500_hvleds_platform_data *pdata = pdev->dev.platform_data; struct ab5500_hvleds *hvleds = NULL; - int err = 0, i; + int ret = 0, i; if (pdata == NULL) { dev_err(&pdev->dev, "platform data required\n"); - err = -ENODEV; + ret = -ENODEV; goto err_out; } hvleds = kzalloc(sizeof(struct ab5500_hvleds), GFP_KERNEL); if (hvleds == NULL) { - err = -ENOMEM; + ret = -ENOMEM; goto err_out; } mutex_init(&hvleds->lock); /* init leds data and register led_classdev */ - err = ab5500_led_register_leds(&pdev->dev, pdata, hvleds); - if (err < 0) { - dev_err(&pdev->dev, "leds registeration failed\n"); + ret = ab5500_led_register_leds(&pdev->dev, pdata, hvleds); + if (ret < 0) { + dev_err(&pdev->dev, "leds registration failed\n"); goto err_out; } /* init device registers and set initial led current */ - err = ab5500_led_init_registers(hvleds); - if (err < 0) { - dev_err(&pdev->dev, "reg init failed: %d\n", err); + ret = ab5500_led_init_registers(hvleds); + if (ret < 0) { + dev_err(&pdev->dev, "reg init failed: %d\n", ret); goto err_reg_init; } - dev_info(&pdev->dev, "enabled\n"); + if (hvleds->hw_fade) + dev_info(&pdev->dev, "v2 enabled\n"); + else + dev_info(&pdev->dev, "v1 enabled\n"); - return err; + return ret; err_reg_init: for (i = 0; i < AB5500_HVLEDS_MAX; i++) { struct ab5500_led *led = &hvleds->leds[i]; - led_classdev_unregister(&led->led_cdev); + if (led->led_on == false) + continue; + device_remove_file(led->led_cdev.dev, &dev_attr_led_current); + if (hvleds->hw_fade) { + device_remove_file(led->led_cdev.dev, + &dev_attr_fade_auto); + device_remove_file(led->led_cdev.dev, + &dev_attr_fade_delay); + } + led_classdev_unregister(&led->led_cdev); cancel_work_sync(&led->led_work); } err_out: kfree(hvleds); - return err; + return ret; } static int __devexit ab5500_hvleds_remove(struct platform_device *pdev) @@ -396,8 +766,17 @@ static int __devexit ab5500_hvleds_remove(struct platform_device *pdev) for (i = 0; i < AB5500_HVLEDS_MAX; i++) { struct ab5500_led *led = &hvleds->leds[i]; - led_classdev_unregister(&led->led_cdev); + if (led->led_on == false) + continue; + device_remove_file(led->led_cdev.dev, &dev_attr_led_current); + if (hvleds->hw_fade) { + device_remove_file(led->led_cdev.dev, + &dev_attr_fade_auto); + device_remove_file(led->led_cdev.dev, + &dev_attr_fade_delay); + } + led_classdev_unregister(&led->led_cdev); cancel_work_sync(&led->led_work); } kfree(hvleds); diff --git a/include/linux/leds-ab5500.h b/include/linux/leds-ab5500.h index 2db6ffd188e..9ba9ac61d90 100644 --- a/include/linux/leds-ab5500.h +++ b/include/linux/leds-ab5500.h @@ -13,19 +13,23 @@ #define AB5500_HVLED2 2 #define AB5500_HVLEDS_MAX 3 -enum ab5500_led_status { - AB5500_LED_OFF = 0x00, - AB5500_LED_ON, +enum ab5500_fade_delay { + AB5500_FADE_DELAY_BYPASS = 0, + AB5500_FADE_DELAY_HALFSEC, + AB5500_FADE_DELAY_ONESEC, + AB5500_FADE_DELAY_TWOSEC }; struct ab5500_led_conf { char *name; u8 led_id; - enum ab5500_led_status status; u8 max_current; + u8 fade_hi; + u8 fade_lo; + bool led_on; }; struct ab5500_hvleds_platform_data { - bool hw_blink; + bool hw_fade; struct ab5500_led_conf leds[AB5500_HVLEDS_MAX]; }; -- cgit v1.2.3 From 67dbd4b164e806b09bd77b9ac8e2b7f1f05ddde1 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 28 Sep 2011 10:35:21 +0200 Subject: U8500: enable again the STM trace driver This driver has been disabled because of some updates required on user side. Now that the user lib are fixed, enable it again. ST-Ericsson ID: 363600 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: - Signed-off-by: Pierre Peiffer Depends-On: I38a2d1ffff4def425d50564de689fb949fe5d6e7, Ib303ad17367e11921471b4124563239d6c26223a, Iad3a2e06c252e4c9dcb323ae3d6a5d51bac579ef Change-Id: I458d4565a5d1dedf84fbbc0c614daf80a9810693 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32438 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index aa28732a74c..5146c79c11c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -116,6 +116,8 @@ CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y +CONFIG_U8500_SIM_DETECT=y +CONFIG_STM_TRACE=y CONFIG_DISPDEV=y CONFIG_U8500_SIM_DETECT=y # CONFIG_STE_AUDIO_IO_DEV is not set -- cgit v1.2.3 From 15a08af004fed2b5f95dd36595978a3bd92e8943 Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Thu, 29 Sep 2011 10:46:44 +0200 Subject: defconfig: enable SW reset feature When there is no crash kernel image loaded, perform a SW reset at a panic. ST-Ericsson ID: 340331 Change-Id: I61e0026c248f4a4f1078a988b0dcd395140e5510 Signed-off-by: Per Fransson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32679 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 5146c79c11c..4e8d3bf7772 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -50,6 +50,7 @@ CONFIG_AEABI=y CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y +CONFIG_CRASH_SWRESET=y CONFIG_CRASH_DUMP=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y -- cgit v1.2.3 From 92b551836c4b990203c3c807b641508dc2a55437 Mon Sep 17 00:00:00 2001 From: Shyam Krishnan M Date: Mon, 3 Oct 2011 13:27:14 +0530 Subject: defconfig: enable cg2900 This patch sets configuration of cg2900. ST-Ericsson Linux next: NA ST-Ericsson ID: 335714 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie114065582f53b3af429660768d17456edfa70d6 Signed-off-by: Shyam Krishnan M Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32800 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4e8d3bf7772..ec3b937806d 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -195,6 +195,8 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_RADIO_CG2900=y CONFIG_DRM=y +CONFIG_SND_SOC_UX500_CG29XX=y +CONFIG_SND_SOC_CG29XX=y CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y -- cgit v1.2.3 From f56f1f95b21e86d61f9983cda8d90bf06cd4a2a3 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Fri, 30 Sep 2011 12:59:59 +0530 Subject: power: ab5500-bm: handle divide by zero warning samples obtained from the fuel gauge is used to calculate the average current. Calculation of average current include division by samples, which ends up with division by zero in case samples is zero. Hence if samples is zero, average current is not calaulated and previous value is used. ST-Ericsson Linux next: NA ST-Ericsson ID: 363829 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I04dd205a7af07cfc7d2ff369fd29cdd1363f6208 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32674 Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_fg.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 0975c7417a4..62710680d1e 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -533,8 +533,12 @@ static void ab5500_fg_acc_cur_work(struct work_struct *work) di->fg_samples = (cnt_low | (cnt_high << 8)); val = (low | (med << 8) | (high << 16)); - di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10)/10000; - di->avg_curr = (val * FG_LSB_IN_MA) / (di->fg_samples * 1000); + if (di->fg_samples) { + di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10)/10000; + di->avg_curr = (val * FG_LSB_IN_MA) / (di->fg_samples * 1000); + } else + dev_err(di->dev, + "samples is zero, using previous calculated average current\n"); di->flags.conv_done = true; mutex_unlock(&di->cc_lock); -- cgit v1.2.3 From a4380d4bdb744cdd5c64c94d0dc299f95fe6bac9 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Tue, 4 Oct 2011 14:34:17 +0200 Subject: u8500: Enable IP multicast Enables CONFIG_IP_MULTICAST in u8500_defconfig ST-Ericsson Linux next: Not tested ST-Ericsson ID: 355020, 353690 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Id652d38efceef6585fbb2505750edbacbc9e82a9 Signed-off-by: Bartosz Markowski Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32958 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index ec3b937806d..9f6f7ec5d6f 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -70,6 +70,8 @@ CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_MROUTE is not set CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_PNP=y -- cgit v1.2.3 From 5b0ed145302430a044ef36489735c15ecc810a70 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 4 Oct 2011 11:18:22 +0200 Subject: misc: audio_io: Remove obsolete and unused driver audio_io is superseded by alsa. ST-Ericsson Linux next: - ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I4641468e1d67e8596b1fcd9af69b0b81b686a0a0 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32904 Reviewed-by: Ola LILJA2 --- arch/arm/configs/u8500_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 9f6f7ec5d6f..0901c06fd81 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -122,8 +122,6 @@ CONFIG_STE_TRACE_MODEM=y CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y CONFIG_DISPDEV=y -CONFIG_U8500_SIM_DETECT=y -# CONFIG_STE_AUDIO_IO_DEV is not set CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_MD=y -- cgit v1.2.3 From 4d31e580408d9b0d90adbafbfd30d70588737d9b Mon Sep 17 00:00:00 2001 From: Kalle Komierowski Date: Tue, 4 Oct 2011 13:51:16 +0200 Subject: arm: mach-ux500: Lower the upper battery temperature limits This is to make it easier to test the temperature limits during battery charging. Customers will change the values to their own preferences. ST-Ericsson ID: 341012 ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I4b6078a82816876d49eccc8c892e7ea2487939a1 Signed-off-by: Kalle Komierowski Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32955 Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/board-mop500-bm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 78f20626cab..91fb887d4f5 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -391,8 +391,8 @@ static const struct ab8500_bm_charger_parameters chg = { struct ab8500_bm_data ab8500_bm_data = { .temp_under = 3, .temp_low = 8, - .temp_high = 55, - .temp_over = 60, + .temp_high = 43, + .temp_over = 48, .main_safety_tmr_h = 4, .temp_interval_chg = 20, .temp_interval_nochg = 120, -- cgit v1.2.3 From 7f03fbd618db7ebfa7e0b0607268e7cee06db172 Mon Sep 17 00:00:00 2001 From: Chris Kimber Date: Wed, 28 Sep 2011 13:27:30 +0100 Subject: hwmon: dbx500: Stop db max alarms from shutting down the platform Setting the critical alarm causes the PRCMU to shutdown the platform, the _max alarm is used by the platform thermal service to try and take actions to prevent the critical shutdown occuring. ST-Ericsson ID: 364370 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I04671800872aba8318f461fb5a710a72aea4280a Signed-off-by: Chris Kimber Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32400 Reviewed-by: Duncan PATERSON Reviewed-by: Andrew LYNN --- drivers/hwmon/dbx500.c | 63 +------------------------------------------------- 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/drivers/hwmon/dbx500.c b/drivers/hwmon/dbx500.c index cd44e78030c..be8ba79c9a8 100644 --- a/drivers/hwmon/dbx500.c +++ b/drivers/hwmon/dbx500.c @@ -26,13 +26,6 @@ #include #include -/* - * If DBX500 warm interrupt is set, user space will be notified. - * If user space doesn't shut down the platform within this time - * frame, this driver will. Time unit is ms. - */ -#define DEFAULT_POWER_OFF_DELAY 10000 - /* * Default measure period to 0xFF x cycle32k */ @@ -50,51 +43,9 @@ struct dbx500_temp { unsigned char min_alarm[NUM_SENSORS]; unsigned char max_alarm[NUM_SENSORS]; unsigned short measure_time; - struct delayed_work power_off_work; struct mutex lock; - /* Delay (ms) before power off */ - unsigned long power_off_delay; }; -static void thermal_power_off(struct work_struct *work) -{ - struct dbx500_temp *data = container_of(work, struct dbx500_temp, - power_off_work.work); - - dev_warn(&data->pdev->dev, "Power off due to DBX500 thermal warning\n"); - pm_power_off(); -} - -static ssize_t set_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int res; - unsigned long delay_in_s; - struct dbx500_temp *data = dev_get_drvdata(dev); - - res = strict_strtoul(buf, 10, &delay_in_s); - if (res < 0) { - dev_warn(&data->pdev->dev, "Set power_off_delay wrong\n"); - return res; - } - - mutex_lock(&data->lock); - data->power_off_delay = delay_in_s * 1000; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_power_off_delay(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct dbx500_temp *data = dev_get_drvdata(dev); - /* return time in s, not ms */ - return sprintf(buf, "%lu\n", (data->power_off_delay) / 1000); -} - /* HWMON sysfs interface */ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) @@ -264,11 +215,6 @@ static ssize_t show_max_alarm(struct device *dev, return sprintf(buf, "%d\n", data->max_alarm[attr->index - 1]); } -/*These node are not included in the kernel hwmon sysfs interface */ -static SENSOR_DEVICE_ATTR(temp_power_off_delay, S_IRUGO | S_IWUSR, - show_temp_power_off_delay, - set_temp_power_off_delay, 0); - /* Chip name, required by hwmon*/ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 1); @@ -282,7 +228,6 @@ static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); static struct attribute *dbx500_temp_attributes[] = { - &sensor_dev_attr_temp_power_off_delay.dev_attr.attr, &sensor_dev_attr_name.dev_attr.attr, &sensor_dev_attr_temp1_start.dev_attr.attr, &sensor_dev_attr_temp1_stop.dev_attr.attr, @@ -315,7 +260,6 @@ static irqreturn_t prcmu_hotmon_low_irq_handler(int irq, void *irq_data) static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) { - unsigned long delay_in_jiffies; struct platform_device *pdev = irq_data; struct dbx500_temp *data = platform_get_drvdata(pdev); @@ -325,10 +269,7 @@ static irqreturn_t prcmu_hotmon_high_irq_handler(int irq, void *irq_data) hwmon_notify(data->max_alarm[0], NULL); sysfs_notify(&pdev->dev.kobj, NULL, "temp1_max_alarm"); - dev_dbg(&pdev->dev, "DBX500 thermal warning, power off in %lu s\n", - (data->power_off_delay) / 1000); - delay_in_jiffies = msecs_to_jiffies(data->power_off_delay); - schedule_delayed_work(&data->power_off_work, delay_in_jiffies); + return IRQ_HANDLED; } @@ -394,10 +335,8 @@ static int __devinit dbx500_temp_probe(struct platform_device *pdev) } mutex_init(&data->lock); - INIT_DELAYED_WORK(&data->power_off_work, thermal_power_off); data->pdev = pdev; - data->power_off_delay = DEFAULT_POWER_OFF_DELAY; data->measure_time = DEFAULT_MEASURE_TIME; platform_set_drvdata(pdev, data); -- cgit v1.2.3 From d8dc8d7a0a4cd180bb59263006ab65497c732243 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 6 Oct 2011 10:49:02 +0200 Subject: arm:config: Update u9500_defconfig with 8500 updates Here is the list of changes: * misc: audio_io: Remove obsolete and unused driver * u8500: Enable IP multicast * defconfig: enable SW reset feature * U8500: enable again the STM trace driver * ARM: u8500: configs: Enable regulator suspend force * u8500_defconfig: Enable ip rule support (339665) * ARM: config: u8500: Enable DB8500 regulators * ARM: ux500: Use u8500_wdt * u8500: watchdog: Reset to mainline status * cpuidle: only go to ApIdle * drivers:cpuidle U8500 support * ARM: ux500: suspend_dbg: Add debug information * ARM: ux500: suspend: Add wake on uart * ARM: ux500: Add suspend support * ARM: u8500: config: Enable cpufreq * ARM: ux500: pm: Added context and pm * ARM: ux500: Add prcmu-debug * ARM: ux500: Add prcmu qos power * ARM: ux500: Replace mach prcmu driver with mainlined version * ARM: ux500: Remove powersave * arm: u8500: Disable HDMI fb auto creation (364125) * ARM: u8500: Not every u8500 has a TPS6105 ST-Ericsson Linux next: - ST-Ericsson ID: 339665, 364125, 363600, 340331, 355020, 353690 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic6a568411a70ed40e7ca3a14a4dfef0e17fc8543 Original Change-Ids: I4641468e1d67e8596b1fcd9af69b0b81b686a0a0 Id652d38efceef6585fbb2505750edbacbc9e82a9 I61e0026c248f4a4f1078a988b0dcd395140e5510 I458d4565a5d1dedf84fbbc0c614daf80a9810693 I26ba2f655d4fb65708913cdeda632e2ca35fea0a I3a570cdf0dbdbea2b2279428fa10d8a1fc63f659 Ieb69b0092465a71e7233cc63bddb149998f96410 I48b2a181e091c3095299646be376b7953a7d849c I14fd6f9990e3fe58671ff256baa8e6dfa0376b1f I952f7521284a41af56698cd8fc72b833210ea30e I792d4c1b4d78f3cf67cc0c0150f0c93341d81979 I48792f56b4edc3fb93897d89ad18402a27652a4b Ia9ae6894333ee8d696a2b946b565496e1c26554f I039557aed52693dfad9b76ea0f2f746193aa4316 I6d29a32251144e3ff33841516ea265ea9964f46e I1cfccc33d6e412dfcaaf1793ce19ea27c4b3b724 I810ae725fe1914ff605cf9704f8bdfb1a07b8f9b Ic803dcddb6656c4c4be82b49b11530624942012d I0c8d97679ee186ca8205aeeafa0030568f540d2e I8ceaa65e5e0905fcd85bf8e793b4a5ab2d2df64c I4098a7640a91c7f2695748a7a7ddf96f16e7981b Iae2433a2060f2415dfcd30dd7a16338728b91ec2 Change-Id: Ic6a568411a70ed40e7ca3a14a4dfef0e17fc8543 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32735 Reviewed-by: Derek MORTON Reviewed-by: Yann GAUTIER Tested-by: Yann GAUTIER Reviewed-by: Christophe GUIBOUT Reviewed-by: Andrew LYNN --- arch/arm/configs/u8500_defconfig | 54 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0901c06fd81..4cf986546b8 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -26,6 +26,7 @@ CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y @@ -33,14 +34,23 @@ CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DBX500_PRCMU_QOS_POWER=y CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_CPU_IDLE=y +CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_STANDBY=y -CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y +CONFIG_UX500_SUSPEND_STANDBY=y +CONFIG_UX500_SUSPEND_MEM=y +CONFIG_UX500_CONTEXT=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -69,11 +79,16 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_MROUTE is not set CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set @@ -83,6 +98,7 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y @@ -105,6 +121,18 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y + +CONFIG_AVERAGE=y + +#WIRELESS +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_COMPAT_WIRELESS=y +CONFIG_COMPAT_WIRELESS_MODULES=y +CONFIG_CFG80211=y +CONFIG_COMPAT_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_COMPAT_RFKILL=y CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_REG_DEBUG=y CONFIG_RFKILL=y @@ -139,6 +167,21 @@ CONFIG_SMSC911X=y CONFIG_PPP=y CONFIG_PPP_ASYNC=y CONFIG_PPP_MPPE=y +CONFIG_CAIF_TTY=m +# CONFIG_CAIF_SPI_SLAVE is not set +CONFIG_CAIF_HSI=m +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=y +# CONFIG_PPPOE is not set +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_SLHC=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -179,8 +222,12 @@ CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_U8500_WATCHDOG_DEBUG=y CONFIG_TPS6105X=y +CONFIG_WATCHDOG_CORE=y +CONFIG_U8500_WATCHDOG_DEBUG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y +CONFIG_MFD_DB8500_PRCMU=y +CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y @@ -202,6 +249,9 @@ CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_MCDE_FB_AVOID_REALLOC=y CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_MCDE_DISPLAY_GENERIC_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y CONFIG_SOUND=y -- cgit v1.2.3 From 5c0710d3925892311ee94fed5def8b671c393641 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 22 Sep 2011 13:09:55 +0530 Subject: power: ab5500-bm: set default charging current In case of standard host, current that can be drawn for charging is to be notified by the usb driver. Until this notification battery driver can go ahead charging by consuming 100mA as per the specs. Change-Id: I2687afa5dca39d0e800011848b38f2822d0bc7e7 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31934 Reviewed-by: Praveena NADAHALLY Reviewed-by: Karl KOMIEROWSKI Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index b4ac1ac6bb7..4ac35fcb1e8 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -313,7 +313,7 @@ static int ab5500_charger_max_usb_curr(struct ab5500_charger *di, case USB_STAT_STD_HOST_C_S: dev_dbg(di->dev, "USB Type - Standard host is " "detected through USB driver\n"); - ret = -1; + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; break; case USB_STAT_HOST_CHG_HS_CHIRP: di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; -- cgit v1.2.3 From c4a98f94c839ab9c1b5647d3cad56cfc99d7ba9f Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Mon, 10 Oct 2011 14:21:05 +0530 Subject: mfd: add irq_wake for TC3589x add enable_irq_wake during suspend and disable_irq_wake during resume for TC3589x keypad ST-Ericsson ID: 365245 ST-Ericsson Linux next: ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Naga Radhesh Change-Id: If9d2f272f4db70048220095c9749fd05245010aa Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33409 Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- drivers/mfd/tc3589x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 8c58389f695..0e79fe2d214 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -453,6 +453,8 @@ static int tc3589x_suspend(struct device *dev) ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, TC3589x_CLKMODE_MODCTL_SLEEP); + } else { + enable_irq_wake(client->irq); } out: return ret; @@ -492,6 +494,8 @@ static int tc3589x_resume(struct device *dev) if (ret < 0) break; } + } else { + disable_irq_wake(client->irq); } out: return ret; -- cgit v1.2.3 From 2b48863885bed4834bbea5132dc7605c4ec86934 Mon Sep 17 00:00:00 2001 From: Joseph V P Date: Fri, 7 Oct 2011 16:10:39 +0530 Subject: arm: u5500: Enable HDMI display For supporting HDMI by default, HDMI configurations are enabled. ST-Ericsson ID: 362962 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1ad6b80f56cbab53462e092eb45768b22ce55a04 Signed-off-by: Joseph V P Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33337 Reviewed-by: Per PERSSON Reviewed-by: Jimmy RUBIN Reviewed-by: Jayarami REDDY Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 4cf986546b8..8c8137f8bd3 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -39,6 +39,9 @@ CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y +CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y +CONFIG_DISPLAY_AV8100_TERTIARY=y +CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y @@ -248,6 +251,10 @@ CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_MCDE_FB_AVOID_REALLOC=y +CONFIG_MCDE_DISPLAY_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_AV8100=y CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_MCDE_DISPLAY_GENERIC_DSI=y CONFIG_MCDE_DISPLAY_AV8100=y -- cgit v1.2.3 From f38d0b775ee6c885fe207b6a3a03f0d4c953dbd4 Mon Sep 17 00:00:00 2001 From: Marcus Lorentzon Date: Mon, 10 Oct 2011 13:11:16 +0200 Subject: ux500: mcde: Include S6D16D0 driver by default ST-Ericsson ID: 365249 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I38bfb6a8d33a76af94b61b0ee94dbcce8cff901e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33449 Reviewed-by: Marcus LORENTZON Tested-by: Marcus LORENTZON Reviewed-by: Jimmy RUBIN Reviewed-by: Per PERSSON Reviewed-by: QABUILD --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 8c8137f8bd3..351ed49e8d7 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -256,6 +256,7 @@ CONFIG_MCDE_DISPLAY_AV8100=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set CONFIG_AV8100=y CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y CONFIG_MCDE_DISPLAY_GENERIC_DSI=y CONFIG_MCDE_DISPLAY_AV8100=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set -- cgit v1.2.3 From e3273c04ff2dc6aa1f6b0be2876f4093bea6efab Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Tue, 4 Oct 2011 10:56:48 +0200 Subject: ab8500: Separate regulator and MFD platform data The ab8500 MFD should not have knowledge about regulator- specific platform data like number of regulators and regulator registers. As the regulator platform data is about to grow with external regulators, this information is moved to a new structure provided by the regulator driver. ST-Ericsson ID: 282517 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I77d03ffcc3273b0659dea3cffd8191b8c94b83d2 Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33615 Reviewed-by: QABUILD Reviewed-by: Yvan FILLION --- include/linux/mfd/abx500/ab8500.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index e7309e5e231..a8ee912bf69 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -258,8 +258,7 @@ struct ab8500 { struct ab8500_charger *charger; }; -struct regulator_reg_init; -struct regulator_init_data; +struct ab8500_regulator_platform_data; struct ab8500_accdet_platform_data; struct ab8500_denc_platform_data; struct ab8500_audio_platform_data; @@ -273,9 +272,6 @@ struct ab8500_gpio_platform_data; * @thermal_time_out: Time out before the thermal alarm should be ignored * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used * @init: board-specific initialization after detection of ab8500 - * @num_regulator_reg_init: number of regulator init registers - * @regulator_reg_init: regulator init registers - * @num_regulator: number of regulators * @regulator: machine-specific constraints for regulators * @accdet: machine-specific Accessory detection data * @battery: machine-specific battery management data @@ -289,10 +285,7 @@ struct ab8500_platform_data { long thermal_set_time_sec; long thermal_time_out; void (*init) (struct ab8500 *); - int num_regulator_reg_init; - struct ab8500_regulator_reg_init *regulator_reg_init; - int num_regulator; - struct regulator_init_data *regulator; + struct ab8500_regulator_platform_data *regulator; struct abx500_accdet_platform_data *accdet; struct ab8500_bm_data *battery; struct ab8500_denc_platform_data *denc; -- cgit v1.2.3 From d295b7a2362f0372b2d670b64f7ea7a3b364f390 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Tue, 4 Oct 2011 11:40:10 +0200 Subject: regulators: ab8500: Add support of low voltage battery Low voltage batteries have a wider voltage range with lower operating voltages. Some consumers in the platform may not work with the lower voltages and therefore need an extra regulator to boost the voltage in this case. This driver adds support for checking the consumers that need higher voltage (Vaux1, 2 and 3 regulators, 3 V SIM) and control the external buck/boost regulator accordingly. Note that to utilize the low voltage battery support, the battery voltage thresholds must be changed. This applies for the low battery voltage threshold of the battery manager and the OTP setting for the AB8500 BattOk levels. ST-Ericsson ID: 282517, 363432 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ife07a622ec9748c027dbbd78b01e4ee7e92629ec Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33616 Reviewed-by: QABUILD --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 351ed49e8d7..25501c1d241 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -237,6 +237,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_AB8500_EXT=y CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_REGULATOR_DB8500_PRCMU=y CONFIG_MEDIA_SUPPORT=y -- cgit v1.2.3 From ea174c50d9ec3d593d645620ee915cf47f95ba3e Mon Sep 17 00:00:00 2001 From: Chris Kimber Date: Wed, 28 Sep 2011 16:19:10 +0100 Subject: hwmon: dbx500: Automatically setup temp monitoring When a value other than 0 is written to either the _min or _max attributes, automatically start the PRCMU monitoring. Also at driver init start monitoring the critical temperature to prevent overheating. ST-Ericsson ID: 364370 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I8fefbf30eeb07d6caf4ee73af487b948fbd2fe7e Signed-off-by: Chris Kimber Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32404 Reviewed-by: QABUILD Reviewed-by: Duncan PATERSON Reviewed-by: Andrew LYNN --- drivers/hwmon/dbx500.c | 101 ++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/drivers/hwmon/dbx500.c b/drivers/hwmon/dbx500.c index be8ba79c9a8..e240f92ede8 100644 --- a/drivers/hwmon/dbx500.c +++ b/drivers/hwmon/dbx500.c @@ -31,6 +31,11 @@ */ #define DEFAULT_MEASURE_TIME 0xFF +/* + * Default critical sensor temperature + */ +#define DEFAULT_CRITICAL_TEMP 85 + /* This driver monitors DB thermal*/ #define NUM_SENSORS 1 @@ -43,9 +48,39 @@ struct dbx500_temp { unsigned char min_alarm[NUM_SENSORS]; unsigned char max_alarm[NUM_SENSORS]; unsigned short measure_time; + bool monitoring_active; struct mutex lock; }; +static inline void start_temp_monitoring(struct dbx500_temp *data, + const int index) +{ + unsigned int i; + + /* determine if there are any sensors worth monitoring */ + for (i = 0; i < NUM_SENSORS; i++) + if (data->min[i] || data->max[i]) + goto start_monitoring; + + return; + +start_monitoring: + /* kick off the monitor job */ + data->min_alarm[index] = 0; + data->max_alarm[index] = 0; + + (void) prcmu_start_temp_sense(data->measure_time); + data->monitoring_active = true; +} + +static inline void stop_temp_monitoring(struct dbx500_temp *data) +{ + if (data->monitoring_active) { + (void) prcmu_stop_temp_sense(); + data->monitoring_active = false; + } +} + /* HWMON sysfs interface */ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) @@ -77,8 +112,13 @@ static ssize_t set_min(struct device *dev, struct device_attribute *devattr, data->min[attr->index - 1] = val; - (void)prcmu_config_hotmon(data->min[attr->index - 1], + stop_temp_monitoring(data); + + (void) prcmu_config_hotmon(data->min[attr->index - 1], data->max[attr->index - 1]); + + start_temp_monitoring(data, (attr->index - 1)); + mutex_unlock(&data->lock); return count; } @@ -100,8 +140,13 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr, data->max[attr->index - 1] = val; - (void)prcmu_config_hotmon(data->min[attr->index - 1], + stop_temp_monitoring(data); + + (void) prcmu_config_hotmon(data->min[attr->index - 1], data->max[attr->index - 1]); + + start_temp_monitoring(data, (attr->index - 1)); + mutex_unlock(&data->lock); return count; @@ -121,50 +166,12 @@ static ssize_t set_crit(struct device *dev, mutex_lock(&data->lock); val &= 0xFF; data->crit[attr->index - 1] = val; - (void)prcmu_config_hotdog(data->crit[attr->index - 1]); + (void) prcmu_config_hotdog(data->crit[attr->index - 1]); mutex_unlock(&data->lock); return count; } -/* start/stop temperature measurement */ -static ssize_t start_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct dbx500_temp *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - mutex_lock(&data->lock); - data->measure_time = val & 0xFFFF; - data->min_alarm[attr->index - 1] = 0; - data->max_alarm[attr->index - 1] = 0; - mutex_unlock(&data->lock); - - (void)prcmu_start_temp_sense(data->measure_time); - dev_dbg(&data->pdev->dev, "DBX500 thermal start measurement\n"); - - return count; -} - -static ssize_t stop_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - unsigned long val; - struct dbx500_temp *data = dev_get_drvdata(dev); - int res = strict_strtoul(buf, 10, &val); - if (res < 0) - return res; - - (void)prcmu_stop_temp_sense(); - dev_dbg(&data->pdev->dev, "DBX500 thermal stop measurement\n"); - - return count; -} - /* * show functions (RO nodes) * Notice that min/max/crit refer to degrees @@ -217,8 +224,6 @@ static ssize_t show_max_alarm(struct device *dev, /* Chip name, required by hwmon*/ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_start, S_IWUSR, NULL, start_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_stop, S_IWUSR, NULL, stop_temp, 1); static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1); static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1); static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, @@ -229,8 +234,6 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1); static struct attribute *dbx500_temp_attributes[] = { &sensor_dev_attr_name.dev_attr.attr, - &sensor_dev_attr_temp1_start.dev_attr.attr, - &sensor_dev_attr_temp1_stop.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, @@ -328,8 +331,8 @@ static int __devinit dbx500_temp_probe(struct platform_device *pdev) for (i = 0; i < NUM_SENSORS; i++) { data->min[i] = 0; - data->max[i] = 0xFF; - data->crit[i] = 0xFF; + data->max[i] = 0; + data->crit[i] = DEFAULT_CRITICAL_TEMP; data->min_alarm[i] = 0; data->max_alarm[i] = 0; } @@ -338,6 +341,10 @@ static int __devinit dbx500_temp_probe(struct platform_device *pdev) data->pdev = pdev; data->measure_time = DEFAULT_MEASURE_TIME; + data->monitoring_active = false; + + /* set PRCMU to disable platform when we get to the critical temp */ + (void) prcmu_config_hotdog(DEFAULT_CRITICAL_TEMP); platform_set_drvdata(pdev, data); -- cgit v1.2.3 From 18c2def0e7158f2a8ad6e8e1ffb6b54a6720a4ef Mon Sep 17 00:00:00 2001 From: Chris Kimber Date: Wed, 5 Oct 2011 16:30:40 +0100 Subject: hwmon: dbx500: Update to reflect new PRCMU location PRCMU has been moved, so fix Kconfig and header include path ST-Ericsson ID: 364370 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I052cf03afa4481e1267c07acf2d16401fac6abc2 Signed-off-by: Chris Kimber Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33124 Reviewed-by: QABUILD Reviewed-by: Duncan PATERSON Reviewed-by: Andrew LYNN --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/dbx500.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 297ad8e3b28..58b2a6c93c8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -66,7 +66,7 @@ config SENSORS_AB5500 config SENSORS_DBX500 tristate "DBX500 thermal monitoring" - depends on U8500_PRCMU || U5500_PRCMU + depends on MFD_DB8500_PRCMU || MFD_DB5500_PRCMU default n help If you say yes here you get support for the thermal sensor part diff --git a/drivers/hwmon/dbx500.c b/drivers/hwmon/dbx500.c index e240f92ede8..c034b48f8dd 100644 --- a/drivers/hwmon/dbx500.c +++ b/drivers/hwmon/dbx500.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From cbc7acb18ea078c70c95bc761b3ccaca3de18374 Mon Sep 17 00:00:00 2001 From: Jimmy Rubin Date: Tue, 11 Oct 2011 13:51:27 +0200 Subject: ux500: config: Enable Sony display for u8500 ST-Ericsson ID: 321190 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Jimmy Rubin Change-Id: Idcf924f1e29b24f31349ee602cb86da1fa9e9065 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33681 Reviewed-by: Jimmy RUBIN Tested-by: Jimmy RUBIN Reviewed-by: QABUILD Reviewed-by: Marcus LORENTZON --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 25501c1d241..ce5a8618af7 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -28,6 +28,9 @@ CONFIG_MACH_UX500_DT=y CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y +CONFIG_DISPLAY_GENERIC_PRIMARY=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY=y +CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y -- cgit v1.2.3 From 4acd2fe2beee669f38c9b74e627885c7bceaa7a7 Mon Sep 17 00:00:00 2001 From: Shyam Krishnan M Date: Wed, 12 Oct 2011 18:27:13 +0530 Subject: audio: hdmi: Config changes for enabling audio This enables audio in u5500_defconfig ST-Ericsson ID: 362962 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I32d8a1b130fcbd962551f3f4d1aa22b7d414062e Signed-off-by: Shyam Krishnan M Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33805 Reviewed-by: QABUILD Reviewed-by: Ganesh V Tested-by: Ganesh V Reviewed-by: Basavaprabhu BANDI Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index ce5a8618af7..eab7f1e88a7 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -398,3 +398,6 @@ CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y CONFIG_LIBCRC32C=m +CONFIG_SYS_SOC=y +CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_SND_SOC_AV8100=y -- cgit v1.2.3 From a9d6b3e3a4130691f026f8c9ace77f438528c990 Mon Sep 17 00:00:00 2001 From: Avinash A Date: Fri, 14 Oct 2011 16:13:15 +0530 Subject: u8500_defconfig: Enable the Cypress touchscreen ST-Ericsson ID: 366971 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I4724b322f5fba1b4fff49abb525380b98e8801a5 Signed-off-by: Avinash A Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34062 Reviewed-by: Avinash A Tested-by: Avinash A Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index eab7f1e88a7..75b9e2034b6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -198,6 +198,8 @@ CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_BU21013=y +CONFIG_TOUCHSCREEN_CYTTSP_CORE=y +CONFIG_TOUCHSCREEN_CYTTSP_SPI=y CONFIG_INPUT_MISC=y CONFIG_INPUT_AB8500_ACCDET=y CONFIG_INPUT_AB8500_PONKEY=y -- cgit v1.2.3 From 76a49952b2cf95bf3562d607dc3c7df0ad6b38be Mon Sep 17 00:00:00 2001 From: Jayarami Reddy Date: Wed, 12 Oct 2011 16:57:22 +0530 Subject: arm: u5500: Enable 32bpp for primary display ST-Ericsson ID: 361885 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic914e764ee4816fbfcfbba5129426e2ba51a88ab Signed-off-by: Jayarami Reddy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33780 Reviewed-by: Jimmy RUBIN --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 75b9e2034b6..294b71f7995 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -42,6 +42,7 @@ CONFIG_UX500_CPUIDLE=y # CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 CONFIG_UX500_CPUIDLE_DEBUG=y +CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y -- cgit v1.2.3 From 87237a263402fe449cebd2ce015b9f280500e6f2 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Mon, 17 Oct 2011 17:19:39 +0200 Subject: config: minimize the defconfig again Change-Id: If872084fce0c37126f9196a70c0f76db1c4cf37c Signed-off-by: Robert Marklund --- arch/arm/configs/u8500_defconfig | 78 +++------------------------------------- 1 file changed, 5 insertions(+), 73 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 294b71f7995..0e5c4d7cbbd 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -26,38 +26,17 @@ CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y -CONFIG_DISPLAY_GENERIC_PRIMARY=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY=y -CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y -CONFIG_DISPLAY_AV8100_TERTIARY=y -CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y -CONFIG_DBX500_PRCMU_QOS_POWER=y -CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_CPU_IDLE=y -CONFIG_UX500_CPUIDLE=y -# CONFIG_UX500_DEBUG_NO_LAUTERBACH is not set -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 -CONFIG_UX500_CPUIDLE_DEBUG=y -CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_CONTEXT=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -86,16 +65,10 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y -# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y -# CONFIG_IP_MROUTE is not set CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_FIB_TRIE_STATS is not set -CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set @@ -105,7 +78,6 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set CONFIG_NETFILTER=y -CONFIG_NETFILTER_NETLINK=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y @@ -128,18 +100,7 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y - -CONFIG_AVERAGE=y - -#WIRELESS -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_COMPAT_WIRELESS=y -CONFIG_COMPAT_WIRELESS_MODULES=y CONFIG_CFG80211=y -CONFIG_COMPAT_MAC80211_RC_DEFAULT="minstrel_ht" -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_COMPAT_RFKILL=y CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_REG_DEBUG=y CONFIG_RFKILL=y @@ -154,9 +115,9 @@ CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_STE_TRACE_MODEM=y +CONFIG_DISPDEV=y CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y -CONFIG_DISPDEV=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_MD=y @@ -171,24 +132,11 @@ CONFIG_SMSC911X=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set -CONFIG_PPP=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_MPPE=y CONFIG_CAIF_TTY=m -# CONFIG_CAIF_SPI_SLAVE is not set CONFIG_CAIF_HSI=m CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set CONFIG_PPP_ASYNC=y -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set CONFIG_PPP_MPPE=y -# CONFIG_PPPOE is not set -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_SLHC=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -231,42 +179,29 @@ CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_U8500_WATCHDOG_DEBUG=y CONFIG_TPS6105X=y -CONFIG_WATCHDOG_CORE=y -CONFIG_U8500_WATCHDOG_DEBUG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y -CONFIG_MFD_DB8500_PRCMU=y -CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_AB8500_EXT=y -CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_REGULATOR_DB8500_PRCMU=y +CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_RADIO_CG2900=y CONFIG_DRM=y -CONFIG_SND_SOC_UX500_CG29XX=y -CONFIG_SND_SOC_CG29XX=y CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_MCDE_FB_AVOID_REALLOC=y -CONFIG_MCDE_DISPLAY_DSI=y -CONFIG_MCDE_DISPLAY_AV8100=y -# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set -CONFIG_AV8100=y -CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y -CONFIG_MCDE_DISPLAY_GENERIC_DSI=y -CONFIG_MCDE_DISPLAY_AV8100=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y CONFIG_SOUND=y @@ -401,6 +336,3 @@ CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y CONFIG_LIBCRC32C=m -CONFIG_SYS_SOC=y -CONFIG_SND_SOC_UX500_AV8100=y -CONFIG_SND_SOC_AV8100=y -- cgit v1.2.3 From 20ca173468656b2a8e7505e4eab7acc917f927bc Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 10 Nov 2011 09:23:10 +0100 Subject: config: Update u8500_defconfig vs new MUSB driver in 3.1 Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0e5c4d7cbbd..21bad62db17 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -216,17 +216,17 @@ CONFIG_SND_SOC_UX500_AV8100=y CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_UX500=y -CONFIG_USB_MUSB_OTG=y -CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_MUSB_HDRC=m CONFIG_USB_ZERO=m CONFIG_USB_ETH=m CONFIG_USB_FILE_STORAGE=m @@ -317,12 +317,10 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_FUNCTION_TRACER=y -- cgit v1.2.3 From 4137ba67f41cc774da35446f6068f33fab46707f Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Fri, 3 Dec 2010 13:19:13 +0100 Subject: irq: Allow threaded and nested irqs to be shared This patch will make the threaded nested handler run all the registered shared action handlers and not just the first registered. Signed-off-by: Mattias Wallin Change-Id: Ib484a2fa50186dbc05aedbcb9936518302ab801b Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/10494 Reviewed-by: Rabin VINCENT Reviewed-by: Jonas ABERG --- kernel/irq/chip.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 3914c1e03cf..468bcbc5db4 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -266,7 +266,7 @@ void handle_nested_irq(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); struct irqaction *action; - irqreturn_t action_ret; + irqreturn_t action_ret = IRQ_NONE; might_sleep(); @@ -281,7 +281,11 @@ void handle_nested_irq(unsigned int irq) irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); raw_spin_unlock_irq(&desc->lock); - action_ret = action->thread_fn(action->irq, action->dev_id); + do { + action_ret |= action->thread_fn(action->irq, action->dev_id); + action = action->next; + } while (action); + if (!noirqdebug) note_interrupt(irq, desc, action_ret); -- cgit v1.2.3 From a44bc2f8bf04d07f529b552876a7575ecaf55e37 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 29 Nov 2011 11:23:53 +0100 Subject: mfd: ab550-power: Include module.h after 3.2 update Signed-off-by: Philippe Langlais --- drivers/mfd/ab5500-power.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/ab5500-power.c b/drivers/mfd/ab5500-power.c index a549b3e7538..9474c32809b 100644 --- a/drivers/mfd/ab5500-power.c +++ b/drivers/mfd/ab5500-power.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include -- cgit v1.2.3 From 20591b20e6becea4e44cb1b0b1cd0a730b1bf125 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 29 Nov 2011 11:24:40 +0100 Subject: gpadc.h regression after 3.2 update to merge somewhere --- include/linux/mfd/abx500/ab8500-gpadc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mfd/abx500/ab8500-gpadc.h b/include/linux/mfd/abx500/ab8500-gpadc.h index 252966769d9..fa706c5a04a 100644 --- a/include/linux/mfd/abx500/ab8500-gpadc.h +++ b/include/linux/mfd/abx500/ab8500-gpadc.h @@ -26,7 +26,7 @@ struct ab8500_gpadc; -struct ab8500_gpadc *ab8500_gpadc_get(char *name); +struct ab8500_gpadc *ab8500_gpadc_get(void); int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel); int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel); int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, -- cgit v1.2.3 From 868f676cb3f97454b121853666e5d1ac3974ed8d Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 10 Jan 2012 15:16:40 +0100 Subject: config: Enable profiling support for Linaro & DS-5 (Gator) and cleanup Signed-off-by: Philippe Langlais Signed-off-by: Lee Jones --- arch/arm/configs/u8500_defconfig | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 21bad62db17..6d5a1b1b282 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -10,8 +10,8 @@ CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -CONFIG_PERF_EVENTS=y CONFIG_SLAB=y +CONFIG_PROFILING=y CONFIG_BOOTTIME=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y @@ -26,17 +26,17 @@ CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_DB8500_MLOADER=y -CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y -CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y -CONFIG_DISPLAY_AV8100_TERTIARY=y -CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y +CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y +CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y +CONFIG_DISPLAY_AV8100_TERTIARY=y +CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y +CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -55,8 +55,6 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_IDLE=y -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 -CONFIG_UX500_CPUIDLE_DEBUG=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y @@ -126,17 +124,14 @@ CONFIG_DM_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y CONFIG_TUN=y -CONFIG_SMSC_PHY=y -CONFIG_NET_ETHERNET=y -CONFIG_SMSC911X=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_WLAN is not set CONFIG_CAIF_TTY=m CONFIG_CAIF_HSI=m +CONFIG_SMSC911X=y +CONFIG_SMSC_PHY=y CONFIG_PPP=y -CONFIG_PPP_ASYNC=y CONFIG_PPP_MPPE=y +CONFIG_PPP_ASYNC=y +# CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set @@ -226,7 +221,6 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_GADGET_MUSB_HDRC=m CONFIG_USB_ZERO=m CONFIG_USB_ETH=m CONFIG_USB_FILE_STORAGE=m @@ -256,8 +250,6 @@ CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y CONFIG_AB5500_SIM=y -CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y -CONFIG_HSEM_U8500=y CONFIG_CG2900=y CONFIG_CG2900_CHIP=y CONFIG_STLC2690_CHIP=y @@ -265,12 +257,14 @@ CONFIG_CG2900_UART=y CONFIG_CG2900_AUDIO=y CONFIG_CG2900_TEST=y CONFIG_BT_CG2900=y +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_CW1200=m CONFIG_CW1200_USE_GPIO_IRQ=y CONFIG_CW1200_DEBUGFS=y CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y +CONFIG_HSEM_U8500=y CONFIG_MODEM=y CONFIG_MODEM_U8500=y CONFIG_U8500_SHRM=y -- cgit v1.2.3 From 672afbe5adffd7adcbd73456412c97cf32503023 Mon Sep 17 00:00:00 2001 From: Kennet Wallden Date: Tue, 27 Sep 2011 09:23:56 +0200 Subject: u8500: Configure SysClkReqRfClkBuf Added the possibility to configure SysCl1kReqRfClkBuf - SysClk8ReqRfClkBuf ST-Ericsson ID: 360052 ST-Ericsson Linux next: N/A ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7813ae4a73701d874e39556c60608ff66e1d016d Signed-off-by: Kennet Wallden Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32261 Reviewed-by: Karl-Johan PERNTZ Reviewed-by: Bengt JONSSON --- drivers/mfd/ab8500-sysctrl.c | 25 +++++++++++++++++++++++++ include/linux/mfd/abx500/ab8500-sysctrl.h | 5 +++++ include/linux/mfd/abx500/ab8500.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 2a328cfaf43..e6befdc9e08 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -154,12 +154,37 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev) { struct ab8500_platform_data *plat; + struct ab8500_sysctrl_platform_data *pdata; sysctrl_dev = &pdev->dev; plat = dev_get_platdata(pdev->dev.parent); if (plat->pm_power_off) pm_power_off = ab8500_power_off; hwmon_notifier_register(&ab8500_notifier); + + pdata = plat->sysctrl; + + if (pdata) { + int ret; + int i; + int j; + for (i = AB8500_SYSCLKREQ1RFCLKBUF; + i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { + j = i - AB8500_SYSCLKREQ1RFCLKBUF; + ret = ab8500_sysctrl_write(i, 0xff, + pdata->initial_req_buf_config[j]); + dev_dbg(&pdev->dev, + "Setting SysClkReq%dRfClkBuf 0x%X\n", + j + 1, + pdata->initial_req_buf_config[j]); + if (ret < 0) { + dev_err(&pdev->dev, + "unable to set sysClkReq%dRfClkBuf: " + "%d\n", j + 1, ret); + } + } + } + return 0; } diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h index 10eb50973c3..ebf12e793db 100644 --- a/include/linux/mfd/abx500/ab8500-sysctrl.h +++ b/include/linux/mfd/abx500/ab8500-sysctrl.h @@ -37,6 +37,11 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits) return ab8500_sysctrl_write(reg, bits, 0); } +/* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */ +struct ab8500_sysctrl_platform_data { + u8 initial_req_buf_config[8]; +}; + /* Registers */ #define AB8500_TURNONSTATUS 0x100 #define AB8500_RESETSTATUS 0x101 diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index a8ee912bf69..c6119f50bf7 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -263,6 +263,7 @@ struct ab8500_accdet_platform_data; struct ab8500_denc_platform_data; struct ab8500_audio_platform_data; struct ab8500_gpio_platform_data; +struct ab8500_sysctrl_platform_data; /** * struct ab8500_platform_data - AB8500 platform data @@ -295,6 +296,7 @@ struct ab8500_platform_data { struct ab8500_fg_platform_data *fg; struct ab8500_chargalg_platform_data *chargalg; struct ab8500_gpio_platform_data *gpio; + struct ab8500_sysctrl_platform_data *sysctrl; }; extern int __devinit ab8500_init(struct ab8500 *ab8500, -- cgit v1.2.3 From 2b6a91fa2618d226d8e8c5a97ad7cb57a75be3cd Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Tue, 18 Oct 2011 16:57:25 +0530 Subject: u5500: Battery temp monitoring in manual mode Add support and enable manual mode battery temperature monitoring. As gpadc bdata auto trigger is not working as expected, switch to manual mode. ST-Ericsson Linux next: NA ST-Ericsson ID: 367324 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I0f4b619bb5527730ee779838507b09f6b37efb3a Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34364 Reviewed-by: Vijaya Kumar K-1 Reviewed-by: QATOOLS Reviewed-by: Arun MURTHY Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_btemp.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 7867455f493..111f0a8b107 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -38,6 +38,9 @@ #define RESET 0x00 #define ADOUT_10K_PULL_UP 0x07 +/* Enable battery temp monitoring manual mode */ +#define BTEMP_MANUAL_MONITORING + #define to_ab5500_btemp_device_info(x) container_of((x), \ struct ab5500_btemp, btemp_psy); @@ -102,6 +105,8 @@ static enum power_supply_property ab5500_btemp_props[] = { static LIST_HEAD(ab5500_btemp_list); +static int ab5500_btemp_bat_temp_trig(int mux); + struct ab5500_btemp *ab5500_btemp_get(void) { struct ab5500_btemp *di; @@ -451,11 +456,25 @@ static void ab5500_btemp_periodic_work(struct work_struct *work) power_supply_changed(&di->btemp_psy); } di->bat->temp_now = di->bat_temp; +#if defined(BTEMP_MANUAL_MONITORING) + /* Check for temperature limits */ + ab5500_btemp_bat_temp_trig(0); + /* Schedule a new measurement */ + if (di->events.usb_conn) + queue_delayed_work(di->btemp_wq, + &di->btemp_periodic_work, + round_jiffies(di->bat->interval_charging * HZ)); + else + queue_delayed_work(di->btemp_wq, + &di->btemp_periodic_work, + round_jiffies(di->bat->interval_not_charging * HZ)); +#else /* Schedule a new measurement */ queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, - round_jiffies(20 * HZ)); + round_jiffies(di->bat->interval_charging * HZ)); +#endif } /** @@ -604,13 +623,18 @@ static int ab5500_btemp_get_ext_psy_data(struct device *dev, void *data) /* USB disconnected */ if (!ret.intval && di->events.usb_conn) { di->events.usb_conn = false; +#if !defined(BTEMP_MANUAL_MONITORING) ab5500_btemp_periodic(di, false); +#endif } /* USB connected */ else if (ret.intval && !di->events.usb_conn) { di->events.usb_conn = true; + +#if !defined(BTEMP_MANUAL_MONITORING) ab5500_btemp_periodic(di, true); +#endif } break; default: @@ -646,6 +670,7 @@ static struct ab5500_btemp_interrupts ab5500_btemp_irq[] = { {"BATT_REMOVAL", ab5500_btemp_batt_removal_handler}, {"BATT_ATTACH", ab5500_btemp_batt_attach_handler}, }; + static int ab5500_btemp_bat_temp_trig(int mux) { struct ab5500_btemp *di = ab5500_btemp_get(); @@ -661,6 +686,7 @@ static int ab5500_btemp_bat_temp_trig(int mux) return 0;; } +#if !defined(BTEMP_MANUAL_MONITORING) static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) { struct adc_auto_input *auto_ip; @@ -684,6 +710,7 @@ static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) "failed to set auto trigger for battery temp\n"); return ret; } +#endif #if defined(CONFIG_PM) static int ab5500_btemp_resume(struct platform_device *pdev) @@ -831,14 +858,21 @@ static int __devinit ab5500_btemp_probe(struct platform_device *pdev) dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", ab5500_btemp_irq[i].name, irq, ret); } +#if defined(BTEMP_MANUAL_MONITORING) + /* Schedule monitoring work only if battery type is known */ + if (di->bat->batt_id != BATTERY_UNKNOWN) + queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); +#else ret = ab5500_btemp_auto_temp(di); if (ret) { dev_err(di->dev, "failed to register auto trigger for battery temp\n"); goto free_irq; } +#endif platform_set_drvdata(pdev, di); + list_add_tail(&di->node, &ab5500_btemp_list); dev_info(di->dev, "probe success\n"); return ret; -- cgit v1.2.3 From 5c1c7cce37d64233331b944e1182908a1e7030c4 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 19 Oct 2011 09:18:03 +0530 Subject: serial/amba-pl011: prevent console port from holding regulator Register the console in a console_initcall() to ensure that pl011_console_setup() gets called early and thus the uart_console() macro usage in pl011_power_startup() returns the correct value the first time it is called, so that the vAPE regulator is not taken for the console port. Note that this problem is seen only when the console port is line 0, since even without this patch pl011_console_setup() gets called (and thus the correct console->index is set) after the first port is added. ST-Ericsson ID: 368522 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7f4ab80e8d8be014bfdbe695ea45007212c9c4ea Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34411 Reviewed-by: Srinidhi KASAGAR Reviewed-by: Shreshtha Kumar SAHU --- drivers/tty/serial/amba-pl011.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 1a65c2d1093..1d4d38918cd 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2196,6 +2196,13 @@ static struct console amba_console = { .data = &amba_reg, }; +static int __init pl011_console_init(void) +{ + register_console(&amba_console); + return 0; +} +console_initcall(pl011_console_init); + #define AMBA_CONSOLE (&amba_console) #else #define AMBA_CONSOLE NULL -- cgit v1.2.3 From 79f46aa4d1b5cffd8bf19a6413cbf61c5b5fe817 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Mon, 17 Oct 2011 13:29:00 +0530 Subject: drivers/leds/leds-lp5521.c: change the return value In sscanf,execution of a %n directive does not always increment the assignment count returned, so ret value need not be 2 always. ST-Ericsson ID: 361235 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Naga Radhesh Change-Id:I7fb54aba0fbbc94d6cdef67f79709c46153a81dc Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34156 Reviewed-by: Srinidhi KASAGAR --- drivers/leds/leds-lp5521.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 410a723b869..75ade5792c3 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -355,7 +355,12 @@ static int lp5521_do_store_load(struct lp5521_engine *engine, while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) { /* separate sscanfs because length is working only for %s */ ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); - if (ret != 2) + /* + * Execution of a %n directive does not always + * increment the assignment count returned at + * completion of execution.so ret need not be 2 + */ + if ((ret != 1) && (ret != 2)) goto fail; ret = sscanf(c, "%2x", &cmd); if (ret != 1) -- cgit v1.2.3 From 4626e363d582062fdb3db76354cb17f335dab99e Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 3 Oct 2011 07:54:28 +0200 Subject: drivers: i2c: nomadik: Put regulator/clock handling in runtime callbacks ST-Ericsson Linux next: - ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7a0dc1ccf4b7f2c84285c0dd1db66c2d84684f40 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33028 Reviewed-by: Linus WALLEIJ --- drivers/i2c/busses/i2c-nomadik.c | 54 ++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index e6f2abba469..9ddf2c97d26 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -628,14 +628,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, dev->busy = true; - if (dev->regulator) - regulator_enable(dev->regulator); pm_runtime_get_sync(&dev->pdev->dev); - clk_enable(dev->clk); - - dev->busy = true; - status = init_hw(dev); if (status) goto out; @@ -668,10 +662,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, } out: - clk_disable(dev->clk); - pm_runtime_put_sync(&dev->pdev->dev); - if (dev->regulator) - regulator_disable(dev->regulator); + + pm_runtime_put(&dev->pdev->dev); dev->busy = false; @@ -861,9 +853,9 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) #ifdef CONFIG_PM -static int nmk_i2c_suspend(struct device *dev) + +static int nmk_i2c_suspend(struct platform_device *pdev, pm_message_t state) { - struct platform_device *pdev = to_platform_device(dev); struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); if (nmk_i2c->busy) @@ -872,23 +864,53 @@ static int nmk_i2c_suspend(struct device *dev) return 0; } -static int nmk_i2c_resume(struct device *dev) +static int nmk_i2c_suspend_noirq(struct device *dev) { + struct nmk_i2c_dev *nmk_i2c = + platform_get_drvdata(to_platform_device(dev)); + + if (nmk_i2c->busy) + return -EBUSY; + return 0; } + #else #define nmk_i2c_suspend NULL -#define nmk_i2c_resume NULL +#define nmk_i2c_suspend_noirq NULL #endif +static int nmk_i2c_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); + + clk_disable(nmk_i2c->clk); + if (nmk_i2c->regulator) + regulator_disable(nmk_i2c->regulator); + return 0; +} + +static int nmk_i2c_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); + + if (nmk_i2c->regulator) + regulator_enable(nmk_i2c->regulator); + clk_enable(nmk_i2c->clk); + return 0; +} + /* * We use noirq so that we suspend late and resume before the wakeup interrupt * to ensure that we do the !pm_runtime_suspended() check in resume before * there has been a regular pm runtime resume (via pm_runtime_get_sync()). */ static const struct dev_pm_ops nmk_i2c_pm = { - .suspend_noirq = nmk_i2c_suspend, - .resume_noirq = nmk_i2c_resume, + SET_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, nmk_i2c_runtime_resume, + NULL) + .suspend_noirq = nmk_i2c_suspend_noirq, }; static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) -- cgit v1.2.3 From 2eebbbe339b9599d9991fe3ea80eeaee1778c121 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Fri, 21 Oct 2011 12:20:05 +0530 Subject: power:ab5500-charger: check the usb type in notifier call When a usb notifier is called, update the notified current only if the plugge in device is a standard host else do not update the current just return. The notifier call that is called in the usb driver is not only for the battery driver but other usb instances, hence usb cannot stop calling the notifier call and do a check to call only if it is a standard host. Hence this check is done in the battery driver, and if relevant update else just return. ST-Ericsson Linux next: NA ST-Ericsson ID: 362955 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I83026aba60b8a60c9f80e2a699b8eded285f8a09 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34799 Reviewed-by: Mian Yousaf KAUKAB Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR Reviewed-by: Praveena NADAHALLY --- drivers/power/ab5500_charger.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index 4ac35fcb1e8..f57e2088a4a 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -1531,6 +1531,11 @@ static int ab5500_charger_usb_notifier_call(struct notifier_block *nb, enum ab5500_usb_state bm_usb_state; unsigned mA = *((unsigned *)power); + if (event != USB_EVENT_VBUS) { + dev_dbg(di->dev, "not a standard host, returning\n"); + return NOTIFY_DONE; + } + /* TODO: State is fabricate here. See if charger really needs USB * state or if mA is enough */ -- cgit v1.2.3 From 0d4c5146c540ecbf7596d759cec3111f6a81eafc Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 11 Jan 2012 13:33:40 +0100 Subject: config: ux500: sensors: Enable ux500 gpio keys handling Signed-off-by: Jonas Aaberg --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 6d5a1b1b282..49d92acfdd8 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -25,6 +25,7 @@ CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y +CONFIG_UX500_GPIO_KEYS=y CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y -- cgit v1.2.3 From 633e4d24f02fabf1dbcdb6db638b6d61d6e1322c Mon Sep 17 00:00:00 2001 From: Christian Nilsson Date: Fri, 21 Oct 2011 15:25:02 +0200 Subject: u8500_defconfig: Add support for active FTP in NAP Allowing active ftp to work when running NAP by adding support in conntrack and nat for it. ST-Ericsson ID: 364593 ST-Ericsson FOSS-OUT ID: NA Change-Id: I1f17ab1ccdef0db7d9a82a60fec686abbf6c2d5f Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34953 Reviewed-by: Christian NILSSON Tested-by: Christian NILSSON Reviewed-by: Carl-Johan SALOMONSSON Reviewed-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 49d92acfdd8..f5235ff566c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -87,6 +87,8 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_NAT_FTP=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y -- cgit v1.2.3 From 13a169d8f53948b0cddc0b27cd0f21b682897873 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 11 Jan 2012 14:29:59 +0100 Subject: configs: mcde: Remove static board configuration Make device registration more dynamic using mach_is_xxx() and uib_is_xxx() type of calls instead of having compile time Kconfig settings. And clean out most unused static configuration data. ST-Ericsson ID: 368402 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Signed-off-by: Marcus Lorentzon --- arch/arm/configs/u8500_defconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index f5235ff566c..3529033d6b0 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -32,10 +32,8 @@ CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y -CONFIG_MCDE_DISPLAY_PRIMARY_32BPP=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y -CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y -CONFIG_DISPLAY_AV8100_TERTIARY=y +CONFIG_U8500_TV_OUTPUT_AV8100=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y @@ -197,6 +195,7 @@ CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_MCDE_FB_AVOID_REALLOC=y +CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set CONFIG_AV8100_HWTRIG_I2SDAT3=y -- cgit v1.2.3 From 02e5d5302d571654906c181750d502c9f06d004b Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 26 Oct 2011 16:49:01 +0530 Subject: ARM: hw_breakpoint: don't fault when debug is not powered If the debug logic is not powered, the processor can unfortunately raise an undefined instruction exception on the instruction that we use to check if the debug logic is powered up or not. Handle this with an undef hook, so that the kernel doesn't crash on boot on such setups. ST-Ericsson ID: 370131 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5802811ac0676d3d13782897b6941dcaee3e4721 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35326 Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- arch/arm/kernel/hw_breakpoint.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd9410..180dd9f5b19 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -853,6 +853,25 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, return ret; } +static int hw_breakpoint_undef(struct pt_regs *regs, unsigned int instr) +{ + int reg = (instr >> 12) & 15; + + /* Fake sticky power-down cleared */ + regs->uregs[reg] = 0; + regs->ARM_pc += 4; + + return 0; +} + +static struct undef_hook hw_breakpoint_hook = { + .instr_mask = 0xffff0fff, + .instr_val = 0xee110e95, + .cpsr_mask = MODE_MASK, + .cpsr_val = SVC_MODE, + .fn = hw_breakpoint_undef, +}; + /* * One-time initialisation. */ @@ -899,6 +918,10 @@ static void reset_ctrl_regs(void *unused) /* * Ensure sticky power-down is clear (i.e. debug logic is * powered up). + * + * This could raise an undefined instruction exception. If it + * does, it is fixed up with an undef hook which constructs + * a fake value with the sticky power-down bit cleared. */ asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); if ((dbg_power & 0x1) == 0) @@ -986,6 +1009,8 @@ static int __init arch_hw_breakpoint_init(void) */ register_undef_hook(&debug_reg_hook); + register_undef_hook(&hw_breakpoint_hook); + /* * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. -- cgit v1.2.3 From 6f2ad0447776831e1bf7d730656b60730fa1966f Mon Sep 17 00:00:00 2001 From: Johan Rudholm Date: Thu, 27 Oct 2011 11:28:24 +0200 Subject: u8500/u5500: Increase number of MMC minor devices Increase the number of MMC minor devices from 8 to 32. This is because Android recovery mode needs access to additional partitions, and it is neat to keep MMC device partitions within major number 179 (otherwise any partition >8 would be assigned major number BLOCK_EXT_MAJOR, 259). 32 was chosen as the highest possible number when considering that the two eMMC devices contain two boot partitions each. ST-Ericsson ID: 356788 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iffc42c595f655fe6ddc874875ae2606366f964ef Signed-off-by: Johan Rudholm Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35465 Reviewed-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3529033d6b0..c987e6021b5 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -238,6 +238,7 @@ CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_CLKGATE=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_BLOCK_MINORS=32 CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y -- cgit v1.2.3 From 5dbb471d379ddc42618236654d3448e3b759bd3b Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Mon, 24 Oct 2011 15:53:36 +0530 Subject: power:ab5500-fg: send UEvent when battery voltage is low/high Send UEvent when battery voltage is low/high so that android power framework is being notified and actions are taken by android accordingly. This also ensure that the paltform is shutdown cleanly when battery voltage is below lower threshold. ST-Ericsson Linux next: NA ST-Ericsson ID: 365061 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I01e3579ba5860244cd5837c8eb59f71bd9b5d719 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35050 Reviewed-by: QABUILD Reviewed-by: Rajagopala VENKATARAVANAPPA X Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_fg.c | 67 +++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 62710680d1e..c29d08bad17 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -218,6 +218,9 @@ static enum power_supply_property ab5500_fg_props[] = { POWER_SUPPLY_PROP_CAPACITY_LEVEL, }; +/* Function Prototype */ +static int ab5500_fg_bat_v_trig(int mux); + struct ab5500_fg *ab5500_fg_get(void) { struct ab5500_fg *di; @@ -1319,9 +1322,11 @@ static void ab5500_fg_low_bat_work(struct work_struct *work) */ queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, round_jiffies(LOW_BAT_CHECK_INTERVAL)); + power_supply_changed(&di->fg_psy); } else { di->flags.low_bat = false; dev_warn(di->dev, "Battery voltage OK again\n"); + power_supply_changed(&di->fg_psy); } /* This is needed to dispatch LOW_BAT */ @@ -1541,33 +1546,6 @@ static int ab5500_fg_get_ext_psy_data(struct device *dev, void *data) return 0; } -static int ab5500_fg_bat_v_trig(int mux) -{ - struct ab5500_fg *di = ab5500_fg_get(); - - /* check if the battery voltage is below low threshold */ - if (di->vbat < 2700) { - dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); - di->flags.low_bat_delay = true; - /* - * Start a timer to check LOW_BAT again after some time - * This is done to avoid shutdown on single voltage dips - */ - queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, - round_jiffies(LOW_BAT_CHECK_INTERVAL)); - } - /* check if battery votlage is above OVV */ - else if (di->vbat > 4200) { - dev_dbg(di->dev, "Battery OVV\n"); - di->flags.bat_ovv = true; - - power_supply_changed(&di->fg_psy); - } else - return -EINVAL; - - return 0; -} - /** * ab5500_fg_init_hw_registers() - Set up FG related registers * @di: pointer to the ab5500_fg structure @@ -1587,8 +1565,8 @@ static int ab5500_fg_init_hw_registers(struct ab5500_fg *di) auto_ip->mux = MAIN_BAT_V; auto_ip->freq = MS500; - auto_ip->min = 2700; - auto_ip->max = 4200; + auto_ip->min = 3560; + auto_ip->max = 4500; auto_ip->auto_adc_callback = ab5500_fg_bat_v_trig; di->gpadc_auto = auto_ip; ret = ab5500_gpadc_convert_auto(di->gpadc, di->gpadc_auto); @@ -1601,6 +1579,37 @@ static int ab5500_fg_init_hw_registers(struct ab5500_fg *di) return ret; } +static int ab5500_fg_bat_v_trig(int mux) +{ + struct ab5500_fg *di = ab5500_fg_get(); + + di->vbat = ab5500_gpadc_convert(di->gpadc, MAIN_BAT_V); + + /* check if the battery voltage is below low threshold */ + if (di->vbat < 3560) { + dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); + di->flags.low_bat_delay = true; + /* + * Start a timer to check LOW_BAT again after some time + * This is done to avoid shutdown on single voltage dips + */ + queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, + round_jiffies(LOW_BAT_CHECK_INTERVAL)); + power_supply_changed(&di->fg_psy); + } + /* check if battery votlage is above OVV */ + else if (di->vbat > 4500) { + dev_warn(di->dev, "Battery OVV\n"); + di->flags.bat_ovv = true; + + power_supply_changed(&di->fg_psy); + } else + return -EINVAL; + kfree(di->gpadc_auto); + ab5500_fg_init_hw_registers(di); + return 0; +} + /** * ab5500_fg_external_power_changed() - callback for power supply changes * @psy: pointer to the structure power_supply -- cgit v1.2.3 From 434f46b4d5013cf21ea054241795ce88147fa25e Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Wed, 2 Nov 2011 14:36:40 +0530 Subject: power:ab5500-charger: improper updation of usb charging current In battery driver during boot i.e in probe, a check is made to ensure enable charging if USB cable is inserted during boot. In this case, battery driver checks for the type of USB cable and starts charging. It is noticed that later after some time, USB line status interrupt is triggered and the previous negiotiated usb charging current obtained by the USB driver is overwritten. In case of standard host, negiotiated chargign current obtained by the usb driver will be 500mA and it will be later over written when line status interrupt is triggered to a value of 100mA. ST-Ericsson Linux next: NA ST-Ericsson ID: 362951 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I54799fb21f61ad05d046c4e0b12a698d5a7c1083 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36050 Reviewed-by: QABUILD Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_charger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/ab5500_charger.c b/drivers/power/ab5500_charger.c index f57e2088a4a..b90c51a4f31 100644 --- a/drivers/power/ab5500_charger.c +++ b/drivers/power/ab5500_charger.c @@ -1309,7 +1309,8 @@ static irqreturn_t ab5500_charger_usblinkstatus_handler(int irq, void *_di) dev_dbg(di->dev, "USB link status changed\n"); - queue_work(di->charger_wq, &di->usb_link_status_work); + if (!di->usb.charger_online) + queue_work(di->charger_wq, &di->usb_link_status_work); return IRQ_HANDLED; } -- cgit v1.2.3 From 134ab877c24ef4c492d918d61c6303b5b2c6139e Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 3 Nov 2011 13:19:37 +0100 Subject: ARM: configs: u8500|snowball|u9500: Disable MMC_CLKGATE This change will have positive effect on throughput. The corresponding clock is controlled by the mmci host driver by using PM runtime instead. Change-Id: I53349b9b2b393c46f6040133a200f17255452036 Signed-off-by: Ulf Hansson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36219 --- arch/arm/configs/u8500_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c987e6021b5..32c601161b9 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -235,7 +235,6 @@ CONFIG_USB_G_HID=m CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y -CONFIG_MMC_CLKGATE=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_MMC_BLOCK_MINORS=32 -- cgit v1.2.3 From 26d4956795ec8b93f715f930817e536df69eac73 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Tue, 13 Sep 2011 18:31:12 +0200 Subject: mfd:ab8500-core: Possible to disable battery management This patch makes it possible to disable battery management via a module boot parameter. When 'ab8500-core.no_bm=1' then ab8500_btemp, ab8500_chargalg, ab8500_charger and ab8500_fg will not be probed. ST-Ericsson ID: 336205 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: Iec69e3353024dfab738301335915d5d798948b93 Signed-off-by: Rickard Andersson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36353 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- drivers/mfd/ab8500-core.c | 55 +++++++++++++++++++++++++++--------------- drivers/power/ab8500_charger.c | 3 +++ 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 63c52edf5cc..204b5576e18 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -100,6 +100,9 @@ #define AB9540_MODEM_CTRL2_REG 0x23 #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) +static bool no_bm; /* No battery management */ +module_param(no_bm, bool, S_IRUGO); + /* * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt * numbers are indexed into this array with (num / 8). The interupts are @@ -780,26 +783,6 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { .num_resources = ARRAY_SIZE(ab8500_rtc_resources), .resources = ab8500_rtc_resources, }, - { - .name = "ab8500-charger", - .num_resources = ARRAY_SIZE(ab8500_charger_resources), - .resources = ab8500_charger_resources, - }, - { - .name = "ab8500-btemp", - .num_resources = ARRAY_SIZE(ab8500_btemp_resources), - .resources = ab8500_btemp_resources, - }, - { - .name = "ab8500-fg", - .num_resources = ARRAY_SIZE(ab8500_fg_resources), - .resources = ab8500_fg_resources, - }, - { - .name = "ab8500-chargalg", - .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), - .resources = ab8500_chargalg_resources, - }, { .name = "ab8500-acc-det", .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), @@ -863,6 +846,29 @@ static struct mfd_cell __devinitdata ab9540_devs[] = { }, }; +static struct mfd_cell __devinitdata ab8500_bm_devs[] = { + { + .name = "ab8500-charger", + .num_resources = ARRAY_SIZE(ab8500_charger_resources), + .resources = ab8500_charger_resources, + }, + { + .name = "ab8500-btemp", + .num_resources = ARRAY_SIZE(ab8500_btemp_resources), + .resources = ab8500_btemp_resources, + }, + { + .name = "ab8500-fg", + .num_resources = ARRAY_SIZE(ab8500_fg_resources), + .resources = ab8500_fg_resources, + }, + { + .name = "ab8500-chargalg", + .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), + .resources = ab8500_chargalg_resources, + }, +}; + static ssize_t show_chip_id(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1133,6 +1139,15 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) if (ret) goto out_freeirq; + if (!no_bm) { + /* Add battery management devices */ + ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, + ARRAY_SIZE(ab8500_bm_devs), NULL, + ab8500->irq_base); + if (ret) + dev_err(ab8500->dev, "error adding bm devices\n"); + } + if (is_ab9540(ab8500)) ret = sysfs_create_group(&ab8500->dev->kobj, &ab9540_attr_group); diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index e2b4accbec8..c355738a31a 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -2421,6 +2421,9 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, else /* Should never occur */ bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; + if (di == NULL) + return; + dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", __func__, bm_usb_state, mA); -- cgit v1.2.3 From f0670e8298bb48256c8019015819c320ae8b2337 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 27 Oct 2011 07:51:35 +0200 Subject: tty: serial: amba-pl011: Release clocks and regulators after probe These will be enabled once in use. ST-Ericsson Linux next: - ST-Ericsson ID: 367599 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1cfe9b00262d78a3326ca01af85268e918170735 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35397 Reviewed-by: QABUILD --- drivers/tty/serial/amba-pl011.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 1d4d38918cd..98da861fc8a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2301,6 +2301,13 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) kfree(uap); } out: + /* + * Disable the silicon block pclk and any voltage domain and just + * power it up and clock it when it's needed + */ + amba_pclk_disable(dev); + amba_vcore_disable(dev); + return ret; } -- cgit v1.2.3 From 39739d5a9f2a68ce4d03b8fed833ecada7378318 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Tue, 8 Nov 2011 09:03:07 +0530 Subject: hwmon: Update sensor attribute index Update internal die temperature sensor attribute index to enable sensor monitoring. ST-Ericsson Linux next: NA ST-Ericsson ID: 339643 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Id8148bb4ebf97b4df432d873871fb1d2fed9afa1 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36759 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/hwmon/abx500.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index de4e6280b4b..7aa9994c54a 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -506,14 +506,14 @@ static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO, /* GPADC - SENSOR5 */ static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5); static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5); -static SENSOR_DEVICE_ATTR(temp5_min, S_IWUSR | S_IRUGO, show_min, set_min, 4); -static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_max, set_max, 4); +static SENSOR_DEVICE_ATTR(temp5_min, S_IWUSR | S_IRUGO, show_min, set_min, 5); +static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_max, set_max, 5); static SENSOR_DEVICE_ATTR(temp5_max_hyst, S_IWUSR | S_IRUGO, - show_max_hyst, set_max_hyst, 4); -static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_min_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_max_alarm, NULL, 4); + show_max_hyst, set_max_hyst, 5); +static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_min_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_max_alarm, NULL, 5); static SENSOR_DEVICE_ATTR(temp5_max_hyst_alarm, S_IRUGO, - show_max_hyst_alarm, NULL, 4); + show_max_hyst_alarm, NULL, 5); static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_crit_alarm, NULL, 5); -- cgit v1.2.3 From aba6325fdb9676f741edc1bebe16100a97c83322 Mon Sep 17 00:00:00 2001 From: pender01 Date: Fri, 28 Oct 2011 16:15:56 +0200 Subject: power: ab8500_bm: Configuration of battok levels Added board config parameters for battok levels and applying them in startup. ST-Ericsson Linux next: NA ST-Ericsson ID: 358904 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic377b86e12d4e8c6b2199a2f4c82b62643ad7ece Signed-off-by: pender01 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35821 Reviewed-by: QATOOLS Reviewed-by: Johan BJORNSTEDT Reviewed-by: QABUILD --- arch/arm/mach-ux500/board-mop500-bm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 91fb887d4f5..e78586ed009 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -372,6 +372,8 @@ static const struct ab8500_fg_parameters fg = { .accu_high_curr = 30, .high_curr_threshold = 50, .lowbat_threshold = 3100, + .battok_falling_th_sel0 = 2860, + .battok_raising_th_sel1 = 2860, }; static const struct ab8500_maxim_parameters maxi_params = { -- cgit v1.2.3 From 056e6e09ac185ed00a3fa08764af0efb18c97f1d Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 12 Jan 2012 11:49:51 +0100 Subject: bm: ux500: Coding style fixes Fix the most obvious violations of the kernel coding style Signed-off-by: Jonas Aaberg --- arch/arm/mach-ux500/board-u5500-bm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index 7cfc6386b35..cbd03a31c6a 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -20,8 +20,8 @@ /* * These are the defined batteries that uses a NTC and ID resistor placed * inside of the battery pack. - * Note that the abx500_res_to_temp table must be strictly sorted by falling resistance - * values to work. + * Note that the abx500_res_to_temp table must be strictly sorted by falling + * resistance values to work. */ static struct abx500_res_to_temp temp_tbl_type1[] = { {-20, 67400}, -- cgit v1.2.3 From 1fa4ffa3bd74c841979a4f05cf6dd9a64e9769e7 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Thu, 3 Nov 2011 16:01:37 +0530 Subject: ab5500: enable GPADC-0 and provide sysfs interfce This patch enables GPADC-0 to convert from voltage range 0 to 1.8v and also adds sysfs interface for reading gpadc ch-0. "/sys/devices/platform/ab5500-core.0/ab5500-adc.0/adc0volt" ST-Ericsson ID: 370066 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic23caa22ff4e10d3dbb151e10eb4625ec5d7078a Signed-off-by: Shreshtha Kumar Sahu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36216 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Linus WALLEIJ --- .../testing/sysfs-devices-platform-ab5500-core-adc | 20 +++++++++++ drivers/mfd/ab5500-gpadc.c | 41 ++++++++++++++++++++++ include/linux/mfd/abx500/ab5500-gpadc.h | 1 + 3 files changed, 62 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc diff --git a/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc b/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc new file mode 100644 index 00000000000..fcfc0ed26fb --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc @@ -0,0 +1,20 @@ +What: /sys/devices/platform/ab5500-core.0/ab5500-adc.0/adc0volt +Date: Nov 2011 +KernelVersion: 3.0 +Contact: Shreshtha Kumar SAHU +Description: The adc0volt attribute allows the userspace to read the + voltage of the device connected to the General Purpose + Analog to Digital Converter (GPADC) channel-0. Voltage + conversion from analog to digital happens only when this + attribute is read. GPADC block is present in AB5500 chip + and has input voltage range of 0-1.8 volt for GPADC Ch-0. + It provides result of the converted voltage in 10 bits. + Other GPADC channels attributes may appear in this path + later. For minimum and maximum input voltage range for + each channel please refer to the ST-Ericssons AB5500 + datasheet. An example usage of GPADC can be an ALS device + connected to the channel and user space adapts the + LCD backlight brightness based on ambient light value + read from the attribute. +Users: HAL. + diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index 6756d3cf37a..51d1fa9049a 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -67,6 +67,7 @@ #define GPADC_MANUAL_ADOUT1_MASK 0xC0 #define GPADC_MANUAL_ADOUT0_ON 0x10 #define GPADC_MANUAL_ADOUT1_ON 0x40 +#define MUX_SCALE_GPADC0_MASK 0x08 #define MUX_SCALE_VBAT_MASK 0x02 #define MUX_SCALE_45 0x02 #define MUX_SCALE_BDATA_MASK 0x01 @@ -74,6 +75,8 @@ #define MUX_SCALE_BDATA18 0x01 #define MUX_SCALE_ACCDET2_MASK 0x01 #define MUX_SCALE_ACCDET3_MASK 0x02 +#define GPADC0_SCALE_VOL27 0x00 +#define GPADC0_SCALE_VOL18 0x01 #define ACCDET2_SCALE_VOL27 0x00 #define ACCDET3_SCALE_VOL27 0x00 #define TRIGX_FREQ_MASK 0x07 @@ -98,6 +101,8 @@ #define CTRL_INDEX 0x01 /* GPADC constants from AB5500 spec */ +#define GPADC0_MIN 0 +#define GPADC0_MAX 1800 #define BTEMP_MIN 0 #define BTEMP_MAX 1800 #define BDATA_MIN 0 @@ -229,6 +234,7 @@ struct adc_data { } struct adc_data adc_tab[] = { + ADC_DATA(GPADC0_V, 0x00, GPADC0_MIN, GPADC0_MAX, 0), ADC_DATA(BTEMP_BALL, 0x0D, BTEMP_MIN, BTEMP_MAX, ADOUT0), ADC_DATA(BAT_CTRL, 0x0D, BDATA_MIN, BDATA_MAX, 0), ADC_DATA(MAIN_BAT_V, 0x0C, VBAT_MIN, VBAT_MAX, 0), @@ -270,6 +276,7 @@ static int ab5500_gpadc_ad_to_voltage(struct ab5500_gpadc *gpadc, int res; switch (in) { + case GPADC0_V: case PCB_TEMP: case BTEMP_BALL: case MAIN_BAT_V: @@ -367,6 +374,15 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) goto out; } break; + case GPADC0_V: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_GPADC0_MASK, GPADC0_SCALE_VOL18); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set gpadc0\n"); + goto out; + } + break; case ACC_DETECT2: ret = abx500_mask_and_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL2, @@ -775,6 +791,19 @@ out: } EXPORT_SYMBOL(ab5500_gpadc_convert_auto); +/* sysfs interface for GPADC0 */ +static ssize_t ab5500_gpadc0_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int voltage; + struct ab5500_gpadc *gpadc = dev_get_drvdata(dev); + + voltage = ab5500_gpadc_convert(gpadc, GPADC0_V); + + return sprintf(buf, "%d\n", voltage); +} +static DEVICE_ATTR(adc0volt, 0644, ab5500_gpadc0_get, NULL); + static void ab5500_gpadc_trigx_work(struct ab5500_gpadc *gp, int trig) { unsigned long flags; @@ -1114,9 +1143,19 @@ static int __devinit ab5500_gpadc_probe(struct platform_device *pdev) dev_err(gpadc->dev, "gpadc: configuration failed\n"); goto free_wq; } + + ret = device_create_file(gpadc->dev, &dev_attr_adc0volt); + if (ret < 0) { + dev_err(gpadc->dev, "File device creation failed: %d\n", ret); + ret = -ENODEV; + goto fail_sysfs; + } list_add_tail(&gpadc->node, &ab5500_gpadc_list); + platform_set_drvdata(pdev, gpadc); + return 0; +fail_sysfs: free_wq: destroy_workqueue(gpadc->gpadc_wq); fail_irq: @@ -1134,6 +1173,8 @@ static int __devexit ab5500_gpadc_remove(struct platform_device *pdev) int i, irq; struct ab5500_gpadc *gpadc = platform_get_drvdata(pdev); + device_remove_file(gpadc->dev, &dev_attr_adc0volt); + /* remove this gpadc entry from the list */ list_del(&gpadc->node); /* Disable interrupts */ diff --git a/include/linux/mfd/abx500/ab5500-gpadc.h b/include/linux/mfd/abx500/ab5500-gpadc.h index 3282b44114e..67dc3cc9034 100644 --- a/include/linux/mfd/abx500/ab5500-gpadc.h +++ b/include/linux/mfd/abx500/ab5500-gpadc.h @@ -33,6 +33,7 @@ #define MAIN_BAT_V_TXON_TRIG_MIN 13 /* VBAT with TX off only min trigger */ #define MAIN_BAT_V_TRIG_MIN 14 +#define GPADC0_V 15 /* * Frequency of auto adc conversion -- cgit v1.2.3 From 886b10019c98b81720052babff9080a66caba721 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 10 Nov 2011 17:50:52 +0530 Subject: u5500:gpadc: Fix ab5500 internal temp conversion formula Fix AB5500 internal die temperature conversion formula and provide 8bit min/max lavel to auto trigger. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I6bb2d0afb657582709f95f1f88466e6c061c1117 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37296 Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Arun MURTHY --- drivers/mfd/ab5500-gpadc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index 51d1fa9049a..d099f1b9d73 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -295,10 +295,10 @@ static int ab5500_gpadc_ad_to_voltage(struct ab5500_gpadc *gpadc, /* * From the AB5500 product specification * T(deg cel) = 27 - ((ADCode - 709)/2.4213) - * 27 + 709/2.4213 - ADCode/2.4123 - * (320 - ADCode)/2.4213 + * 27 + 709/2.4213 - ADCode/2.4213 + * 320 - (ADCode/2.4213) */ - res = 320 - (((unsigned long)ad_val * 1000000) / 242130) / 10; + res = 320 - (((unsigned long)ad_val * 10000) / 24213); break; default: dev_err(gpadc->dev, @@ -747,13 +747,16 @@ int ab5500_gpadc_convert_auto(struct ab5500_gpadc *gpadc, case DIE_TEMP: /* * From the AB5500 product specification - * T(deg_cel) = 27 -(ADCode - 709)/2.4123) - * adc min and max values are based on the above formula. + * T(deg_cel) = 27 - (ADCode - 709)/2.4213) + * ADCode = 709 + (2.4213 * (27 - T)) + * Auto trigger min/max level is of 8bit precision. + * Hence use AB5500_GPADC_MANDATAH_REG value + * obtained by 2 bit right shift of ADCode. */ gpadc->adc_trig[trig].trig_min = - 709 - (22413 * (in->min - 27))/10000; + (709 + ((24213 * (27 - in->min))/10000))>>2; gpadc->adc_trig[trig].trig_max = - 709 - (22413 * (in->max - 27))/10000; + (709 + ((24213 * (27 - in->max))/10000))>>2; gpadc->adc_trig[trig].adout = adc_tab[in->mux].adout; break; -- cgit v1.2.3 From b341172c469db547de725da483a86df54659436d Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 10 Nov 2011 17:57:52 +0530 Subject: u5500:hwmon: Fix ab5500 die temp auto trigger GPADC voltage decreases as temperature increases. So pass min and max values accordingly to monitor ab5500 internal die temperature. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9743bcbeb3f27baaba9b49867b656135c2d2d70e Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37297 Reviewed-by: QABUILD Reviewed-by: QATOOLS Reviewed-by: Srinidhi KASAGAR Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Arun MURTHY --- drivers/hwmon/ab5500.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/ab5500.c b/drivers/hwmon/ab5500.c index 0122f315ac6..cafadeba51c 100644 --- a/drivers/hwmon/ab5500.c +++ b/drivers/hwmon/ab5500.c @@ -128,8 +128,13 @@ static int ab5500_temp_shutdown_auto(struct abx500_temp *data) auto_ip->mux = DIE_TEMP; auto_ip->freq = MS500; - auto_ip->min = SHUTDOWN_AUTO_MIN_LIMIT; - auto_ip->max = SHUTDOWN_AUTO_MAX_LIMIT; + /* + * As per product specification, voltage decreases as + * temperature increases. Hence the min and max values + * should be passed in reverse order. + */ + auto_ip->min = SHUTDOWN_AUTO_MAX_LIMIT; + auto_ip->max = SHUTDOWN_AUTO_MIN_LIMIT; auto_ip->auto_adc_callback = temp_shutdown_trig; data->gpadc_auto = auto_ip; ret = ab5500_gpadc_convert_auto(data->ab5500_gpadc, -- cgit v1.2.3 From fecc63f228ed0d11d6f4e3f2bec3d789fe5c4900 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Fri, 11 Nov 2011 07:52:10 +0100 Subject: mfd: ab8500: sysctrl: export read/write symbols Export ab8500_sysctrl_read and write symobols. They will be used by LTP test cases. ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Id4b8950b75f4345c67669fab8a5ee850340065b3 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37390 Reviewed-by: QABUILD Reviewed-by: Bengt JONSSON --- drivers/mfd/ab8500-sysctrl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index e6befdc9e08..d5865d41514 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -135,6 +135,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value) return abx500_get_register_interruptible(sysctrl_dev, bank, (u8)(reg & 0xFF), value); } +EXPORT_SYMBOL(ab8500_sysctrl_read); int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) { @@ -150,6 +151,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank, (u8)(reg & 0xFF), mask, value); } +EXPORT_SYMBOL(ab8500_sysctrl_write); static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev) { -- cgit v1.2.3 From ec0eb4b5a300afef03b256b78a5c2833db346dac Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 9 Nov 2011 11:00:51 +0100 Subject: drivers: serial: amba-pl011: Introduce runtime pm ST-Ericsson Linux next: - ST-Ericsson ID: 373766 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie2a7719ca602abf3fbb3e4cef05adc4f7ab07035 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37021 Reviewed-by: QABUILD Reviewed-by: Ulf HANSSON --- drivers/tty/serial/amba-pl011.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 98da861fc8a..07d7081344e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -1231,6 +1232,7 @@ static void pl011_clock_off(struct work_struct *work) struct circ_buf *xmit = &port->state->xmit; unsigned long flags; bool disable_regulator = false; + bool runtime_put = false; unsigned int busy, interrupt_status; spin_lock_irqsave(&port->lock, flags); @@ -1244,6 +1246,7 @@ static void pl011_clock_off(struct work_struct *work) pl011_backup(uap, true); disable_regulator = true; } + runtime_put = true; uap->clk_state = PL011_CLK_OFF; clk_disable(uap->clk); } else @@ -1255,6 +1258,8 @@ static void pl011_clock_off(struct work_struct *work) if (disable_regulator) regulator_disable(uap->regulator); + if (runtime_put) + pm_runtime_put_sync(uap->port.dev); } /* Request to turn off uart clock once pending TX is flushed */ @@ -1285,6 +1290,7 @@ static void pl011_clock_on(struct uart_port *port) switch (uap->clk_state) { case PL011_CLK_OFF: + pm_runtime_get_sync(uap->port.dev); clk_enable(uap->clk); if (!uart_console(&uap->port) && uap->regulator) { spin_unlock_irqrestore(&port->lock, flags); @@ -1319,13 +1325,16 @@ static int pl011_power_startup(struct uart_amba_port *uap) int retval = 0; if (uap->clk_state == PL011_PORT_OFF) { + pm_runtime_get_sync(uap->port.dev); if (!uart_console(&uap->port) && uap->regulator) regulator_enable(uap->regulator); retval = clk_enable(uap->clk); - if (!retval) + if (!retval) { uap->clk_state = PL011_CLK_ON; - else + } else { uap->clk_state = PL011_PORT_OFF; + pm_runtime_put_sync(uap->port.dev); + } } return retval; @@ -1334,6 +1343,7 @@ static int pl011_power_startup(struct uart_amba_port *uap) static void pl011_power_shutdown(struct uart_amba_port *uap) { bool disable_regulator = false; + bool runtime_put = false; cancel_delayed_work_sync(&uap->clk_off_work); @@ -1341,6 +1351,7 @@ static void pl011_power_shutdown(struct uart_amba_port *uap) if (uap->clk_state == PL011_CLK_ON || uap->clk_state == PL011_CLK_REQUEST_OFF) { clk_disable(uap->clk); + runtime_put = true; if (!uart_console(&uap->port) && uap->regulator) disable_regulator = true; } @@ -1349,6 +1360,8 @@ static void pl011_power_shutdown(struct uart_amba_port *uap) if (disable_regulator) regulator_disable(uap->regulator); + if (runtime_put) + pm_runtime_put_sync(uap->port.dev); } static void @@ -1378,12 +1391,14 @@ static inline void pl011_clock_check(struct uart_amba_port *uap) static inline int pl011_power_startup(struct uart_amba_port *uap) { + pm_runtime_get_sync(uap->port.dev); return clk_enable(uap->clk); } static inline void pl011_power_shutdown(struct uart_amba_port *uap) { clk_disable(uap->clk); + pm_runtime_put_sync(uap->port.dev); } static inline void @@ -2288,6 +2303,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) pl011_clock_control_init(uap); ret = uart_add_one_port(&amba_reg, &uap->port); + + if (!ret) + pm_runtime_put(&dev->dev); + if (ret) { amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; @@ -2301,12 +2320,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) kfree(uap); } out: - /* - * Disable the silicon block pclk and any voltage domain and just - * power it up and clock it when it's needed - */ - amba_pclk_disable(dev); - amba_vcore_disable(dev); return ret; } @@ -2318,6 +2331,8 @@ static int pl011_remove(struct amba_device *dev) amba_set_drvdata(dev, NULL); + pm_runtime_get_sync(uap->port.dev); + uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) -- cgit v1.2.3 From 56df9125dba0d979cf7e692b5b5f193823ec2b97 Mon Sep 17 00:00:00 2001 From: Johan Bjornstedt Date: Mon, 14 Nov 2011 09:26:13 +0100 Subject: power: ab8500_bm: Use FG resistance value in calculation The fuel gauge resistor value was only used for the instant current calculation. This patch will use this value in the average calculation. The unit for the FG resistance is now in 0.1mOhm to increase precision ST-Ericsson ID: 370883 ST-Ericsson Linux next: Not tested ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I62af322addd8af7c049cfaccd449a0349faa7946 Signed-off-by: Johan Bjornstedt Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37524 Reviewed-by: Jonas ABERG Reviewed-by: Karl KOMIEROWSKI --- arch/arm/mach-ux500/board-mop500-bm.c | 2 +- arch/arm/mach-ux500/board-u5500-bm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index e78586ed009..085661e7491 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -409,7 +409,7 @@ struct ab8500_bm_data ab8500_bm_data = { #endif .chg_unknown_bat = false, .enable_overshoot = false, - .fg_res = 10, + .fg_res = 100, .cap_levels = &cap_levels, .bat_type = bat_type, .n_btypes = ARRAY_SIZE(bat_type), diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index cbd03a31c6a..fb181c2cb9a 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -472,7 +472,7 @@ struct abx500_bm_data ab5500_bm_data = { #endif .chg_unknown_bat = false, .enable_overshoot = false, - .fg_res = 20, + .fg_res = 200, .cap_levels = &cap_levels, .bat_type = bat_type, .n_btypes = ARRAY_SIZE(bat_type), -- cgit v1.2.3 From 728cd2fbcc97cadca14c2848364ded2438971aa2 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 10 Nov 2011 14:54:16 +0530 Subject: power:ab5500-fg: Move battery threshold to plat data Move battery low and over battery threshold to platform data. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I63127e9753a7ec946afc3261af4c1dad6523d7ad Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37269 Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-bm.c | 3 ++- drivers/power/ab5500_fg.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index fb181c2cb9a..1f54b0d1deb 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -437,7 +437,8 @@ static const struct abx500_fg_parameters fg = { .accu_charging = 30, .accu_high_curr = 30, .high_curr_threshold = 50, - .lowbat_threshold = 3100, + .lowbat_threshold = 3560, + .overbat_threshold = 4400, }; static const struct abx500_maxim_parameters maxi_params = { diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index c29d08bad17..ab481f53bc3 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -1565,8 +1565,8 @@ static int ab5500_fg_init_hw_registers(struct ab5500_fg *di) auto_ip->mux = MAIN_BAT_V; auto_ip->freq = MS500; - auto_ip->min = 3560; - auto_ip->max = 4500; + auto_ip->min = di->bat->fg_params->lowbat_threshold; + auto_ip->max = di->bat->fg_params->overbat_threshold; auto_ip->auto_adc_callback = ab5500_fg_bat_v_trig; di->gpadc_auto = auto_ip; ret = ab5500_gpadc_convert_auto(di->gpadc, di->gpadc_auto); @@ -1586,7 +1586,7 @@ static int ab5500_fg_bat_v_trig(int mux) di->vbat = ab5500_gpadc_convert(di->gpadc, MAIN_BAT_V); /* check if the battery voltage is below low threshold */ - if (di->vbat < 3560) { + if (di->vbat < di->bat->fg_params->lowbat_threshold) { dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); di->flags.low_bat_delay = true; /* @@ -1598,7 +1598,7 @@ static int ab5500_fg_bat_v_trig(int mux) power_supply_changed(&di->fg_psy); } /* check if battery votlage is above OVV */ - else if (di->vbat > 4500) { + else if (di->vbat > di->bat->fg_params->overbat_threshold) { dev_warn(di->dev, "Battery OVV\n"); di->flags.bat_ovv = true; -- cgit v1.2.3 From d6c1a5592d8ebfb7eb25293c5e60818e8b5c4a56 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Thu, 10 Nov 2011 15:03:47 +0530 Subject: power:ab5500-fg: Fix gpadc auto trigger Re-register gpadc auto trigger for battery voltage monitoring in gpadc auto trigger callback. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ida9811bbd710000749484e2d1e409fd76c540042 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37270 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_fg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index ab481f53bc3..5e3a4f46cd0 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -1604,7 +1604,9 @@ static int ab5500_fg_bat_v_trig(int mux) power_supply_changed(&di->fg_psy); } else - return -EINVAL; + dev_err(di->dev, + "Invalid gpadc auto trigger for battery voltage\n"); + kfree(di->gpadc_auto); ab5500_fg_init_hw_registers(di); return 0; -- cgit v1.2.3 From dbeeede095da06655414a619175828303ed69b83 Mon Sep 17 00:00:00 2001 From: Avinash A Date: Thu, 10 Nov 2011 11:54:28 +0530 Subject: leds: Pull the HWEN gpio low when brightness is 0 When the brightness is zero the HWEN gpio line should be pulled low in order to achieve lowest power consumption on LM3530 ST-Ericsson ID: 373161 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5fc0ad22022a9fcfc66683c59a2df27359c90371 Signed-off-by: Avinash A Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37248 Reviewed-by: Avinash A Tested-by: Avinash A Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- drivers/leds/leds-lm3530.c | 23 +++++++++++++++++++++++ include/linux/led-lm3530.h | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 968fd5fef4f..6f1314df926 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -19,6 +19,7 @@ #include #include #include +#include #define LM3530_LED_DEV "lcd-backlight" #define LM3530_NAME "lm3530-led" @@ -101,6 +102,7 @@ static struct lm3530_mode_map mode_map[] = { * @mode: mode of operation - manual, ALS, PWM * @regulator: regulator * @brighness: previous brightness value + * @hw_en_gpio: GPIO line for LM3530 HWEN * @enable: regulator is enabled */ struct lm3530_data { @@ -110,6 +112,7 @@ struct lm3530_data { enum lm3530_mode mode; struct regulator *regulator; enum led_brightness brightness; + int hw_en_gpio; bool enable; }; @@ -230,6 +233,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) reg_val[13] = LM3530_DEF_ZT_4; /* LM3530_ALS_Z4T_REG */ if (!drvdata->enable) { + if (drvdata->hw_en_gpio != LM3530_NO_HWEN_GPIO) + gpio_set_value(drvdata->hw_en_gpio, 1); ret = regulator_enable(drvdata->regulator); if (ret) { dev_err(&drvdata->client->dev, @@ -294,6 +299,8 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev, if (err) dev_err(&drvdata->client->dev, "Disable regulator failed\n"); + if (drvdata->hw_en_gpio != LM3530_NO_HWEN_GPIO) + gpio_set_value(drvdata->hw_en_gpio, 0); drvdata->enable = false; } break; @@ -397,6 +404,7 @@ static int __devinit lm3530_probe(struct i2c_client *client, drvdata->client = client; drvdata->pdata = pdata; drvdata->brightness = LED_OFF; + drvdata->hw_en_gpio = pdata->hw_en_gpio; drvdata->enable = false; drvdata->led_dev.name = LM3530_LED_DEV; drvdata->led_dev.brightness_set = lm3530_brightness_set; @@ -404,6 +412,15 @@ static int __devinit lm3530_probe(struct i2c_client *client, i2c_set_clientdata(client, drvdata); + if (gpio_is_valid(drvdata->hw_en_gpio)) { + err = gpio_request_one(drvdata->hw_en_gpio, GPIOF_OUT_INIT_HIGH, + "lm3530_hw_en"); + if (err < 0) { + dev_err(&client->dev, "lm3530 hw_en gpio failed: %d\n", err); + goto err_gpio_request; + } + } + drvdata->regulator = regulator_get(&client->dev, "vin"); if (IS_ERR(drvdata->regulator)) { dev_err(&client->dev, "regulator get failed\n"); @@ -443,6 +460,10 @@ err_class_register: err_reg_init: regulator_put(drvdata->regulator); err_regulator_get: + if (gpio_is_valid(drvdata->hw_en_gpio)) + gpio_free(drvdata->hw_en_gpio); +err_gpio_request: + i2c_set_clientdata(client, NULL); kfree(drvdata); err_out: return err; @@ -457,6 +478,8 @@ static int __devexit lm3530_remove(struct i2c_client *client) if (drvdata->enable) regulator_disable(drvdata->regulator); regulator_put(drvdata->regulator); + if (gpio_is_valid(drvdata->hw_en_gpio)) + gpio_free(drvdata->hw_en_gpio); led_classdev_unregister(&drvdata->led_dev); kfree(drvdata); return 0; diff --git a/include/linux/led-lm3530.h b/include/linux/led-lm3530.h index eeae6e74247..7b5ae415d10 100644 --- a/include/linux/led-lm3530.h +++ b/include/linux/led-lm3530.h @@ -58,6 +58,12 @@ #define LM3530_ALS_IMPD_700Ohm (0x0E) #define LM3530_ALS_IMPD_667Ohm (0x0F) +/* + * If lm3530 does not use a gpio for HWEN, set LM3530_NO_HWEN_GPIO + * for hw_en_gpio in lm3530_platform data member + */ +#define LM3530_NO_HWEN_GPIO -1 + enum lm3530_mode { LM3530_BL_MODE_MANUAL = 0, /* "man" */ LM3530_BL_MODE_ALS, /* "als" */ @@ -94,6 +100,7 @@ struct lm3530_pwm_data { * @als_vmax: als input voltage calibrated for min brightness in mV * @brt_val: brightness value (0-255) * @pwm_data: PWM control functions (only valid when the mode is PWM) + * @hw_en_gpio: GPIO line for LM3530 HWEN */ struct lm3530_platform_data { enum lm3530_mode mode; @@ -116,6 +123,8 @@ struct lm3530_platform_data { u8 brt_val; struct lm3530_pwm_data pwm_data; + + int hw_en_gpio; }; #endif /* _LINUX_LED_LM3530_H__ */ -- cgit v1.2.3 From c33b4a6e9b68f64c09519b5521815a4b5aa3b956 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Thu, 17 Nov 2011 17:28:12 +0530 Subject: ux500: pl011: remove hardcoding of uart instance amba-pl011 mechanism detects the hardware register deadlock situation, and triggers a workaround tasklet. Tasklet implementation should execute workaround for the instance of the uart on which deadlock is detected. This patch provides the uart line number on whcich the deadlock is detected to the tasklet. ST-Ericsson ID: 355971 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie8fbea42dc20cae1b604b555815935bcb5a70241 Signed-off-by: Shreshtha Kumar Sahu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/38415 Reviewed-by: Srinidhi KASAGAR --- drivers/tty/serial/amba-pl011.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 07d7081344e..0faee493eff 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -122,7 +122,9 @@ static const u32 uart_wa_reg[UART_WA_SAVE_NR] = { }; static u32 uart_wa_regdata[UART_WA_SAVE_NR]; -static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, 0); +static unsigned int uart_wa_tlet_line; +static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, + (unsigned long) &uart_wa_tlet_line); /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { @@ -1111,7 +1113,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) */ static void pl011_lockup_wa(unsigned long data) { - struct uart_amba_port *uap = amba_ports[0]; + struct uart_amba_port *uap = amba_ports[*(unsigned int *)data]; void __iomem *base = uap->port.membase; struct circ_buf *xmit = &uap->port.state->xmit; struct tty_struct *tty = uap->port.state->port.tty; @@ -1566,8 +1568,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id) pl011_tx_chars(uap); if (pass_counter-- == 0) { - if (uap->interrupt_may_hang) + if (uap->interrupt_may_hang) { + uart_wa_tlet_line = uap->port.line; tasklet_schedule(&pl011_lockup_tlet); + } break; } -- cgit v1.2.3 From d214bc2e37dbcbbab01672ac40f93d3e0c785d6b Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 21 Nov 2011 17:13:55 +0530 Subject: rtc: ab: only enable alarm in set_alarm if requested We should not enable the alarm if alarm->enabled is false. ST-Ericsson ID: 375473 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I8a73bc3752fbdbd19783a426a76213d35b48a870 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/39113 Reviewed-by: QATEST Reviewed-by: QABUILD --- drivers/rtc/rtc-ab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-ab.c b/drivers/rtc/rtc-ab.c index db1992632fa..393dd5a0e09 100644 --- a/drivers/rtc/rtc-ab.c +++ b/drivers/rtc/rtc-ab.c @@ -370,7 +370,7 @@ static int ab_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) return err; } - return ab_rtc_alarm_enable(dev, true); + return alarm->enabled ? ab_rtc_alarm_enable(dev, true) : 0; } static const struct rtc_class_ops ab_rtc_ops = { -- cgit v1.2.3 From 9ee4288c5075e878f00523287fe5b2abc017e5e1 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 28 Apr 2011 15:41:36 +0530 Subject: ARM: Set bit 22 in the PL310 (cache controller) AuxCtlr register Clearing bit 22 in the PL310 Auxiliary Control register (shared attribute override enable) has the side effect of transforming Normal Shared Non-cacheable reads into Cacheable no-allocate reads. Coherent DMA buffers in Linux always have a Cacheable alias via the kernel linear mapping and the processor can speculatively load cache lines into the PL310 controller. With bit 22 cleared, Non-cacheable reads would unexpectedly hit such cache lines leading to buffer corruption. This patch ensures that bit 22 is set in the l2x0_init() function if PL310 and not rely on the platform code to specify it. It also modifies the 'aux' variable only if the actual register is written so that the final printk displays the real hardware value. ST-Ericsson ID: 281924 ST-Ericsson Linux next: Already in patch tracker Change-Id: I9175c4ca935db4072d944202741e744f55927092 Signed-off-by: srinidhi kasagar Signed-off-by: Catalin Marinas Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21841 Reviewed-by: Vijaya Kumar K-1 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40015 Reviewed-by: Jonas ABERG --- arch/arm/mm/cache-l2x0.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 2a8e380501e..1768e4038fc 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -319,9 +319,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); - aux &= aux_mask; - aux |= aux_val; - /* Determine the number of ways */ switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: @@ -335,6 +332,13 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) sync_reg_offset = L2X0_DUMMY_REG; #endif outer_cache.set_debug = pl310_set_debug; + + /* + * Set bit 22 in the auxiliary control register. If this bit + * is cleared, PL310 treats Normal Shared Non-cacheable + * accesses as Cacheable no-allocate. + */ + aux_val |= 1 << 22; break; case L2X0_CACHE_ID_PART_L210: ways = (aux >> 13) & 0xf; @@ -362,6 +366,9 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) * accessing the below registers will fault. */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + aux &= aux_mask; + aux |= aux_val; + /* Make sure that I&D is not locked down when starting */ l2x0_unlock(cache_id); -- cgit v1.2.3 From 1011373c550f88639007f5209bf920a7b6311068 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 12 Jan 2012 16:37:18 +0100 Subject: config : misc : stm driver not functional configure stm mode to software to fix the broken driver Signed-off-by: Bibek Basu --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 32c601161b9..7ca5373bb33 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -117,6 +117,7 @@ CONFIG_STE_TRACE_MODEM=y CONFIG_DISPDEV=y CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y +CONFIG_STM_DEFAULT_MASTERS_MODES=0x20 CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_MD=y -- cgit v1.2.3 From 785d648f9b1734221b9db2c2a8e9b79bfe43117b Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 1 Dec 2011 12:43:48 +0530 Subject: power: ab5500-btemp: optimize the delay in battery identification In battery identification, a current source is to be enabled before reading the batctrl/bdata pin. After enabling the current some delay is required so as to be able to read the bdata/batctrl pin. ST-Ericsson Linux next: NA ST-Ericsson ID: 364300 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib090bd617fc8363ea63379c731189859553d7627 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40454 Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_btemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 111f0a8b107..08d5ae89dbe 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -262,7 +262,7 @@ static int ab5500_btemp_get_batctrl_res(struct ab5500_btemp *di) ret = ab5500_btemp_curr_source_enable(di, true); /* TODO: This delay has to be optimised */ - mdelay(1000); + msleep(100); if (ret) { dev_err(di->dev, "%s curr source enable failed\n", __func__); return ret; -- cgit v1.2.3 From 4dfe8cf9c9bca22538e82ea1012175ed081d088a Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 1 Dec 2011 12:01:10 +0530 Subject: mach-ux500: update the battery capacity ST-Ericsson Linux next: NA ST-Ericsson ID: 375503 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I89f912270ab7852aa03c944b6ec7794fdb2d03b0 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40449 Reviewed-by: Rabin VINCENT --- arch/arm/mach-ux500/board-u5500-bm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index 1f54b0d1deb..f7ca803da42 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -250,7 +250,7 @@ static const struct abx500_battery_type bat_type[] = { .resis_high = 70000, .resis_low = 8200, .battery_resistance = 300, - .charge_full_design = 900, + .charge_full_design = 1500, .nominal_voltage = 3600, .termination_vol = 4150, .termination_curr = 80, -- cgit v1.2.3 From 67f7b9c9b957753ea710eeb765800159a215d93f Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Thu, 1 Dec 2011 12:08:01 +0530 Subject: power: re-order in makefile Change the oder in which linking happens, the expected result is ab5500_charger should be probed first followed by ab5500_btemp and ab5500_fg. ST-Ericsson Linux next: NA ST-Ericsson ID: 375503 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I56456ea36f23d5c461c1913e942afa6cd8cdb757 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40450 Reviewed-by: Rabin VINCENT --- drivers/power/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5fcd08d9df4..af27f1d08aa 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o -obj-$(CONFIG_AB5500_BM) += ab5500_charger.o abx500_chargalg.o ab5500_fg.o ab5500_btemp.o +obj-$(CONFIG_AB5500_BM) += ab5500_charger.o ab5500_btemp.o ab5500_fg.o abx500_chargalg.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o -- cgit v1.2.3 From 296369d9b4c1d3b5682675ef7dc353819ae4eaac Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Wed, 30 Nov 2011 16:25:34 +0530 Subject: power: ab5500-fg: battery capacity based on fuel gauge On enabling reset_on_read in fuel gauge register with offset 0x0C, the accumulator should be reset after reading. But it doesnt due to the hardware issue reported in ER374581. This patch adds a software workaround for the above mentione issue. ST-Ericsson Linux next: NA ST-Ericsson ID: 375503 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I92e06e3429faa2b58318015c6d93647d67c31160 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40341 Reviewed-by: Rajagopala VENKATARAVANAPPA X Reviewed-by: QABUILD Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Rabin VINCENT --- drivers/power/ab5500_fg.c | 70 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 5e3a4f46cd0..0f1dc4a13df 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -37,11 +37,13 @@ static LIST_HEAD(ab5500_fg_list); #define FG_ACC_RESET_ON_READ 0x08 #define EN_READOUT_MASK 0x01 #define EN_READOUT 0x01 +#define EN_ACC_RESET_ON_READ 0x08 +#define ACC_RESET_ON_READ 0x08 #define RESET 0x00 #define EOC_52_mA 0x04 #define MILLI_TO_MICRO 1000 #define FG_LSB_IN_MA 770 -#define QLSB_NANO_AMP_HOURS_X10 1129 +#define QLSB_NANO_AMP_HOURS_X100 5353 #define SEC_TO_SAMPLE(S) (S * 4) #define NBR_AVG_SAMPLES 20 #define LOW_BAT_CHECK_INTERVAL (2 * HZ) @@ -444,6 +446,7 @@ static void ab5500_fg_acc_cur_timer_expired(unsigned long data) queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); } +static int prev_samples, prev_val; /** * ab5500_fg_acc_cur_work() - average battery current * @work: pointer to the work_struct structure @@ -453,7 +456,7 @@ static void ab5500_fg_acc_cur_timer_expired(unsigned long data) */ static void ab5500_fg_acc_cur_work(struct work_struct *work) { - int val; + int val, raw_val, sample; int ret; u8 low, med, high, cnt_low, cnt_high; @@ -473,6 +476,11 @@ static void ab5500_fg_acc_cur_work(struct work_struct *work) goto exit; /* If charging read charging registers for accumulated values */ if (di->flags.charging) { + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + ACC_RESET_ON_READ, EN_ACC_RESET_ON_READ); + if (ret < 0) + goto exit; /* Read CC Sample conversion value Low and high */ ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_FG_BATTCOM_ACC, @@ -500,9 +508,19 @@ static void ab5500_fg_acc_cur_work(struct work_struct *work) AB5500_FG_VAL_COUNT1, &cnt_high); if (ret < 0) goto exit; + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + ACC_RESET_ON_READ, RESET); + if (ret < 0) + goto exit; queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, di->bat->interval_charging * HZ); } else { /* discharging */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + ACC_RESET_ON_READ, EN_ACC_RESET_ON_READ); + if (ret < 0) + goto exit; /* Read CC Sample conversion value Low and high */ ret = abx500_get_register_interruptible(di->dev, AB5500_BANK_FG_BATTCOM_ACC, @@ -530,19 +548,48 @@ static void ab5500_fg_acc_cur_work(struct work_struct *work) AB5500_FG_VAL_COUNT1, &cnt_high); if (ret < 0) goto exit; + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_FG_CONTROL_A, + ACC_RESET_ON_READ, RESET); + if (ret < 0) + goto exit; queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, di->bat->interval_not_charging * HZ); } di->fg_samples = (cnt_low | (cnt_high << 8)); + /* + * TODO: Workaround due to the hardware issue that accumulator is not + * reset after setting reset_on_read bit and reading the accumulator + * Registers. + */ + if (prev_samples > di->fg_samples) { + /* overflow has occured */ + sample = (0xFFFF - prev_samples) + di->fg_samples; + } else + sample = di->fg_samples - prev_samples; + prev_samples = di->fg_samples; + di->fg_samples = sample; val = (low | (med << 8) | (high << 16)); + /* + * TODO: Workaround due to the hardware issue that accumulator is not + * reset after setting reset_on_read bit and reading the accumulator + * Registers. + */ + if (prev_val > val) + raw_val = (0xFFFFFF - prev_val) + val; + else + raw_val = val - prev_val; + prev_val = val; + val = raw_val; if (di->fg_samples) { - di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10)/10000; + di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X100)/100000; di->avg_curr = (val * FG_LSB_IN_MA) / (di->fg_samples * 1000); } else dev_err(di->dev, "samples is zero, using previous calculated average current\n"); di->flags.conv_done = true; + di->calib_state = AB5500_FG_CALIB_END; mutex_unlock(&di->cc_lock); @@ -1372,8 +1419,6 @@ static int ab5500_fg_get_property(struct power_supply *psy, union power_supply_propval *val) { struct ab5500_fg *di; - int i, tbl_size; - struct abx500_v_to_cap *tbl; di = to_ab5500_fg_device_info(psy); @@ -1432,20 +1477,7 @@ static int ab5500_fg_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY: if (di->flags.batt_unknown && !di->bat->chg_unknown_bat) val->intval = 100; - else if (di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl) { - tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, - tbl_size = di->bat->bat_type[ - di->bat->batt_id].n_v_cap_tbl_elements; - - for (i = 0; i < tbl_size; ++i) { - if (di->vbat < tbl[i].voltage && - di->vbat > tbl[i+1].voltage) { - di->v_to_cap = tbl[i].capacity; - break; - } - } - val->intval = di->v_to_cap; - } else + else val->intval = di->bat_cap.prev_percent; break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: -- cgit v1.2.3 From eae204c3822fdd41221fdbe3b08feba120a1aed7 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 22 Nov 2011 10:53:41 +0100 Subject: misc: bh1780gli: Fix some obvious short commings Unbalanced regulator handling on error during probe and msleep on times less than 10 ms. ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic1080bf38a2f1e1922ec015b305b5a2de3b30f0e Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/39196 Reviewed-by: Bengt JONSSON --- drivers/misc/bh1780gli.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 7eb13d1085c..1035cb37695 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -146,7 +146,7 @@ static ssize_t bh1780_store_power_state(struct device *dev, if (val == BH1780_POFF) regulator_disable(ddata->regulator); - msleep(BH1780_PON_DELAY); + mdelay(BH1780_PON_DELAY); ddata->power_state = val; mutex_unlock(&ddata->lock); @@ -202,7 +202,7 @@ static int __devinit bh1780_probe(struct i2c_client *client, ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); if (ret < 0) { dev_err(&client->dev, "failed to read part ID\n"); - goto put_regulator; + goto disable_regulator; } #ifdef CONFIG_HAS_EARLYSUSPEND ddata->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; @@ -220,13 +220,15 @@ static int __devinit bh1780_probe(struct i2c_client *client, mutex_init(&ddata->lock); ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); - if (ret) + if (ret) { + dev_err(&client->dev, "failed to create sysfs group\n"); goto put_regulator; + } return 0; - -put_regulator: +disable_regulator: regulator_disable(ddata->regulator); +put_regulator: regulator_put(ddata->regulator); free_ddata: kfree(ddata); -- cgit v1.2.3 From f8091a73a0bc7bd411c74603ebe2221be5c824e5 Mon Sep 17 00:00:00 2001 From: Johan Bjornstedt Date: Tue, 29 Nov 2011 12:03:36 +0100 Subject: power: ab8500_bm: Estimate capacity in maintenance Battery capacity will be estimated when the charging algorithm reports that we're in maintenance state. Previously we always reported "100%" in maintenance. ST-Ericsson ID: 398336 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I931b570a26733ced091d7f3cfb1f6ad9d9a5f8f6 Signed-off-by: Johan Bjornstedt Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/39748 Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/board-mop500-bm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 085661e7491..3556ae78538 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -374,6 +374,8 @@ static const struct ab8500_fg_parameters fg = { .lowbat_threshold = 3100, .battok_falling_th_sel0 = 2860, .battok_raising_th_sel1 = 2860, + .user_cap_limit = 15, + .maint_thres = 97, }; static const struct ab8500_maxim_parameters maxi_params = { -- cgit v1.2.3 From 705d0d3b154a284300caf8f6b9a2d8773674f88a Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Tue, 6 Dec 2011 19:05:32 +0530 Subject: Documentation:add kernel-doc for keypad and sensor Add kernel docs for keypad and sensors ST-Ericsson ID: 354484 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:I8086df2c21e1716074c641296c864e4264e4a18e Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/41229 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- Documentation/DocBook/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 80c42603ff2..a1bb15bd435 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -15,11 +15,11 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml drm.xml media_api.xml \ - i2s.xml msp.xml shrm.xml stmpe.xml touchp.xml \ + i2s.xml msp.xml shrm.xml touchp.xml \ tc_keypad.xml prcmu-fw-api.xml cg2900_fm_radio.xml \ synaptics_rmi4_touchp.xml db5500_keypad.xml \ u5500_LogicalMailbox.xml cg2900.xml \ - lsm303dlh.xml ste_ff_vibra.xml ux500_usb.xml + lsm303dlh.xml ske_keypad.xml ste_ff_vibra.xml ux500_usb.xml include $(srctree)/Documentation/DocBook/media/Makefile -- cgit v1.2.3 From 4319fb8d747fc76ce2527497450ae6bf2920ef15 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Mon, 28 Nov 2011 18:13:23 +0530 Subject: u8500_defconfig: set CONFIG_LSM303DLHC to y Add LSM303DLHC in u8500 defconfig ST-Ericsson ID: 374970 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:Ie6cf0571dd7532ba4490cd821ad98692a3517710 Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40028 Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 7ca5373bb33..bd3051b4e51 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -172,6 +172,7 @@ CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y CONFIG_SENSORS_AB8500=y CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_U8500_WATCHDOG_DEBUG=y -- cgit v1.2.3 From 79792248054be397b142f7c235503784b5006857 Mon Sep 17 00:00:00 2001 From: Anil Kumar Date: Thu, 8 Dec 2011 15:42:59 +0530 Subject: drivers/leds/leds-lp5521.c: assign valid value Assign a valid value to variable ret to prevent returning it uninitialized ST-Ericsson ID: 401383 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ib1759f8483ecaf898f642118dfb82ce56cfeb45b Signed-off-by: Anil Kumar Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/41588 Reviewed-by: Srinidhi KASAGAR --- drivers/leds/leds-lp5521.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 75ade5792c3..2f667071278 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -792,6 +792,7 @@ static int __devinit lp5521_probe(struct i2c_client *client, ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf); if (buf != LP5521_REG_R_CURR_DEFAULT) { dev_err(&client->dev, "error in resetting chip\n"); + ret = -EIO; goto fail2; } usleep_range(10000, 20000); -- cgit v1.2.3 From 2cba36356d6b4ae61040e4e967526c4bca4b0076 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Mon, 5 Dec 2011 11:49:10 +0530 Subject: ab5500_bm: Add interface to reinit FG algorithm A function has been added to enable reinitialisation of the fuel gauge algorithm. This can be used to to reinitialise with a different battery voltage at start-up, for verification reasons. ST-Ericsson Linux next: NA ST-Ericsson ID: 357480 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I80d6e770a57affbe7f3af0fdf82052ca1b7fe8b4 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40903 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_fg.c | 78 +++++++++++++++++++++++++++++++++++- include/linux/mfd/abx500/ab5500-bm.h | 2 + 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 0f1dc4a13df..464e4bff6e2 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -163,6 +163,7 @@ struct ab5500_fg_flags { * @fg_wq: Work queue for running the FG algorithm * @fg_periodic_work: Work to run the FG algorithm periodically * @fg_low_bat_work: Work to check low bat condition + * @fg_reinit_work: Work to reset and re-initialize fuel gauge * @fg_work: Work to run the FG algorithm instantly * @fg_acc_cur_work: Work to read the FG accumulator * @cc_lock: Mutex for locking the CC @@ -198,6 +199,7 @@ struct ab5500_fg { struct workqueue_struct *fg_wq; struct delayed_work fg_periodic_work; struct delayed_work fg_low_bat_work; + struct delayed_work fg_reinit_work; struct work_struct fg_work; struct delayed_work fg_acc_cur_work; struct mutex cc_lock; @@ -223,6 +225,8 @@ static enum power_supply_property ab5500_fg_props[] = { /* Function Prototype */ static int ab5500_fg_bat_v_trig(int mux); +static int prev_samples, prev_val; + struct ab5500_fg *ab5500_fg_get(void) { struct ab5500_fg *di; @@ -287,6 +291,29 @@ static int ab5500_fg_add_cap_sample(struct ab5500_fg *di, int sample) return avg->avg; } +/** + * ab5500_fg_clear_cap_samples() - Clear average filter + * @di: pointer to the ab5500_fg structure + * + * The capacity filter is is reset to zero. + */ +static void ab5500_fg_clear_cap_samples(struct ab5500_fg *di) +{ + int i; + struct ab5500_fg_avg_cap *avg = &di->avg_cap; + + avg->pos = 0; + avg->nbr_samples = 0; + avg->sum = 0; + avg->avg = 0; + + for (i = 0; i < NBR_AVG_SAMPLES; i++) { + avg->samples[i] = 0; + avg->time_stamps[i] = 0; + } +} + + /** * ab5500_fg_fill_cap_sample() - Fill average filter * @di: pointer to the ab5500_fg structure @@ -446,7 +473,6 @@ static void ab5500_fg_acc_cur_timer_expired(unsigned long data) queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); } -static int prev_samples, prev_val; /** * ab5500_fg_acc_cur_work() - average battery current * @work: pointer to the work_struct structure @@ -1661,6 +1687,50 @@ static void ab5500_fg_external_power_changed(struct power_supply *psy) &di->fg_psy, ab5500_fg_get_ext_psy_data); } +/** + * abab5500_fg_reinit_work() - work to reset the FG algorithm + * @work: pointer to the work_struct structure + * + * Used to reset the current battery capacity to be able to + * retrigger a new voltage base capacity calculation. For + * test and verification purpose. + */ +static void ab5500_fg_reinit_work(struct work_struct *work) +{ + struct ab5500_fg *di = container_of(work, struct ab5500_fg, + fg_reinit_work.work); + + if (di->flags.calibrate == false) { + dev_dbg(di->dev, "Resetting FG state machine to init.\n"); + ab5500_fg_clear_cap_samples(di); + ab5500_fg_calc_cap_discharge_voltage(di, true); + ab5500_fg_charge_state_to(di, AB5500_FG_CHARGE_INIT); + ab5500_fg_discharge_state_to(di, AB5500_FG_DISCHARGE_INIT); + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + } else { + dev_err(di->dev, + "Residual offset calibration ongoing retrying..\n"); + /* Wait one second until next try*/ + queue_delayed_work(di->fg_wq, &di->fg_reinit_work, + round_jiffies(1)); + } +} + +/** + * ab5500_fg_reinit() - forces FG algorithm to reinitialize with current values + * + * This function can be used to force the FG algorithm to recalculate a new + * voltage based battery capacity. + */ +void ab5500_fg_reinit(void) +{ + struct ab5500_fg *di = ab5500_fg_get(); + /* User won't be notified if a null pointer returned. */ + if (di != NULL) + queue_delayed_work(di->fg_wq, &di->fg_reinit_work, 0); +} + #if defined(CONFIG_PM) static int ab5500_fg_resume(struct platform_device *pdev) { @@ -1789,6 +1859,10 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) INIT_DELAYED_WORK_DEFERRABLE(&di->fg_acc_cur_work, ab5500_fg_acc_cur_work); + /* Init work for reinitialising the fg algorithm */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_reinit_work, + ab5500_fg_reinit_work); + /* Work delayed Queue to run the state machine */ INIT_DELAYED_WORK_DEFERRABLE(&di->fg_periodic_work, ab5500_fg_periodic_work); @@ -1823,7 +1897,7 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) init_timer(&di->avg_current_timer); di->avg_current_timer.function = ab5500_fg_acc_cur_timer_expired; di->avg_current_timer.data = (unsigned long) di; - di->avg_current_timer.expires = 60 * HZ;; + di->avg_current_timer.expires = 60 * HZ; if (!timer_pending(&di->avg_current_timer)) add_timer(&di->avg_current_timer); else diff --git a/include/linux/mfd/abx500/ab5500-bm.h b/include/linux/mfd/abx500/ab5500-bm.h index cfad11c530c..05ebc8c3840 100644 --- a/include/linux/mfd/abx500/ab5500-bm.h +++ b/include/linux/mfd/abx500/ab5500-bm.h @@ -101,6 +101,7 @@ #ifdef CONFIG_AB5500_BM struct ab5500_btemp *ab5500_btemp_get(void); int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp); +void ab5500_fg_reinit(void); #else static inline struct ab5500_btemp *ab5500_btemp_get(void) { @@ -110,5 +111,6 @@ static inline int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *btemp) { return 0; } +static inline void ab5500_fg_reinit(void) {} #endif #endif /* _AB5500_BM_H */ -- cgit v1.2.3 From 3efcc80b657b1d23c5437ae8fc021634b60d0acb Mon Sep 17 00:00:00 2001 From: Anil Kumar Date: Wed, 7 Dec 2011 17:10:41 +0530 Subject: drivers/leds/leds-lm3530.c: initialize array Declare array with initializer to avoid using uninitialized values ST-Ericsson ID: 401383 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I908280e8a6a73c42f0dc56bb65fefeadc3418bc6 Signed-off-by: Anil Kumar Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/41378 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/leds/leds-lm3530.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 6f1314df926..41aed6c89ab 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -154,7 +154,7 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) u8 als_imp_sel = 0; u8 brightness; u8 reg_val[LM3530_REG_MAX]; - u8 zones[LM3530_ALS_ZB_MAX]; + u8 zones[LM3530_ALS_ZB_MAX] = {0}; u32 als_vmin, als_vmax, als_vstep; struct lm3530_platform_data *pdata = drvdata->pdata; struct i2c_client *client = drvdata->client; -- cgit v1.2.3 From 0ab0a31d6ca3195b83c0d2cf5f5ad0dcf59d351d Mon Sep 17 00:00:00 2001 From: Peter Enderborg Date: Wed, 7 Dec 2011 14:12:26 +0100 Subject: power:ab8500_charger autopower settings Change the power loss handling so we do a reboot instead of poweroff when charger is connected. ST-Ericsson Linux next: NA ST-Ericsson ID: 373445 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Idfafba3f359829b87a0725d89cf86a72652dc1be Signed-off-by: pender01 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40696 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Johan BJORNSTEDT --- arch/arm/mach-ux500/board-mop500-bm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 3556ae78538..1d13eb82ba2 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -336,6 +336,7 @@ static char *ab8500_chargalg_supplied_to[] = { struct ab8500_charger_platform_data ab8500_charger_plat_data = { .supplied_to = ab8500_charger_supplied_to, .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to), + .autopower_cfg = false, }; struct ab8500_btemp_platform_data ab8500_btemp_plat_data = { -- cgit v1.2.3 From b441b5e39b0bf9c833b73e880bdd93c4cc343d3f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 16 Jan 2012 09:42:42 +0100 Subject: DocBook: ASoC: Remove old i2s-layer The old multi-client i2s driver-layer located in drivers/misc/i2s is removed and the MSP-operation for i2s is moved into the file ux500_msp_i2s.c in the Ux500 ASoC-folder. Signed-off-by: Ola Lilja --- Documentation/DocBook/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index a1bb15bd435..f0e9b64b910 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml drm.xml media_api.xml \ - i2s.xml msp.xml shrm.xml touchp.xml \ + shrm.xml touchp.xml \ tc_keypad.xml prcmu-fw-api.xml cg2900_fm_radio.xml \ synaptics_rmi4_touchp.xml db5500_keypad.xml \ u5500_LogicalMailbox.xml cg2900.xml \ -- cgit v1.2.3 From 128d83c8fe266f06a80a8bd2dc55cfe6b3998437 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Fri, 16 Dec 2011 18:51:30 +0530 Subject: watchdog: Driver rename Rename the u8500 watchdog driver as ux500 watchdog driver. This is done inorder to add 5500 support. ST-Ericsson Linux next: NA ST-Ericsson ID: 316540 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iae9ec02191620da09780881169045b58bdc0230a Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42935 Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/watchdog/Kconfig | 10 +- drivers/watchdog/Makefile | 2 +- drivers/watchdog/u8500_wdt.c | 433 ------------------------------------------- drivers/watchdog/ux500_wdt.c | 432 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 438 insertions(+), 439 deletions(-) delete mode 100644 drivers/watchdog/u8500_wdt.c create mode 100644 drivers/watchdog/ux500_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 57386b4feaa..64289e67c39 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -349,18 +349,18 @@ config IMX2_WDT To compile this driver as a module, choose M here: the module will be called imx2_wdt. -config U8500_WATCHDOG - bool "ST-Ericsson U8500 watchdog" +config UX500_WATCHDOG + bool "ST-Ericsson Ux500 watchdog" depends on UX500_SOC_DB8500 default y help Say Y here to include Watchdog timer support for the - watchdog existing in the prcmu of ST-Ericsson U8500 series platforms. + watchdog existing in the prcmu of ST-Ericsson Ux500 series platforms. This watchdog is used to reset the system and thus cannot be compiled as a module. -config U8500_WATCHDOG_DEBUG - bool "ST-Ericsson U8500 watchdog DEBUG" +config UX500_WATCHDOG_DEBUG + bool "ST-Ericsson Ux500 watchdog DEBUG" depends on UX500_SOC_DB8500 && DEBUG_FS help Say Y here to add various debugfs entries in wdog/ diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 7e77ba49897..738a0f3ad21 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -53,7 +53,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o -obj-$(CONFIG_U8500_WATCHDOG) += u8500_wdt.o +obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/u8500_wdt.c b/drivers/watchdog/u8500_wdt.c deleted file mode 100644 index 3ac23ab05f3..00000000000 --- a/drivers/watchdog/u8500_wdt.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * - * Author: Jonas Aaberg for ST-Ericsson - * - * Heavily based upon geodewdt.c - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WATCHDOG_TIMEOUT 600 /* 10 minutes */ - -#define WDT_FLAGS_OPEN 1 -#define WDT_FLAGS_ORPHAN 2 - -static unsigned long wdt_flags; - -static int timeout = WATCHDOG_TIMEOUT; -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, - "Watchdog timeout in seconds. default=" - __MODULE_STRING(WATCHDOG_TIMEOUT) "."); - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static u8 wdog_id; -static bool wdt_en; -static bool wdt_auto_off = false; -static bool safe_close; - -static int u8500_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) - return -EBUSY; - - if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) - __module_get(THIS_MODULE); - - prcmu_enable_a9wdog(wdog_id); - wdt_en = true; - - return nonseekable_open(inode, file); -} - -static int u8500_wdt_release(struct inode *inode, struct file *file) -{ - if (safe_close) { - prcmu_disable_a9wdog(wdog_id); - module_put(THIS_MODULE); - } else { - pr_crit("Unexpected close - watchdog is not stopping.\n"); - prcmu_kick_a9wdog(wdog_id); - - set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); - } - - clear_bit(WDT_FLAGS_OPEN, &wdt_flags); - safe_close = false; - return 0; -} - -static ssize_t u8500_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - if (!len) - return len; - - if (!nowayout) { - size_t i; - safe_close = false; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - - if (c == 'V') - safe_close = true; - } - } - - prcmu_kick_a9wdog(wdog_id); - - return len; -} - -static long u8500_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int interval; - - static const struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 1, - .identity = "U8500 WDT", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &ident, - sizeof(ident)) ? -EFAULT : 0; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - - case WDIOC_SETOPTIONS: - { - int options; - int ret = -EINVAL; - - if (get_user(options, p)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) { - prcmu_disable_a9wdog(wdog_id); - wdt_en = false; - ret = 0; - } - - if (options & WDIOS_ENABLECARD) { - prcmu_enable_a9wdog(wdog_id); - wdt_en = true; - ret = 0; - } - - return ret; - } - case WDIOC_KEEPALIVE: - return prcmu_kick_a9wdog(wdog_id); - - case WDIOC_SETTIMEOUT: - if (get_user(interval, p)) - return -EFAULT; - - /* 28 bit resolution in ms, becomes 268435.455 s */ - if (interval > 268435 || interval < 0) - return -EINVAL; - timeout = interval; - prcmu_disable_a9wdog(wdog_id); - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - - /* Fall through */ - case WDIOC_GETTIMEOUT: - return put_user(timeout, p); - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations u8500_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = u8500_wdt_write, - .unlocked_ioctl = u8500_wdt_ioctl, - .open = u8500_wdt_open, - .release = u8500_wdt_release, -}; - -static struct miscdevice u8500_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &u8500_wdt_fops, -}; - -#ifdef CONFIG_U8500_WATCHDOG_DEBUG - -enum wdog_dbg { - WDOG_DBG_CONFIG, - WDOG_DBG_LOAD, - WDOG_DBG_KICK, - WDOG_DBG_EN, - WDOG_DBG_DIS, -}; - -static ssize_t wdog_dbg_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - unsigned long val; - int err; - enum wdog_dbg v = (enum wdog_dbg)((struct seq_file *) - (file->private_data))->private; - - switch(v) { - case WDOG_DBG_CONFIG: - err = kstrtoul_from_user(user_buf, count, 0, &val); - - if (!err) { - wdt_auto_off = val != 0; - (void) prcmu_config_a9wdog(1, - wdt_auto_off); - } - else { - pr_err("u8500_wdt:dbg: unknown value\n"); - } - break; - case WDOG_DBG_LOAD: - err = kstrtoul_from_user(user_buf, count, 0, &val); - - if (!err) { - timeout = val; - /* Convert seconds to ms */ - prcmu_disable_a9wdog(wdog_id); - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - else { - pr_err("u8500_wdt:dbg: unknown value\n"); - } - break; - case WDOG_DBG_KICK: - (void) prcmu_kick_a9wdog(wdog_id); - break; - case WDOG_DBG_EN: - wdt_en = true; - (void) prcmu_enable_a9wdog(wdog_id); - break; - case WDOG_DBG_DIS: - wdt_en = false; - (void) prcmu_disable_a9wdog(wdog_id); - break; - } - - return count; -} - -static int wdog_dbg_read(struct seq_file *s, void *p) -{ - enum wdog_dbg v = (enum wdog_dbg)s->private; - - switch(v) { - case WDOG_DBG_CONFIG: - seq_printf(s,"wdog is on id %d, auto off on sleep: %s\n", - (int)wdog_id, - wdt_auto_off ? "enabled": "disabled"); - break; - case WDOG_DBG_LOAD: - /* In 1s */ - seq_printf(s, "wdog load is: %d s\n", - timeout); - break; - case WDOG_DBG_KICK: - break; - case WDOG_DBG_EN: - case WDOG_DBG_DIS: - seq_printf(s, "wdog is %sabled\n", - wdt_en ? "en" : "dis"); - break; - } - return 0; -} - -static int wdog_dbg_open(struct inode *inode, - struct file *file) -{ - return single_open(file, wdog_dbg_read, inode->i_private); -} - -static const struct file_operations wdog_dbg_fops = { - .open = wdog_dbg_open, - .write = wdog_dbg_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int __init wdog_dbg_init(void) -{ - struct dentry *wdog_dir; - - wdog_dir = debugfs_create_dir("wdog", NULL); - if (IS_ERR_OR_NULL(wdog_dir)) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_u8("id", - S_IWUGO | S_IRUGO, wdog_dir, - &wdog_id))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("config", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_CONFIG, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("load", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_LOAD, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("kick", - S_IWUGO, wdog_dir, - (void *)WDOG_DBG_KICK, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("enable", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_EN, - &wdog_dbg_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("disable", - S_IWUGO | S_IRUGO, wdog_dir, - (void *)WDOG_DBG_DIS, - &wdog_dbg_fops))) - goto fail; - - return 0; -fail: - pr_err("u8500:wdog: Failed to initialize wdog dbg\n"); - debugfs_remove_recursive(wdog_dir); - - return -EFAULT; -} - -#else -static inline int __init wdog_dbg_init(void) -{ - return 0; -} -#endif - -static int __init u8500_wdt_probe(struct platform_device *pdev) -{ - int ret; - - /* Number of watch dogs */ - prcmu_config_a9wdog(1, wdt_auto_off); - /* convert to ms */ - prcmu_load_a9wdog(wdog_id, timeout * 1000); - - ret = misc_register(&u8500_wdt_miscdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register misc\n"); - return ret; - } - - ret = wdog_dbg_init(); - if (ret < 0) - goto fail; - - dev_info(&pdev->dev, "initialized\n"); - - return 0; -fail: - misc_deregister(&u8500_wdt_miscdev); - return ret; -} - -static int __exit u8500_wdt_remove(struct platform_device *dev) -{ - prcmu_disable_a9wdog(wdog_id); - wdt_en = false; - misc_deregister(&u8500_wdt_miscdev); - return 0; -} -#ifdef CONFIG_PM -static int u8500_wdt_suspend(struct platform_device *pdev, - pm_message_t state) -{ - if (wdt_en && !wdt_auto_off) { - prcmu_disable_a9wdog(wdog_id); - prcmu_config_a9wdog(1, true); - - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - return 0; -} - -static int u8500_wdt_resume(struct platform_device *pdev) -{ - if (wdt_en && !wdt_auto_off) { - prcmu_disable_a9wdog(wdog_id); - prcmu_config_a9wdog(1, wdt_auto_off); - - prcmu_load_a9wdog(wdog_id, timeout * 1000); - prcmu_enable_a9wdog(wdog_id); - } - return 0; -} - -#else -#define u8500_wdt_suspend NULL -#define u8500_wdt_resume NULL -#endif -static struct platform_driver u8500_wdt_driver = { - .remove = __exit_p(u8500_wdt_remove), - .driver = { - .owner = THIS_MODULE, - .name = "u8500_wdt", - }, - .suspend = u8500_wdt_suspend, - .resume = u8500_wdt_resume, -}; - -static int __init u8500_wdt_init(void) -{ - return platform_driver_probe(&u8500_wdt_driver, u8500_wdt_probe); -} -module_init(u8500_wdt_init); - -MODULE_AUTHOR("Jonas Aaberg "); -MODULE_DESCRIPTION("U8500 Watchdog Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c new file mode 100644 index 00000000000..78c03285be3 --- /dev/null +++ b/drivers/watchdog/ux500_wdt.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Jonas Aaberg for ST-Ericsson + * + * Heavily based upon geodewdt.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WATCHDOG_TIMEOUT 600 /* 10 minutes */ + +#define WDT_FLAGS_OPEN 1 +#define WDT_FLAGS_ORPHAN 2 + +static unsigned long wdt_flags; + +static int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +static u8 wdog_id; +static bool wdt_en; +static bool wdt_auto_off = false; +static bool safe_close; + +static int ux500_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) + return -EBUSY; + + if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) + __module_get(THIS_MODULE); + + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + + return nonseekable_open(inode, file); +} + +static int ux500_wdt_release(struct inode *inode, struct file *file) +{ + if (safe_close) { + prcmu_disable_a9wdog(wdog_id); + module_put(THIS_MODULE); + } else { + pr_crit("Unexpected close - watchdog is not stopping.\n"); + prcmu_kick_a9wdog(wdog_id); + + set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); + } + + clear_bit(WDT_FLAGS_OPEN, &wdt_flags); + safe_close = false; + return 0; +} + +static ssize_t ux500_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + if (!len) + return len; + + if (!nowayout) { + size_t i; + safe_close = false; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + safe_close = true; + } + } + + prcmu_kick_a9wdog(wdog_id); + + return len; +} + +static long ux500_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int interval; + + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "Ux500 WDT", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + { + int options; + int ret = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + prcmu_enable_a9wdog(wdog_id); + wdt_en = true; + ret = 0; + } + + return ret; + } + case WDIOC_KEEPALIVE: + return prcmu_kick_a9wdog(wdog_id); + + case WDIOC_SETTIMEOUT: + if (get_user(interval, p)) + return -EFAULT; + + /* 28 bit resolution in ms, becomes 268435.455 s */ + if (interval > 268435 || interval < 0) + return -EINVAL; + timeout = interval; + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + + /* Fall through */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations ux500_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = ux500_wdt_write, + .unlocked_ioctl = ux500_wdt_ioctl, + .open = ux500_wdt_open, + .release = ux500_wdt_release, +}; + +static struct miscdevice ux500_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ux500_wdt_fops, +}; + +#ifdef CONFIG_UX500_WATCHDOG_DEBUG +enum wdog_dbg { + WDOG_DBG_CONFIG, + WDOG_DBG_LOAD, + WDOG_DBG_KICK, + WDOG_DBG_EN, + WDOG_DBG_DIS, +}; + +static ssize_t wdog_dbg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + unsigned long val; + int err; + enum wdog_dbg v = (enum wdog_dbg)((struct seq_file *) + (file->private_data))->private; + + switch(v) { + case WDOG_DBG_CONFIG: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + wdt_auto_off = val != 0; + (void) prcmu_config_a9wdog(1, + wdt_auto_off); + } + else { + pr_err("ux500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_LOAD: + err = kstrtoul_from_user(user_buf, count, 0, &val); + + if (!err) { + timeout = val; + /* Convert seconds to ms */ + prcmu_disable_a9wdog(wdog_id); + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + else { + pr_err("ux500_wdt:dbg: unknown value\n"); + } + break; + case WDOG_DBG_KICK: + (void) prcmu_kick_a9wdog(wdog_id); + break; + case WDOG_DBG_EN: + wdt_en = true; + (void) prcmu_enable_a9wdog(wdog_id); + break; + case WDOG_DBG_DIS: + wdt_en = false; + (void) prcmu_disable_a9wdog(wdog_id); + break; + } + + return count; +} + +static int wdog_dbg_read(struct seq_file *s, void *p) +{ + enum wdog_dbg v = (enum wdog_dbg)s->private; + + switch(v) { + case WDOG_DBG_CONFIG: + seq_printf(s,"wdog is on id %d, auto off on sleep: %s\n", + (int)wdog_id, + wdt_auto_off ? "enabled": "disabled"); + break; + case WDOG_DBG_LOAD: + /* In 1s */ + seq_printf(s, "wdog load is: %d s\n", + timeout); + break; + case WDOG_DBG_KICK: + break; + case WDOG_DBG_EN: + case WDOG_DBG_DIS: + seq_printf(s, "wdog is %sabled\n", + wdt_en ? "en" : "dis"); + break; + } + return 0; +} + +static int wdog_dbg_open(struct inode *inode, + struct file *file) +{ + return single_open(file, wdog_dbg_read, inode->i_private); +} + +static const struct file_operations wdog_dbg_fops = { + .open = wdog_dbg_open, + .write = wdog_dbg_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int __init wdog_dbg_init(void) +{ + struct dentry *wdog_dir; + + wdog_dir = debugfs_create_dir("wdog", NULL); + if (IS_ERR_OR_NULL(wdog_dir)) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_u8("id", + S_IWUGO | S_IRUGO, wdog_dir, + &wdog_id))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("config", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_CONFIG, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("load", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_LOAD, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("kick", + S_IWUGO, wdog_dir, + (void *)WDOG_DBG_KICK, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("enable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_EN, + &wdog_dbg_fops))) + goto fail; + + if (IS_ERR_OR_NULL(debugfs_create_file("disable", + S_IWUGO | S_IRUGO, wdog_dir, + (void *)WDOG_DBG_DIS, + &wdog_dbg_fops))) + goto fail; + + return 0; +fail: + pr_err("ux500:wdog: Failed to initialize wdog dbg\n"); + debugfs_remove_recursive(wdog_dir); + + return -EFAULT; +} + +#else +static inline int __init wdog_dbg_init(void) +{ + return 0; +} +#endif + +static int __init ux500_wdt_probe(struct platform_device *pdev) +{ + int ret; + + /* Number of watch dogs */ + prcmu_config_a9wdog(1, wdt_auto_off); + /* convert to ms */ + prcmu_load_a9wdog(wdog_id, timeout * 1000); + + ret = misc_register(&ux500_wdt_miscdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register misc\n"); + return ret; + } + + ret = wdog_dbg_init(); + if (ret < 0) + goto fail; + + dev_info(&pdev->dev, "initialized\n"); + + return 0; +fail: + misc_deregister(&ux500_wdt_miscdev); + return ret; +} + +static int __exit ux500_wdt_remove(struct platform_device *dev) +{ + prcmu_disable_a9wdog(wdog_id); + wdt_en = false; + misc_deregister(&ux500_wdt_miscdev); + return 0; +} +#ifdef CONFIG_PM +static int ux500_wdt_suspend(struct platform_device *pdev, + pm_message_t state) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, true); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} + +static int ux500_wdt_resume(struct platform_device *pdev) +{ + if (wdt_en && !wdt_auto_off) { + prcmu_disable_a9wdog(wdog_id); + prcmu_config_a9wdog(1, wdt_auto_off); + + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + } + return 0; +} + +#else +#define ux500_wdt_suspend NULL +#define ux500_wdt_resume NULL +#endif +static struct platform_driver ux500_wdt_driver = { + .remove = __exit_p(ux500_wdt_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ux500_wdt", + }, + .suspend = ux500_wdt_suspend, + .resume = ux500_wdt_resume, +}; + +static int __init ux500_wdt_init(void) +{ + return platform_driver_probe(&ux500_wdt_driver, ux500_wdt_probe); +} +module_init(ux500_wdt_init); + +MODULE_AUTHOR("Jonas Aaberg "); +MODULE_DESCRIPTION("Ux500 Watchdog Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From 8e5d509593b5dd0c3ab78f6af0cc67b0e32c30f6 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Fri, 16 Dec 2011 19:00:12 +0530 Subject: watchdog: Add 5500 support ST-Ericsson Linux next: NA ST-Ericsson ID: 316540 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I55bf6d145fe3cf4a1fc8de8c45266832c9769a54 Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42473 Reviewed-by: Srinidhi KASAGAR --- drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/ux500_wdt.c | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 64289e67c39..14e568be223 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -351,7 +351,7 @@ config IMX2_WDT config UX500_WATCHDOG bool "ST-Ericsson Ux500 watchdog" - depends on UX500_SOC_DB8500 + depends on UX500_SOC_DB8500 || UX500_SOC_DB5500 default y help Say Y here to include Watchdog timer support for the @@ -361,7 +361,7 @@ config UX500_WATCHDOG config UX500_WATCHDOG_DEBUG bool "ST-Ericsson Ux500 watchdog DEBUG" - depends on UX500_SOC_DB8500 && DEBUG_FS + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && DEBUG_FS help Say Y here to add various debugfs entries in wdog/ diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index 78c03285be3..52747e59172 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -152,9 +152,17 @@ static long ux500_wdt_ioctl(struct file *file, unsigned int cmd, if (get_user(interval, p)) return -EFAULT; - /* 28 bit resolution in ms, becomes 268435.455 s */ - if (interval > 268435 || interval < 0) + if (cpu_is_u8500()) { + /* 28 bit resolution in ms, becomes 268435.455 s */ + if (interval > 268435 || interval < 0) + return -EINVAL; + } else if (cpu_is_u5500()) { + /* 32 bit resolution in ms, becomes 4294967.295 s */ + if (interval > 4294967 || interval < 0) + return -EINVAL; + } else return -EINVAL; + timeout = interval; prcmu_disable_a9wdog(wdog_id); prcmu_load_a9wdog(wdog_id, timeout * 1000); @@ -384,6 +392,11 @@ static int __exit ux500_wdt_remove(struct platform_device *dev) static int ux500_wdt_suspend(struct platform_device *pdev, pm_message_t state) { + if (wdt_en && cpu_is_u5500()) { + prcmu_disable_a9wdog(wdog_id); + return 0; + } + if (wdt_en && !wdt_auto_off) { prcmu_disable_a9wdog(wdog_id); prcmu_config_a9wdog(1, true); @@ -396,6 +409,12 @@ static int ux500_wdt_suspend(struct platform_device *pdev, static int ux500_wdt_resume(struct platform_device *pdev) { + if (wdt_en && cpu_is_u5500()) { + prcmu_load_a9wdog(wdog_id, timeout * 1000); + prcmu_enable_a9wdog(wdog_id); + return 0; + } + if (wdt_en && !wdt_auto_off) { prcmu_disable_a9wdog(wdog_id); prcmu_config_a9wdog(1, wdt_auto_off); -- cgit v1.2.3 From a5933fec9d466a13e6c940d1ccb0768533e685d2 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Thu, 15 Dec 2011 18:35:39 +0530 Subject: u8500_defconfig: Update the watchdog config name ST-Ericsson Linux next: NA ST-Ericsson ID: 316540 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1abe08f4b5ab5b5911583568ff935b78ae12b763 Signed-off-by: Virupax Sadashivpetimath Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42703 Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index bd3051b4e51..47fa8cfbabd 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -175,7 +175,7 @@ CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y -CONFIG_U8500_WATCHDOG_DEBUG=y +CONFIG_UX500_WATCHDOG_DEBUG=y CONFIG_TPS6105X=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y -- cgit v1.2.3 From b89b85a8fc033805f4264068d254301a89944afa Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Wed, 4 Jan 2012 16:35:15 +0530 Subject: power: ab5500-fg: optimize delays during probe Optimize delays during fg psy registration by powering up fuel gauge before registration and scheduling periodic workqueues at 250msec so that enough samples are available for conversion. ST-Ericsson Linux next: NA ST-Ericsson ID: 373975 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iff0ec497a90399d0dcc514df24b12d594eb06459 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44315 Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_fg.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 464e4bff6e2..c74d351bd8b 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -47,6 +47,7 @@ static LIST_HEAD(ab5500_fg_list); #define SEC_TO_SAMPLE(S) (S * 4) #define NBR_AVG_SAMPLES 20 #define LOW_BAT_CHECK_INTERVAL (2 * HZ) +#define FG_PERIODIC_START_INTERVAL (250 * HZ)/1000 /* 250 msec */ #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */ @@ -405,11 +406,6 @@ static int ab5500_fg_inst_curr(struct ab5500_fg *di) } mutex_lock(&di->cc_lock); - /* - * Since there is no interrupt for this, just wait for 250ms - * 250ms is one sample conversion time with 32.768 Khz RTC clock - */ - msleep(250); /* Enable read request */ ret = abx500_mask_and_set_register_interruptible(di->dev, @@ -1823,6 +1819,8 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) ret = -EINVAL; goto free_device_info; } + /* powerup fg to start sampling */ + ab5500_fg_coulomb_counter(di, true); di->fg_psy.name = "ab5500_fg"; di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; @@ -1891,7 +1889,6 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) } di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); - ab5500_fg_coulomb_counter(di, true); /* Initilialize avg current timer */ init_timer(&di->avg_current_timer); @@ -1909,8 +1906,10 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) di->flags.calibrate = true; di->calib_state = AB5500_FG_CALIB_INIT; /* Run the FG algorithm */ - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); - queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, + FG_PERIODIC_START_INTERVAL); + queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, + FG_PERIODIC_START_INTERVAL); dev_info(di->dev, "probe success\n"); return ret; -- cgit v1.2.3 From fedc606ff80e0d56732134c41ffaf8e1597dd42f Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Wed, 4 Jan 2012 11:30:43 +0530 Subject: ux500: disable Old ABI compatibility support (OABI_COMPAT) This patch disables support for legacy ABI binaries. Only new ARM ABI i.e. EABI compiled user space is supported. If legacy ABI binary is executed, results will be unpredictable. This is done because race condition is seen in swap-out code on SMP in following kernel panic dump - <1>[35225.247131] Unable to handle kernel paging request at virtual address afd0c638 <1>[35225.247131] pgd = e0020000 <1>[35225.247161] [afd0c638] *pgd=2005a031, *pte=2331971d, *ppte=00000000 <0>[35225.247253] Internal error: Oops: 17 [#1] PREEMPT SMP <6>[35225.247283] dbx500_dump notified of crash <4>[35225.249298] PC is at vector_swi+0x28/0x88 <4>[35225.249328] LR is at 0xafd0c63c <4>[35225.249328] pc : [] lr : [] psr: 60000093 <4>[35225.249359] sp : e013bfb0 ip : 82d08528 fp : 82d0731c <4>[35225.249359] r10: 00000000 r9 : 47ac2738 r8 : 20000010 <4>[35225.249389] r7 : 000000a8 r6 : 00000000 r5 : 00000010 r4 : 001341d0 <4>[35225.249389] r3 : 00000001 r2 : ffffffff r1 : 00000008 r0 : 0013421c <4>[35225.249420] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user <4>[35225.249420] Control: 10c57c7d Table: 2002004a DAC: 00000015 <4>[35225.249450] <4>[35225.249450] PC: 0xc02937a8: <4>[35225.249450] 37a8 e59d1040 e5bde03c e16ff001 f57ff01f e95d7fff e1a00000 e28dd00c e1b0f00e <4>[35225.249511] 37c8 eb00f275 e1a096ad e1a09689 e5991000 e3a08001 e3110c01 0affffec e1a0100d <4>[35225.249542] 37e8 e3a00001 eb0006f0 eaffffe8 e320f000 e320f000 e320f000 e24dd048 e88d1fff <4>[35225.249603] 3808 e28d803c e9486000 e14f8000 e58de03c e58d8040 e58d0044 e3180020 13a0a000 <4>[35225.249664] 3828 051ea004 e59fc0ac e59cc000 ee01cf10 f1080080 e1a096ad e1a09689 e28f809c <4>[35225.249694] 3848 e599c000 e3daa4ff 122a7609 159f8088 e92d0030 e31c0c01 1a000008 e3570e17 <4>[35225.249755] 3868 e24fee13 3798f107 e28d1008 e3a08000 e357080f e2270000 2a0010fc ea0173f0 <4>[35225.249786] 3888 e1a02007 e28d1008 e3a00000 eb0006c6 e28fe014 e1a07000 e28d1008 e3570e17 <4>[35225.249847] <4>[35225.249847] SP: 0xe013bf30: <4>[35225.249847] bf30 00000000 00000102 c0978064 c0322794 e013a000 00000001 00000024 c09d9cc0 <4>[35225.249908] bf50 00000000 ffffffff e013bf9c 00000000 000000a8 c02931ec 0013421c 00000008 <4>[35225.249938] bf70 ffffffff 00000001 001341d0 00000010 00000000 000000a8 20000010 47ac2738 <4>[35225.249969] bf90 00000000 82d0731c 82d08528 e013bfb0 afd0c63c c0293828 60000093 ffffffff <4>[35225.250030] bfb0 0013421c 00000008 ffffffff 00000001 001341d0 00000010 00000000 000000a8 <4>[35225.250091] bfd0 00000000 47ac2738 00000000 82d0731c 82d08528 47ac2050 82d0340b afd0c63c <4>[35225.250122] bff0 20000010 0013421c 40990310 d0610c09 00000000 00000001 bf000000 e00ba180 <4>[35225.250183] c010 c0999f28 00000000 00000015 c1639940 e00ba180 e013c000 c0ab67bc e1fb9720 <0>[35225.250244] Stack: (0xe013bfb0 to 0xe013c000) <0>[35225.250274] bfa0: 0013421c 00000008 ffffffff 00000001 <0>[35225.250274] bfc0: 001341d0 00000010 00000000 000000a8 00000000 47ac2738 00000000 82d0731c <0>[35225.250305] bfe0: 82d08528 47ac2050 82d0340b afd0c63c 20000010 0013421c 40990310 d0610c09 <0>[35225.250335] Code: e58d8040 e58d0044 e3180020 13a0a000 (051ea004) <2>[35225.250366] CPU0: stopping <4>[35225.250396] [] (unwind_backtrace+0x0/0xf0) from [] (dump_stack+0x10/0x24) <4>[35225.250427] [] (dump_stack+0x10/0x24) from [] (do_IPI+0xc8/0x164) <4>[35225.250457] [] (do_IPI+0xc8/0x164) from [] (__irq_svc+0x4c/0xe4) <4>[35225.250457] Exception stack(0xc0977ed8 to 0xc0977f20) <4>[35225.250488] 7ec0: c09deb84 00000000 <4>[35225.250488] 7ee0: 00000000 c09deb48 00000001 00000001 6b99a329 c09deb48 159c928a 00000006 <4>[35225.250518] 7f00: 6b9c6db8 000017c4 00000002 c0977f20 c02a3774 c02a3790 60000113 ffffffff <4>[35225.250549] [] (__irq_svc+0x4c/0xe4) from [] (enter_sleep+0x6e8/0x728) <4>[35225.250579] [] (enter_sleep+0x6e8/0x728) from [] (cpuidle_idle_call+0xb0/0x190) <4>[35225.250610] [] (cpuidle_idle_call+0xb0/0x190) from [] (cpu_idle+0x94/0xf0) <4>[35225.250610] [] (cpu_idle+0x94/0xf0) from [] (start_kernel+0x310/0x380) <4>[35225.250640] unwind: Unknown symbol address c0008bd4 <4>[35225.250640] unwind: Index not found c0008bd4 <4>[35225.251861] ---[ end trace 58829f802d64ca85 ]--- <0>[35225.251861] Kernel panic - not syncing: Fatal exception <4>[35225.251892] [] (unwind_backtrace+0x0/0xf0) from [] (dump_stack+0x10/0x24) <4>[35225.251922] [] (dump_stack+0x10/0x24) from [] (panic+0x6c/0x1ac) <4>[35225.251953] [] (panic+0x6c/0x1ac) from [] (die+0x1b0/0x1f8) <4>[35225.251983] [] (die+0x1b0/0x1f8) from [] (__do_kernel_fault+0x64/0x84) <4>[35225.251983] [] (__do_kernel_fault+0x64/0x84) from [] (do_page_fault+0x2a8/0x2cc) <4>[35225.252014] [] (do_page_fault+0x2a8/0x2cc) from [] (do_DataAbort+0x34/0x94) <4>[35225.252044] [] (do_DataAbort+0x34/0x94) from [] (__dabt_svc+0x4c/0x60) <4>[35225.252044] Exception stack(0xe013bf68 to 0xe013bfb0) <4>[35225.252044] bf60: 0013421c 00000008 ffffffff 00000001 001341d0 00000010 <4>[35225.252075] bf80: 00000000 000000a8 20000010 47ac2738 00000000 82d0731c 82d08528 e013bfb0 <4>[35225.252075] bfa0: afd0c63c c0293828 60000093 ffffffff <4>[35225.252105] [] (__dabt_svc+0x4c/0x60) from [] (vector_swi+0x28/0x88) Solution is proposed based on discussion in following link - http://lists.infradead.org/pipermail/linux-arm-kernel/2011-January/038059.html ST-Ericsson ID: 408168 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ief923b60fd4cb93ce96af1a6af87ade691ec6770 Signed-off-by: Shreshtha Kumar Sahu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44267 Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 47fa8cfbabd..c6a1a58850a 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -42,6 +42,7 @@ CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y -- cgit v1.2.3 From 4d065fcbb3d121c28d06e2201cf9c3fc93d848c1 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 25 Jan 2012 13:19:56 +0100 Subject: smsc911x: Enable fsmc clock and vape regulator Now fsmc clock is disabled at boot and vape is not maintained, so to have the ethernet driver working on Snowball we have to enable them. So add fsmc clock management if any and use the not use vddvario regulator mapped on vape for Snowball board. Signed-off-by: Philippe Langlais --- drivers/net/ethernet/smsc/smsc911x.c | 38 +++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index dbeb806f123..edbf830a23f 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -33,6 +33,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -144,6 +145,9 @@ struct smsc911x_data { /* regulators */ struct regulator_bulk_data supplies[SMSC911X_NUM_SUPPLIES]; + + /* clock */ + struct clk *fsmc_clk; }; /* Easy access to information */ @@ -369,7 +373,7 @@ out: } /* - * enable resources, currently just regulators. + * enable resources, regulators & clocks. */ static int smsc911x_enable_resources(struct platform_device *pdev) { @@ -379,9 +383,17 @@ static int smsc911x_enable_resources(struct platform_device *pdev) ret = regulator_bulk_enable(ARRAY_SIZE(pdata->supplies), pdata->supplies); - if (ret) + if (ret) { netdev_err(ndev, "failed to enable regulators %d\n", ret); + return ret; + } + + if (pdata->fsmc_clk) { + ret = clk_enable(pdata->fsmc_clk); + if (ret < 0) + netdev_err(ndev, "failed to enable clock %d\n", ret); + } return ret; } @@ -396,6 +408,8 @@ static int smsc911x_disable_resources(struct platform_device *pdev) ret = regulator_bulk_disable(ARRAY_SIZE(pdata->supplies), pdata->supplies); + if (pdata->fsmc_clk) + clk_disable(pdata->fsmc_clk); return ret; } @@ -418,9 +432,17 @@ static int smsc911x_request_resources(struct platform_device *pdev) ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(pdata->supplies), pdata->supplies); - if (ret) - netdev_err(ndev, "couldn't get regulators %d\n", - ret); + if (ret) { + netdev_err(ndev, "couldn't get regulators %d\n", ret); + return ret; + } + + /* Request clock, ignore if not here */ + pdata->fsmc_clk = clk_get(NULL, "fsmc"); + if (IS_ERR(pdata->fsmc_clk)) { + netdev_warn(ndev, "couldn't get clock %d\n", ret); + pdata->fsmc_clk = NULL; + } return ret; } @@ -436,6 +458,12 @@ static void smsc911x_free_resources(struct platform_device *pdev) /* Free regulators */ regulator_bulk_free(ARRAY_SIZE(pdata->supplies), pdata->supplies); + + /* Free clock */ + if (pdata->fsmc_clk) { + clk_put(pdata->fsmc_clk); + pdata->fsmc_clk = NULL; + } } /* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read -- cgit v1.2.3 From 6a0539427c26331555fb63ac77fed4685fb4c4b7 Mon Sep 17 00:00:00 2001 From: Gregory Hermant Date: Mon, 9 Jan 2012 16:05:16 +0100 Subject: Add support for the 9100 Li-ION battery and adjust the bkup battery charger parameters Signed-off-by: Gregory Hermant --- arch/arm/mach-ux500/board-mop500-bm.c | 56 +++++++++++++++++++++++++++++++++++ drivers/power/Kconfig | 6 ++++ drivers/power/ab8500_charger.c | 18 +++++++---- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 1d13eb82ba2..400f89a85cc 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -149,6 +149,40 @@ static struct res_to_temp temp_tbl[] = { {65, 9425}, }; +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +static struct batres_vs_temp temp_to_batres_tbl[] = { + { 40, 120}, + { 30, 135}, + { 20, 165}, + { 10, 230}, + { 00, 325}, + {-10, 445}, + {-20, 595}, +}; +#else +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY +#define BATRES 180 +#else +#define BATRES 300 +#endif +static struct batres_vs_temp temp_to_batres_tbl[] = { + { 60, BATRES}, + { 30, BATRES}, + { 20, BATRES}, + { 10, BATRES}, + { 00, BATRES}, + {-10, BATRES}, + {-20, BATRES}, +}; +#endif static const struct battery_type bat_type[] = { [BATTERY_UNKNOWN] = { /* First element always represent the UNKNOWN battery */ @@ -156,13 +190,27 @@ static const struct battery_type bat_type[] = { .resis_high = 0, .resis_low = 0, .battery_resistance = 300, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .charge_full_design = 2600, +#else .charge_full_design = 612, +#endif .nominal_voltage = 3700, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .termination_vol = 4150, +#else .termination_vol = 4050, +#endif .termination_curr = 200, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .recharge_vol = 4130, + .normal_cur_lvl = 520, + .normal_vol_lvl = 4200, +#else .recharge_vol = 3990, .normal_cur_lvl = 400, .normal_vol_lvl = 4100, +#endif .maint_a_cur_lvl = 400, .maint_a_vol_lvl = 4050, .maint_a_chg_timer_h = 60, @@ -404,13 +452,21 @@ struct ab8500_bm_data ab8500_bm_data = { .usb_safety_tmr_h = 4, .bkup_bat_v = BUP_VCH_SEL_2P6V, .bkup_bat_i = BUP_ICH_SEL_150UA, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .no_maintenance = true, +#else .no_maintenance = false, +#endif #ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL .adc_therm = ADC_THERM_BATCTRL, #else .adc_therm = ADC_THERM_BATTEMP, #endif +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .chg_unknown_bat = true, +#else .chg_unknown_bat = false, +#endif .enable_overshoot = false, .fg_res = 100, .cap_levels = &cap_levels, diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 0626dfa9ff6..56dfe432b74 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -308,6 +308,12 @@ config AB8500_BATTERY_THERM_ON_BATCTRL Say Y to enable battery temperature measurements using thermistor connected on BATCTRL ADC. +config AB8500_9100_LI_ION_BATTERY + bool "Enable support of the 9100 Li-ion battery charging" + depends on AB8500_BM + help + Say Y to enable support of the 9100 Li-ion battery charging. + config AB5500_BM bool "AB5500 Battery Management Driver" depends on AB5500_CORE && AB5500_GPADC && MACH_U5500 diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index c355738a31a..13f2975445f 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -29,6 +29,7 @@ #include #include #include +#include /* Charger constants */ #define NO_PW_CONN 0 @@ -2354,11 +2355,18 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) } /* Backup battery voltage and current */ - ret = abx500_set_register_interruptible(di->dev, - AB8500_RTC, - AB8500_RTC_BACKUP_CHG_REG, - di->bat->bkup_bat_v | - di->bat->bkup_bat_i); + if (machine_is_snowball()) + ret = abx500_set_register_interruptible(di->dev, + AB8500_RTC, + AB8500_RTC_BACKUP_CHG_REG, + BUP_VCH_SEL_3P1V | + BUP_ICH_SEL_150UA); + else + ret = abx500_set_register_interruptible(di->dev, + AB8500_RTC, + AB8500_RTC_BACKUP_CHG_REG, + di->bat->bkup_bat_v | + di->bat->bkup_bat_i); if (ret) { dev_err(di->dev, "failed to setup backup battery charging\n"); goto out; -- cgit v1.2.3 From ee2f8865a8f9b156807fc02eefb47855dc9b07ab Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 30 Jan 2012 11:26:08 +0100 Subject: mfd: ab8500-denc: Changes for porting on 3.3 Signed-off-by: Philippe Langlais --- drivers/mfd/ab8500-denc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-denc.c b/drivers/mfd/ab8500-denc.c index 1bf61e41bcd..17efee62110 100644 --- a/drivers/mfd/ab8500-denc.c +++ b/drivers/mfd/ab8500-denc.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -21,8 +22,8 @@ #include #include #include -#include #include +#include #include #include -- cgit v1.2.3 From 89d5cb3ec9dc185c1d6db4fceccc299e5a0b5384 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 19 Jan 2012 16:41:21 +0100 Subject: config: Align u8500_defconfig with STE internal defconfig Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c6a1a58850a..c4ca3504034 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -33,8 +33,6 @@ CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y -CONFIG_U8500_TV_OUTPUT_AV8100=y -CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -55,7 +53,6 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_IDLE=y -CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM_RUNTIME=y @@ -79,6 +76,7 @@ CONFIG_NETFILTER=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CT_NETLINK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y CONFIG_NETFILTER_XT_MATCH_STATE=y @@ -86,8 +84,6 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_ULOG=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_NAT_FTP=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_PHONET=y @@ -140,11 +136,9 @@ CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_NOMADIK_SKE=y -CONFIG_KEYBOARD_STMPE=y CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_BU21013=y CONFIG_TOUCHSCREEN_CYTTSP_CORE=y CONFIG_TOUCHSCREEN_CYTTSP_SPI=y CONFIG_INPUT_MISC=y @@ -177,20 +171,19 @@ CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_UX500_WATCHDOG_DEBUG=y -CONFIG_TPS6105X=y -CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y +CONFIG_MFD_DB8500_PRCMU=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_DB8500_PRCMU=y CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set # CONFIG_VIDEO_CAPTURE_DRIVERS is not set CONFIG_RADIO_CG2900=y CONFIG_DRM=y @@ -198,8 +191,9 @@ CONFIG_GPU_MALI=y CONFIG_FB=y CONFIG_FB_MCDE=y CONFIG_MCDE_FB_AVOID_REALLOC=y -CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y +CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y # CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y @@ -238,13 +232,11 @@ CONFIG_USB_G_HID=m CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_BLOCK_MINORS=32 # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y -CONFIG_MMC_BLOCK_MINORS=32 CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y -CONFIG_LEDS_LM3530=y -CONFIG_LEDS_LP5521=y CONFIG_LEDS_PWM=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y @@ -270,7 +262,6 @@ CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y CONFIG_HSEM_U8500=y -CONFIG_MODEM=y CONFIG_MODEM_U8500=y CONFIG_U8500_SHRM=y CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y @@ -285,23 +276,13 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y -CONFIG_AUTOFS4_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y -CONFIG_UDF_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -CONFIG_CRAMFS=m -CONFIG_VXFS_FS=m -CONFIG_MINIX_FS=m -CONFIG_ROMFS_FS=m -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m CONFIG_9P_FS=y CONFIG_PARTITION_ADVANCED=y CONFIG_BLKDEV_PARTITION=y -- cgit v1.2.3 From 73c6a8ed0c68d36ccf610a2e526b54d4133dcc74 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 2 Feb 2012 13:30:27 +0100 Subject: config: Enable built-in USB_GADGET_MUSB_HDRC to get USB OTG working on U8500 Signed-off-by: Lee Jones Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c4ca3504034..3398c4ed252 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -220,6 +220,7 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ZERO=m CONFIG_USB_ETH=m CONFIG_USB_FILE_STORAGE=m -- cgit v1.2.3 From 08906f257d27908c530c0a82ef367caff72529ef Mon Sep 17 00:00:00 2001 From: Kalle Vahlman Date: Fri, 17 Feb 2012 08:32:03 +0100 Subject: serial/amba-pl011: Return early in deadlock work-around if there is no tty The first amba port does not always have an attached tty, which will result in a crash if the work-around is activated. This seems to be the case for example on Snowball which has no modem hw, which seems to be the main use-case for this work-around. --- drivers/tty/serial/amba-pl011.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0faee493eff..5bbd97e61ff 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1120,6 +1120,10 @@ static void pl011_lockup_wa(unsigned long data) int buf_empty_retries = 200; int loop; + /* Exit early if there is no tty */ + if (!tty) + return; + /* Stop HCI layer from submitting data for tx */ tty->hw_stopped = 1; while (!uart_circ_empty(xmit)) { -- cgit v1.2.3 From cb0a6ce65b2018ea6227c613b8aae105868b7fbd Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 21 Feb 2012 14:54:11 +0100 Subject: config: Add u8500 Android default config Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 335 +++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 arch/arm/configs/u8500_android_defconfig diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig new file mode 100644 index 00000000000..47cc2a037a9 --- /dev/null +++ b/arch/arm/configs/u8500_android_defconfig @@ -0,0 +1,335 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_BOOTTIME=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_BLKDEV_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_DEFAULT_DEADLINE=y +CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB8500=y +CONFIG_MACH_HREFV60=y +CONFIG_MACH_SNOWBALL=y +CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_UX500_SUSPEND=y +CONFIG_UX500_SUSPEND_STANDBY=y +CONFIG_UX500_SUSPEND_MEM=y +CONFIG_UX500_SUSPEND_DBG=y +CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y +# CONFIG_UX500_USECASE_GOVERNOR is not set +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y +CONFIG_DB8500_MLOADER=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" +CONFIG_KEXEC=y +CONFIG_CRASH_SWRESET=y +CONFIG_CRASH_DUMP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 +CONFIG_UX500_CPUIDLE_DEBUG=y +CONFIG_FPE_NWFPE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_WAKELOCK=y +CONFIG_PM_RUNTIME=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_IPV6_SIT is not set +CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_PHONET=y +CONFIG_NET_SCHED=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_BT_HCIUART=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_REGULATOR=y +CONFIG_RFKILL_GPIO=y +CONFIG_NET_9P=y +CONFIG_CAIF=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=73728 +CONFIG_AB8500_PWM=y +CONFIG_SENSORS_BH1780=y +CONFIG_STE_TRACE_MODEM=y +CONFIG_DISPDEV=y +CONFIG_U8500_SIM_DETECT=y +CONFIG_STM_TRACE=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_NETDEVICES=y +CONFIG_TUN=y +CONFIG_CAIF_TTY=m +CONFIG_CAIF_HSI=m +CONFIG_SMSC911X=y +CONFIG_SMSC_PHY=y +CONFIG_PPP=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_ASYNC=y +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_STMPE=y +CONFIG_KEYBOARD_TC3589X=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_BU21013=y +CONFIG_TOUCHSCREEN_CYTTSP_CORE=y +CONFIG_TOUCHSCREEN_CYTTSP_SPI=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_ACCDET=y +CONFIG_INPUT_AB8500_PONKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_NOMADIK=y +CONFIG_SPI=y +# CONFIG_STM_MSP_SPI is not set +CONFIG_SPI_PL022=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_TC3589X=y +CONFIG_GPIO_AB8500=y +CONFIG_POWER_SUPPLY=y +CONFIG_AB8500_BM=y +CONFIG_SENSORS_AB8500=y +CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_LSM303DLHC=y +CONFIG_SENSORS_L3G4200D=y +CONFIG_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_U8500_WATCHDOG_DEBUG=y +CONFIG_TPS6105X=y +CONFIG_MFD_STMPE=y +CONFIG_MFD_TC3589X=y +CONFIG_AB5500_CORE=y +CONFIG_AB8500_CORE=y +CONFIG_MFD_DB8500_PRCMU=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_DB8500_PRCMU=y +CONFIG_REGULATOR_AB8500_DEBUG=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +# CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_RADIO_CG2900=y +CONFIG_GPU_MALI=y +CONFIG_FB=y +CONFIG_FB_MCDE=y +CONFIG_MCDE_FB_AVOID_REALLOC=y +CONFIG_MCDE_DISPLAY_GENERIC_DSI=y +CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y +CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_FB_B2R2=y +CONFIG_B2R2_PLUG_CONF=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_AB5500=y +CONFIG_SND_SOC_UX500_AB8500=y +CONFIG_SND_SOC_UX500_CG29XX=y +CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_USB=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_MON=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_UX500=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_G_ANDROID=y +CONFIG_AB8500_USB=y +CONFIG_MMC=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_LM3530=y +CONFIG_LEDS_LP5521=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB=y +CONFIG_RTC_DRV_AB8500=y +CONFIG_DMADEVICES=y +CONFIG_STE_DMA40=y +CONFIG_STAGING=y +CONFIG_AB5500_SIM=y +CONFIG_CG2900=y +CONFIG_CG2900_CHIP=y +CONFIG_STLC2690_CHIP=y +CONFIG_CG2900_UART=y +CONFIG_CG2900_AUDIO=y +CONFIG_CG2900_TEST=y +CONFIG_BT_CG2900=y +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_RAM_CONSOLE=y +CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_CW1200=m +CONFIG_CW1200_USE_GPIO_IRQ=y +CONFIG_CW1200_DEBUGFS=y +CONFIG_U8500_MMIO=y +CONFIG_U8500_CM=y +CONFIG_U8500_FLASH=y +CONFIG_MODEM_U8500=y +CONFIG_U8500_SHRM=y +CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HFS_FS=m +CONFIG_BEFS_FS=m +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_9P_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_INFO=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_FUNCTION_TRACER=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_USER=y +CONFIG_KEYS=y +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_HASH=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=m -- cgit v1.2.3 From 28f7178601de2ee1e7d23e68168d2d5defa72926 Mon Sep 17 00:00:00 2001 From: "Mathieu J. Poirier" Date: Wed, 7 Mar 2012 21:07:17 +0100 Subject: snowball: android: automatic creation of frame buffer device This is normally done by HDMIServices but the daemon is not running in the linaro-android environment, hence enabling by default. Signed-off-by: Mathieu Poirier --- arch/arm/configs/u8500_android_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index 47cc2a037a9..60057aa913c 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -210,7 +210,7 @@ CONFIG_MCDE_DISPLAY_GENERIC_DSI=y CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y CONFIG_MCDE_DISPLAY_AV8100=y -# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE=y CONFIG_AV8100_HWTRIG_I2SDAT3=y CONFIG_FB_B2R2=y CONFIG_B2R2_PLUG_CONF=y -- cgit v1.2.3 From f3b5b691dd7104041e24320046d21c4b3675832c Mon Sep 17 00:00:00 2001 From: "ramesh.chandrasekaran" Date: Tue, 13 Mar 2012 11:28:45 +0100 Subject: config: sound: Fix for audio doesn't work in IK 3.3 Enable CONFIG_STM_MSP_SPI kernel config which initializes MSPs and audio codecs. Signed-off-by: Ramesh Chandrasekaran --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 3398c4ed252..98e7e499fe6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -156,7 +156,7 @@ CONFIG_HW_RANDOM_NOMADIK=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_NOMADIK=y CONFIG_SPI=y -# CONFIG_STM_MSP_SPI is not set +CONFIG_STM_MSP_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_TC3589X=y -- cgit v1.2.3 From b466e3dea99f96105e26f65d211c94572bb7097e Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 13 Mar 2012 14:14:01 +0100 Subject: config: android: sound: Now CONFIG_STM_MSP_SPI is enabled by default Fix for audio doesn't work in IK 3.3 Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index 60057aa913c..c5ed034a99e 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -172,7 +172,6 @@ CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_NOMADIK=y CONFIG_SPI=y -# CONFIG_STM_MSP_SPI is not set CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_TC3589X=y -- cgit v1.2.3 From 83f68a69c23b069d0b71d3a45061acff3b60b98f Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Thu, 12 Jan 2012 11:38:44 +0100 Subject: drivers:watchdog:ux500: Disable when timeout == 0 Setting the watchdog timeout to 0 makes any attempt to open the dev node fail. This makes it possible to disable the watchdog functionality on the kernel commandline with "ux500_wdt.timeout=0", ST-Ericsson ID: 365851 ST-Ericsson Linux next:NA ST-Ericsson FOSS-OUT ID:Trivial Change-Id: I917258c9310ea2267c877c3c13d00dc08c30a147 Signed-off-by: Per Fransson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45299 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/watchdog/ux500_wdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index 52747e59172..a1e8c2dbf10 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -44,6 +44,9 @@ static bool safe_close; static int ux500_wdt_open(struct inode *inode, struct file *file) { + if (!timeout) + return -ENODEV; + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) return -EBUSY; -- cgit v1.2.3 From f773f909f17144a20f4a7c1d23e7615ebca62062 Mon Sep 17 00:00:00 2001 From: Sean Sandoval Date: Thu, 12 Jan 2012 09:51:57 +0100 Subject: net: add ipv6 multiple tables support ST-Ericsson Linux next: NA ST-Ericsson ID: 410101 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic8c6e6aedc1c30fb96bd468b0fbdb395328c841a Signed-off-by: Sean Sandoval Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45222 Reviewed-by: Markus GRAPE Tested-by: Markus GRAPE Reviewed-by: Hakan GARDRUP Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 98e7e499fe6..e31afba9279 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -72,6 +72,7 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set +CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y -- cgit v1.2.3 From 3a3a2a4eb80d4ed20313afd53b2bd50f499af253 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Tue, 20 Dec 2011 09:45:56 +0530 Subject: power: ab5500-btemp: manual mode monitoring as platform data Move battery temperature manual mode monitoring selection to platform data. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9224e5cc8bed77be6a10344d32e480a7717a1d22 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43248 Reviewed-by: QABUILD Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-bm.c | 1 + drivers/power/ab5500_btemp.c | 68 ++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index f7ca803da42..96b7cc656eb 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -473,6 +473,7 @@ struct abx500_bm_data ab5500_bm_data = { #endif .chg_unknown_bat = false, .enable_overshoot = false, + .auto_trig = false, .fg_res = 200, .cap_levels = &cap_levels, .bat_type = bat_type, diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 08d5ae89dbe..3ce07f149e2 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -38,9 +38,6 @@ #define RESET 0x00 #define ADOUT_10K_PULL_UP 0x07 -/* Enable battery temp monitoring manual mode */ -#define BTEMP_MANUAL_MONITORING - #define to_ab5500_btemp_device_info(x) container_of((x), \ struct ab5500_btemp, btemp_psy); @@ -335,7 +332,7 @@ static int ab5500_btemp_measure_temp(struct ab5500_btemp *di) id = di->bat->batt_id; if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && - id != BATTERY_UNKNOWN) { + id != BATTERY_UNKNOWN && !di->bat->auto_trig) { rbat = ab5500_btemp_get_batctrl_res(di); if (rbat < 0) { dev_err(di->dev, "%s get batctrl res failed\n", @@ -456,25 +453,26 @@ static void ab5500_btemp_periodic_work(struct work_struct *work) power_supply_changed(&di->btemp_psy); } di->bat->temp_now = di->bat_temp; -#if defined(BTEMP_MANUAL_MONITORING) - /* Check for temperature limits */ - ab5500_btemp_bat_temp_trig(0); - /* Schedule a new measurement */ - if (di->events.usb_conn) + if (!di->bat->auto_trig) { + /* Check for temperature limits */ + ab5500_btemp_bat_temp_trig(0); + + /* Schedule a new measurement */ + if (di->events.usb_conn) + queue_delayed_work(di->btemp_wq, + &di->btemp_periodic_work, + round_jiffies(di->bat->interval_charging * HZ)); + else + queue_delayed_work(di->btemp_wq, + &di->btemp_periodic_work, + round_jiffies(di->bat->interval_not_charging * HZ)); + } else { + /* Schedule a new measurement */ queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, round_jiffies(di->bat->interval_charging * HZ)); - else - queue_delayed_work(di->btemp_wq, - &di->btemp_periodic_work, - round_jiffies(di->bat->interval_not_charging * HZ)); -#else - /* Schedule a new measurement */ - queue_delayed_work(di->btemp_wq, - &di->btemp_periodic_work, - round_jiffies(di->bat->interval_charging * HZ)); -#endif + } } /** @@ -623,18 +621,15 @@ static int ab5500_btemp_get_ext_psy_data(struct device *dev, void *data) /* USB disconnected */ if (!ret.intval && di->events.usb_conn) { di->events.usb_conn = false; -#if !defined(BTEMP_MANUAL_MONITORING) + if (di->bat->auto_trig) ab5500_btemp_periodic(di, false); -#endif } /* USB connected */ else if (ret.intval && !di->events.usb_conn) { di->events.usb_conn = true; - -#if !defined(BTEMP_MANUAL_MONITORING) + if (di->bat->auto_trig) ab5500_btemp_periodic(di, true); -#endif } break; default: @@ -686,7 +681,6 @@ static int ab5500_btemp_bat_temp_trig(int mux) return 0;; } -#if !defined(BTEMP_MANUAL_MONITORING) static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) { struct adc_auto_input *auto_ip; @@ -710,7 +704,6 @@ static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) "failed to set auto trigger for battery temp\n"); return ret; } -#endif #if defined(CONFIG_PM) static int ab5500_btemp_resume(struct platform_device *pdev) @@ -858,18 +851,19 @@ static int __devinit ab5500_btemp_probe(struct platform_device *pdev) dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", ab5500_btemp_irq[i].name, irq, ret); } -#if defined(BTEMP_MANUAL_MONITORING) - /* Schedule monitoring work only if battery type is known */ - if (di->bat->batt_id != BATTERY_UNKNOWN) - queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); -#else - ret = ab5500_btemp_auto_temp(di); - if (ret) { - dev_err(di->dev, - "failed to register auto trigger for battery temp\n"); - goto free_irq; + + if (!di->bat->auto_trig) { + /* Schedule monitoring work only if battery type is known */ + if (di->bat->batt_id != BATTERY_UNKNOWN) + queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); + } else { + ret = ab5500_btemp_auto_temp(di); + if (ret) { + dev_err(di->dev, + "failed to register auto trigger for battery temp\n"); + goto free_irq; + } } -#endif platform_set_drvdata(pdev, di); list_add_tail(&di->node, &ab5500_btemp_list); -- cgit v1.2.3 From 028210d984a5ca2dae29d4aebea90bfd98f0371b Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Tue, 20 Dec 2011 12:43:05 +0530 Subject: power: ab5500-btemp: support btemp_ball node measurement Support battery temperature measurement through btemp_ball node for btemp gpadc auto trigger. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7e99a106a5840d21a108a0bae04e79f091bb26e1 Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43249 Reviewed-by: QABUILD Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/ab5500-gpadc.c | 21 ++++++++- drivers/power/ab5500_btemp.c | 105 ++++++++++++++++++++++--------------------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index d099f1b9d73..4718e26bee8 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -134,6 +134,9 @@ #define ADC_RESOLUTION 1023 #define AUTO_ADC_RESOLUTION 255 +/* ADOUT prestart time */ +#define ADOUT0_TRIGX_PRESTART 0x18 + enum adc_auto_channels { ADC_INPUT_TRIG0 = 0, ADC_INPUT_TRIG1, @@ -350,7 +353,7 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) case BTEMP_BALL: ret = abx500_mask_and_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, - MUX_SCALE_BDATA_MASK, MUX_SCALE_BDATA27); + MUX_SCALE_BDATA_MASK, MUX_SCALE_BDATA18); if (ret < 0) { dev_err(gpadc->dev, "gpadc: fail to set mux scale\n"); goto out; @@ -425,6 +428,8 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) dev_err(gpadc->dev, "gpadc: fail to set ADOUT\n"); goto out; } + /* delay required to ramp up voltage on BDATA node */ + usleep_range(10000, 12000); } ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MUX_CTRL, adc_tab[input].mux); @@ -533,6 +538,7 @@ static int ab5500_gpadc_program_auto(struct ab5500_gpadc *gpadc, int trig) #define MIN_INDEX 0x02 #define MAX_INDEX 0x03 #define CTRL_INDEX 0x01 + ret = abx500_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, AB5500_GPADC_AUTO_TRIG_INDEX + (trig << 2) + MIN_INDEX, gpadc->adc_trig[trig].trig_min); @@ -709,7 +715,6 @@ int ab5500_gpadc_convert_auto(struct ab5500_gpadc *gpadc, goto out; } switch (in->mux) { - case BTEMP_BALL: case MAIN_BAT_V: /* * The value of mux scale volatage depends @@ -727,6 +732,18 @@ int ab5500_gpadc_convert_auto(struct ab5500_gpadc *gpadc, "gpadc: failed to read status\n"); goto out; } + + case BTEMP_BALL: + ret = abx500_set_register_interruptible( + gpadc->dev, AB5500_BANK_ADC, + AB5500_GPADC_AUTO_TRIG_ADOUT0_CTRL, + ADOUT0_TRIGX_PRESTART); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc: failed to set prestart\n"); + goto out; + } + case ACC_DETECT2: case ACC_DETECT3: case VBUS_V: diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index 3ce07f149e2..cfaab870cab 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -124,31 +124,32 @@ int ab5500_btemp_get_batctrl_temp(struct ab5500_btemp *di) } /** - * ab5500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance + * ab5500_btemp_volt_to_res() - convert batctrl voltage to resistance * @di: pointer to the ab5500_btemp structure - * @v_batctrl: measured batctrl voltage + * @volt: measured batctrl/btemp_ball voltage + * @batcrtl: batctrl/btemp_ball node * * This function returns the battery resistance that is - * derived from the BATCTRL voltage. + * derived from the BATCTRL/BTEMP_BALL voltage. * Returns value in Ohms. */ -static int ab5500_btemp_batctrl_volt_to_res(struct ab5500_btemp *di, - int v_batctrl) +static int ab5500_btemp_volt_to_res(struct ab5500_btemp *di, + int volt, bool batctrl) { int rbs; - if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { + if (batctrl) { /* * If the battery has internal NTC, we use the current * source to calculate the resistance, 7uA or 20uA */ - rbs = v_batctrl * 1000 / di->curr_source; + rbs = volt * 1000 / di->curr_source; } else { /* - * BAT_CTRL is internally + * BTEMP_BALL is internally * connected to 1.8V through a 10k resistor */ - rbs = (10000 * (v_batctrl)) / (1800 - v_batctrl); + rbs = (10000 * volt) / (1800 - volt); } return rbs; } @@ -266,7 +267,7 @@ static int ab5500_btemp_get_batctrl_res(struct ab5500_btemp *di) } batctrl = ab5500_btemp_read_batctrl_voltage(di); - res = ab5500_btemp_batctrl_volt_to_res(di, batctrl); + res = ab5500_btemp_volt_to_res(di, batctrl, true); ret = ab5500_btemp_curr_source_enable(di, false); if (ret) { @@ -280,6 +281,36 @@ static int ab5500_btemp_get_batctrl_res(struct ab5500_btemp *di) return res; } +/** + * ab5500_btemp_get_btemp_ball_res() - get battery resistance + * @di: pointer to the ab5500_btemp structure + * + * This function returns the battery pack identification + * resistance using resistor pull-up mode. Returns value in Ohms. + */ +static int ab5500_btemp_get_btemp_ball_res(struct ab5500_btemp *di) +{ + int ret, vntc; + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB5500_BANK_FG_BATTCOM_ACC, AB5500_UART, + UART_MODE, ADOUT_10K_PULL_UP); + if (ret) { + dev_err(di->dev, + "failed to enable 10k pull up to Vadout\n"); + return ret; + } + + vntc = ab5500_gpadc_convert(di->gpadc, BTEMP_BALL); + if (vntc < 0) { + dev_err(di->dev, "%s gpadc conversion failed," + " using previous value\n", __func__); + return vntc; + } + + return ab5500_btemp_volt_to_res(di, vntc, false); +} + /** * ab5500_btemp_res_to_temp() - resistance to temperature * @di: pointer to the ab5500_btemp structure @@ -324,55 +355,29 @@ static int ab5500_btemp_res_to_temp(struct ab5500_btemp *di, */ static int ab5500_btemp_measure_temp(struct ab5500_btemp *di) { - int temp, ret; - static int prev; - int rbat, vntc; - int rntc = 0; + int temp, rbat; u8 id; id = di->bat->batt_id; if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && - id != BATTERY_UNKNOWN && !di->bat->auto_trig) { + id != BATTERY_UNKNOWN && !di->bat->auto_trig) rbat = ab5500_btemp_get_batctrl_res(di); - if (rbat < 0) { - dev_err(di->dev, "%s get batctrl res failed\n", - __func__); - /* - * Return out-of-range temperature so that - * charging is stopped - */ - return BTEMP_THERMAL_LOW_LIMIT; - } + else + rbat = ab5500_btemp_get_btemp_ball_res(di); - temp = ab5500_btemp_res_to_temp(di, - di->bat->bat_type[id].r_to_t_tbl, - di->bat->bat_type[id].n_temp_tbl_elements, rbat); - } else { - ret = abx500_mask_and_set_register_interruptible(di->dev, - AB5500_BANK_FG_BATTCOM_ACC, AB5500_UART, - UART_MODE, ADOUT_10K_PULL_UP); - if (ret) { - dev_err(di->dev, - "failed to enable 10k pull up to Vadout\n"); - } - vntc = ab5500_gpadc_convert(di->gpadc, BTEMP_BALL); - if (vntc < 0) { - dev_err(di->dev, - "%s gpadc conversion failed," - " using previous value\n", __func__); - return prev; - } + if (rbat < 0) { + dev_err(di->dev, "%s failed to get resistance\n", __func__); /* - * The PCB NTC is sourced from 2.75v via a 10kOhm - * resistor. + * Return out-of-range temperature so that + * charging is stopped */ - rntc = 10000 * vntc / (27500 - vntc); - - temp = ab5500_btemp_res_to_temp(di, - di->bat->bat_type[id].r_to_t_tbl, - di->bat->bat_type[id].n_temp_tbl_elements, rntc); - prev = temp; + return BTEMP_THERMAL_LOW_LIMIT; } + + temp = ab5500_btemp_res_to_temp(di, + di->bat->bat_type[id].r_to_t_tbl, + di->bat->bat_type[id].n_temp_tbl_elements, rbat); + dev_dbg(di->dev, "Battery temperature is %d\n", temp); return temp; } -- cgit v1.2.3 From 5d5a579ad6f1440e22b70ed7a0f0a1e451b69e75 Mon Sep 17 00:00:00 2001 From: Rajagopala V Date: Tue, 20 Dec 2011 16:43:42 +0530 Subject: power: ab5500-btemp: enable btemp auto trigger Fix and enable battery temperature auto trigger. ST-Ericsson Linux next: NA ST-Ericsson ID: 372448 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I83d57133d5bebea00b658d170139a62be8e6f79f Signed-off-by: Rajagopala V Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43250 Reviewed-by: QABUILD Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-bm.c | 2 +- drivers/power/ab5500_btemp.c | 86 +++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c index 96b7cc656eb..333f2cb8563 100644 --- a/arch/arm/mach-ux500/board-u5500-bm.c +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -473,7 +473,7 @@ struct abx500_bm_data ab5500_bm_data = { #endif .chg_unknown_bat = false, .enable_overshoot = false, - .auto_trig = false, + .auto_trig = true, .fg_res = 200, .cap_levels = &cap_levels, .bat_type = bat_type, diff --git a/drivers/power/ab5500_btemp.c b/drivers/power/ab5500_btemp.c index cfaab870cab..3709299d6cb 100644 --- a/drivers/power/ab5500_btemp.c +++ b/drivers/power/ab5500_btemp.c @@ -311,6 +311,66 @@ static int ab5500_btemp_get_btemp_ball_res(struct ab5500_btemp *di) return ab5500_btemp_volt_to_res(di, vntc, false); } +/** + * ab5500_btemp_temp_to_res() - temperature to resistance + * @di: pointer to the ab5500_btemp structure + * @tbl: pointer to the resiatance to temperature table + * @tbl_size: size of the resistance to temperature table + * @temp: temperature to calculate the resistance from + * + * This function returns the battery resistance in ohms + * based on temperature. + */ +static int ab5500_btemp_temp_to_res(struct ab5500_btemp *di, + const struct abx500_res_to_temp *tbl, int tbl_size, int temp) +{ + int i, res; + /* + * Calculate the formula for the straight line + * Simple interpolation if we are within + * the resistance table limits, extrapolate + * if resistance is outside the limits. + */ + if (temp < tbl[0].temp) + i = 0; + else if (temp >= tbl[tbl_size - 1].temp) + i = tbl_size - 2; + else { + i = 0; + while (!(temp >= tbl[i].temp && + temp < tbl[i + 1].temp)) + i++; + } + + res = tbl[i].resist + ((tbl[i + 1].resist - tbl[i].resist) * + (temp - tbl[i].temp)) / (tbl[i + 1].temp - tbl[i].temp); + return res; +} + +/** + * ab5500_btemp_temp_to_volt() - temperature to adc voltage + * @di: pointer to the ab5500_btemp structure + * @temp: temperature to calculate the voltage from + * + * This function returns the adc voltage in millivolts + * based on temperature. + */ +static int ab5500_btemp_temp_to_volt(struct ab5500_btemp *di, int temp) +{ + int res, id; + + id = di->bat->batt_id; + res = ab5500_btemp_temp_to_res(di, + di->bat->bat_type[id].r_to_t_tbl, + di->bat->bat_type[id].n_temp_tbl_elements, + temp); + /* + * BTEMP_BALL is internally connected to 1.8V + * through a 10k resistor + */ + return((1800 * res) / (10000 + res)); +} + /** * ab5500_btemp_res_to_temp() - resistance to temperature * @di: pointer to the ab5500_btemp structure @@ -377,8 +437,8 @@ static int ab5500_btemp_measure_temp(struct ab5500_btemp *di) temp = ab5500_btemp_res_to_temp(di, di->bat->bat_type[id].r_to_t_tbl, di->bat->bat_type[id].n_temp_tbl_elements, rbat); - dev_dbg(di->dev, "Battery temperature is %d\n", temp); + return temp; } @@ -461,7 +521,15 @@ static void ab5500_btemp_periodic_work(struct work_struct *work) if (!di->bat->auto_trig) { /* Check for temperature limits */ - ab5500_btemp_bat_temp_trig(0); + if (di->bat_temp <= BTEMP_THERMAL_LOW_LIMIT) { + dev_err(di->dev, + "battery temp less than lower threshold\n"); + power_supply_changed(&di->btemp_psy); + } else if (di->bat_temp >= BTEMP_THERMAL_HIGH_LIMIT_62) { + dev_err(di->dev, + "battery temp greater them max threshold\n"); + power_supply_changed(&di->btemp_psy); + } /* Schedule a new measurement */ if (di->events.usb_conn) @@ -674,16 +742,18 @@ static struct ab5500_btemp_interrupts ab5500_btemp_irq[] = { static int ab5500_btemp_bat_temp_trig(int mux) { struct ab5500_btemp *di = ab5500_btemp_get(); + int temp = ab5500_btemp_measure_temp(di); - if (di->bat_temp < BTEMP_THERMAL_LOW_LIMIT) { + if (temp < (BTEMP_THERMAL_LOW_LIMIT+1)) { dev_err(di->dev, "battery temp less than lower threshold (-10 deg cel)\n"); power_supply_changed(&di->btemp_psy); - } else if (di->bat_temp > BTEMP_THERMAL_HIGH_LIMIT_62) { + } else if (temp > (BTEMP_THERMAL_HIGH_LIMIT_62-1)) { dev_err(di->dev, "battery temp greater them max threshold\n"); power_supply_changed(&di->btemp_psy); } - return 0;; + + return 0; } static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) @@ -699,8 +769,10 @@ static int ab5500_btemp_auto_temp(struct ab5500_btemp *di) auto_ip->mux = BTEMP_BALL; auto_ip->freq = MS500; - auto_ip->min = BTEMP_THERMAL_LOW_LIMIT; - auto_ip->max = BTEMP_THERMAL_HIGH_LIMIT_62; + auto_ip->min = ab5500_btemp_temp_to_volt(di, + BTEMP_THERMAL_HIGH_LIMIT_62); + auto_ip->max = ab5500_btemp_temp_to_volt(di, + BTEMP_THERMAL_LOW_LIMIT); auto_ip->auto_adc_callback = ab5500_btemp_bat_temp_trig; di->gpadc_auto = auto_ip; ret = ab5500_gpadc_convert_auto(di->gpadc, di->gpadc_auto); -- cgit v1.2.3 From 4e321b9cdfec86b9693b92d33f3c8cb339927d03 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 21 Dec 2011 11:50:51 +0100 Subject: defconfig: Add CONFIG_HIDRAW defconfig option This is needed by test application used for BT HID PTS qualification. Also usefull when making userspace drivers for custom HID devices. ST-Ericsson Linux next: NA ST-Ericsson ID: 405447 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Szymon Janc Change-Id: If3b0f9d416b5ab28fccdfad3a9fe9397af818eb1 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43721 Tested-by: SZYMON JANC Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index e31afba9279..7aca5c32ee6 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -315,4 +315,4 @@ CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y -CONFIG_LIBCRC32C=m +CONFIG_HIDRAW=y -- cgit v1.2.3 From fd13fc6db0451ec7dc777e8759fc452f0a7b4373 Mon Sep 17 00:00:00 2001 From: Markus Grape Date: Tue, 24 Jan 2012 16:04:43 +0100 Subject: net: add support for datausage This will add support for datausage that is located in the google Settings application. ST-Ericsson Linux next: NA ST-Ericsson ID: 350337 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie824b09788c09ec6723f6f6af22ffef8ab0b3d2c Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46415 Tested-by: Markus GRAPE Reviewed-by: QATEST Reviewed-by: Hakan GARDRUP Reviewed-by: Anders NILSSON2 Reviewed-by: Rabin VINCENT --- arch/arm/configs/u8500_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 7aca5c32ee6..5be43983501 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -68,6 +68,8 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set @@ -81,6 +83,9 @@ CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CT_NETLINK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_TPROXY=y CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y -- cgit v1.2.3 From 2a033b8ca5b3c9df4d1971ae2a67874e68f4405b Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Thu, 26 Jan 2012 15:39:20 +0100 Subject: mfd: ab8500: add debugfs node to read all registers Update the ab8500_registers_print() to reuse it from multiple places. ST-Ericsson Linux next: - ST-Ericsson ID: 402239 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie3ea115f8f408befbe095a5d426954f30db18156 Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46908 Reviewed-by: Linus WALLEIJ Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/mfd/ab8500-debugfs.c | 95 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 9521d738fd0..37ea089f84a 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -495,15 +495,12 @@ static irqreturn_t ab8500_debug_handler(int irq, void *data) return IRQ_HANDLED; } -static int ab8500_registers_print(struct seq_file *s, void *p) +/* Prints to seq_file or log_buf */ +static int ab8500_registers_print(struct device *dev, u32 bank, + struct seq_file *s) { - struct device *dev = s->private; unsigned int i; - u32 bank = debug_bank; - - seq_printf(s, AB8500_NAME_STRING " register values:\n"); - seq_printf(s, " bank %u:\n", bank); for (i = 0; i < debug_ranges[bank].num_ranges; i++) { u32 reg; @@ -520,22 +517,42 @@ static int ab8500_registers_print(struct seq_file *s, void *p) return err; } - err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", bank, - reg, value); - if (err < 0) { - dev_err(dev, "seq_printf overflow\n"); - /* Error is not returned here since - * the output is wanted in any case */ - return 0; + if (s) { + err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", + bank, reg, value); + if (err < 0) { + dev_err(dev, + "seq_printf overflow bank=%d reg=%d\n", + bank, reg); + /* Error is not returned here since + * the output is wanted in any case */ + return 0; + } + } else { + printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank, + reg, value); } } } return 0; } +static int ab8500_print_bank_registers(struct seq_file *s, void *p) +{ + struct device *dev = s->private; + u32 bank = debug_bank; + + seq_printf(s, AB8500_NAME_STRING " register values:\n"); + + seq_printf(s, " bank %u:\n", bank); + + ab8500_registers_print(dev, bank, s); + return 0; +} + static int ab8500_registers_open(struct inode *inode, struct file *file) { - return single_open(file, ab8500_registers_print, inode->i_private); + return single_open(file, ab8500_print_bank_registers, inode->i_private); } static const struct file_operations ab8500_registers_fops = { @@ -546,6 +563,51 @@ static const struct file_operations ab8500_registers_fops = { .owner = THIS_MODULE, }; +static int ab8500_print_all_banks(struct seq_file *s, void *p) +{ + struct device *dev = s->private; + unsigned int i; + int err; + + seq_printf(s, AB8500_NAME_STRING " register values:\n"); + + for (i = 1; i < AB8500_NUM_BANKS; i++) { + err = seq_printf(s, " bank %u:\n", i); + if (err < 0) + dev_err(dev, "seq_printf overflow, bank=%d\n", i); + + ab8500_registers_print(dev, i, s); + } + return 0; +} + +static int ab8500_all_banks_open(struct inode *inode, struct file *file) +{ + struct seq_file *s; + int err; + + err = single_open(file, ab8500_print_all_banks, inode->i_private); + if (!err) { + /* Default buf size in seq_read is not enough */ + s = (struct seq_file *)file->private_data; + s->size = (PAGE_SIZE * 2); + s->buf = kmalloc(s->size, GFP_KERNEL); + if (!s->buf) { + single_release(inode, file); + err = -ENOMEM; + } + } + return err; +} + +static const struct file_operations ab8500_all_banks_fops = { + .open = ab8500_all_banks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static int ab8500_bank_print(struct seq_file *s, void *p) { return seq_printf(s, "%d\n", debug_bank); @@ -1473,6 +1535,11 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) if (!file) goto err; + file = debugfs_create_file("all-banks", S_IRUGO, + ab8500_dir, &plf->dev, &ab8500_all_banks_fops); + if (!file) + goto err; + file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); if (!file) -- cgit v1.2.3 From 7749ca5e2b52ed36d77a2d409b1a33327df09bd9 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 27 Jan 2012 11:22:16 +0100 Subject: mfd: abx500: add api to dump all registers Some drivers can detect sub system failures e.g. shared memory driver can detect modem sub system failures. It would be helpful in analyzing these failures if AB register dump is available at that point. This patch adds the API for the drivers to dump AB registers in the kernel log. ST-Ericsson Linux next: - ST-Ericsson ID: 402239 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I544e40b4e2f68a80a6aa73135d4a15c433ec6a8b Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46909 Reviewed-by: Linus WALLEIJ Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/mfd/abx500-core.c | 16 ++++++++++++++++ include/linux/mfd/abx500.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 7ce65f49480..9818afba251 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c @@ -153,6 +153,22 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq) } EXPORT_SYMBOL(abx500_startup_irq_enabled); +void abx500_dump_all_banks(void) +{ + struct abx500_ops *ops; + struct device dummy_child = {0}; + struct abx500_device_entry *dev_entry; + + list_for_each_entry(dev_entry, &abx500_list, list) { + dummy_child.parent = dev_entry->dev; + ops = &dev_entry->ops; + + if ((ops != NULL) && (ops->dump_all_banks != NULL)) + ops->dump_all_banks(&dummy_child); + } +} +EXPORT_SYMBOL(abx500_dump_all_banks); + MODULE_AUTHOR("Mattias Wallin "); MODULE_DESCRIPTION("ABX500 core driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 33bf25b9e58..2cf7f7b1823 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -444,6 +444,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank, int abx500_get_chip_id(struct device *dev); int abx500_event_registers_startup_state_get(struct device *dev, u8 *event); int abx500_startup_irq_enabled(struct device *dev, unsigned int irq); +void abx500_dump_all_banks(void); #define abx500_get abx500_get_register_interruptible #define abx500_set abx500_set_register_interruptible @@ -460,6 +461,7 @@ struct abx500_ops { int (*mask_and_set_register) (struct device *, u8, u8, u8, u8); int (*event_registers_startup_state_get) (struct device *, u8 *); int (*startup_irq_enabled) (struct device *, unsigned int); + void (*dump_all_banks) (struct device *); }; int abx500_register_ops(struct device *core_dev, struct abx500_ops *ops); -- cgit v1.2.3 From c5fa7887b5c77de54bff68ba4fbf1c1e8178af56 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 27 Jan 2012 11:35:41 +0100 Subject: mfd: ab8500: implement api to dump all registers ST-Ericsson Linux next: - ST-Ericsson ID: 402239 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I46b16d38d8d521e0f994e6a92a0b3892eaa5382f Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46910 Reviewed-by: Linus WALLEIJ Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/mfd/ab8500-core.c | 1 + drivers/mfd/ab8500-debugfs.c | 13 +++++++++++++ include/linux/mfd/abx500/ab8500.h | 6 ++++++ 3 files changed, 20 insertions(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 204b5576e18..0542381185b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -260,6 +260,7 @@ static struct abx500_ops ab8500_ops = { .mask_and_set_register = ab8500_mask_and_set_register, .event_registers_startup_state_get = NULL, .startup_irq_enabled = NULL, + .dump_all_banks = ab8500_dump_all_banks, }; static void ab8500_irq_lock(struct irq_data *data) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 37ea089f84a..befdbb31678 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -581,6 +581,19 @@ static int ab8500_print_all_banks(struct seq_file *s, void *p) return 0; } +/* Dump registers to kernel log */ +void ab8500_dump_all_banks(struct device *dev) +{ + unsigned int i; + + printk(KERN_INFO"ab8500 register values:\n"); + + for (i = 1; i < AB8500_NUM_BANKS; i++) { + printk(KERN_INFO" bank %u:\n", i); + ab8500_registers_print(dev, i, NULL); + } +} + static int ab8500_all_banks_open(struct inode *inode, struct file *file) { struct seq_file *s; diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index c6119f50bf7..8d2a57e2fa7 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -347,4 +347,10 @@ static inline int is_ab8500_2p0(struct ab8500 *ab) return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0)); } +#ifdef CONFIG_AB8500_DEBUG +void ab8500_dump_all_banks(struct device *dev); +#else +static inline void ab8500_dump_all_banks(struct device *dev) {} +#endif + #endif /* MFD_AB8500_H */ -- cgit v1.2.3 From 95bf79961b622ea2e6854139cf0b00b36241d785 Mon Sep 17 00:00:00 2001 From: Rajkumar Kasirajan Date: Wed, 1 Feb 2012 18:18:37 +0530 Subject: RTC: pl031: Removed RTC Timer interrupt handling. Removed RTT interrupt handling, since PIE mode interrupts now emulated in generic code via an hrtimer. ST-Ericsson ID: 345151 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Signed-off-by: Rajkumar Kasirajan Change-Id: I27f3803c50120a8e7369104fe0eb2c5536f314cb Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47378 Reviewed-by: Rabin VINCENT --- drivers/rtc/rtc-pl031.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index f027c063fb2..cc0533994f6 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -220,17 +220,9 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id) unsigned long events = 0; rtcmis = readl(ldata->base + RTC_MIS); - if (rtcmis) { - writel(rtcmis, ldata->base + RTC_ICR); - - if (rtcmis & RTC_BIT_AI) - events |= (RTC_AF | RTC_IRQF); - - /* Timer interrupt is only available in ST variants */ - if ((rtcmis & RTC_BIT_PI) && - (ldata->hw_designer == AMBA_VENDOR_ST)) - events |= (RTC_PF | RTC_IRQF); - + if (rtcmis & RTC_BIT_AI) { + writel(RTC_BIT_AI, ldata->base + RTC_ICR); + events |= (RTC_AF | RTC_IRQF); rtc_update_irq(ldata->rtc, 1, events); return IRQ_HANDLED; -- cgit v1.2.3 From dd49b5972e691ab15a15d518abc2196c0f8d8eb9 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 31 Jan 2012 14:36:37 +0530 Subject: tty: serial: amba-pl011: use pm_runtime_irq_safe() PL011 should use pm_runtime_irq_safe() since it calls the pm_runtime routines with interrupts disabled. Found via lockdep: ================================= [ INFO: inconsistent lock state ] 3.0.8+ #1187 --------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. kworker/u:0/5 [HC0[0]:SC0[0]:HE1:SE1] takes: (&port_lock_key){?.....}, at: [] pl011_clock_on+0xc/0xc4 {IN-HARDIRQ-W} state was registered at: [] mark_irqflags+0x68/0x170 [] __lock_acquire+0x598/0x788 [] lock_acquire+0x10c/0x130 [] _raw_spin_lock_irqsave+0x5c/0x98 [] pl011_int+0x10/0x128 [] handle_irq_event_percpu+0x98/0x1f4 [] handle_irq_event+0x3c/0x5c [] handle_fasteoi_irq+0xc8/0x100 [] generic_handle_irq+0x28/0x30 [] asm_do_IRQ+0x78/0xb8 [] __irq_svc+0x50/0xf4 [] _raw_spin_unlock_irq+0x28/0x54 [] uart_carrier_raised+0x3c/0x44 [] tty_port_carrier_raised+0x1c/0x20 [] tty_port_block_til_ready+0x220/0x2cc [] tty_open+0x1f0/0x32c [] chrdev_open+0x20c/0x238 [] __dentry_open+0x220/0x338 [] nameidata_to_filp+0x50/0x5c [] do_last+0x43c/0x4c4 [] path_openat+0xb8/0x37c [] do_filp_open+0x30/0x7c [] do_sys_open+0xd8/0x170 [] ret_fast_syscall+0x0/0x3c irq event stamp: 60637 hardirqs last enabled at (60636): [] mutex_lock_nested+0x364/0x3c8 hardirqs last disabled at (60637): [] _raw_spin_lock_irqsave+0x1c/0x98 softirqs last enabled at (60509): [] irq_exit+0x5c/0xc0 softirqs last disabled at (60490): [] irq_exit+0x5c/0xc0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&port_lock_key); lock(&port_lock_key); *** DEADLOCK *** 7 locks held by kworker/u:0/5: #0: ((hdev->name)){.+.+.+}, at: [] process_one_work+0x1cc/0x4c8 #1: ((&hdev->power_on)){+.+.+.}, at: [] process_one_work+0x1cc/0x4c8 #2: (&hdev->req_lock){+.+.+.}, at: [] hci_dev_open+0x28/0x334 #3: (&main_info->man_mutex#2){+.+.+.}, at: [] cg2900_open+0xa8/0x49c #4: (&(uart_info->sleep_state_lock)){+.+.+.}, at: [] uart_set_chip_power+0x64/0x228 #5: (&tty->termios_mutex){+.+...}, at: [] cg2900_hci_uart_set_baudrate+0x34/0x8c #6: (&port_lock_key){?.....}, at: [] pl011_clock_on+0xc/0xc4 stack backtrace: [] (unwind_backtrace+0x0/0xec) from [] (print_usage_bug+0x184/0x1c4) [] (print_usage_bug+0x184/0x1c4) from [] (mark_lock_irq+0xbc/0x280) [] (mark_lock_irq+0xbc/0x280) from [] (mark_lock+0x2c8/0x3f8) [] (mark_lock+0x2c8/0x3f8) from [] (mark_held_locks+0x5c/0x80) [] (mark_held_locks+0x5c/0x80) from [] (trace_hardirqs_on_caller+0x138/0x18c) [] (trace_hardirqs_on_caller+0x138/0x18c) from [] (_raw_spin_unlock_irq+0x24/0x54) [] (_raw_spin_unlock_irq+0x24/0x54) from [] (rpm_callback+0x3c/0x5c) [] (rpm_callback+0x3c/0x5c) from [] (rpm_resume+0x2ec/0x3c0) [] (rpm_resume+0x2ec/0x3c0) from [] (__pm_runtime_resume+0x48/0x60) [] (__pm_runtime_resume+0x48/0x60) from [] (pl011_clock_on+0x34/0xc4) [] (pl011_clock_on+0x34/0xc4) from [] (pl011_set_termios+0x28/0x308) [] (pl011_set_termios+0x28/0x308) from [] (uart_change_speed+0x90/0x94) [] (uart_change_speed+0x90/0x94) from [] (uart_set_termios+0x68/0x1b4) [] (uart_set_termios+0x68/0x1b4) from [] (cg2900_hci_uart_set_baudrate+0x78/0x8c) [] (cg2900_hci_uart_set_baudrate+0x78/0x8c) from [] (uart_set_chip_power+0x100/0x228) [] (uart_set_chip_power+0x100/0x228) from [] (cg2900_open+0x228/0x49c) [] (cg2900_open+0x228/0x49c) from [] (btcg2900_open+0x84/0x188) [] (btcg2900_open+0x84/0x188) from [] (hci_dev_open+0x94/0x334) [] (hci_dev_open+0x94/0x334) from [] (hci_power_on+0x14/0x6c) [] (hci_power_on+0x14/0x6c) from [] (process_one_work+0x2ac/0x4c8) [] (process_one_work+0x2ac/0x4c8) from [] (worker_thread+0x144/0x234) [] (worker_thread+0x144/0x234) from [] (kthread+0x80/0x88) [] (kthread+0x80/0x88) from [] (kernel_thread_exit+0x0/0x8) Change-Id: I8b05184e348656a0d422b5b68267ee03246c6563 Signed-off-by: Rabin Vincent ST-Ericsson ID: 413918 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Id5a17f56dfa1b1b8c469237be5b9c236ad212137 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47173 Reviewed-by: QABUILD Tested-by: Rabin VINCENT Reviewed-by: Jonas ABERG Reviewed-by: Rabin VINCENT --- drivers/tty/serial/amba-pl011.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 5bbd97e61ff..bed430df99e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2308,6 +2308,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) amba_set_drvdata(dev, uap); + pm_runtime_irq_safe(&dev->dev); + pl011_clock_control_init(uap); ret = uart_add_one_port(&amba_reg, &uap->port); -- cgit v1.2.3 From 3c2571945199c6f9080b815d58a107a5efab4bf5 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 29 Feb 2012 14:13:13 +0100 Subject: config: mcde: remove synchronized_update The synchronized_update parameter is removed and replaced by SYNCSRC_OFF when disabling vertical synchronization for display. Signed-off-by: Anders Bauer --- arch/arm/configs/u8500_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 5be43983501..053b02ebc09 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -32,7 +32,6 @@ CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y -CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -- cgit v1.2.3 From 7d465f0f807deefcf396d0b61b938ac9893a3261 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 3 Feb 2012 11:19:05 +0100 Subject: mfd/ab8500: remaining mainline differences This collects the AB9540 changes that could not be included in the mainline patch set due to differences in the internal code (esp re GPIO driver). Signed-off-by: Linus Walleij Change-Id: Ia5ed55f1f44da923e8b9ae22f9b47b681bbb8403 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47743 --- drivers/mfd/ab8500-debugfs.c | 51 +++++++++++++++++++++++++++++++++++--------- include/linux/mfd/abx500.h | 1 + 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index befdbb31678..7f893aeba22 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -94,10 +94,11 @@ static u32 debug_address; static int irq_first; static int irq_last; -static u32 irq_count[AB8500_NR_IRQS]; +static u32 *irq_count; +static int num_irqs; -static struct device_attribute *dev_attr[AB8500_NR_IRQS]; -static char *event_name[AB8500_NR_IRQS]; +static struct device_attribute **dev_attr; +static char **event_name; /** * struct ab8500_reg_range @@ -483,7 +484,7 @@ static irqreturn_t ab8500_debug_handler(int irq, void *data) struct kobject *kobj = (struct kobject *)data; unsigned int irq_abb = irq - irq_first; - if (irq_abb < AB8500_NR_IRQS) + if (irq_abb < num_irqs) irq_count[irq_abb]++; /* * This makes it possible to use poll for events (POLLPRI | POLLERR) @@ -1337,7 +1338,7 @@ static ssize_t show_irq(struct device *dev, return err; irq_index = name - irq_first; - if (irq_index >= AB8500_NR_IRQS) + if (irq_index >= num_irqs) return -EINVAL; else return sprintf(buf, "%u\n", irq_count[irq_index]); @@ -1373,7 +1374,7 @@ static ssize_t ab8500_subscribe_write(struct file *file, } irq_index = user_val - irq_first; - if (irq_index >= AB8500_NR_IRQS) + if (irq_index >= num_irqs) return -EINVAL; /* @@ -1436,7 +1437,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file, } irq_index = user_val - irq_first; - if (irq_index >= AB8500_NR_IRQS) + if (irq_index >= num_irqs) return -EINVAL; /* Set irq count to 0 when unsubscribe */ @@ -1517,21 +1518,40 @@ static struct dentry *ab8500_gpadc_dir; static int __devinit ab8500_debug_probe(struct platform_device *plf) { struct dentry *file; + int ret = -ENOMEM; + struct ab8500 *ab8500; debug_bank = AB8500_MISC; debug_address = AB8500_REV_REG & 0x00FF; + ab8500 = dev_get_drvdata(plf->dev.parent); + num_irqs = ab8500->mask_size; + + irq_count = kzalloc(sizeof(irq_count)*num_irqs, GFP_KERNEL); + if (!irq_count) + return -ENOMEM; + + dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL); + if (!dev_attr) + goto out_freeirq_count; + + event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL); + if (!event_name) + goto out_freedev_attr; + irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); if (irq_first < 0) { dev_err(&plf->dev, "First irq not found, err %d\n", irq_first); - return irq_first; + ret = irq_first; + goto out_freeevent_name; } irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); if (irq_last < 0) { dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last); - return irq_last; + ret = irq_last; + goto out_freeevent_name; } ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); @@ -1654,12 +1674,23 @@ err: if (ab8500_dir) debugfs_remove_recursive(ab8500_dir); dev_err(&plf->dev, "failed to create debugfs entries.\n"); - return -ENOMEM; +out_freeevent_name: + kfree(event_name); +out_freedev_attr: + kfree(dev_attr); +out_freeirq_count: + kfree(irq_count); + + return ret; } static int __devexit ab8500_debug_remove(struct platform_device *plf) { debugfs_remove_recursive(ab8500_dir); + kfree(event_name); + kfree(dev_attr); + kfree(irq_count); + return 0; } diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 2cf7f7b1823..1eb4c001471 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -33,6 +33,7 @@ struct device; #define AB5500_1_0 0x20 #define AB5500_1_1 0x21 #define AB5500_2_0 0x24 +#define AB5500_2_1 0x25 /* * AB3100, EVENTA1, A2 and A3 event register flags -- cgit v1.2.3 From 9214e0ef6bbdd783a4332492ee93c22b2be6f38f Mon Sep 17 00:00:00 2001 From: Johan Rudholm Date: Thu, 2 Feb 2012 13:52:23 +0100 Subject: ARM: Update mach-types ST-Ericsson Linux next: NA ST-Ericsson ID: 371953 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I57af85e8d2b40cc21a6ba4260e94ba03c436c625 Signed-off-by: Johan Rudholm Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47588 Reviewed-by: Jonas ABERG Reviewed-by: Linus WALLEIJ --- arch/arm/tools/mach-types | 2796 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 2790 insertions(+), 6 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index f9c9f33f8cb..bb2f9e9d6d2 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,531 +12,3179 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# This is a cut-down version of the file; it contains only machines that -# are merged into mainline or have been edited in the machine database -# within the last 12 months. References to machine_is_NAME() do not count! -# -# Last update: Tue Dec 6 11:07:38 2011 +# Last update: Thu Feb 2 12:49:17 2012 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # ebsa110 ARCH_EBSA110 EBSA110 0 riscpc ARCH_RPC RISCPC 1 +nexuspci ARCH_NEXUSPCI NEXUSPCI 3 ebsa285 ARCH_EBSA285 EBSA285 4 netwinder ARCH_NETWINDER NETWINDER 5 cats ARCH_CATS CATS 6 +tbox ARCH_TBOX TBOX 7 +co285 ARCH_CO285 CO285 8 +clps7110 ARCH_CLPS7110 CLPS7110 9 +archimedes ARCH_ARC ARCHIMEDES 10 +a5k ARCH_A5K A5K 11 +etoile ARCH_ETOILE ETOILE 12 +lacie_nas ARCH_LACIE_NAS LACIE_NAS 13 +clps7500 ARCH_CLPS7500 CLPS7500 14 shark ARCH_SHARK SHARK 15 brutus SA1100_BRUTUS BRUTUS 16 personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17 +itsy SA1100_ITSY ITSY 18 l7200 ARCH_L7200 L7200 19 pleb SA1100_PLEB PLEB 20 integrator ARCH_INTEGRATOR INTEGRATOR 21 h3600 SA1100_H3600 H3600 22 +ixp1200 ARCH_IXP1200 IXP1200 23 p720t ARCH_P720T P720T 24 assabet SA1100_ASSABET ASSABET 25 +victor SA1100_VICTOR VICTOR 26 lart SA1100_LART LART 27 +ranger SA1100_RANGER RANGER 28 graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29 xp860 SA1100_XP860 XP860 30 cerf SA1100_CERF CERF 31 nanoengine SA1100_NANOENGINE NANOENGINE 32 +fpic SA1100_FPIC FPIC 33 +extenex1 SA1100_EXTENEX1 EXTENEX1 34 +sherman SA1100_SHERMAN SHERMAN 35 +accelent_sa SA1100_ACCELENT ACCELENT_SA 36 +accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37 +netport SA1100_NETPORT NETPORT 38 +pangolin SA1100_PANGOLIN PANGOLIN 39 +yopy SA1100_YOPY YOPY 40 +coolidge SA1100_COOLIDGE COOLIDGE 41 +huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42 +spotme ARCH_SPOTME SPOTME 43 +freebird ARCH_FREEBIRD FREEBIRD 44 +ti925 ARCH_TI925 TI925 45 +riscstation ARCH_RISCSTATION RISCSTATION 46 +cavy SA1100_CAVY CAVY 47 jornada720 SA1100_JORNADA720 JORNADA720 48 +omnimeter SA1100_OMNIMETER OMNIMETER 49 edb7211 ARCH_EDB7211 EDB7211 50 +citygo SA1100_CITYGO CITYGO 51 pfs168 SA1100_PFS168 PFS168 52 +spot SA1100_SPOT SPOT 53 flexanet SA1100_FLEXANET FLEXANET 54 +webpal ARCH_WEBPAL WEBPAL 55 +linpda SA1100_LINPDA LINPDA 56 +anakin ARCH_ANAKIN ANAKIN 57 +mvi SA1100_MVI MVI 58 +jupiter SA1100_JUPITER JUPITER 59 +psionw ARCH_PSIONW PSIONW 60 +aln SA1100_ALN ALN 61 +epxa ARCH_CAMELOT CAMELOT 62 +gds2200 SA1100_GDS2200 GDS2200 63 +netbook SA1100_PSION_SERIES7 PSION_SERIES7 64 +xfile SA1100_XFILE XFILE 65 +accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66 +ic200 ARCH_IC200 IC200 67 +creditlart SA1100_CREDITLART CREDITLART 68 +htm SA1100_HTM HTM 69 +iq80310 ARCH_IQ80310 IQ80310 70 +freebot SA1100_FREEBOT FREEBOT 71 +entel ARCH_ENTEL ENTEL 72 +enp3510 ARCH_ENP3510 ENP3510 73 +trizeps SA1100_TRIZEPS TRIZEPS 74 +nesa SA1100_NESA NESA 75 +venus ARCH_VENUS VENUS 76 +tardis ARCH_TARDIS TARDIS 77 +mercury ARCH_MERCURY MERCURY 78 +empeg SA1100_EMPEG EMPEG 79 +adi_evb ARCH_I80200FCC I80200FCC 80 +itt_cpb SA1100_ITT_CPB ITT_CPB 81 +svc SA1100_SVC SVC 82 +alpha2 SA1100_ALPHA2 ALPHA2 84 +alpha1 SA1100_ALPHA1 ALPHA1 85 +netarm ARCH_NETARM NETARM 86 simpad SA1100_SIMPAD SIMPAD 87 +pda1 ARCH_PDA1 PDA1 88 lubbock ARCH_LUBBOCK LUBBOCK 89 +aniko ARCH_ANIKO ANIKO 90 clep7212 ARCH_CLEP7212 CLEP7212 91 +cs89712 ARCH_CS89712 CS89712 92 +weararm SA1100_WEARARM WEARARM 93 +possio_px SA1100_POSSIO_PX POSSIO_PX 94 +sidearm SA1100_SIDEARM SIDEARM 95 +stork SA1100_STORK STORK 96 shannon SA1100_SHANNON SHANNON 97 +ace ARCH_ACE ACE 98 +ballyarm SA1100_BALLYARM BALLYARM 99 +simputer SA1100_SIMPUTER SIMPUTER 100 +nexterm SA1100_NEXTERM NEXTERM 101 +sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102 +gator SA1100_GATOR GATOR 103 +granite ARCH_GRANITE GRANITE 104 consus SA1100_CONSUS CONSUS 105 aaed2000 ARCH_AAED2000 AAED2000 106 cdb89712 ARCH_CDB89712 CDB89712 107 graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108 adsbitsy SA1100_ADSBITSY ADSBITSY 109 pxa_idp ARCH_PXA_IDP PXA_IDP 110 +plce ARCH_PLCE PLCE 111 pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112 +murphy ARCH_MEDALB MEDALB 113 +eagle ARCH_EAGLE EAGLE 114 +dsc21 ARCH_DSC21 DSC21 115 +dsc24 ARCH_DSC24 DSC24 116 +ti5472 ARCH_TI5472 TI5472 117 autcpu12 ARCH_AUTCPU12 AUTCPU12 118 +uengine ARCH_UENGINE UENGINE 119 +bluestem SA1100_BLUESTEM BLUESTEM 120 +xingu8 ARCH_XINGU8 XINGU8 121 +bushstb ARCH_BUSHSTB BUSHSTB 122 +epsilon1 SA1100_EPSILON1 EPSILON1 123 +balloon SA1100_BALLOON BALLOON 124 +puppy ARCH_PUPPY PUPPY 125 +elroy SA1100_ELROY ELROY 126 +gms720 ARCH_GMS720 GMS720 127 +s24x ARCH_S24X S24X 128 +jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129 +cx821xx ARCH_CX821XX CX821XX 130 +edb7312 ARCH_EDB7312 EDB7312 131 +bsa1110 SA1100_BSA1110 BSA1110 132 +powerpin ARCH_POWERPIN POWERPIN 133 +openarm ARCH_OPENARM OPENARM 134 +whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135 h3100 SA1100_H3100 H3100 136 +h3800 SA1100_H3800 H3800 137 +blue_v1 ARCH_BLUE_V1 BLUE_V1 138 +pxa_cerf ARCH_PXA_CERF PXA_CERF 139 +arm7tevb ARCH_ARM7TEVB ARM7TEVB 140 +d7400 SA1100_D7400 D7400 141 +piranha ARCH_PIRANHA PIRANHA 142 +sbcamelot SA1100_SBCAMELOT SBCAMELOT 143 +kings SA1100_KINGS KINGS 144 +smdk2400 ARCH_SMDK2400 SMDK2400 145 collie SA1100_COLLIE COLLIE 146 +idr ARCH_IDR IDR 147 badge4 SA1100_BADGE4 BADGE4 148 +webnet ARCH_WEBNET WEBNET 149 +d7300 SA1100_D7300 D7300 150 +cep SA1100_CEP CEP 151 fortunet ARCH_FORTUNET FORTUNET 152 +vc547x ARCH_VC547X VC547X 153 +filewalker SA1100_FILEWALKER FILEWALKER 154 +netgateway SA1100_NETGATEWAY NETGATEWAY 155 +symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156 +suns SA1100_SUNS SUNS 157 +frodo SA1100_FRODO FRODO 158 +ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159 mx1ads ARCH_MX1ADS MX1ADS 160 h7201 ARCH_H7201 H7201 161 h7202 ARCH_H7202 H7202 162 +amico ARCH_AMICO AMICO 163 +iam SA1100_IAM IAM 164 +tt530 SA1100_TT530 TT530 165 +sam2400 ARCH_SAM2400 SAM2400 166 +jornada56x SA1100_JORNADA56X JORNADA56X 167 +active SA1100_ACTIVE ACTIVE 168 iq80321 ARCH_IQ80321 IQ80321 169 +wid SA1100_WID WID 170 +sabinal ARCH_SABINAL SABINAL 171 +ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172 +miniprint SA1100_MINIPRINT MINIPRINT 173 +adm510x ARCH_ADM510X ADM510X 174 +svs200 SA1100_SVS200 SVS200 175 +atg_tcu ARCH_ATG_TCU ATG_TCU 176 +jornada820 SA1100_JORNADA820 JORNADA820 177 +s3c44b0 ARCH_S3C44B0 S3C44B0 178 +margis2 ARCH_MARGIS2 MARGIS2 179 ks8695 ARCH_KS8695 KS8695 180 +brh ARCH_BRH BRH 181 +s3c2410 ARCH_S3C2410 S3C2410 182 +possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183 +s3c2800 ARCH_S3C2800 S3C2800 184 +fleetwood SA1100_FLEETWOOD FLEETWOOD 185 +omaha ARCH_OMAHA OMAHA 186 +ta7 ARCH_TA7 TA7 187 +nova SA1100_NOVA NOVA 188 +hmk ARCH_HMK HMK 189 karo ARCH_KARO KARO 190 +fester SA1100_FESTER FESTER 191 +gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 +i519 ARCH_I519 I519 194 +nexio SA1100_NEXIO NEXIO 195 +bitbox SA1100_BITBOX BITBOX 196 +g200 SA1100_G200 G200 197 +gill SA1100_GILL GILL 198 +pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199 ceiva ARCH_CEIVA CEIVA 200 +fret SA1100_FRET FRET 201 +emailphone SA1100_EMAILPHONE EMAILPHONE 202 +h3900 ARCH_H3900 H3900 203 +pxa1 ARCH_PXA1 PXA1 204 +koan369 SA1100_KOAN369 KOAN369 205 +cogent ARCH_COGENT COGENT 206 +esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207 +esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208 +esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209 +hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210 +he500 ARCH_HE500 HE500 211 +inhandelf2 SA1100_INHANDELF2 INHANDELF2 212 +inhandftip SA1100_INHANDFTIP INHANDFTIP 213 +dnp1110 SA1100_DNP1110 DNP1110 214 +pnp1110 SA1100_PNP1110 PNP1110 215 +csb226 ARCH_CSB226 CSB226 216 +arnold SA1100_ARNOLD ARNOLD 217 voiceblue MACH_VOICEBLUE VOICEBLUE 218 +jz8028 ARCH_JZ8028 JZ8028 219 h5400 ARCH_H5400 H5400 220 +forte SA1100_FORTE FORTE 221 +acam SA1100_ACAM ACAM 222 +abox SA1100_ABOX ABOX 223 +atmel ARCH_ATMEL ATMEL 224 +sitsang ARCH_SITSANG SITSANG 225 +cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226 +mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227 +opus_a1 ARCH_OPUS_A1 OPUS_A1 228 +daytona ARCH_DAYTONA DAYTONA 229 +killbear SA1100_KILLBEAR KILLBEAR 230 +yoho ARCH_YOHO YOHO 231 +jasper ARCH_JASPER JASPER 232 +dsc25 ARCH_DSC25 DSC25 233 omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234 +mnci ARCH_RAMSES RAMSES 235 +s28x ARCH_S28X S28X 236 +mport3 ARCH_MPORT3 MPORT3 237 +pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 +pdb ARCH_PDB PDB 239 +blue_2g SA1100_BLUE_2G BLUE_2G 240 +bluearch SA1100_BLUEARCH BLUEARCH 241 ixdp2400 ARCH_IXDP2400 IXDP2400 242 ixdp2800 ARCH_IXDP2800 IXDP2800 243 +explorer SA1100_EXPLORER EXPLORER 244 ixdp425 ARCH_IXDP425 IXDP425 245 +chimp ARCH_CHIMP CHIMP 246 +stork_nest ARCH_STORK_NEST STORK_NEST 247 +stork_egg ARCH_STORK_EGG STORK_EGG 248 +wismo SA1100_WISMO WISMO 249 +ezlinx ARCH_EZLINX EZLINX 250 +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251 +adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252 +neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 +pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255 +lavinna SA1100_LAVINNA LAVINNA 256 +pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257 +innokom ARCH_INNOKOM INNOKOM 258 +bms ARCH_BMS BMS 259 ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260 +prpmc1100 ARCH_PRPMC1100 PRPMC1100 261 at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262 +armstick ARCH_ARMSTICK ARMSTICK 263 +armonie ARCH_ARMONIE ARMONIE 264 +mport1 ARCH_MPORT1 MPORT1 265 +s3c5410 ARCH_S3C5410 S3C5410 266 +zcp320a ARCH_ZCP320A ZCP320A 267 +i_box ARCH_I_BOX I_BOX 268 +stlc1502 ARCH_STLC1502 STLC1502 269 +siren ARCH_SIREN SIREN 270 +greenlake ARCH_GREENLAKE GREENLAKE 271 +argus ARCH_ARGUS ARGUS 272 +combadge SA1100_COMBADGE COMBADGE 273 +rokepxa ARCH_ROKEPXA ROKEPXA 274 cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 +guidea07 ARCH_GUIDEA07 GUIDEA07 276 +tat257 ARCH_TAT257 TAT257 277 +igp2425 ARCH_IGP2425 IGP2425 278 +bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 +ipod ARCH_IPOD IPOD 280 +adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 +trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 viper ARCH_VIPER VIPER 283 +adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 +adsagc SA1100_ADSAGC ADSAGC 285 +stp7312 ARCH_STP7312 STP7312 286 +nx_phnx MACH_NX_PHNX NX_PHNX 287 +wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 +inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 +iyonix ARCH_IYONIX IYONIX 291 +damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 +meg03 ARCH_MEG03 MEG03 293 +pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 +nwsc ARCH_NWSC NWSC 295 +nwlarm ARCH_NWLARM NWLARM 296 +ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297 +pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298 ixdp2401 ARCH_IXDP2401 IXDP2401 299 ixdp2801 ARCH_IXDP2801 IXDP2801 300 +zodiac ARCH_ZODIAC ZODIAC 301 +armmodul ARCH_ARMMODUL ARMMODUL 302 +ketop SA1100_KETOP KETOP 303 +av7200 ARCH_AV7200 AV7200 304 +arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305 +acq200 ARCH_ACQ200 ACQ200 306 +pt_dafit SA1100_PT_DAFIT PT_DAFIT 307 +ihba ARCH_IHBA IHBA 308 +quinque ARCH_QUINQUE QUINQUE 309 +nimbraone ARCH_NIMBRAONE NIMBRAONE 310 +nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 +nimbra210 ARCH_NIMBRA210 NIMBRA210 312 +hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 +labarm ARCH_LABARM LABARM 314 +m825xx ARCH_M825XX M825XX 315 +m7100 SA1100_M7100 M7100 316 +nipc2 ARCH_NIPC2 NIPC2 317 +fu7202 ARCH_FU7202 FU7202 318 +adsagx ARCH_ADSAGX ADSAGX 319 +pxa_pooh ARCH_PXA_POOH PXA_POOH 320 +bandon ARCH_BANDON BANDON 321 +pcm7210 ARCH_PCM7210 PCM7210 322 +nms9200 ARCH_NMS9200 NMS9200 323 +logodl ARCH_LOGODL LOGODL 324 +m7140 SA1100_M7140 M7140 325 +korebot ARCH_KOREBOT KOREBOT 326 iq31244 ARCH_IQ31244 IQ31244 327 +koan393 SA1100_KOAN393 KOAN393 328 +inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329 +gonzo ARCH_GONZO GONZO 330 bast ARCH_BAST BAST 331 +scanpass ARCH_SCANPASS SCANPASS 332 +ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333 +ta7s ARCH_TA7S TA7S 334 +ta7v ARCH_TA7V TA7V 335 +icarus SA1100_ICARUS ICARUS 336 +h1900 ARCH_H1900 H1900 337 +gemini SA1100_GEMINI GEMINI 338 +axim ARCH_AXIM AXIM 339 +audiotron ARCH_AUDIOTRON AUDIOTRON 340 +h2200 ARCH_H2200 H2200 341 +loox600 ARCH_LOOX600 LOOX600 342 +niop ARCH_NIOP NIOP 343 +dm310 ARCH_DM310 DM310 344 +seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345 +ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346 h1940 ARCH_H1940 H1940 347 +scorpio ARCH_SCORPIO SCORPIO 348 +viva ARCH_VIVA VIVA 349 +pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350 +csb335 ARCH_CSB335 CSB335 351 +ixrd425 ARCH_IXRD425 IXRD425 352 +iq80315 ARCH_IQ80315 IQ80315 353 +nmp7312 ARCH_NMP7312 NMP7312 354 +cx861xx ARCH_CX861XX CX861XX 355 enp2611 ARCH_ENP2611 ENP2611 356 +xda SA1100_XDA XDA 357 +csir_ims ARCH_CSIR_IMS CSIR_IMS 358 +ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359 +pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360 +toto ARCH_TOTO TOTO 361 s3c2440 ARCH_S3C2440 S3C2440 362 +ks8695p ARCH_KS8695P KS8695P 363 +se4000 ARCH_SE4000 SE4000 364 +quadriceps ARCH_QUADRICEPS QUADRICEPS 365 +bronco ARCH_BRONCO BRONCO 366 +esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367 +esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368 +s5c7375 ARCH_S5C7375 S5C7375 369 +spearhead ARCH_SPEARHEAD SPEARHEAD 370 +pantera ARCH_PANTERA PANTERA 371 +prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372 gumstix ARCH_GUMSTIX GUMSTIX 373 +rcube ARCH_RCUBE RCUBE 374 +rea_olv ARCH_REA_OLV REA_OLV 375 +pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 +s3c3410 ARCH_S3C3410 S3C3410 377 +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378 +mp1x ARCH_MP1X MP1X 379 +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380 +adsvgx ARCH_ADSVGX ADSVGX 381 omap_h2 MACH_OMAP_H2 OMAP_H2 382 +pelee ARCH_PELEE PELEE 383 e740 MACH_E740 E740 384 iq80331 ARCH_IQ80331 IQ80331 385 versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387 kev7a400 MACH_KEV7A400 KEV7A400 388 lpd7a400 MACH_LPD7A400 LPD7A400 389 lpd7a404 MACH_LPD7A404 LPD7A404 390 +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391 +janus2m ARCH_JANUS2M JANUS2M 392 +embtf MACH_EMBTF EMBTF 393 +hpm MACH_HPM HPM 394 +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395 +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396 +streetracer MACH_STREETRACER STREETRACER 397 +eframe MACH_EFRAME EFRAME 398 csb337 MACH_CSB337 CSB337 399 +pxa_lark MACH_PXA_LARK PXA_LARK 400 +pxa_pnp2110 MACH_PNP2110 PNP2110 401 +tcc72x MACH_TCC72X TCC72X 402 +altair MACH_ALTAIR ALTAIR 403 +kc3 MACH_KC3 KC3 404 +sinteftd MACH_SINTEFTD SINTEFTD 405 mainstone MACH_MAINSTONE MAINSTONE 406 +aday4x MACH_ADAY4X ADAY4X 407 +lite300 MACH_LITE300 LITE300 408 +s5c7376 MACH_S5C7376 S5C7376 409 +mt02 MACH_MT02 MT02 410 +mport3s MACH_MPORT3S MPORT3S 411 +ra_alpha MACH_RA_ALPHA RA_ALPHA 412 xcep MACH_XCEP XCEP 413 arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414 +stargate MACH_STARGATE STARGATE 415 +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 +elroy_jack MACH_ELROY_JACK ELROY_JACK 417 +backend MACH_BACKEND BACKEND 418 +s5linbox MACH_S5LINBOX S5LINBOX 419 nomadik MACH_NOMADIK NOMADIK 420 +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421 +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422 corgi MACH_CORGI CORGI 423 poodle MACH_POODLE POODLE 424 +ten MACH_TEN TEN 425 +roverp5p MACH_ROVERP5P ROVERP5P 426 +sc2700 MACH_SC2700 SC2700 427 +ex_eagle MACH_EX_EAGLE EX_EAGLE 428 +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429 +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430 +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431 +i819 MACH_I819 I819 432 +ixmb995e MACH_IXMB995E IXMB995E 433 +skyrider MACH_SKYRIDER SKYRIDER 434 +skyhawk MACH_SKYHAWK SKYHAWK 435 +enterprise MACH_ENTERPRISE ENTERPRISE 436 +dep2410 MACH_DEP2410 DEP2410 437 armcore MACH_ARMCORE ARMCORE 438 +hobbit MACH_HOBBIT HOBBIT 439 +h7210 MACH_H7210 H7210 440 +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441 +acc MACH_ACC ACC 442 +esl_sarva MACH_ESL_SARVA ESL_SARVA 443 +xm250 MACH_XM250 XM250 444 +t6tc1xb MACH_T6TC1XB T6TC1XB 445 +ess710 MACH_ESS710 ESS710 446 mx31ads MACH_MX31ADS MX31ADS 447 himalaya MACH_HIMALAYA HIMALAYA 448 +bolfenk MACH_BOLFENK BOLFENK 449 +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 edb9312 MACH_EDB9312 EDB9312 451 omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452 +aximx3 MACH_AXIMX3 AXIMX3 453 +eb67xdip MACH_EB67XDIP EB67XDIP 454 +webtxs MACH_WEBTXS WEBTXS 455 +hawk MACH_HAWK HAWK 456 +ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457 +expresso MACH_EXPRESSO EXPRESSO 458 +h4000 MACH_H4000 H4000 459 +dino MACH_DINO DINO 460 +ml675k MACH_ML675K ML675K 461 edb9301 MACH_EDB9301 EDB9301 462 edb9315 MACH_EDB9315 EDB9315 463 +reciva_tt MACH_RECIVA_TT RECIVA_TT 464 +cstcb01 MACH_CSTCB01 CSTCB01 465 +cstcb1 MACH_CSTCB1 CSTCB1 466 +shadwell MACH_SHADWELL SHADWELL 467 +goepel263 MACH_GOEPEL263 GOEPEL263 468 +acq100 MACH_ACQ100 ACQ100 469 +mx1fs2 MACH_MX1FS2 MX1FS2 470 +hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471 +sparky MACH_SPARKY SPARKY 472 +ns9750 MACH_NS9750 NS9750 473 +phoenix MACH_PHOENIX PHOENIX 474 vr1000 MACH_VR1000 VR1000 475 +deisterpxa MACH_DEISTERPXA DEISTERPXA 476 +bcm1160 MACH_BCM1160 BCM1160 477 +pcm022 MACH_PCM022 PCM022 478 +adsgcx MACH_ADSGCX ADSGCX 479 +dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480 +dm320 MACH_DM320 DM320 481 +markov MACH_MARKOV MARKOV 482 +cos7a400 MACH_COS7A400 COS7A400 483 +milano MACH_MILANO MILANO 484 +ue9328 MACH_UE9328 UE9328 485 +uex255 MACH_UEX255 UEX255 486 +ue2410 MACH_UE2410 UE2410 487 +a620 MACH_A620 A620 488 +ocelot MACH_OCELOT OCELOT 489 +cheetah MACH_CHEETAH CHEETAH 490 omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491 +zvue MACH_ZVUE ZVUE 492 +roverp1 MACH_ROVERP1 ROVERP1 493 +asidial2 MACH_ASIDIAL2 ASIDIAL2 494 +s3c24a0 MACH_S3C24A0 S3C24A0 495 e800 MACH_E800 E800 496 e750 MACH_E750 E750 497 +s3c5500 MACH_S3C5500 S3C5500 498 +smdk5500 MACH_SMDK5500 SMDK5500 499 +signalsync MACH_SIGNALSYNC SIGNALSYNC 500 +nbc MACH_NBC NBC 501 +kodiak MACH_KODIAK KODIAK 502 +netbookpro MACH_NETBOOKPRO NETBOOKPRO 503 +hw90200 MACH_HW90200 HW90200 504 +condor MACH_CONDOR CONDOR 505 +cup MACH_CUP CUP 506 +kite MACH_KITE KITE 507 scb9328 MACH_SCB9328 SCB9328 508 omap_h3 MACH_OMAP_H3 OMAP_H3 509 omap_h4 MACH_OMAP_H4 OMAP_H4 510 +n10 MACH_N10 N10 511 +montejade MACH_MONTAJADE MONTAJADE 512 +sg560 MACH_SG560 SG560 513 +dp1000 MACH_DP1000 DP1000 514 omap_osk MACH_OMAP_OSK OMAP_OSK 515 +rg100v3 MACH_RG100V3 RG100V3 516 +mx2ads MACH_MX2ADS MX2ADS 517 +pxa_kilo MACH_PXA_KILO PXA_KILO 518 +ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519 tosa MACH_TOSA TOSA 520 +mb2520f MACH_MB2520F MB2520F 521 +emc1000 MACH_EMC1000 EMC1000 522 +tidsc25 MACH_TIDSC25 TIDSC25 523 +akcpmxl MACH_AKCPMXL AKCPMXL 524 +av3xx MACH_AV3XX AV3XX 525 avila MACH_AVILA AVILA 526 +pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527 +pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528 +sgold MACH_SGOLD SGOLD 529 +oscar MACH_OSCAR OSCAR 530 +epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531 +xsengine MACH_XSENGINE XSENGINE 532 +ip600 MACH_IP600 IP600 533 +mcan2 MACH_MCAN2 MCAN2 534 +ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535 +skyminder MACH_SKYMINDER SKYMINDER 536 +lpd79520 MACH_LPD79520 LPD79520 537 edb9302 MACH_EDB9302 EDB9302 538 +hw90340 MACH_HW90340 HW90340 539 +cip_box MACH_CIP_BOX CIP_BOX 540 +ivpn MACH_IVPN IVPN 541 +rsoc2 MACH_RSOC2 RSOC2 542 husky MACH_HUSKY HUSKY 543 +boxer MACH_BOXER BOXER 544 shepherd MACH_SHEPHERD SHEPHERD 545 +aml42800aa MACH_AML42800AA AML42800AA 546 +lpc2294 MACH_LPC2294 LPC2294 548 +switchgrass MACH_SWITCHGRASS SWITCHGRASS 549 +ens_cmu MACH_ENS_CMU ENS_CMU 550 +mm6_sdb MACH_MM6_SDB MM6_SDB 551 +saturn MACH_SATURN SATURN 552 +i30030evb MACH_I30030EVB I30030EVB 553 +mxc27530evb MACH_MXC27530EVB MXC27530EVB 554 +smdk2800 MACH_SMDK2800 SMDK2800 555 +mtwilson MACH_MTWILSON MTWILSON 556 +ziti MACH_ZITI ZITI 557 +grandfather MACH_GRANDFATHER GRANDFATHER 558 +tengine MACH_TENGINE TENGINE 559 +s3c2460 MACH_S3C2460 S3C2460 560 +pdm MACH_PDM PDM 561 h4700 MACH_H4700 H4700 562 +h6300 MACH_H6300 H6300 563 +rz1700 MACH_RZ1700 RZ1700 564 +a716 MACH_A716 A716 565 +estk2440a MACH_ESTK2440A ESTK2440A 566 +atwixp425 MACH_ATWIXP425 ATWIXP425 567 +csb336 MACH_CSB336 CSB336 568 +rirm2 MACH_RIRM2 RIRM2 569 +cx23518 MACH_CX23518 CX23518 570 +cx2351x MACH_CX2351X CX2351X 571 +computime MACH_COMPUTIME COMPUTIME 572 +izarus MACH_IZARUS IZARUS 573 +pxa_rts MACH_RTS RTS 574 +se5100 MACH_SE5100 SE5100 575 +s3c2510 MACH_S3C2510 S3C2510 576 +csb437tl MACH_CSB437TL CSB437TL 577 +slauson MACH_SLAUSON SLAUSON 578 +pearlriver MACH_PEARLRIVER PEARLRIVER 579 +tdc_p210 MACH_TDC_P210 TDC_P210 580 +sg580 MACH_SG580 SG580 581 +wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582 +ipd MACH_IPD IPD 583 +pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584 +xaeniax MACH_XAENIAX XAENIAX 585 +somn4250 MACH_SOMN4250 SOMN4250 586 +pleb2 MACH_PLEB2 PLEB2 587 +cornwallis MACH_CORNWALLIS CORNWALLIS 588 +gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589 +chaffee MACH_CHAFFEE CHAFFEE 590 +rms101 MACH_RMS101 RMS101 591 rx3715 MACH_RX3715 RX3715 592 +swift MACH_SWIFT SWIFT 593 +roverp7 MACH_ROVERP7 ROVERP7 594 +pr818s MACH_PR818S PR818S 595 +trxpro MACH_TRXPRO TRXPRO 596 nslu2 MACH_NSLU2 NSLU2 597 e400 MACH_E400 E400 598 +trab MACH_TRAB TRAB 599 +cmc_pu2 MACH_CMC_PU2 CMC_PU2 600 +fulcrum MACH_FULCRUM FULCRUM 601 +netgate42x MACH_NETGATE42X NETGATE42X 602 +str710 MACH_STR710 STR710 603 ixdpg425 MACH_IXDPG425 IXDPG425 604 +tomtomgo MACH_TOMTOMGO TOMTOMGO 605 versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606 edb9307 MACH_EDB9307 EDB9307 607 +sg565 MACH_SG565 SG565 608 +lpd79524 MACH_LPD79524 LPD79524 609 +lpd79525 MACH_LPD79525 LPD79525 610 +rms100 MACH_RMS100 RMS100 611 kb9200 MACH_KB9200 KB9200 612 sx1 MACH_SX1 SX1 613 +hms39c7092 MACH_HMS39C7092 HMS39C7092 614 +armadillo MACH_ARMADILLO ARMADILLO 615 +ipcu MACH_IPCU IPCU 616 +loox720 MACH_LOOX720 LOOX720 617 ixdp465 MACH_IXDP465 IXDP465 618 ixdp2351 MACH_IXDP2351 IXDP2351 619 +adsvix MACH_ADSVIX ADSVIX 620 +dm270 MACH_DM270 DM270 621 +socltplus MACH_SOCLTPLUS SOCLTPLUS 622 +ecia MACH_ECIA ECIA 623 +cm4008 MACH_CM4008 CM4008 624 +p2001 MACH_P2001 P2001 625 +twister MACH_TWISTER TWISTER 626 +mudshark MACH_MUDSHARK MUDSHARK 627 +hb2 MACH_HB2 HB2 628 iq80332 MACH_IQ80332 IQ80332 629 +sendt MACH_SENDT SENDT 630 +mx2jazz MACH_MX2JAZZ MX2JAZZ 631 +multiio MACH_MULTIIO MULTIIO 632 +hrdisplay MACH_HRDISPLAY HRDISPLAY 633 +mxc27530ads MACH_MXC27530ADS MXC27530ADS 634 +trizeps3 MACH_TRIZEPS3 TRIZEPS3 635 +zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636 +zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637 +zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638 +zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639 +zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640 gtwx5715 MACH_GTWX5715 GTWX5715 641 +astro_jack MACH_ASTRO_JACK ASTRO_JACK 643 +tip03 MACH_TIP03 TIP03 644 +a9200ec MACH_A9200EC A9200EC 645 +pnx0105 MACH_PNX0105 PNX0105 646 +adcpoecpu MACH_ADCPOECPU ADCPOECPU 647 csb637 MACH_CSB637 CSB637 648 +mb9200 MACH_MB9200 MB9200 650 +kulun MACH_KULUN KULUN 651 +snapper MACH_SNAPPER SNAPPER 652 +optima MACH_OPTIMA OPTIMA 653 +dlhsbc MACH_DLHSBC DLHSBC 654 +x30 MACH_X30 X30 655 n30 MACH_N30 N30 656 +manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657 +ajax MACH_AJAX AJAX 658 nec_mp900 MACH_NEC_MP900 NEC_MP900 659 +vvtk1000 MACH_VVTK1000 VVTK1000 661 kafa MACH_KAFA KAFA 662 +vvtk3000 MACH_VVTK3000 VVTK3000 663 +pimx1 MACH_PIMX1 PIMX1 664 +ollie MACH_OLLIE OLLIE 665 +skymax MACH_SKYMAX SKYMAX 666 +jazz MACH_JAZZ JAZZ 667 +tel_t3 MACH_TEL_T3 TEL_T3 668 +aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669 +btweb MACH_BTWEB BTWEB 670 +dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671 +cm41xx MACH_CM41XX CM41XX 672 ts72xx MACH_TS72XX TS72XX 673 +nggpxa MACH_NGGPXA NGGPXA 674 +csb535 MACH_CSB535 CSB535 675 +csb536 MACH_CSB536 CSB536 676 +pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677 +praxis MACH_PRAXIS PRAXIS 678 +lh75411 MACH_LH75411 LH75411 679 otom MACH_OTOM OTOM 680 nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681 +loox410 MACH_LOOX410 LOOX410 682 +westlake MACH_WESTLAKE WESTLAKE 683 +nsb MACH_NSB NSB 684 +esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685 +esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686 +esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687 +esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688 +typhoon MACH_TYPHOON TYPHOON 689 +cnav MACH_CNAV CNAV 690 +a730 MACH_A730 A730 691 +netstar MACH_NETSTAR NETSTAR 692 +supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693 +shiva1100 MACH_SHIVA1100 SHIVA1100 694 +etexsc MACH_ETEXSC ETEXSC 695 +ixdpg465 MACH_IXDPG465 IXDPG465 696 +a9m2410 MACH_A9M2410 A9M2410 697 +a9m2440 MACH_A9M2440 A9M2440 698 +a9m9750 MACH_A9M9750 A9M9750 699 +a9m9360 MACH_A9M9360 A9M9360 700 +unc90 MACH_UNC90 UNC90 701 eco920 MACH_ECO920 ECO920 702 +satview MACH_SATVIEW SATVIEW 703 roadrunner MACH_ROADRUNNER ROADRUNNER 704 at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705 +gp32 MACH_GP32 GP32 706 +gem MACH_GEM GEM 707 +i858 MACH_I858 I858 708 +hx2750 MACH_HX2750 HX2750 709 +mxc91131evb MACH_MXC91131EVB MXC91131EVB 710 +p700 MACH_P700 P700 711 +cpe MACH_CPE CPE 712 spitz MACH_SPITZ SPITZ 713 +nimbra340 MACH_NIMBRA340 NIMBRA340 714 +lpc22xx MACH_LPC22XX LPC22XX 715 +omap_comet3 MACH_COMET3 COMET3 716 +omap_comet4 MACH_COMET4 COMET4 717 +csb625 MACH_CSB625 CSB625 718 +fortunet2 MACH_FORTUNET2 FORTUNET2 719 +s5h2200 MACH_S5H2200 S5H2200 720 +optorm920 MACH_OPTORM920 OPTORM920 721 +adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722 adssphere MACH_ADSSPHERE ADSSPHERE 723 +adsportal MACH_ADSPORTAL ADSPORTAL 724 +ln2410sbc MACH_LN2410SBC LN2410SBC 725 +cb3rufc MACH_CB3RUFC CB3RUFC 726 +mp2usb MACH_MP2USB MP2USB 727 +ntnp425c MACH_NTNP425C NTNP425C 728 colibri MACH_COLIBRI COLIBRI 729 +pcm7220 MACH_PCM7220 PCM7220 730 gateway7001 MACH_GATEWAY7001 GATEWAY7001 731 pcm027 MACH_PCM027 PCM027 732 +cmpxa MACH_CMPXA CMPXA 733 anubis MACH_ANUBIS ANUBIS 734 +ite8152 MACH_ITE8152 ITE8152 735 +lpc3xxx MACH_LPC3XXX LPC3XXX 736 +puppeteer MACH_PUPPETEER PUPPETEER 737 +e570 MACH_E570 E570 739 +x50 MACH_X50 X50 740 +recon MACH_RECON RECON 741 +xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742 +fpic2 MACH_FPIC2 FPIC2 743 akita MACH_AKITA AKITA 744 +a81 MACH_A81 A81 745 +svm_sc25x MACH_SVM_SC25X SVM_SC25X 746 +vt020 MACH_VADATECH020 VADATECH020 747 +tli MACH_TLI TLI 748 +edb9315lc MACH_EDB9315LC EDB9315LC 749 +passec MACH_PASSEC PASSEC 750 +ds_tiger MACH_DS_TIGER DS_TIGER 751 +e310 MACH_E310 E310 752 e330 MACH_E330 E330 753 +rt3000 MACH_RT3000 RT3000 754 nokia770 MACH_NOKIA770 NOKIA770 755 +pnx0106 MACH_PNX0106 PNX0106 756 +hx21xx MACH_HX21XX HX21XX 757 +faraday MACH_FARADAY FARADAY 758 +sbc9312 MACH_SBC9312 SBC9312 759 +batman MACH_BATMAN BATMAN 760 +jpd201 MACH_JPD201 JPD201 761 +mipsa MACH_MIPSA MIPSA 762 +kacom MACH_KACOM KACOM 763 +swarcocpu MACH_SWARCOCPU SWARCOCPU 764 +swarcodsl MACH_SWARCODSL SWARCODSL 765 +blueangel MACH_BLUEANGEL BLUEANGEL 766 +hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767 +banff MACH_BANFF BANFF 768 carmeva MACH_CARMEVA CARMEVA 769 +sam255 MACH_SAM255 SAM255 770 +ppm10 MACH_PPM10 PPM10 771 edb9315a MACH_EDB9315A EDB9315A 772 +sunset MACH_SUNSET SUNSET 773 stargate2 MACH_STARGATE2 STARGATE2 774 intelmote2 MACH_INTELMOTE2 INTELMOTE2 775 trizeps4 MACH_TRIZEPS4 TRIZEPS4 776 +mainstone2 MACH_MAINSTONE2 MAINSTONE2 777 +ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778 +tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779 +universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780 +hicoarm9 MACH_HICOARM9 HICOARM9 781 pnx4008 MACH_PNX4008 PNX4008 782 +kws6000 MACH_KWS6000 KWS6000 783 +portux920t MACH_PORTUX920T PORTUX920T 784 +ez_x5 MACH_EZ_X5 EZ_X5 785 +omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786 cpuat91 MACH_CPUAT91 CPUAT91 787 +rea9200 MACH_REA9200 REA9200 788 +acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789 +ixp425 MACH_IXP425 IXP425 790 +i30030ads MACH_I30030ADS I30030ADS 791 +perch MACH_PERCH PERCH 792 +eis05r1 MACH_EIS05R1 EIS05R1 793 +pepperpad MACH_PEPPERPAD PEPPERPAD 794 +sb3010 MACH_SB3010 SB3010 795 +rm9200 MACH_RM9200 RM9200 796 +dma03 MACH_DMA03 DMA03 797 +road_s101 MACH_ROAD_S101 ROAD_S101 798 iq81340sc MACH_IQ81340SC IQ81340SC 799 +iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800 iq81340mc MACH_IQ81340MC IQ81340MC 801 +iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802 +iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803 +mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804 +cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805 +gesbc931x MACH_GESBC931X GESBC931X 806 +centipad MACH_CENTIPAD CENTIPAD 807 +armsoc MACH_ARMSOC ARMSOC 808 +se4200 MACH_SE4200 SE4200 809 +ems197a MACH_EMS197A EMS197A 810 micro9 MACH_MICRO9 MICRO9 811 micro9l MACH_MICRO9L MICRO9L 812 +uc5471dsp MACH_UC5471DSP UC5471DSP 813 +sj5471eng MACH_SJ5471ENG SJ5471ENG 814 +none MACH_CMPXA26X CMPXA26X 815 +nc1 MACH_NC NC 816 omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817 +ajax52x MACH_AJAX52X AJAX52X 818 +siriustar MACH_SIRIUSTAR SIRIUSTAR 819 +iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820 +at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821 +biosafe MACH_BIOSAFE BIOSAFE 822 +mp1000 MACH_MP1000 MP1000 823 +parsy MACH_PARSY PARSY 824 +ccxp270 MACH_CCXP CCXP 825 +omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826 realview_eb MACH_REALVIEW_EB REALVIEW_EB 827 +samoa MACH_SAMOA SAMOA 828 +palmt3 MACH_PALMT3 PALMT3 829 +i878 MACH_I878 I878 830 borzoi MACH_BORZOI BORZOI 831 +gecko MACH_GECKO GECKO 832 +ds101 MACH_DS101 DS101 833 +omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834 palmld MACH_PALMLD PALMLD 835 +cc9c MACH_CC9C CC9C 836 +sbc1670 MACH_SBC1670 SBC1670 837 ixdp28x5 MACH_IXDP28X5 IXDP28X5 838 omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839 +ml696k MACH_ML696K ML696K 840 arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841 osiris MACH_OSIRIS OSIRIS 842 +maestro MACH_MAESTRO MAESTRO 843 palmte2 MACH_PALMTE2 PALMTE2 844 +ixbbm MACH_IXBBM IXBBM 845 mx27ads MACH_MX27ADS MX27ADS 846 +ax8004 MACH_AX8004 AX8004 847 at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848 loft MACH_LOFT LOFT 849 +magpie MACH_MAGPIE MAGPIE 850 mx21ads MACH_MX21ADS MX21ADS 851 +mb87m3400 MACH_MB87M3400 MB87M3400 852 +mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853 +davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854 +htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855 +tpad MACH_TPAD TPAD 856 +roverp3 MACH_ROVERP3 ROVERP3 857 +jornada928 MACH_JORNADA928 JORNADA928 858 +mv88fxx81 MACH_MV88FXX81 MV88FXX81 859 +stmp36xx MACH_STMP36XX STMP36XX 860 +sxni79524 MACH_SXNI79524 SXNI79524 861 ams_delta MACH_AMS_DELTA AMS_DELTA 862 +uranium MACH_URANIUM URANIUM 863 +ucon MACH_UCON UCON 864 nas100d MACH_NAS100D NAS100D 865 +l083 MACH_L083_1000 L083_1000 866 +ezx MACH_EZX EZX 867 +pnx5220 MACH_PNX5220 PNX5220 868 +butte MACH_BUTTE BUTTE 869 +srm2 MACH_SRM2 SRM2 870 +dsbr MACH_DSBR DSBR 871 +crystalball MACH_CRYSTALBALL CRYSTALBALL 872 +tinypxa27x MACH_TINYPXA27X TINYPXA27X 873 +herbie MACH_HERBIE HERBIE 874 magician MACH_MAGICIAN MAGICIAN 875 +cm4002 MACH_CM4002 CM4002 876 +b4 MACH_B4 B4 877 +maui MACH_MAUI MAUI 878 +cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879 nxdkn MACH_NXDKN NXDKN 880 +mio8390 MACH_MIO8390 MIO8390 881 +omi_board MACH_OMI_BOARD OMI_BOARD 882 +mx21civ MACH_MX21CIV MX21CIV 883 +mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884 palmtx MACH_PALMTX PALMTX 885 s3c2413 MACH_S3C2413 S3C2413 887 +samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888 +wg302v1 MACH_WG302V1 WG302V1 889 wg302v2 MACH_WG302V2 WG302V2 890 +eb42x MACH_EB42X EB42X 891 +iq331es MACH_IQ331ES IQ331ES 892 +cosydsp MACH_COSYDSP COSYDSP 893 +uplat7d_proto MACH_UPLAT7D UPLAT7D 894 +ptdavinci MACH_PTDAVINCI PTDAVINCI 895 +mbus MACH_MBUS MBUS 896 +nadia2vb MACH_NADIA2VB NADIA2VB 897 +r1000 MACH_R1000 R1000 898 +hw90250 MACH_HW90250 HW90250 899 omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900 davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901 +omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902 +olocreek MACH_OLOCREEK OLOCREEK 903 palmz72 MACH_PALMZ72 PALMZ72 904 nxdb500 MACH_NXDB500 NXDB500 905 apf9328 MACH_APF9328 APF9328 906 +omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907 +omap_twip MACH_OMAP_TWIP OMAP_TWIP 908 +treo650 MACH_TREO650 TREO650 909 +acumen MACH_ACUMEN ACUMEN 910 +xp100 MACH_XP100 XP100 911 +fs2410 MACH_FS2410 FS2410 912 +pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913 +sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914 +bsemserver MACH_BSEMSERVER BSEMSERVER 915 +netclient MACH_NETCLIENT NETCLIENT 916 palmt5 MACH_PALMT5 PALMT5 917 palmtc MACH_PALMTC PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 +mxc30030evb MACH_MXC30030EVB MXC30030EVB 920 +rea_cpu2 MACH_REA_2D REA_2D 921 +eti3e524 MACH_TI3E524 TI3E524 922 ateb9200 MACH_ATEB9200 ATEB9200 923 +auckland MACH_AUCKLAND AUCKLAND 924 +ak3220m MACH_AK3320M AK3320M 925 +duramax MACH_DURAMAX DURAMAX 926 n35 MACH_N35 N35 927 +pronghorn MACH_PRONGHORN PRONGHORN 928 +fundy MACH_FUNDY FUNDY 929 logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930 +cpu777 MACH_CPU777 CPU777 931 +simicon9201 MACH_SIMICON9201 SIMICON9201 932 +leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933 +cm922txa10 MACH_CM922TXA10 CM922TXA10 934 +sandgate MACH_PXA PXA 935 +sandgate2 MACH_SANDGATE2 SANDGATE2 936 +sandgate2g MACH_SANDGATE2G SANDGATE2G 937 +sandgate2p MACH_SANDGATE2P SANDGATE2P 938 +fred_jack MACH_FRED_JACK FRED_JACK 939 +ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940 nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941 +netdcu8 MACH_NETDCU8 NETDCU8 942 +ng_fvx538 MACH_NG_FVX538 NG_FVX538 944 +ng_fvs338 MACH_NG_FVS338 NG_FVS338 945 +pnx4103 MACH_PNX4103 PNX4103 946 +hesdb MACH_HESDB HESDB 947 +xsilo MACH_XSILO XSILO 948 espresso MACH_ESPRESSO ESPRESSO 949 +emlc MACH_EMLC EMLC 950 +sisteron MACH_SISTERON SISTERON 951 rx1950 MACH_RX1950 RX1950 952 +tsc_venus MACH_TSC_VENUS TSC_VENUS 953 +ds101j MACH_DS101J DS101J 954 +mxc30030ads MACH_MXC30030ADS MXC30030ADS 955 +fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956 +dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957 gesbc9312 MACH_GESBC9312 GESBC9312 958 +htcapache MACH_HTCAPACHE HTCAPACHE 959 +ixdp435 MACH_IXDP435 IXDP435 960 +catprovt100 MACH_CATPROVT100 CATPROVT100 961 +picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962 picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963 dsmg600 MACH_DSMG600 DSMG600 964 +empc2 MACH_EMPC2 EMPC2 965 +ventura MACH_VENTURA VENTURA 966 +phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967 +ij3k MACH_IJ3K IJ3K 968 +pisgah MACH_PISGAH PISGAH 969 omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970 +sg720 MACH_SG720 SG720 971 +redfox MACH_REDFOX REDFOX 972 +mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973 +tpf106 MACH_TPF106 TPF106 974 +at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975 +rcmt2 MACH_SLEDB SLEDB 976 +ontrack MACH_ONTRACK ONTRACK 977 +pm1200 MACH_PM1200 PM1200 978 +ess24562 MACH_ESS24XXX ESS24XXX 979 +coremp7 MACH_COREMP7 COREMP7 980 +nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981 +stvc8380 MACH_STVC8380 STVC8380 982 +teklynx MACH_TEKLYNX TEKLYNX 983 +carbonado MACH_CARBONADO CARBONADO 984 +sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985 snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986 +pgigim MACH_PGIGIM PGIGIM 987 +ptx9160p2 MACH_PTX9160P2 PTX9160P2 988 +dcore1 MACH_DCORE1 DCORE1 989 +victorpxa MACH_VICTORPXA VICTORPXA 990 +mx2dtb MACH_MX2DTB MX2DTB 991 +pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992 omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993 +bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994 +hw50251 MACH_HW50251 HW50251 995 +ibox MACH_IBOX IBOX 996 +atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997 +pt2026 MACH_PT2026 PT2026 998 +htcalpine MACH_HTCALPINE HTCALPINE 999 +bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000 +vcoreii MACH_VCOREII VCOREII 1001 +pdnb3 MACH_PDNB3 PDNB3 1002 +htcbeetles MACH_HTCBEETLES HTCBEETLES 1003 +s3c6400 MACH_S3C6400 S3C6400 1004 +s3c2443 MACH_S3C2443 S3C2443 1005 +omap_ldk MACH_OMAP_LDK OMAP_LDK 1006 +smdk2460 MACH_SMDK2460 SMDK2460 1007 +smdk2440 MACH_SMDK2440 SMDK2440 1008 smdk2412 MACH_SMDK2412 SMDK2412 1009 +webbox MACH_WEBBOX WEBBOX 1010 +cwwndp MACH_CWWNDP CWWNDP 1011 +i839 MACH_DRAGON DRAGON 1012 +opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013 +ccm2200 MACH_CCM2200 CCM2200 1014 +etwarm MACH_ETWARM ETWARM 1015 +m93030 MACH_M93030 M93030 1016 +cc7u MACH_CC7U CC7U 1017 +mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018 +nexus MACH_NEXUS NEXUS 1019 +desman MACH_DESMAN DESMAN 1020 +bkde303 MACH_BKDE303 BKDE303 1021 smdk2413 MACH_SMDK2413 SMDK2413 1022 +aml_m7200 MACH_AML_M7200 AML_M7200 1023 aml_m5900 MACH_AML_M5900 AML_M5900 1024 +sg640 MACH_SG640 SG640 1025 +edg79524 MACH_EDG79524 EDG79524 1026 +ai2410 MACH_AI2410 AI2410 1027 +ixp465 MACH_IXP465 IXP465 1028 balloon3 MACH_BALLOON3 BALLOON3 1029 +heins MACH_HEINS HEINS 1030 +mpluseva MACH_MPLUSEVA MPLUSEVA 1031 +rt042 MACH_RT042 RT042 1032 +cwiem MACH_CWIEM CWIEM 1033 +cm_x270 MACH_CM_X270 CM_X270 1034 +cm_x255 MACH_CM_X255 CM_X255 1035 +esh_at91 MACH_ESH_AT91 ESH_AT91 1036 +sandgate3 MACH_SANDGATE3 SANDGATE3 1037 +primo MACH_PRIMO PRIMO 1038 +gemstone MACH_GEMSTONE GEMSTONE 1039 +pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040 +sidewinder MACH_SIDEWINDER SIDEWINDER 1041 +picomod1 MACH_PICOMOD1 PICOMOD1 1042 +sg590 MACH_SG590 SG590 1043 +akai9307 MACH_AKAI9307 AKAI9307 1044 +fontaine MACH_FONTAINE FONTAINE 1045 +wombat MACH_WOMBAT WOMBAT 1046 +acq300 MACH_ACQ300 ACQ300 1047 +mod272 MACH_MOD_270 MOD_270 1048 +vmc_vc0820 MACH_VC0820 VC0820 1049 +ani_aim MACH_ANI_AIM ANI_AIM 1050 +jellyfish MACH_JELLYFISH JELLYFISH 1051 +amanita MACH_AMANITA AMANITA 1052 +vlink MACH_VLINK VLINK 1053 +dexflex MACH_DEXFLEX DEXFLEX 1054 +eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055 +arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056 +tabla MACH_TABLA TABLA 1057 +mdirac3 MACH_MDIRAC3 MDIRAC3 1058 +mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059 +at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060 +ani_apm MACH_ANI_APM ANI_APM 1061 +ella1 MACH_ELLA1 ELLA1 1062 +inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063 +inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064 +empos_xm MACH_EMPOS_XM EMPOS_XM 1065 +empos MACH_EMPOS EMPOS 1066 +empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067 +empos_sm MACH_EMPOS_SM EMPOS_SM 1068 +egret MACH_EGRET EGRET 1069 +ostrich MACH_OSTRICH OSTRICH 1070 +n50 MACH_N50 N50 1071 ecbat91 MACH_ECBAT91 ECBAT91 1072 +stareast MACH_STAREAST STAREAST 1073 +dspg_dw MACH_DSPG_DW DSPG_DW 1074 onearm MACH_ONEARM ONEARM 1075 +mrg110_6 MACH_MRG110_6 MRG110_6 1076 +wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077 +xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078 +msm6100 MACH_MSM6100 MSM6100 1079 +eti_b1 MACH_ETI_B1 ETI_B1 1080 +za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081 +bit2440 MACH_BIT2440 BIT2440 1082 +nbi MACH_NBI NBI 1083 smdk2443 MACH_SMDK2443 SMDK2443 1084 +vdavinci MACH_VDAVINCI VDAVINCI 1085 +atc6 MACH_ATC6 ATC6 1086 +multmdw MACH_MULTMDW MULTMDW 1087 +mba2440 MACH_MBA2440 MBA2440 1088 +ecsd MACH_ECSD ECSD 1089 +palmz31 MACH_PALMZ31 PALMZ31 1090 fsg MACH_FSG FSG 1091 +razor101 MACH_RAZOR101 RAZOR101 1092 +opera_tdm MACH_OPERA_TDM OPERA_TDM 1093 +comcerto MACH_COMCERTO COMCERTO 1094 +tb0319 MACH_TB0319 TB0319 1095 +kws8000 MACH_KWS8000 KWS8000 1096 +b2 MACH_B2 B2 1097 +lcl54 MACH_LCL54 LCL54 1098 at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099 glantank MACH_GLANTANK GLANTANK 1100 n2100 MACH_N2100 N2100 1101 +n4100 MACH_N4100 N4100 1102 +rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103 +sg8100 MACH_SG8100 SG8100 1104 +im42xx MACH_IM42XX IM42XX 1105 +ftxx MACH_FTXX FTXX 1106 +lwfusion MACH_LWFUSION LWFUSION 1107 qt2410 MACH_QT2410 QT2410 1108 kixrp435 MACH_KIXRP435 KIXRP435 1109 +ccw9c MACH_CCW9C CCW9C 1110 +dabhs MACH_DABHS DABHS 1111 +gzmx MACH_GZMX GZMX 1112 +ipnw100ap MACH_IPNW100AP IPNW100AP 1113 cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114 +cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115 +cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116 +cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117 +nx70v MACH_NX70V NX70V 1118 +at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119 +se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120 +mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121 +vcmx212 MACH_VCMX212 VCMX212 1122 +lynx MACH_LYNX LYNX 1123 +at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124 +hw86052 MACH_HW86052 HW86052 1125 +pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126 edb9302a MACH_EDB9302A EDB9302A 1127 edb9307a MACH_EDB9307A EDB9307A 1128 +ct_dfs MACH_CT_DFS CT_DFS 1129 +pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130 +xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131 +smdk2442b MACH_SMDK2442B SMDK2442B 1132 +xnode MACH_XNODE XNODE 1133 +aidx270 MACH_AIDX270 AIDX270 1134 +rema MACH_REMA REMA 1135 +bps1000 MACH_BPS1000 BPS1000 1136 +hw90350 MACH_HW90350 HW90350 1137 omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138 +bluetouch MACH_BLUETOUCH BLUETOUCH 1139 vstms MACH_VSTMS VSTMS 1140 +xsbase270 MACH_XSBASE270 XSBASE270 1141 +at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142 +adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143 +oti4110 MACH_OTI4110 OTI4110 1144 +hme_pxa MACH_HME_PXA HME_PXA 1145 +deisterdca MACH_DEISTERDCA DEISTERDCA 1146 +ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147 +ces_mtr MACH_CES_MTR CES_MTR 1148 +tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149 +everest MACH_EVEREST EVEREST 1150 +pnx4010 MACH_PNX4010 PNX4010 1151 +oxnas MACH_OXNAS OXNAS 1152 +fiori MACH_FIORI FIORI 1153 +ml1200 MACH_ML1200 ML1200 1154 +pecos MACH_PECOS PECOS 1155 +nb2xxx MACH_NB2XXX NB2XXX 1156 +hw6900 MACH_HW6900 HW6900 1157 +cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158 +quicksilver MACH_QUICKSILVER QUICKSILVER 1159 +uplat926 MACH_UPLAT926 UPLAT926 1160 +dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161 +dtk2410 MACH_DTK2410 DTK2410 1162 +chili MACH_CHILI CHILI 1163 +demeter MACH_DEMETER DEMETER 1164 +dionysus MACH_DIONYSUS DIONYSUS 1165 +as352x MACH_AS352X AS352X 1166 +service MACH_SERVICE SERVICE 1167 +cs_e9301 MACH_CS_E9301 CS_E9301 1168 micro9m MACH_MICRO9M MICRO9M 1169 +ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170 +ql201b MACH_QL201B QL201B 1171 +bbm MACH_BBM BBM 1174 +exxx MACH_EXXX EXXX 1175 +wma11b MACH_WMA11B WMA11B 1176 +pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177 +g500 MACH_G500 G500 1178 bug MACH_BUG BUG 1179 +mx33ads MACH_MX33ADS MX33ADS 1180 +chub MACH_CHUB CHUB 1181 +neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182 +w90n740 MACH_W90N740 W90N740 1183 +medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184 +ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185 +dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186 +pm9261 MACH_PM9261 PM9261 1187 +ml7304 MACH_ML7304 ML7304 1189 +ucp250 MACH_UCP250 UCP250 1190 +intboard MACH_INTBOARD INTBOARD 1191 +gulfstream MACH_GULFSTREAM GULFSTREAM 1192 +labquest MACH_LABQUEST LABQUEST 1193 +vcmx313 MACH_VCMX313 VCMX313 1194 +urg200 MACH_URG200 URG200 1195 +cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196 +netdcu9 MACH_NETDCU9 NETDCU9 1197 +netdcu10 MACH_NETDCU10 NETDCU10 1198 +dspg_dga MACH_DSPG_DGA DSPG_DGA 1199 +dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200 +solos MACH_SOLOS SOLOS 1201 at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202 +osstbox MACH_OSSTBOX OSSTBOX 1203 +kbat9261 MACH_KBAT9261 KBAT9261 1204 +ct1100 MACH_CT1100 CT1100 1205 +akcppxa MACH_AKCPPXA AKCPPXA 1206 +ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207 +hitrack MACH_HITRACK HITRACK 1208 +syme1 MACH_SYME1 SYME1 1209 +syhl1 MACH_SYHL1 SYHL1 1210 +empca400 MACH_EMPCA400 EMPCA400 1211 em7210 MACH_EM7210 EM7210 1212 +htchermes MACH_HTCHERMES HTCHERMES 1213 +eti_c1 MACH_ETI_C1 ETI_C1 1214 +ac100 MACH_AC100 AC100 1216 +sneetch MACH_SNEETCH SNEETCH 1217 +studentmate MACH_STUDENTMATE STUDENTMATE 1218 +zir2410 MACH_ZIR2410 ZIR2410 1219 +zir2413 MACH_ZIR2413 ZIR2413 1220 +dlonip3 MACH_DLONIP3 DLONIP3 1221 +instream MACH_INSTREAM INSTREAM 1222 +ambarella MACH_AMBARELLA AMBARELLA 1223 +nevis MACH_NEVIS NEVIS 1224 +htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225 +ql202b MACH_QL202B QL202B 1226 vpac270 MACH_VPAC270 VPAC270 1227 +rd129 MACH_RD129 RD129 1228 +htcwizard MACH_HTCWIZARD HTCWIZARD 1229 treo680 MACH_TREO680 TREO680 1230 +tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231 zylonite MACH_ZYLONITE ZYLONITE 1233 +gene1270 MACH_GENE1270 GENE1270 1234 +zir2412 MACH_ZIR2412 ZIR2412 1235 mx31lite MACH_MX31LITE MX31LITE 1236 +t700wx MACH_T700WX T700WX 1237 +vf100 MACH_VF100 VF100 1238 +nsb2 MACH_NSB2 NSB2 1239 +nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240 +nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241 +n4100pro MACH_N4100PRO N4100PRO 1242 +sam9260 MACH_SAM9260 SAM9260 1243 +omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244 +indy2410 MACH_INDY2410 INDY2410 1245 +nelt_a MACH_NELT_A NELT_A 1246 +n311 MACH_N311 N311 1248 +at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249 +at91leppe MACH_AT91LEPPE AT91LEPPE 1250 +at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251 +apc7100 MACH_APC7100 APC7100 1252 +stargazer MACH_STARGAZER STARGAZER 1253 +sonata MACH_SONATA SONATA 1254 +schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255 +aztool MACH_AZTOOL AZTOOL 1256 mioa701 MACH_MIOA701 MIOA701 1257 +sxni9260 MACH_SXNI9260 SXNI9260 1258 +mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259 armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260 +mb9260 MACH_MB9260 MB9260 1261 +mb9263 MACH_MB9263 MB9263 1262 +ipac9302 MACH_IPAC9302 IPAC9302 1263 cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264 +gallium MACH_GALLIUM GALLIUM 1265 +msc2410 MACH_MSC2410 MSC2410 1266 +ghi270 MACH_GHI270 GHI270 1267 +davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268 +oiab MACH_OIAB OIAB 1269 smdk6400 MACH_SMDK6400 SMDK6400 1270 nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271 +greenphone MACH_GREENPHONE GREENPHONE 1272 +compex42x MACH_COMPEXWP18 COMPEXWP18 1273 +xmate MACH_XMATE XMATE 1274 +energizer MACH_ENERGIZER ENERGIZER 1275 +ime1 MACH_IME1 IME1 1276 +sweda_tms MACH_SWEDATMS SWEDATMS 1277 +ntnp435c MACH_NTNP435C NTNP435C 1278 +spectro2 MACH_SPECTRO2 SPECTRO2 1279 +h6039 MACH_H6039 H6039 1280 ep80219 MACH_EP80219 EP80219 1281 +samoa_ii MACH_SAMOA_II SAMOA_II 1282 +cwmxl MACH_CWMXL CWMXL 1283 +as9200 MACH_AS9200 AS9200 1284 +sfx1149 MACH_SFX1149 SFX1149 1285 +navi010 MACH_NAVI010 NAVI010 1286 +multmdp MACH_MULTMDP MULTMDP 1287 +scb9520 MACH_SCB9520 SCB9520 1288 +htcathena MACH_HTCATHENA HTCATHENA 1289 +xp179 MACH_XP179 XP179 1290 +h4300 MACH_H4300 H4300 1291 goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292 +mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293 +adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294 +adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295 +mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296 em_x270 MACH_EM_X270 EM_X270 1297 +tpp302 MACH_TPP302 TPP302 1298 +tpp104 MACH_TPM104 TPM104 1299 +tpm102 MACH_TPM102 TPM102 1300 +tpm109 MACH_TPM109 TPM109 1301 +fbxo1 MACH_FBXO1 FBXO1 1302 +hxd8 MACH_HXD8 HXD8 1303 neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304 +emtest MACH_EMTEST EMTEST 1305 +ad6900 MACH_AD6900 AD6900 1306 +europa MACH_EUROPA EUROPA 1307 +metroconnect MACH_METROCONNECT METROCONNECT 1308 +ez_s2410 MACH_EZ_S2410 EZ_S2410 1309 +ez_s2440 MACH_EZ_S2440 EZ_S2440 1310 +ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311 +ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312 +ez_x7 MACH_EZ_X7 EZ_X7 1313 +godotdb MACH_GODOTDB GODOTDB 1314 +mistral MACH_MISTRAL MISTRAL 1315 +msm MACH_MSM MSM 1316 +ct5910 MACH_CT5910 CT5910 1317 +ct5912 MACH_CT5912 CT5912 1318 +argonst_mp MACH_HYNET_INE HYNET_INE 1319 +hynet_app MACH_HYNET_APP HYNET_APP 1320 +msm7200 MACH_MSM7200 MSM7200 1321 +msm7600 MACH_MSM7600 MSM7600 1322 +ceb255 MACH_CEB255 CEB255 1323 +ciel MACH_CIEL CIEL 1324 +slm5650 MACH_SLM5650 SLM5650 1325 at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326 +comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327 +sbc2410x MACH_SBC2410X SBC2410X 1328 +at4x0bd MACH_AT4X0BD AT4X0BD 1329 +cbifr MACH_CBIFR CBIFR 1330 +arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331 +matrix520 MACH_MATRIX520 MATRIX520 1332 +matrix510 MACH_MATRIX510 MATRIX510 1333 +matrix500 MACH_MATRIX500 MATRIX500 1334 +m501 MACH_M501 M501 1335 +aaeon1270 MACH_AAEON1270 AAEON1270 1336 +matrix500ev MACH_MATRIX500EV MATRIX500EV 1337 +pac500 MACH_PAC500 PAC500 1338 +pnx8181 MACH_PNX8181 PNX8181 1339 colibri320 MACH_COLIBRI320 COLIBRI320 1340 +aztoolbb MACH_AZTOOLBB AZTOOLBB 1341 +aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342 +dvlhost MACH_DVLHOST DVLHOST 1343 +zir9200 MACH_ZIR9200 ZIR9200 1344 +zir9260 MACH_ZIR9260 ZIR9260 1345 +cocopah MACH_COCOPAH COCOPAH 1346 +nds MACH_NDS NDS 1347 +rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348 +fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349 +classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350 cam60 MACH_CAM60 CAM60 1351 +mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352 +datacall MACH_DATACALL DATACALL 1353 at91eb01 MACH_AT91EB01 AT91EB01 1354 +rty MACH_RTY RTY 1355 +dwl2100 MACH_DWL2100 DWL2100 1356 +vinsi MACH_VINSI VINSI 1357 db88f5281 MACH_DB88F5281 DB88F5281 1358 csb726 MACH_CSB726 CSB726 1359 +tik27 MACH_TIK27 TIK27 1360 +mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361 +rirm3 MACH_RIRM3 RIRM3 1362 +pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363 +adx_abox MACH_ADX_ABOX ADX_ABOX 1365 +adx_tpid MACH_ADX_TPID ADX_TPID 1366 +minicheck MACH_MINICHECK MINICHECK 1367 +idam MACH_IDAM IDAM 1368 +mario_mx MACH_MARIO_MX MARIO_MX 1369 +vi1888 MACH_VI1888 VI1888 1370 +zr4230 MACH_ZR4230 ZR4230 1371 +t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372 +syhq2 MACH_SYHQ2 SYHQ2 1373 +computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374 +oratis MACH_ORATIS ORATIS 1375 +mikko MACH_MIKKO MIKKO 1376 +holon MACH_HOLON HOLON 1377 +olip8 MACH_OLIP8 OLIP8 1378 +ghi270hg MACH_GHI270HG GHI270HG 1379 davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380 davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381 +blackriver MACH_BLACKRIVER BLACKRIVER 1383 +sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384 +cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385 +quark963 MACH_QUARK963 QUARK963 1386 +csb735 MACH_CSB735 CSB735 1387 littleton MACH_LITTLETON LITTLETON 1388 +mio_p550 MACH_MIO_P550 MIO_P550 1389 +motion2440 MACH_MOTION2440 MOTION2440 1390 +imm500 MACH_IMM500 IMM500 1391 +homematic MACH_HOMEMATIC HOMEMATIC 1392 +ermine MACH_ERMINE ERMINE 1393 +kb9202b MACH_KB9202B KB9202B 1394 +hs1xx MACH_HS1XX HS1XX 1395 +studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396 +arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397 +dep2410k MACH_DEP2410K DEP2410K 1398 +xxsvideo MACH_XXSVIDEO XXSVIDEO 1399 +im4004 MACH_IM4004 IM4004 1400 +ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401 +lep9261 MACH_LEP9261 LEP9261 1402 +svenmeb MACH_SVENMEB SVENMEB 1403 +fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404 +nxhx MACH_NXHX NXHX 1406 realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407 +ids500 MACH_IDS500 IDS500 1408 +ors_n725 MACH_ORS_N725 ORS_N725 1409 +hsdarm MACH_HSDARM HSDARM 1410 +sha_pon003 MACH_SHA_PON003 SHA_PON003 1411 +sha_pon004 MACH_SHA_PON004 SHA_PON004 1412 +sha_pon007 MACH_SHA_PON007 SHA_PON007 1413 +sha_pon011 MACH_SHA_PON011 SHA_PON011 1414 +h6042 MACH_H6042 H6042 1415 +h6043 MACH_H6043 H6043 1416 +looxc550 MACH_LOOXC550 LOOXC550 1417 +cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418 +app3xx MACH_APP3XX APP3XX 1419 +sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420 +treo700p MACH_TREO700P TREO700P 1421 +treo700w MACH_TREO700W TREO700W 1422 +treo750 MACH_TREO750 TREO750 1423 +treo755p MACH_TREO755P TREO755P 1424 +ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425 +sarge MACH_SARGE SARGE 1426 +a696 MACH_A696 A696 1427 +turtle1916 MACH_TURTLE TURTLE 1428 mx27_3ds MACH_MX27_3DS MX27_3DS 1430 +bishop MACH_BISHOP BISHOP 1431 +pxx MACH_PXX PXX 1432 +redwood MACH_REDWOOD REDWOOD 1433 +omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436 +omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437 +sardine MACH_SARDINE SARDINE 1438 halibut MACH_HALIBUT HALIBUT 1439 trout MACH_TROUT TROUT 1440 +goldfish MACH_GOLDFISH GOLDFISH 1441 +gesbc2440 MACH_GESBC2440 GESBC2440 1442 +nomad MACH_NOMAD NOMAD 1443 +rosalind MACH_ROSALIND ROSALIND 1444 +cc9p9215 MACH_CC9P9215 CC9P9215 1445 +cc9p9210 MACH_CC9P9210 CC9P9210 1446 +cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447 +cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448 +nasffe MACH_NASFFE NASFFE 1449 +tn2x0bd MACH_TN2X0BD TN2X0BD 1450 +gwmpxa MACH_GWMPXA GWMPXA 1451 +exyplus MACH_EXYPLUS EXYPLUS 1452 +jadoo21 MACH_JADOO21 JADOO21 1453 +looxn560 MACH_LOOXN560 LOOXN560 1454 +bonsai MACH_BONSAI BONSAI 1455 +adsmilgato MACH_ADSMILGATO ADSMILGATO 1456 +gba MACH_GBA GBA 1457 +h6044 MACH_H6044 H6044 1458 +app MACH_APP APP 1459 tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460 herald MACH_HERALD HERALD 1461 +artemis MACH_ARTEMIS ARTEMIS 1462 +htctitan MACH_HTCTITAN HTCTITAN 1463 +qranium MACH_QRANIUM QRANIUM 1464 +adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465 +adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466 +bboard MACH_BBOARD BBOARD 1467 +cambria MACH_CAMBRIA CAMBRIA 1468 +mt7xxx MACH_MT7XXX MT7XXX 1469 +matrix512 MACH_MATRIX512 MATRIX512 1470 +matrix522 MACH_MATRIX522 MATRIX522 1471 +ipac5010 MACH_IPAC5010 IPAC5010 1472 +sakura MACH_SAKURA SAKURA 1473 +grocx MACH_GROCX GROCX 1474 +pm9263 MACH_PM9263 PM9263 1475 sim_one MACH_SIM_ONE SIM_ONE 1476 +acq132 MACH_ACQ132 ACQ132 1477 +datr MACH_DATR DATR 1478 +actux1 MACH_ACTUX1 ACTUX1 1479 +actux2 MACH_ACTUX2 ACTUX2 1480 +actux3 MACH_ACTUX3 ACTUX3 1481 +flexit MACH_FLEXIT FLEXIT 1482 +bh2x0bd MACH_BH2X0BD BH2X0BD 1483 +atb2002 MACH_ATB2002 ATB2002 1484 +xenon MACH_XENON XENON 1485 +fm607 MACH_FM607 FM607 1486 +matrix514 MACH_MATRIX514 MATRIX514 1487 +matrix524 MACH_MATRIX524 MATRIX524 1488 +inpod MACH_INPOD INPOD 1489 jive MACH_JIVE JIVE 1490 +tll_mx21 MACH_TLL_MX21 TLL_MX21 1491 +sbc2800 MACH_SBC2800 SBC2800 1492 +cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493 +ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494 +ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495 +ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496 +aml_m8000 MACH_AML_M8000 AML_M8000 1497 +snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498 +omap_bbx MACH_OMAP_BBX OMAP_BBX 1499 +ucn2410 MACH_UCN2410 UCN2410 1500 sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501 +eti_c2 MACH_ETI_C2 ETI_C2 1502 +avalanche MACH_AVALANCHE AVALANCHE 1503 realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504 +dp1500 MACH_DP1500 DP1500 1505 +apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506 yl9200 MACH_YL9200 YL9200 1507 rd88f5182 MACH_RD88F5182 RD88F5182 1508 kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509 +se_poet MACH_SE_POET SE_POET 1510 mx31_3ds MACH_MX31_3DS MX31_3DS 1511 +r270 MACH_R270 R270 1512 +armour21 MACH_ARMOUR21 ARMOUR21 1513 +dt2 MACH_DT2 DT2 1514 +vt4 MACH_VT4 VT4 1515 +tyco320 MACH_TYCO320 TYCO320 1516 +adma MACH_ADMA ADMA 1517 +wp188 MACH_WP188 WP188 1518 +corsica MACH_CORSICA CORSICA 1519 +bigeye MACH_BIGEYE BIGEYE 1520 +tll5000 MACH_TLL5000 TLL5000 1522 +bebot MACH_BEBOT BEBOT 1523 qong MACH_QONG QONG 1524 +tcompact MACH_TCOMPACT TCOMPACT 1525 +puma5 MACH_PUMA5 PUMA5 1526 +elara MACH_ELARA ELARA 1527 +ellington MACH_ELLINGTON ELLINGTON 1528 +xda_atom MACH_XDA_ATOM XDA_ATOM 1529 +energizer2 MACH_ENERGIZER2 ENERGIZER2 1530 +odin MACH_ODIN ODIN 1531 +actux4 MACH_ACTUX4 ACTUX4 1532 +esl_omap MACH_ESL_OMAP ESL_OMAP 1533 omap2evm MACH_OMAP2EVM OMAP2EVM 1534 omap3evm MACH_OMAP3EVM OMAP3EVM 1535 +adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536 +monaco MACH_MONACO MONACO 1537 +levante MACH_LEVANTE LEVANTE 1538 +tmxipx425 MACH_TMXIPX425 TMXIPX425 1539 +leep MACH_LEEP LEEP 1540 +raad MACH_RAAD RAAD 1541 dns323 MACH_DNS323 DNS323 1542 +ap1000 MACH_AP1000 AP1000 1543 +a9sam6432 MACH_A9SAM6432 A9SAM6432 1544 +shiny MACH_SHINY SHINY 1545 omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546 +csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547 nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548 +c270 MACH_C270 C270 1549 +sentry MACH_SENTRY SENTRY 1550 pcm038 MACH_PCM038 PCM038 1551 +anc300 MACH_ANC300 ANC300 1552 +htckaiser MACH_HTCKAISER HTCKAISER 1553 +sbat100 MACH_SBAT100 SBAT100 1554 +modunorm MACH_MODUNORM MODUNORM 1555 +pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556 +flank MACH_FLANK FLANK 1557 +sirloin MACH_SIRLOIN SIRLOIN 1558 +brisket MACH_BRISKET BRISKET 1559 +chuck MACH_CHUCK CHUCK 1560 +otter MACH_OTTER OTTER 1561 +davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562 +phreedom MACH_PHREEDOM PHREEDOM 1563 +sg310 MACH_SG310 SG310 1564 ts209 MACH_TS209 TS209 1565 at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566 +tion9315 MACH_TION9315 TION9315 1567 +mast MACH_MAST MAST 1568 +pfw MACH_PFW PFW 1569 +yl_p2440 MACH_YL_P2440 YL_P2440 1570 +zsbc32 MACH_ZSBC32 ZSBC32 1571 +omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572 +imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573 mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574 +mx37_3ds MACH_MX37_3DS MX37_3DS 1575 +rcc MACH_RCC RCC 1576 +dmp MACH_ARM9 ARM9 1577 vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578 +scly1000 MACH_SCLY1000 SCLY1000 1579 +fontel_ep MACH_FONTEL_EP FONTEL_EP 1580 +voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581 +tt9200 MACH_TT9200 TT9200 1582 +digi2410 MACH_DIGI2410 DIGI2410 1583 terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584 linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585 +motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587 +motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588 +motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589 +motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590 +ur2410 MACH_UR2410 UR2410 1591 +tas9261 MACH_TAS9261 TAS9261 1592 +davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593 +davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594 +stargazer2 MACH_STARGAZER2 STARGAZER2 1595 e350 MACH_E350 E350 1596 +wpcm450 MACH_WPCM450 WPCM450 1597 +cartesio MACH_CARTESIO CARTESIO 1598 +toybox MACH_TOYBOX TOYBOX 1599 +tx27 MACH_TX27 TX27 1600 ts409 MACH_TS409 TS409 1601 +p300 MACH_P300 P300 1602 +xdacomet MACH_XDACOMET XDACOMET 1603 +dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604 +ow MACH_OW OW 1605 +armebs3 MACH_ARMEBS3 ARMEBS3 1606 +u3 MACH_U3 U3 1607 +smdk2450 MACH_SMDK2450 SMDK2450 1608 rsi_ews MACH_RSI_EWS RSI_EWS 1609 +tnb MACH_TNB TNB 1610 +toepath MACH_TOEPATH TOEPATH 1611 +kb9263 MACH_KB9263 KB9263 1612 +mt7108 MACH_MT7108 MT7108 1613 +smtr2440 MACH_SMTR2440 SMTR2440 1614 +manao MACH_MANAO MANAO 1615 cm_x300 MACH_CM_X300 CM_X300 1616 +gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617 +lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618 +arma37 MACH_ARMA37 ARMA37 1619 +mendel MACH_MENDEL MENDEL 1620 +pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621 +unit2p MACH_UNIT2P UNIT2P 1622 +inc20otter MACH_INC20OTTER INC20OTTER 1623 at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624 +sc_ge2 MACH_STORCENTER STORCENTER 1625 smdk6410 MACH_SMDK6410 SMDK6410 1626 u300 MACH_U300 U300 1627 +u500 MACH_U500 U500 1628 +ds9260 MACH_DS9260 DS9260 1629 +riverrock MACH_RIVERROCK RIVERROCK 1630 +scibath MACH_SCIBATH SCIBATH 1631 +at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632 wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633 +multimedia MACH_MULTIMEDIA MULTIMEDIA 1634 +marvin MACH_MARVIN MARVIN 1635 +x500 MACH_X500 X500 1636 +awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637 +palermoc MACH_PALERMOC PALERMOC 1638 omap_ldp MACH_OMAP_LDP OMAP_LDP 1639 +ip500 MACH_IP500 IP500 1640 +ase2 MACH_ASE2 ASE2 1642 +mx35evb MACH_MX35EVB MX35EVB 1643 +aml_m8050 MACH_AML_M8050 AML_M8050 1644 mx35_3ds MACH_MX35_3DS MX35_3DS 1645 +mars MACH_MARS MARS 1646 neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647 +badger MACH_BADGER BADGER 1648 trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649 +trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650 +marlin MACH_MARLIN MARLIN 1651 ts78xx MACH_TS78XX TS78XX 1652 +hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653 +at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654 +ne1board MACH_NE1BOARD NE1BOARD 1655 +zante MACH_ZANTE ZANTE 1656 sffsdr MACH_SFFSDR SFFSDR 1657 +tw2662 MACH_TW2662 TW2662 1658 +vf10xx MACH_VF10XX VF10XX 1659 +zoran43xx MACH_ZORAN43XX ZORAN43XX 1660 +sonix926 MACH_SONIX926 SONIX926 1661 +celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662 +cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663 +tw5334 MACH_TW5334 TW5334 1664 +omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665 +nal_hlite MACH_NAL_HLITE NAL_HLITE 1666 +htcvogue MACH_HTCVOGUE HTCVOGUE 1667 +smartweb MACH_SMARTWEB SMARTWEB 1668 +mv86xx MACH_MV86XX MV86XX 1669 +mv87xx MACH_MV87XX MV87XX 1670 +songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671 +younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672 pcm037 MACH_PCM037 PCM037 1673 +mmvp MACH_MMVP MMVP 1674 +mmap MACH_MMAP MMAP 1675 +ptid2410 MACH_PTID2410 PTID2410 1676 +james_926 MACH_JAMES_926 JAMES_926 1677 +fm6000 MACH_FM6000 FM6000 1678 db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680 rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681 rd88f6281 MACH_RD88F6281 RD88F6281 1682 db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683 smdk2416 MACH_SMDK2416 SMDK2416 1685 +oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686 +oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687 +rovern6 MACH_ROVERN6 ROVERN6 1688 +pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689 wbd111 MACH_WBD111 WBD111 1690 +elaracpe MACH_ELARACPE ELARACPE 1691 +mabv3 MACH_MABV3 MABV3 1692 mv2120 MACH_MV2120 MV2120 1693 +csb737 MACH_CSB737 CSB737 1695 mx51_3ds MACH_MX51_3DS MX51_3DS 1696 +g900 MACH_G900 G900 1697 +apf27 MACH_APF27 APF27 1698 +ggus2000 MACH_GGUS2000 GGUS2000 1699 +omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700 imx27lite MACH_IMX27LITE IMX27LITE 1701 +almex MACH_ALMEX ALMEX 1702 +control MACH_CONTROL CONTROL 1703 +mba2410 MACH_MBA2410 MBA2410 1704 +volcano MACH_VOLCANO VOLCANO 1705 +zenith MACH_ZENITH ZENITH 1706 +muchip MACH_MUCHIP MUCHIP 1707 +magellan MACH_MAGELLAN MAGELLAN 1708 usb_a9260 MACH_USB_A9260 USB_A9260 1709 usb_a9263 MACH_USB_A9263 USB_A9263 1710 qil_a9260 MACH_QIL_A9260 QIL_A9260 1711 +cme9210 MACH_CME9210 CME9210 1712 +hczh4 MACH_HCZH4 HCZH4 1713 +spearbasic MACH_SPEARBASIC SPEARBASIC 1714 +dep2440 MACH_DEP2440 DEP2440 1715 +hdl_gxr MACH_HDL_GXR HDL_GXR 1716 +hdl_gt MACH_HDL_GT HDL_GT 1717 +hdl_4g MACH_HDL_4G HDL_4G 1718 +s3c6000 MACH_S3C6000 S3C6000 1719 +mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720 +mpx220 MACH_MPX220 MPX220 1721 kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722 +htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723 +htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724 +lg_ks20 MACH_LG_KS20 LG_KS20 1725 +hhgps MACH_HHGPS HHGPS 1726 nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727 +insight MACH_INSIGHT INSIGHT 1728 sapphire MACH_SAPPHIRE SAPPHIRE 1729 +csb637xo MACH_CSB637XO CSB637XO 1730 +evisiong MACH_EVISIONG EVISIONG 1731 stmp37xx MACH_STMP37XX STMP37XX 1732 stmp378x MACH_STMP378X STMP378X 1733 +tnt MACH_TNT TNT 1734 +tbxt MACH_TBXT TBXT 1735 +playmate MACH_PLAYMATE PLAYMATE 1736 +pns10 MACH_PNS10 PNS10 1737 +eznavi MACH_EZNAVI EZNAVI 1738 +ps4000 MACH_PS4000 PS4000 1739 ezx_a780 MACH_EZX_A780 EZX_A780 1740 ezx_e680 MACH_EZX_E680 EZX_E680 1741 ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742 ezx_e6 MACH_EZX_E6 EZX_E6 1743 ezx_e2 MACH_EZX_E2 EZX_E2 1744 ezx_a910 MACH_EZX_A910 EZX_A910 1745 +cwmx31 MACH_CWMX31 CWMX31 1746 +sl2312 MACH_SL2312 SL2312 1747 +blenny MACH_BLENNY BLENNY 1748 +ds107 MACH_DS107 DS107 1749 +dsx07 MACH_DSX07 DSX07 1750 +picocom1 MACH_PICOCOM1 PICOCOM1 1751 +lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752 +ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753 +kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754 +m700 MACH_M700 M700 1755 edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756 zipit2 MACH_ZIPIT2 ZIPIT2 1757 +hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758 +daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759 +sg560usb MACH_SG560USB SG560USB 1760 omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761 +usr8200 MACH_USR8200 USR8200 1762 +s1s65k MACH_S1S65K S1S65K 1763 +s2s65a MACH_S2S65A S2S65A 1764 +icore MACH_ICORE ICORE 1765 mss2 MACH_MSS2 MSS2 1766 +belmont MACH_BELMONT BELMONT 1767 +asusp525 MACH_ASUSP525 ASUSP525 1768 lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769 +hipxa MACH_HIPXA HIPXA 1770 mx25_3ds MACH_MX25_3DS MX25_3DS 1771 +m800 MACH_M800 M800 1772 omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773 +prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774 +mx31bt1 MACH_MX31BT1 MX31BT1 1775 +atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776 +mx31cicada MACH_MX31CICADA MX31CICADA 1777 +mi424wr MACH_MI424WR MI424WR 1778 +axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 +at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781 +ep9302 MACH_EP9302 EP9302 1782 +at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 +cybook3 MACH_CYBOOK3 CYBOOK3 1784 +wdg002 MACH_WDG002 WDG002 1785 +sg560adsl MACH_SG560ADSL SG560ADSL 1786 +nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787 dove_db MACH_DOVE_DB DOVE_DB 1788 +vandihud MACH_VANDIHUD VANDIHUD 1790 +magx_e8 MACH_MAGX_E8 MAGX_E8 1791 +magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792 +magx_v8 MACH_MAGX_V8 MAGX_V8 1793 +magx_u9 MACH_MAGX_U9 MAGX_U9 1794 +toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795 +zw4400 MACH_ZW4400 ZW4400 1796 +marat91 MACH_MARAT91 MARAT91 1797 overo MACH_OVERO OVERO 1798 at2440evb MACH_AT2440EVB AT2440EVB 1799 neocore926 MACH_NEOCORE926 NEOCORE926 1800 wnr854t MACH_WNR854T WNR854T 1801 +imx27 MACH_IMX27 IMX27 1802 +moose_db MACH_MOOSE_DB MOOSE_DB 1803 +fab4 MACH_FAB4 FAB4 1804 +htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805 +fiona MACH_FIONA FIONA 1806 +mxc30030_x MACH_MXC30030_X MXC30030_X 1807 +bmp1000 MACH_BMP1000 BMP1000 1808 +logi9200 MACH_LOGI9200 LOGI9200 1809 +tqma31 MACH_TQMA31 TQMA31 1810 +ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811 rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812 +sifmain MACH_SIFMAIN SIFMAIN 1813 +sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814 +cc9m2443 MACH_CC9M2443 CC9M2443 1815 +xaria300 MACH_XARIA300 XARIA300 1816 +it9200 MACH_IT9200 IT9200 1817 rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818 +kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819 +pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820 +jade MACH_JADE JADE 1821 +ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822 +gprisc3 MACH_GPRISC3 GPRISC3 1823 stamp9g20 MACH_STAMP9G20 STAMP9G20 1824 +smdk6430 MACH_SMDK6430 SMDK6430 1825 smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 saar MACH_SAAR SAAR 1828 +deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829 at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830 +linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831 +hit_b0 MACH_HIT_B0 HIT_B0 1832 +adx_rmu MACH_ADX_RMU ADX_RMU 1833 +xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834 +edb9407a MACH_EDB9407A EDB9407A 1835 +dtb9608 MACH_DTB9608 DTB9608 1836 +em104v1 MACH_EM104V1 EM104V1 1837 +demo MACH_DEMO DEMO 1838 +logi9260 MACH_LOGI9260 LOGI9260 1839 +mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840 usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841 +picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842 +cs_e9315 MACH_CS_E9315 CS_E9315 1843 +qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844 +sha_pon020 MACH_SHA_PON020 SHA_PON020 1845 +nad MACH_NAD NAD 1846 +sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847 +sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848 +davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849 +uwc MACH_UWC UWC 1850 mxlads MACH_MXLADS MXLADS 1851 +htcnike MACH_HTCNIKE HTCNIKE 1852 +deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853 +cme9210js MACH_CME9210JS CME9210JS 1854 +cc9p9360 MACH_CC9P9360 CC9P9360 1855 +mocha MACH_MOCHA MOCHA 1856 +wapd170ag MACH_WAPD170AG WAPD170AG 1857 linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858 afeb9260 MACH_AFEB9260 AFEB9260 1859 +w90x900 MACH_W90X900 W90X900 1860 +w90x700 MACH_W90X700 W90X700 1861 +kt300ip MACH_KT300IP KT300IP 1862 +kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863 +srcm MACH_SRCM SRCM 1864 +wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865 +openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866 +osprey2 MACH_OSPREY2 OSPREY2 1867 +kbio9260 MACH_KBIO9260 KBIO9260 1868 +ginza MACH_GINZA GINZA 1869 +a636n MACH_A636N A636N 1870 imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871 +nemoc MACH_NEMOC NEMOC 1872 +geneva MACH_GENEVA GENEVA 1873 +htcpharos MACH_HTCPHAROS HTCPHAROS 1874 +neonc MACH_NEONC NEONC 1875 +nas7100 MACH_NAS7100 NAS7100 1876 +teuphone MACH_TEUPHONE TEUPHONE 1877 +annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878 +csb733 MACH_CSB733 CSB733 1879 +bk3 MACH_BK3 BK3 1880 +omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881 +et9261cp MACH_ET9261CP ET9261CP 1882 +jasperc MACH_JASPERC JASPERC 1883 +issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884 +ued MACH_UED UED 1885 +esiblade MACH_ESIBLADE ESIBLADE 1886 +eye02 MACH_EYE02 EYE02 1887 +imx27kbd MACH_IMX27KBD IMX27KBD 1888 +kixvp435 MACH_KIXVP435 KIXVP435 1890 +kixnp435 MACH_KIXNP435 KIXNP435 1891 +africa MACH_AFRICA AFRICA 1892 +nh233 MACH_NH233 NH233 1893 rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894 +bcm4760 MACH_BCM4760 BCM4760 1895 +eddy_v2 MACH_EDDY_V2 EDDY_V2 1896 realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897 +hid_a7 MACH_HID_A7 HID_A7 1898 +hero MACH_HERO HERO 1899 +omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900 realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901 micro9s MACH_MICRO9S MICRO9S 1902 +mako MACH_MAKO MAKO 1903 +xdaflame MACH_XDAFLAME XDAFLAME 1904 +phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905 +limestone MACH_LIMESTONE LIMESTONE 1906 +iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907 rut100 MACH_RUT100 RUT100 1908 +asusp535 MACH_ASUSP535 ASUSP535 1909 +htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910 +sygdg1 MACH_SYGDG1 SYGDG1 1911 +sygdg2 MACH_SYGDG2 SYGDG2 1912 +seoul MACH_SEOUL SEOUL 1913 +salerno MACH_SALERNO SALERNO 1914 +ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915 +msm7201a MACH_MSM7201A MSM7201A 1916 +lpr1 MACH_LPR1 LPR1 1917 +armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918 g3evm MACH_G3EVM G3EVM 1919 +z3_dm355 MACH_Z3_DM355 Z3_DM355 1920 w90p910evb MACH_W90P910EVB W90P910EVB 1921 +w90p920evb MACH_W90P920EVB W90P920EVB 1922 w90p950evb MACH_W90P950EVB W90P950EVB 1923 w90n960evb MACH_W90N960EVB W90N960EVB 1924 +camhd MACH_CAMHD CAMHD 1925 +mvc100 MACH_MVC100 MVC100 1926 +electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927 +htcjade MACH_HTCJADE HTCJADE 1928 +memphis MACH_MEMPHIS MEMPHIS 1929 +imx27sbc MACH_IMX27SBC IMX27SBC 1930 +lextar MACH_LEXTAR LEXTAR 1931 mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932 ncp MACH_NCP NCP 1933 +z32an_series MACH_Z32AN Z32AN 1934 +tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935 +omap3_wl MACH_OMAP3_WL OMAP3_WL 1936 +chumby MACH_CHUMBY CHUMBY 1937 +atsarm9 MACH_ATSARM9 ATSARM9 1938 davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939 +bahamas MACH_BAHAMAS BAHAMAS 1940 +das MACH_DAS DAS 1941 +minidas MACH_MINIDAS MINIDAS 1942 +vk1000 MACH_VK1000 VK1000 1943 centro MACH_CENTRO CENTRO 1944 +ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945 +edgeconnect MACH_EDGECONNECT EDGECONNECT 1946 +nd27000 MACH_ND27000 ND27000 1947 +cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948 +ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949 +pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950 +blackstone MACH_BLACKSTONE BLACKSTONE 1951 +topaz MACH_TOPAZ TOPAZ 1952 +aixle MACH_AIXLE AIXLE 1953 +mw998 MACH_MW998 MW998 1954 nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955 +vsc5605ev MACH_VSC5605EV VSC5605EV 1956 +nt98700dk MACH_NT98700DK NT98700DK 1957 +icontact MACH_ICONTACT ICONTACT 1958 +swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959 +swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960 +bbox_p16 MACH_BBOX_P16 BBOX_P16 1961 +bstd MACH_BSTD BSTD 1962 +sbc2440ii MACH_SBC2440II SBC2440II 1963 +pcm034 MACH_PCM034 PCM034 1964 +neso MACH_NESO NESO 1965 +wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966 omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967 +totemnova MACH_TOTEMNOVA TOTEMNOVA 1968 +c5000 MACH_C5000 C5000 1969 +unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970 +ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 +arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 +cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 eukrea_cpuimx27 MACH_EUKREA_CPUIMX27 EUKREA_CPUIMX27 1975 +cheflux MACH_CHEFLUX CHEFLUX 1976 +eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 +opcotec MACH_OPCOTEC OPCOTEC 1978 +yt MACH_YT YT 1979 +motoq MACH_MOTOQ MOTOQ 1980 +bsb1 MACH_BSB1 BSB1 1981 acs5k MACH_ACS5K ACS5K 1982 +milan MACH_MILAN MILAN 1983 +quartzv2 MACH_QUARTZV2 QUARTZV2 1984 +rsvp MACH_RSVP RSVP 1985 +rmp200 MACH_RMP200 RMP200 1986 snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987 dsm320 MACH_DSM320 DSM320 1988 +adsgcm MACH_ADSGCM ADSGCM 1989 +ase2_400 MACH_ASE2_400 ASE2_400 1990 +pizza MACH_PIZZA PIZZA 1991 +spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992 +armata MACH_ARMATA ARMATA 1993 exeda MACH_EXEDA EXEDA 1994 +mx31sf005 MACH_MX31SF005 MX31SF005 1995 +f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996 +q2440 MACH_Q2440 Q2440 1997 +qq2440 MACH_QQ2440 QQ2440 1998 mini2440 MACH_MINI2440 MINI2440 1999 colibri300 MACH_COLIBRI300 COLIBRI300 2000 +jades MACH_JADES JADES 2001 +spark MACH_SPARK SPARK 2002 +benzina MACH_BENZINA BENZINA 2003 +blaze MACH_BLAZE BLAZE 2004 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 +htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006 +sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007 +hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008 +sapphira MACH_SAPPHIRA SAPPHIRA 2009 +dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010 +armbox MACH_ARMBOX ARMBOX 2011 +harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012 +ribaldo MACH_RIBALDO RIBALDO 2013 +agora MACH_AGORA AGORA 2014 +omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015 +a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016 +usg2410 MACH_USG2410 USG2410 2017 +pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018 +mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019 +topas910 MACH_TOPAS910 TOPAS910 2020 +hyena MACH_HYENA HYENA 2021 +pospax MACH_POSPAX POSPAX 2022 +hdl_gx MACH_HDL_GX HDL_GX 2023 +ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024 +ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025 +crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026 +egauge2 MACH_EGAUGE2 EGAUGE2 2027 +didj MACH_DIDJ DIDJ 2028 +m_s3c2443 MACH_MEISTER MEISTER 2029 +htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030 cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031 smdk6440 MACH_SMDK6440 SMDK6440 2032 +omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033 +ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034 +pvg610_100 MACH_PVG610 PVG610 2035 +hprw6815 MACH_HPRW6815 HPRW6815 2036 +omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037 nas4220b MACH_NAS4220B NAS4220B 2038 +htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039 +htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040 +scaler MACH_SCALER SCALER 2041 zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042 aspenite MACH_ASPENITE ASPENITE 2043 +teton MACH_TETON TETON 2044 ttc_dkb MACH_TTC_DKB TTC_DKB 2045 +bishop2 MACH_BISHOP2 BISHOP2 2046 +ippv5 MACH_IPPV5 IPPV5 2047 +farm926 MACH_FARM926 FARM926 2048 +mmccpu MACH_MMCCPU MMCCPU 2049 +sgmsfl MACH_SGMSFL SGMSFL 2050 +tt8000 MACH_TT8000 TT8000 2051 +zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052 +mptc MACH_MPTC MPTC 2053 +h6051 MACH_H6051 H6051 2054 +pvg610_101 MACH_PVG610_101 PVG610_101 2055 +stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056 +pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057 +tny_a9260 MACH_TNY_A9260 TNY_A9260 2058 +tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059 +aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060 +dx900 MACH_DX900 DX900 2061 +cpodc2 MACH_CPODC2 CPODC2 2062 +tilt_8925 MACH_TILT_8925 TILT_8925 2063 +davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064 +swordfish MACH_SWORDFISH SWORDFISH 2065 +corvus MACH_CORVUS CORVUS 2066 +taurus MACH_TAURUS TAURUS 2067 +axm MACH_AXM AXM 2068 +axc MACH_AXC AXC 2069 +baby MACH_BABY BABY 2070 +mp200 MACH_MP200 MP200 2071 pcm043 MACH_PCM043 PCM043 2072 +hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073 +kbk9g20 MACH_KBK9G20 KBK9G20 2074 +adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075 +avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076 +suc82x MACH_SUC SUC 2077 +at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078 +mendoza MACH_MENDOZA MENDOZA 2079 +kira MACH_KIRA KIRA 2080 +mx1hbm MACH_MX1HBM MX1HBM 2081 +quatro43xx MACH_QUATRO43XX QUATRO43XX 2082 +quatro4230 MACH_QUATRO4230 QUATRO4230 2083 +nsb400 MACH_NSB400 NSB400 2084 +drp255 MACH_DRP255 DRP255 2085 +thoth MACH_THOTH THOTH 2086 +firestone MACH_FIRESTONE FIRESTONE 2087 +asusp750 MACH_ASUSP750 ASUSP750 2088 +ctera_dl MACH_CTERA_DL CTERA_DL 2089 +socr MACH_SOCR SOCR 2090 +htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091 +heroc MACH_HEROC HEROC 2092 +zeno6800 MACH_ZENO6800 ZENO6800 2093 +sc2mcs MACH_SC2MCS SC2MCS 2094 +gene100 MACH_GENE100 GENE100 2095 +as353x MACH_AS353X AS353X 2096 sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 +at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098 +mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099 +cc9200 MACH_CC9200 CC9200 2100 +sm9200 MACH_SM9200 SM9200 2101 +tp9200 MACH_TP9200 TP9200 2102 +snapperdv MACH_SNAPPERDV SNAPPERDV 2103 avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 +avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105 +omap3axon MACH_OMAP3AXON OMAP3AXON 2106 +ma8xx MACH_MA8XX MA8XX 2107 +mp201ek MACH_MP201EK MP201EK 2108 +davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109 +mpa1600 MACH_MPA1600 MPA1600 2110 +pelco_troy MACH_PELCO_TROY PELCO_TROY 2111 +nsb667 MACH_NSB667 NSB667 2112 +rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113 +twocom MACH_TWOCOM TWOCOM 2114 +ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115 +hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116 +afeusb MACH_AFEUSB AFEUSB 2117 +t830 MACH_T830 T830 2118 +spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119 +om_3d7k MACH_OM_3D7K OM_3D7K 2120 +picocom2 MACH_PICOCOM2 PICOCOM2 2121 +uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122 +uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123 +cherry MACH_CHERRY CHERRY 2124 mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 +s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126 tx37 MACH_TX37 TX37 2127 +sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128 +benzglb MACH_BENZGLB BENZGLB 2129 +benztd MACH_BENZTD BENZTD 2130 +cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131 +solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132 +mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 +fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 +smallogger MACH_SMALLOGGER SMALLOGGER 2136 +ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137 dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138 ts219 MACH_TS219 TS219 2139 +tny_a9263 MACH_TNY_A9263 TNY_A9263 2140 +apollo MACH_APOLLO APOLLO 2141 +at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142 +spc300 MACH_SPC300 SPC300 2143 +eko MACH_EKO EKO 2144 +ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145 +ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146 +m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147 +str9104nas MACH_STAR9104NAS STAR9104NAS 2148 pca100 MACH_PCA100 PCA100 2149 +z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150 +hipox MACH_HIPOX HIPOX 2151 +omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152 +bm150r MACH_BM150R BM150R 2153 +tbone MACH_TBONE TBONE 2154 +merlin MACH_MERLIN MERLIN 2155 +falcon MACH_FALCON FALCON 2156 davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157 +s5p6440 MACH_S5P6440 S5P6440 2158 at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159 omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160 +lpc313x MACH_LPC313X LPC313X 2161 magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162 +magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163 +magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164 +meesc MACH_MEESC MEESC 2165 +otc570 MACH_OTC570 OTC570 2166 +bcu2412 MACH_BCU2412 BCU2412 2167 +beacon MACH_BEACON BEACON 2168 +actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169 +e4430 MACH_E4430 E4430 2170 +ql300 MACH_QL300 QL300 2171 btmavb101 MACH_BTMAVB101 BTMAVB101 2172 btmawb101 MACH_BTMAWB101 BTMAWB101 2173 +sq201 MACH_SQ201 SQ201 2174 +quatro45xx MACH_QUATRO45XX QUATRO45XX 2175 +openpad MACH_OPENPAD OPENPAD 2176 tx25 MACH_TX25 TX25 2177 omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178 +htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179 +lal43 MACH_LAL43 LAL43 2181 +htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182 anw6410 MACH_ANW6410 ANW6410 2183 +htcprophet MACH_HTCPROPHET HTCPROPHET 2185 +cfa_10022 MACH_CFA_10022 CFA_10022 2186 imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187 +px2imx27 MACH_PX2IMX27 PX2IMX27 2188 +stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189 +dvs10 MACH_DVS10 DVS10 2190 portuxg20 MACH_PORTUXG20 PORTUXG20 2191 +arm_spv MACH_ARM_SPV ARM_SPV 2192 smdkc110 MACH_SMDKC110 SMDKC110 2193 +cabespresso MACH_CABESPRESSO CABESPRESSO 2194 +hmc800 MACH_HMC800 HMC800 2195 +sholes MACH_SHOLES SHOLES 2196 +btmxc31 MACH_BTMXC31 BTMXC31 2197 +dt501 MACH_DT501 DT501 2198 +ktx MACH_KTX KTX 2199 omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200 netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201 netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202 d2net_v2 MACH_D2NET_V2 D2NET_V2 2203 net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204 +net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205 net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206 +endb2443 MACH_ENDB2443 ENDB2443 2207 inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208 +tros MACH_TROS TROS 2209 +pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210 +ofsp8 MACH_OFSP8 OFSP8 2211 at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212 +guf_cupid MACH_GUF_CUPID GUF_CUPID 2213 +eab1r MACH_EAB1R EAB1R 2214 +desirec MACH_DESIREC DESIREC 2215 +cordoba MACH_CORDOBA CORDOBA 2216 +irvine MACH_IRVINE IRVINE 2217 +sff772 MACH_SFF772 SFF772 2218 +pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219 pc7302 MACH_PC7302 PC7302 2220 +bip6000 MACH_BIP6000 BIP6000 2221 +silvermoon MACH_SILVERMOON SILVERMOON 2222 +vc0830 MACH_VC0830 VC0830 2223 +dt430 MACH_DT430 DT430 2224 +ji42pf MACH_JI42PF JI42PF 2225 +gnet_ksm MACH_GNET_KSM GNET_KSM 2226 +gnet_sgm MACH_GNET_SGM GNET_SGM 2227 +gnet_sgr MACH_GNET_SGR GNET_SGR 2228 +omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229 +pnp MACH_PNP PNP 2230 +ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231 +ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232 +sas_c MACH_SAS_C SAS_C 2233 +vma2315 MACH_VMA2315 VMA2315 2234 +vcs MACH_VCS VCS 2235 spear600 MACH_SPEAR600 SPEAR600 2236 spear300 MACH_SPEAR300 SPEAR300 2237 +spear1300 MACH_SPEAR1300 SPEAR1300 2238 lilly1131 MACH_LILLY1131 LILLY1131 2239 +arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240 +mapphone MACH_MAPPHONE MAPPHONE 2241 +legend MACH_LEGEND LEGEND 2242 +salsa MACH_SALSA SALSA 2243 +lounge MACH_LOUNGE LOUNGE 2244 +vision MACH_VISION VISION 2245 +vmb20 MACH_VMB20 VMB20 2246 +hy2410 MACH_HY2410 HY2410 2247 +hy9315 MACH_HY9315 HY9315 2248 +bullwinkle MACH_BULLWINKLE BULLWINKLE 2249 +arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250 +vs_v210 MACH_VS_V210 VS_V210 2252 +vs_v212 MACH_VS_V212 VS_V212 2253 hmt MACH_HMT HMT 2254 +km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255 +vesper MACH_VESPER VESPER 2256 +str9 MACH_STR9 STR9 2257 +omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258 +simcom MACH_SIMCOM SIMCOM 2259 +mcwebio MACH_MCWEBIO MCWEBIO 2260 +omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261 +darwin MACH_DARWIN DARWIN 2262 +oratiscomu MACH_ORATISCOMU ORATISCOMU 2263 +rtsbc20 MACH_RTSBC20 RTSBC20 2264 +sgh_i780 MACH_I780 I780 2265 +gemini324 MACH_GEMINI324 GEMINI324 2266 +oratislan MACH_ORATISLAN ORATISLAN 2267 +oratisalog MACH_ORATISALOG ORATISALOG 2268 +oratismadi MACH_ORATISMADI ORATISMADI 2269 +oratisot16 MACH_ORATISOT16 ORATISOT16 2270 +oratisdesk MACH_ORATISDESK ORATISDESK 2271 vexpress MACH_VEXPRESS VEXPRESS 2272 +sintexo MACH_SINTEXO SINTEXO 2273 +cm3389 MACH_CM3389 CM3389 2274 +omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275 +sgh_i900 MACH_SGH_I900 SGH_I900 2276 +bst100 MACH_BST100 BST100 2277 +passion MACH_PASSION PASSION 2278 +indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279 +c4_badger MACH_C4_BADGER C4_BADGER 2280 +c4_viper MACH_C4_VIPER C4_VIPER 2281 d2net MACH_D2NET D2NET 2282 bigdisk MACH_BIGDISK BIGDISK 2283 +notalvision MACH_NOTALVISION NOTALVISION 2284 +omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285 +cyclone MACH_CYCLONE CYCLONE 2286 +ninja MACH_NINJA NINJA 2287 at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288 bcmring MACH_BCMRING BCMRING 2289 +resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290 +ifosw MACH_IFOSW IFOSW 2291 +htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292 +htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293 +matrix504 MACH_MATRIX504 MATRIX504 2294 +mrfsa MACH_MRFSA MRFSA 2295 +sc_p270 MACH_SC_P270 SC_P270 2296 +atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297 +pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298 +dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299 +leonardo MACH_LEONARDO LEONARDO 2300 +zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301 dp6xx MACH_DP6XX DP6XX 2302 +bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303 mahimahi MACH_MAHIMAHI MAHIMAHI 2304 +clickc MACH_CLICKC CLICKC 2305 +zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306 +tazcard MACH_TAZCARD TAZCARD 2307 +tazdev MACH_TAZDEV TAZDEV 2308 +annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309 +annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310 +cerebric MACH_CEREBRIC CEREBRIC 2311 +orca MACH_ORCA ORCA 2312 +pc9260 MACH_PC9260 PC9260 2313 +ems285a MACH_EMS285A EMS285A 2314 +gec2410 MACH_GEC2410 GEC2410 2315 +gec2440 MACH_GEC2440 GEC2440 2316 +mw903 MACH_ARCH_MW903 ARCH_MW903 2317 +mw2440 MACH_MW2440 MW2440 2318 +ecac2378 MACH_ECAC2378 ECAC2378 2319 +tazkiosk MACH_TAZKIOSK TAZKIOSK 2320 +whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321 +sbox9263 MACH_SBOX9263 SBOX9263 2322 smdk6442 MACH_SMDK6442 SMDK6442 2324 openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 +incredible MACH_INCREDIBLE INCREDIBLE 2326 +incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 +heroct MACH_HEROCT HEROCT 2328 +mmnet1000 MACH_MMNET1000 MMNET1000 2329 devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330 +devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331 +mx31txtr MACH_MX31TXTR MX31TXTR 2332 +u380 MACH_U380 U380 2333 +oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334 +npcmx50 MACH_NPCMX50 NPCMX50 2335 mx51_efikamx MACH_MX51_EFIKAMX MX51_EFIKAMX 2336 +mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337 +riom MACH_RIOM RIOM 2338 +comcas MACH_COMCAS COMCAS 2339 +wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340 cm_t35 MACH_CM_T35 CM_T35 2341 net2big MACH_NET2BIG NET2BIG 2342 +motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343 igep0020 MACH_IGEP0020 IGEP0020 2344 +igep0010 MACH_IGEP0010 IGEP0010 2345 +mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346 +scat100 MACH_SCAT100 SCAT100 2347 +sanmina MACH_SANMINA SANMINA 2348 +momento MACH_MOMENTO MOMENTO 2349 +nuc9xx MACH_NUC9XX NUC9XX 2350 +nuc910evb MACH_NUC910EVB NUC910EVB 2351 +nuc920evb MACH_NUC920EVB NUC920EVB 2352 +nuc950evb MACH_NUC950EVB NUC950EVB 2353 +nuc945evb MACH_NUC945EVB NUC945EVB 2354 +nuc960evb MACH_NUC960EVB NUC960EVB 2355 nuc932evb MACH_NUC932EVB NUC932EVB 2356 +nuc900 MACH_NUC900 NUC900 2357 +sd1soc MACH_SD1SOC SD1SOC 2358 +ln2440bc MACH_LN2440BC LN2440BC 2359 +rsbc MACH_RSBC RSBC 2360 openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 +hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 +wayland MACH_WAYLAND WAYLAND 2363 +acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 +hwat91 MACH_HWAT91 HWAT91 2365 +at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366 +csb732 MACH_CSB732 CSB732 2367 u8500 MACH_U8500 U8500 2368 +huqiu MACH_HUQIU HUQIU 2369 mx51_efikasb MACH_MX51_EFIKASB MX51_EFIKASB 2370 +pmt1g MACH_PMT1G PMT1G 2371 +htcelf MACH_HTCELF HTCELF 2372 +armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373 +armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374 +u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375 +csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376 +dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377 +hy9307 MACH_HY9307 HY9307 2378 +aspire_easystore MACH_A_ES A_ES 2379 +davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380 +agama9263 MACH_AGAMA9263 AGAMA9263 2381 marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382 flint MACH_FLINT FLINT 2383 tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384 +sch_m490 MACH_SCH_M490 SCH_M490 2386 +rbl01 MACH_RBL01 RBL01 2387 +omnifi MACH_OMNIFI OMNIFI 2388 +otavalo MACH_OTAVALO OTAVALO 2389 +htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391 +htc_opal MACH_HTC_OPAL HTC_OPAL 2392 touchbook MACH_TOUCHBOOK TOUCHBOOK 2393 +latte MACH_LATTE LATTE 2394 +xa200 MACH_XA200 XA200 2395 +nimrod MACH_NIMROD NIMROD 2396 +cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397 +cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398 +tk71 MACH_TK71 TK71 2399 +comham3525 MACH_COMHAM3525 COMHAM3525 2400 +mx31erebus MACH_MX31EREBUS MX31EREBUS 2401 +mcardmx27 MACH_MCARDMX27 MCARDMX27 2402 +paradise MACH_PARADISE PARADISE 2403 +tide MACH_TIDE TIDE 2404 +wzl2440 MACH_WZL2440 WZL2440 2405 +sdrdemo MACH_SDRDEMO SDRDEMO 2406 +ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407 +ecmimg20 MACH_ECMIMG20 ECMIMG20 2408 +omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409 +halo MACH_HALO HALO 2410 +huangshan MACH_HUANGSHAN HUANGSHAN 2411 +vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412 raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 +multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416 +multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417 tnetv107x MACH_TNETV107X TNETV107X 2418 +snake MACH_SNAKE SNAKE 2419 +cwmx27 MACH_CWMX27 CWMX27 2420 +sch_m480 MACH_SCH_M480 SCH_M480 2421 +platypus MACH_PLATYPUS PLATYPUS 2422 +pss2 MACH_PSS2 PSS2 2423 +davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424 +str9100 MACH_STR9100 STR9100 2425 +net5big MACH_NET5BIG NET5BIG 2426 +seabed9263 MACH_SEABED9263 SEABED9263 2427 mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428 +octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429 +klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430 +klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431 +klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432 +supersonic MACH_SUPERSONIC SUPERSONIC 2433 +liberty MACH_LIBERTY LIBERTY 2434 +mh355 MACH_MH355 MH355 2435 +pc7802 MACH_PC7802 PC7802 2436 +gnet_sgc MACH_GNET_SGC GNET_SGC 2437 +einstein15 MACH_EINSTEIN15 EINSTEIN15 2438 +cmpd MACH_CMPD CMPD 2439 +davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440 +lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441 +ea313x MACH_EA313X EA313X 2442 +fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443 +fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444 +pelco_moe MACH_PELCO_MOE PELCO_MOE 2445 +minimix27 MACH_MINIMIX27 MINIMIX27 2446 +omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447 +passionc MACH_PASSIONC PASSIONC 2448 +mx27amata MACH_MX27AMATA MX27AMATA 2449 +bgat1 MACH_BGAT1 BGAT1 2450 +buzz MACH_BUZZ BUZZ 2451 +mb9g20 MACH_MB9G20 MB9G20 2452 +yushan MACH_YUSHAN YUSHAN 2453 +lizard MACH_LIZARD LIZARD 2454 +omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455 smdkv210 MACH_SMDKV210 SMDKV210 2456 +bravo MACH_BRAVO BRAVO 2457 +siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458 +siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459 +sm3k MACH_SM3K SM3K 2460 +acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461 +glittertind MACH_GLITTERTIND GLITTERTIND 2463 omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464 omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465 +cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466 +torino_s MACH_TORINO_S TORINO_S 2467 +havana MACH_HAVANA HAVANA 2468 +beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469 +vanguard MACH_VANGUARD VANGUARD 2470 +s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471 +cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472 +aster MACH_ASTER ASTER 2473 +voguesv210 MACH_VOGUESV210 VOGUESV210 2474 +acm500x MACH_ACM500X ACM500X 2475 +km9260 MACH_KM9260 KM9260 2476 +nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477 +ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478 smartq7 MACH_SMARTQ7 SMARTQ7 2479 +at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480 +asusp527 MACH_ASUSP527 ASUSP527 2481 +at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482 +topasa900 MACH_TOPASA900 TOPASA900 2483 +electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484 +mx51grb MACH_MX51GRB MX51GRB 2485 +xea300 MACH_XEA300 XEA300 2486 +htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487 +lima MACH_LIMA LIMA 2488 +csb740 MACH_CSB740 CSB740 2489 +usb_s8815 MACH_USB_S8815 USB_S8815 2490 watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491 +milkyway MACH_MILKYWAY MILKYWAY 2492 g4evm MACH_G4EVM G4EVM 2493 +picomod6 MACH_PICOMOD6 PICOMOD6 2494 omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495 +ip6000 MACH_IP6000 IP6000 2496 +ip6010 MACH_IP6010 IP6010 2497 +utm400 MACH_UTM400 UTM400 2498 +omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499 +wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500 +sx560 MACH_SX560 SX560 2501 ts41x MACH_TS41X TS41X 2502 +elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503 +rhobot MACH_RHOBOT RHOBOT 2504 +mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505 +ls9260 MACH_LS9260 LS9260 2506 +shank MACH_SHANK SHANK 2507 +qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508 +at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509 +hiram MACH_HIRAM HIRAM 2510 phy3250 MACH_PHY3250 PHY3250 2511 +ea3250 MACH_EA3250 EA3250 2512 +fdi3250 MACH_FDI3250 FDI3250 2513 +at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515 +ccmx51 MACH_CCMX51 CCMX51 2516 +ccmx51js MACH_CCMX51JS CCMX51JS 2517 +ccwmx51 MACH_CCWMX51 CCWMX51 2518 +ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519 mini6410 MACH_MINI6410 MINI6410 2520 +tiny6410 MACH_TINY6410 TINY6410 2521 +nano6410 MACH_NANO6410 NANO6410 2522 +at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523 +htcleo MACH_HTCLEO HTCLEO 2524 +avp13 MACH_AVP13 AVP13 2525 +xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526 +vpnext MACH_VPNEXT VPNEXT 2527 +swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528 tx51 MACH_TX51 TX51 2529 +dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530 mx28evk MACH_MX28EVK MX28EVK 2531 +phoenix260 MACH_PHOENIX260 PHOENIX260 2532 +uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533 smartq5 MACH_SMARTQ5 SMARTQ5 2534 +all3078 MACH_ALL3078 ALL3078 2535 +ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536 +siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537 +epb5000 MACH_EPB5000 EPB5000 2538 +hy9263 MACH_HY9263 HY9263 2539 +acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540 +acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541 +acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542 +acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543 +acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544 +bonnell MACH_BONNELL BONNELL 2545 +oht_mx27 MACH_OHT_MX27 OHT_MX27 2546 +htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547 davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 +c3ax03 MACH_C3AX03 C3AX03 2549 mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 +esyx MACH_ESYX ESYX 2551 +dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552 +bulldog MACH_BULLDOG BULLDOG 2553 +derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554 +bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555 +bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556 +bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557 +bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558 +bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559 +bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560 +bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561 +bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562 +bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563 +bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564 +bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565 +acer_s200 MACH_ACER_S200 ACER_S200 2566 +bt270 MACH_BT270 BT270 2567 +iseo MACH_ISEO ISEO 2568 +cezanne MACH_CEZANNE CEZANNE 2569 +lucca MACH_LUCCA LUCCA 2570 +supersmart MACH_SUPERSMART SUPERSMART 2571 +arm11_board MACH_CS_MISANO CS_MISANO 2572 +magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573 +emxx MACH_EMXX EMXX 2574 +outlaw MACH_OUTLAW OUTLAW 2575 riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 +riot_gx2 MACH_RIOT_VOX RIOT_VOX 2577 riot_x37 MACH_RIOT_X37 RIOT_X37 2578 +mega25mx MACH_MEGA25MX MEGA25MX 2579 +benzina2 MACH_BENZINA2 BENZINA2 2580 +ignite MACH_IGNITE IGNITE 2581 +foggia MACH_FOGGIA FOGGIA 2582 +arezzo MACH_AREZZO AREZZO 2583 +leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584 +jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585 +gts_nova MACH_GTS_NOVA GTS_NOVA 2586 +p3600 MACH_P3600 P3600 2587 +dlt2 MACH_DLT2 DLT2 2588 +df3120 MACH_DF3120 DF3120 2589 +ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590 +nautel_am35xx MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 +glacier MACH_GLACIER GLACIER 2592 +phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593 +omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594 pca101 MACH_PCA101 PCA101 2595 +buzzc MACH_BUZZC BUZZC 2596 +sasie2 MACH_SASIE2 SASIE2 2597 +smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599 +wzl6410 MACH_WZL6410 WZL6410 2600 +wzl6410m MACH_WZL6410M WZL6410M 2601 +wzl6410f MACH_WZL6410F WZL6410F 2602 +wzl6410i MACH_WZL6410I WZL6410I 2603 +spacecom1 MACH_SPACECOM1 SPACECOM1 2604 +pingu920 MACH_PINGU920 PINGU920 2605 +bravoc MACH_BRAVOC BRAVOC 2606 +vdssw MACH_VDSSW VDSSW 2608 +romulus MACH_ROMULUS ROMULUS 2609 +omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610 +eltd100 MACH_ELTD100 ELTD100 2611 capc7117 MACH_CAPC7117 CAPC7117 2612 +swan MACH_SWAN SWAN 2613 +veu MACH_VEU VEU 2614 +rm2 MACH_RM2 RM2 2615 +tt2100 MACH_TT2100 TT2100 2616 +venice MACH_VENICE VENICE 2617 +pc7323 MACH_PC7323 PC7323 2618 +masp MACH_MASP MASP 2619 +fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620 +fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621 +lexikon MACH_LEXIKON LEXIKON 2622 +mini2440v2 MACH_MINI2440V2 MINI2440V2 2623 icontrol MACH_ICONTROL ICONTROL 2624 gplugd MACH_GPLUGD GPLUGD 2625 +qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 +bee MACH_BEE BEE 2628 mx23evk MACH_MX23EVK MX23EVK 2629 ap4evb MACH_AP4EVB AP4EVB 2630 +stockholm MACH_STOCKHOLM STOCKHOLM 2631 +lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632 +stingray MACH_STINGRAY STINGRAY 2633 +kraken MACH_KRAKEN KRAKEN 2634 +gw2388 MACH_GW2388 GW2388 2635 +jadecpu MACH_JADECPU JADECPU 2636 +carlisle MACH_CARLISLE CARLISLE 2637 +lux_sf9 MACH_LUX_SF9 LUX_SF9 2638 +nemid_tb MACH_NEMID_TB NEMID_TB 2639 +terrier MACH_TERRIER TERRIER 2640 +turbot MACH_TURBOT TURBOT 2641 +sanddab MACH_SANDDAB SANDDAB 2642 +mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643 +ghi2703d MACH_GHI2703D GHI2703D 2644 +lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645 +lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646 +lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647 +hw90240 MACH_HW90240 HW90240 2648 +dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649 mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650 +scat110 MACH_SCAT110 SCAT110 2651 +acer_a1 MACH_ACER_A1 ACER_A1 2652 +cmcontrol MACH_CMCONTROL CMCONTROL 2653 +pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654 +rfp43 MACH_RFP43 RFP43 2655 +sk86r0301 MACH_SK86R0301 SK86R0301 2656 +ctpxa MACH_CTPXA CTPXA 2657 +epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658 guruplug MACH_GURUPLUG GURUPLUG 2659 spear310 MACH_SPEAR310 SPEAR310 2660 spear320 MACH_SPEAR320 SPEAR320 2661 +robotx MACH_ROBOTX ROBOTX 2662 +lsxhl MACH_LSXHL LSXHL 2663 +smartlite MACH_SMARTLITE SMARTLITE 2664 +cws2 MACH_CWS2 CWS2 2665 +m619 MACH_M619 M619 2666 +smartview MACH_SMARTVIEW SMARTVIEW 2667 +lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668 +kizbox MACH_KIZBOX KIZBOX 2669 +htccharmer MACH_HTCCHARMER HTCCHARMER 2670 +guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671 +pm9g45 MACH_PM9G45 PM9G45 2672 +htcpanther MACH_HTCPANTHER HTCPANTHER 2673 +htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674 +reb01 MACH_REB01 REB01 2675 aquila MACH_AQUILA AQUILA 2676 +spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677 esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 +micro2440 MACH_MICRO2440 MICRO2440 2680 +am2440 MACH_AM2440 AM2440 2681 +tq2440 MACH_TQ2440 TQ2440 2682 ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683 +ak880x MACH_AK880X AK880X 2684 +cobra3530 MACH_COBRA3530 COBRA3530 2685 +pmppb MACH_PMPPB PMPPB 2686 +u6715 MACH_U6715 U6715 2687 +axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688 +g30_dvb MACH_G30_DVB G30_DVB 2689 +vc088x MACH_VC088X VC088X 2690 +mioa702 MACH_MIOA702 MIOA702 2691 +hpmin MACH_HPMIN HPMIN 2692 +ak880xak MACH_AK880XAK AK880XAK 2693 +arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694 +lkevm MACH_LKEVM LKEVM 2695 +mw6410 MACH_MW6410 MW6410 2696 terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697 +cpu8000e MACH_CPU8000E CPU8000E 2698 +tokyo MACH_TOKYO TOKYO 2700 +msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701 +msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702 msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703 msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704 msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705 msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706 msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707 qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708 +qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709 +qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710 +qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711 +qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712 +adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713 +mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714 +mobikt MACH_MOBIKT MOBIKT 2715 mx53_evk MACH_MX53_EVK MX53_EVK 2716 igep0030 MACH_IGEP0030 IGEP0030 2717 +axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718 +dtcommod MACH_DTCOMMOD DTCOMMOD 2719 +gould MACH_GOULD GOULD 2720 +siberia MACH_SIBERIA SIBERIA 2721 sbc3530 MACH_SBC3530 SBC3530 2722 +qarm MACH_QARM QARM 2723 +mips MACH_MIPS MIPS 2724 +mx27grb MACH_MX27GRB MX27GRB 2725 +sbc8100 MACH_SBC8100 SBC8100 2726 saarb MACH_SAARB SAARB 2727 +omap3mini MACH_OMAP3MINI OMAP3MINI 2728 +cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729 +catan MACH_CATAN CATAN 2730 harmony MACH_HARMONY HARMONY 2731 +tonga MACH_TONGA TONGA 2732 +cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733 +htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734 +epc_g45 MACH_EPC_G45 EPC_G45 2735 +epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736 +mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737 +rtw1000 MACH_RTW1000 RTW1000 2738 +bobcat MACH_BOBCAT BOBCAT 2739 +trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740 msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741 +nedap9263 MACH_NEDAP9263 NEDAP9263 2742 +netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743 +bmx MACH_BMX BMX 2744 +netstream MACH_NETSTREAM NETSTREAM 2745 +vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746 +vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747 +bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748 +sgarm10 MACH_SGARM10 SGARM10 2749 cm_t3517 MACH_CM_T3517 CM_T3517 2750 +dig297 MACH_OMAP3_CPS OMAP3_CPS 2751 +axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752 wbd222 MACH_WBD222 WBD222 2753 +mt65xx MACH_MT65XX MT65XX 2754 msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755 msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756 tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758 nanos MACH_NANOS NANOS 2759 +stamp9g10 MACH_STAMP9G10 STAMP9G10 2760 stamp9g45 MACH_STAMP9G45 STAMP9G45 2761 +h6053 MACH_H6053 H6053 2762 +smint01 MACH_SMINT01 SMINT01 2763 +prtlvt2 MACH_PRTLVT2 PRTLVT2 2764 +ap420 MACH_AP420 AP420 2765 +davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767 +msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768 +msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769 +esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770 +sbc35 MACH_SBC35 SBC35 2771 +mpx6446 MACH_MPX6446 MPX6446 2772 +oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773 +kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774 +ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775 cns3420vb MACH_CNS3420VB CNS3420VB 2776 +lpc_evo MACH_LPC2 LPC2 2777 +olympus MACH_OLYMPUS OLYMPUS 2778 +vortex MACH_VORTEX VORTEX 2779 +s5pc200 MACH_S5PC200 S5PC200 2780 +ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781 +smdkc200 MACH_SMDKC200 SMDKC200 2782 +emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783 +apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784 +songshan MACH_SONGSHAN SONGSHAN 2785 +tianshan MACH_TIANSHAN TIANSHAN 2786 +vpx500 MACH_VPX500 VPX500 2787 +am3517sam MACH_AM3517SAM AM3517SAM 2788 +skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789 +skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790 omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791 +df7220 MACH_DF7220 DF7220 2792 +nemini MACH_NEMINI NEMINI 2793 +t8200 MACH_T8200 T8200 2794 +apf51 MACH_APF51 APF51 2795 +dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796 +bordeaux MACH_BORDEAUX BORDEAUX 2797 +catania_b MACH_CATANIA_B CATANIA_B 2798 +mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799 ti8168evm MACH_TI8168EVM TI8168EVM 2800 +neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801 +withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802 +dbps MACH_DBPS DBPS 2803 +pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805 +speedy MACH_SPEEDY SPEEDY 2806 +chrysaor MACH_CHRYSAOR CHRYSAOR 2807 +tango MACH_TANGO TANGO 2808 +synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809 +hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810 +hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811 +hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812 +iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813 +irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814 +irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815 teton_bga MACH_TETON_BGA TETON_BGA 2816 +snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817 +tam3517 MACH_TAM3517 TAM3517 2818 +pdc100 MACH_PDC100 PDC100 2819 eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25SD EUKREA_CPUIMX25SD 2820 eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821 eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 +p565 MACH_P565 P565 2824 +acer_a4 MACH_ACER_A4 ACER_A4 2825 +davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826 +eshare MACH_ESHARE ESHARE 2827 +wlbargn MACH_WLBARGN WLBARGN 2829 +bm170 MACH_BM170 BM170 2830 +netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831 +netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832 +siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833 +elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834 +mcu1 MACH_MCU1 MCU1 2835 +omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836 +omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837 smdkc210 MACH_SMDKC210 SMDKC210 2838 -pca102 MACH_PCA102 PCA102 2843 +omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839 +spyplug MACH_SPYPLUG SPYPLUG 2840 +ginger MACH_GINGER GINGER 2841 +tny_t3530 MACH_TNY_T3530 TNY_T3530 2842 +pcaal1 MACH_PCAAL1 PCAAL1 2843 +spade MACH_SPADE SPADE 2844 +mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845 t5325 MACH_T5325 T5325 2846 +gw2361 MACH_GW2361 GW2361 2847 +elog MACH_ELOG ELOG 2848 income MACH_INCOME INCOME 2849 +bcm589x MACH_BCM589X BCM589X 2850 +etna MACH_ETNA ETNA 2851 +hawks MACH_HAWKS HAWKS 2852 +meson MACH_MESON MESON 2853 +xsbase255 MACH_XSBASE255 XSBASE255 2854 +pvm2030 MACH_PVM2030 PVM2030 2855 +mioa502 MACH_MIOA502 MIOA502 2856 vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857 vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858 vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859 +htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860 mx257sx MACH_MX257SX MX257SX 2861 goni MACH_GONI GONI 2862 +msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863 +msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864 +quickstep MACH_QUICKSTEP QUICKSTEP 2865 +dmw96 MACH_DMW96 DMW96 2866 +hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867 +trident MACH_TRIDENT TRIDENT 2868 +lightning MACH_LIGHTNING LIGHTNING 2869 +iconnect MACH_ICONNECT ICONNECT 2870 +autobot MACH_AUTOBOT AUTOBOT 2871 +coconut MACH_COCONUT COCONUT 2872 +durian MACH_DURIAN DURIAN 2873 +cayenne MACH_CAYENNE CAYENNE 2874 +fuji MACH_FUJI FUJI 2875 +synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876 +em1sy MACH_EM1SY EM1SY 2877 +m502 MACH_M502 M502 2878 +matrix518 MACH_MATRIX518 MATRIX518 2879 +tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880 +spear1310 MACH_SPEAR1310 SPEAR1310 2881 bv07 MACH_BV07 BV07 2882 +mxt_td61 MACH_MXT_TD61 MXT_TD61 2883 openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884 devixp MACH_DEVIXP DEVIXP 2885 miccpt MACH_MICCPT MICCPT 2886 mic256 MACH_MIC256 MIC256 2887 +as1167 MACH_AS1167 AS1167 2888 +omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889 u5500 MACH_U5500 U5500 2890 +davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891 +mecha MACH_MECHA MECHA 2892 +bubba3 MACH_BUBBA3 BUBBA3 2893 +pupitre MACH_PUPITRE PUPITRE 2894 +tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896 +tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897 +simplenet MACH_SIMPLENET SIMPLENET 2898 +ec4350tbm MACH_EC4350TBM EC4350TBM 2899 +pec_tc MACH_PEC_TC PEC_TC 2900 +pec_hc2 MACH_PEC_HC2 PEC_HC2 2901 +esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902 +esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903 +esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904 +esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905 +unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906 +blueshark MACH_BLUESHARK BLUESHARK 2907 +e10 MACH_E10 E10 2908 +app3k_robin MACH_APP3K_ROBIN APP3K_ROBIN 2909 +pov15hd MACH_POV15HD POV15HD 2910 +stella MACH_STELLA STELLA 2911 linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913 +netwalker MACH_NETWALKER NETWALKER 2914 +acsx106 MACH_ACSX106 ACSX106 2915 +atlas5_c1 MACH_ATLAS5_C1 ATLAS5_C1 2916 +nsb3ast MACH_NSB3AST NSB3AST 2917 +gnet_slc MACH_GNET_SLC GNET_SLC 2918 +af4000 MACH_AF4000 AF4000 2919 +ark9431 MACH_ARK9431 ARK9431 2920 +fs_s5pc100 MACH_FS_S5PC100 FS_S5PC100 2921 +omap3505nova8 MACH_OMAP3505NOVA8 OMAP3505NOVA8 2922 +omap3621_edp1 MACH_OMAP3621_EDP1 OMAP3621_EDP1 2923 +oratisaes MACH_ORATISAES ORATISAES 2924 smdkv310 MACH_SMDKV310 SMDKV310 2925 +siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926 +ventana MACH_VENTANA VENTANA 2927 wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928 +ec4350sdb MACH_EC4350SDB EC4350SDB 2929 +mimas MACH_MIMAS MIMAS 2930 +titan MACH_TITAN TITAN 2931 craneboard MACH_CRANEBOARD CRANEBOARD 2932 +es2440 MACH_ES2440 ES2440 2933 +najay_a9263 MACH_NAJAY_A9263 NAJAY_A9263 2934 +htctornado MACH_HTCTORNADO HTCTORNADO 2935 +dimm_mx257 MACH_DIMM_MX257 DIMM_MX257 2936 +jigen301 MACH_JIGEN JIGEN 2937 smdk6450 MACH_SMDK6450 SMDK6450 2938 +meno_qng MACH_MENO_QNG MENO_QNG 2939 +ns2416 MACH_NS2416 NS2416 2940 +rpc353 MACH_RPC353 RPC353 2941 +tq6410 MACH_TQ6410 TQ6410 2942 +sky6410 MACH_SKY6410 SKY6410 2943 +dynasty MACH_DYNASTY DYNASTY 2944 +vivo MACH_VIVO VIVO 2945 +bury_bl7582 MACH_BURY_BL7582 BURY_BL7582 2946 +bury_bps5270 MACH_BURY_BPS5270 BURY_BPS5270 2947 +basi MACH_BASI BASI 2948 +tn200 MACH_TN200 TN200 2949 +c2mmi MACH_C2MMI C2MMI 2950 +meson_6236m MACH_MESON_6236M MESON_6236M 2951 +meson_8626m MACH_MESON_8626M MESON_8626M 2952 +tube MACH_TUBE TUBE 2953 +messina MACH_MESSINA MESSINA 2954 +mx50_arm2 MACH_MX50_ARM2 MX50_ARM2 2955 +cetus9263 MACH_CETUS9263 CETUS9263 2956 brownstone MACH_BROWNSTONE BROWNSTONE 2957 +vmx25 MACH_VMX25 VMX25 2958 +vmx51 MACH_VMX51 VMX51 2959 +abacus MACH_ABACUS ABACUS 2960 +cm4745 MACH_CM4745 CM4745 2961 +oratislink MACH_ORATISLINK ORATISLINK 2962 +davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963 +netviz MACH_NETVIZ NETVIZ 2964 flexibity MACH_FLEXIBITY FLEXIBITY 2965 +wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966 +lpc24xx MACH_LPC24XX LPC24XX 2967 +spica MACH_SPICA SPICA 2968 +gpsdisplay MACH_GPSDISPLAY GPSDISPLAY 2969 +bipnet MACH_BIPNET BIPNET 2970 +overo_ctu_inertial MACH_OVERO_CTU_INERTIAL OVERO_CTU_INERTIAL 2971 +davinci_dm355_mmm MACH_DAVINCI_DM355_MMM DAVINCI_DM355_MMM 2972 +pc9260_v2 MACH_PC9260_V2 PC9260_V2 2973 +ptx7545 MACH_PTX7545 PTX7545 2974 +tm_efdc MACH_TM_EFDC TM_EFDC 2975 +omap3_waldo1 MACH_OMAP3_WALDO1 OMAP3_WALDO1 2977 +flyer MACH_FLYER FLYER 2978 +tornado3240 MACH_TORNADO3240 TORNADO3240 2979 +soli_01 MACH_SOLI_01 SOLI_01 2980 +omapl138_europalc MACH_OMAPL138_EUROPALC OMAPL138_EUROPALC 2981 +helios_v1 MACH_HELIOS_V1 HELIOS_V1 2982 +netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983 +ssc MACH_SSC SSC 2984 +premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985 +wasabi MACH_WASABI WASABI 2986 mx50_rdp MACH_MX50_RDP MX50_RDP 2988 universal_c210 MACH_UNIVERSAL_C210 UNIVERSAL_C210 2989 real6410 MACH_REAL6410 REAL6410 2990 +spx_sakura MACH_SPX_SAKURA SPX_SAKURA 2991 +ij3k_2440 MACH_IJ3K_2440 IJ3K_2440 2992 +omap3_bc10 MACH_OMAP3_BC10 OMAP3_BC10 2993 +thebe MACH_THEBE THEBE 2994 +rv082 MACH_RV082 RV082 2995 +armlguest MACH_ARMLGUEST ARMLGUEST 2996 +tjinc1000 MACH_TJINC1000 TJINC1000 2997 dockstar MACH_DOCKSTAR DOCKSTAR 2998 +ax8008 MACH_AX8008 AX8008 2999 +gnet_sgce MACH_GNET_SGCE GNET_SGCE 3000 +pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001 +ea20 MACH_EA20 EA20 3002 +awm2 MACH_AWM2 AWM2 3003 ti8148evm MACH_TI8148EVM TI8148EVM 3004 seaboard MACH_SEABOARD SEABOARD 3005 +linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006 +tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007 +rubys MACH_RUBYS RUBYS 3008 +aquarius MACH_AQUARIUS AQUARIUS 3009 mx53_ard MACH_MX53_ARD MX53_ARD 3010 mx53_smd MACH_MX53_SMD MX53_SMD 3011 +lswxl MACH_LSWXL LSWXL 3012 +dove_avng_v3 MACH_DOVE_AVNG_V3 DOVE_AVNG_V3 3013 +sdi_ess_9263 MACH_SDI_ESS_9263 SDI_ESS_9263 3014 +jocpu550 MACH_JOCPU550 JOCPU550 3015 msm8x60_rumi3 MACH_MSM8X60_RUMI3 MSM8X60_RUMI3 3016 msm8x60_ffa MACH_MSM8X60_FFA MSM8X60_FFA 3017 +yanomami MACH_YANOMAMI YANOMAMI 3018 +gta04 MACH_GTA04 GTA04 3019 cm_a510 MACH_CM_A510 CM_A510 3020 +omap3_rfs200 MACH_OMAP3_RFS200 OMAP3_RFS200 3021 +kx33xx MACH_KX33XX KX33XX 3022 +ptx7510 MACH_PTX7510 PTX7510 3023 +top9000 MACH_TOP9000 TOP9000 3024 +teenote MACH_TEENOTE TEENOTE 3025 +ts3 MACH_TS3 TS3 3026 +a0 MACH_A0 A0 3027 +fsm9xxx_surf MACH_FSM9XXX_SURF FSM9XXX_SURF 3028 +fsm9xxx_ffa MACH_FSM9XXX_FFA FSM9XXX_FFA 3029 +frrhwcdma60w MACH_FRRHWCDMA60W FRRHWCDMA60W 3030 +remus MACH_REMUS REMUS 3031 +at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032 +at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033 +kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034 +armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036 +spdm MACH_SPDM SPDM 3037 +gtib MACH_GTIB GTIB 3038 +dgm3240 MACH_DGM3240 DGM3240 3039 +htcmega MACH_HTCMEGA HTCMEGA 3041 +tricorder MACH_TRICORDER TRICORDER 3042 tx28 MACH_TX28 TX28 3043 +bstbrd MACH_BSTBRD BSTBRD 3044 +pwb3090 MACH_PWB3090 PWB3090 3045 +idea6410 MACH_IDEA6410 IDEA6410 3046 +qbc9263 MACH_QBC9263 QBC9263 3047 +borabora MACH_BORABORA BORABORA 3048 +valdez MACH_VALDEZ VALDEZ 3049 +ls9g20 MACH_LS9G20 LS9G20 3050 +mios_v1 MACH_MIOS_V1 MIOS_V1 3051 +s5pc110_crespo MACH_S5PC110_CRESPO S5PC110_CRESPO 3052 +controltek9g20 MACH_CONTROLTEK9G20 CONTROLTEK9G20 3053 +tin307 MACH_TIN307 TIN307 3054 +tin510 MACH_TIN510 TIN510 3055 +ep3505 MACH_EP3517 EP3517 3056 +bluecheese MACH_BLUECHEESE BLUECHEESE 3057 +tem3x30 MACH_TEM3X30 TEM3X30 3058 +harvest_desoto MACH_HARVEST_DESOTO HARVEST_DESOTO 3059 +msm8x60_qrdc MACH_MSM8X60_QRDC MSM8X60_QRDC 3060 +spear900 MACH_SPEAR900 SPEAR900 3061 pcontrol_g20 MACH_PCONTROL_G20 PCONTROL_G20 3062 +rdstor MACH_RDSTOR RDSTOR 3063 +usdloader MACH_USDLOADER USDLOADER 3064 +tsoploader MACH_TSOPLOADER TSOPLOADER 3065 +kronos MACH_KRONOS KRONOS 3066 +ffcore MACH_FFCORE FFCORE 3067 +mone MACH_MONE MONE 3068 +unit2s MACH_UNIT2S UNIT2S 3069 +acer_a5 MACH_ACER_A5 ACER_A5 3070 +etherpro_isp MACH_ETHERPRO_ISP ETHERPRO_ISP 3071 +stretchs7000 MACH_STRETCHS7000 STRETCHS7000 3072 +p87_smartsim MACH_P87_SMARTSIM P87_SMARTSIM 3073 +tulip MACH_TULIP TULIP 3074 +sunflower MACH_SUNFLOWER SUNFLOWER 3075 +rib MACH_RIB RIB 3076 +clod MACH_CLOD CLOD 3077 +rump MACH_RUMP RUMP 3078 +tenderloin MACH_TENDERLOIN TENDERLOIN 3079 +shortloin MACH_SHORTLOIN SHORTLOIN 3080 +antares MACH_ANTARES ANTARES 3082 +wb40n MACH_WB40N WB40N 3083 +herring MACH_HERRING HERRING 3084 +naxy400 MACH_NAXY400 NAXY400 3085 +naxy1200 MACH_NAXY1200 NAXY1200 3086 vpr200 MACH_VPR200 VPR200 3087 +bug20 MACH_BUG20 BUG20 3088 +goflexnet MACH_GOFLEXNET GOFLEXNET 3089 torbreck MACH_TORBRECK TORBRECK 3090 +saarb_mg1 MACH_SAARB_MG1 SAARB_MG1 3091 +callisto MACH_CALLISTO CALLISTO 3092 +multhsu MACH_MULTHSU MULTHSU 3093 +saluda MACH_SALUDA SALUDA 3094 +pemp_omap3_apollo MACH_PEMP_OMAP3_APOLLO PEMP_OMAP3_APOLLO 3095 +vc0718 MACH_VC0718 VC0718 3096 +mvblx MACH_MVBLX MVBLX 3097 +inhand_apeiron MACH_INHAND_APEIRON INHAND_APEIRON 3098 +inhand_fury MACH_INHAND_FURY INHAND_FURY 3099 +inhand_siren MACH_INHAND_SIREN INHAND_SIREN 3100 +hdnvp MACH_HDNVP HDNVP 3101 +softwinner MACH_SOFTWINNER SOFTWINNER 3102 prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 +nas6210 MACH_NAS6210 NAS6210 3104 +unisdev MACH_UNISDEV UNISDEV 3105 +sbca11 MACH_SBCA11 SBCA11 3106 +saga MACH_SAGA SAGA 3107 +ns_k330 MACH_NS_K330 NS_K330 3108 +tanna MACH_TANNA TANNA 3109 +imate8502 MACH_IMATE8502 IMATE8502 3110 +aspen MACH_ASPEN ASPEN 3111 +daintree_cwac MACH_DAINTREE_CWAC DAINTREE_CWAC 3112 +zmx25 MACH_ZMX25 ZMX25 3113 +maple1 MACH_MAPLE1 MAPLE1 3114 +qsd8x72_surf MACH_QSD8X72_SURF QSD8X72_SURF 3115 +qsd8x72_ffa MACH_QSD8X72_FFA QSD8X72_FFA 3116 +abilene MACH_ABILENE ABILENE 3117 +eigen_ttr MACH_EIGEN_TTR EIGEN_TTR 3118 +iomega_ix2_200 MACH_IOMEGA_IX2_200 IOMEGA_IX2_200 3119 +coretec_vcx7400 MACH_CORETEC_VCX7400 CORETEC_VCX7400 3120 +santiago MACH_SANTIAGO SANTIAGO 3121 +mx257sol MACH_MX257SOL MX257SOL 3122 +strasbourg MACH_STRASBOURG STRASBOURG 3123 +msm8x60_fluid MACH_MSM8X60_FLUID MSM8X60_FLUID 3124 +smartqv5 MACH_SMARTQV5 SMARTQV5 3125 +smartqv3 MACH_SMARTQV3 SMARTQV3 3126 +smartqv7 MACH_SMARTQV7 SMARTQV7 3127 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 +fwbd_0404 MACH_FWBD_0404 FWBD_0404 3131 +hdgu MACH_HDGU HDGU 3132 +pyramid MACH_PYRAMID PYRAMID 3133 +epiphan MACH_EPIPHAN EPIPHAN 3134 +omap_bender MACH_OMAP_BENDER OMAP_BENDER 3135 +gurnard MACH_GURNARD GURNARD 3136 +gtl_it5100 MACH_GTL_IT5100 GTL_IT5100 3137 +bcm2708 MACH_BCM2708 BCM2708 3138 +mx51_ggc MACH_MX51_GGC MX51_GGC 3139 +sharespace MACH_SHARESPACE SHARESPACE 3140 +haba_knx_explorer MACH_HABA_KNX_EXPLORER HABA_KNX_EXPLORER 3141 +simtec_kirkmod MACH_SIMTEC_KIRKMOD SIMTEC_KIRKMOD 3142 +crux MACH_CRUX CRUX 3143 +mx51_bravo MACH_MX51_BRAVO MX51_BRAVO 3144 +charon MACH_CHARON CHARON 3145 +picocom3 MACH_PICOCOM3 PICOCOM3 3146 +picocom4 MACH_PICOCOM4 PICOCOM4 3147 +serrano MACH_SERRANO SERRANO 3148 +doubleshot MACH_DOUBLESHOT DOUBLESHOT 3149 +evsy MACH_EVSY EVSY 3150 +huashan MACH_HUASHAN HUASHAN 3151 +lausanne MACH_LAUSANNE LAUSANNE 3152 +emerald MACH_EMERALD EMERALD 3153 +tqma35 MACH_TQMA35 TQMA35 3154 +marvel MACH_MARVEL MARVEL 3155 +manuae MACH_MANUAE MANUAE 3156 +chacha MACH_CHACHA CHACHA 3157 +lemon MACH_LEMON LEMON 3158 +csc MACH_CSC CSC 3159 +gira_knxip_router MACH_GIRA_KNXIP_ROUTER GIRA_KNXIP_ROUTER 3160 +t20 MACH_T20 T20 3161 +hdmini MACH_HDMINI HDMINI 3162 +sciphone_g2 MACH_SCIPHONE_G2 SCIPHONE_G2 3163 +express MACH_EXPRESS EXPRESS 3164 +express_kt MACH_EXPRESS_KT EXPRESS_KT 3165 +maximasp MACH_MAXIMASP MAXIMASP 3166 +nitrogen_imx51 MACH_NITROGEN_IMX51 NITROGEN_IMX51 3167 +nitrogen_imx53 MACH_NITROGEN_IMX53 NITROGEN_IMX53 3168 +sunfire MACH_SUNFIRE SUNFIRE 3169 +arowana MACH_AROWANA AROWANA 3170 +tegra_daytona MACH_TEGRA_DAYTONA TEGRA_DAYTONA 3171 +tegra_swordfish MACH_TEGRA_SWORDFISH TEGRA_SWORDFISH 3172 +edison MACH_EDISON EDISON 3173 +svp8500v1 MACH_SVP8500V1 SVP8500V1 3174 +svp8500v2 MACH_SVP8500V2 SVP8500V2 3175 +svp5500 MACH_SVP5500 SVP5500 3176 +b5500 MACH_B5500 B5500 3177 +s5500 MACH_S5500 S5500 3178 +icon MACH_ICON ICON 3179 +elephant MACH_ELEPHANT ELEPHANT 3180 +shooter MACH_SHOOTER SHOOTER 3182 +spade_lte MACH_SPADE_LTE SPADE_LTE 3183 +philhwani MACH_PHILHWANI PHILHWANI 3184 +gsncomm MACH_GSNCOMM GSNCOMM 3185 +strasbourg_a2 MACH_STRASBOURG_A2 STRASBOURG_A2 3186 +mmm MACH_MMM MMM 3187 +davinci_dm365_bv MACH_DAVINCI_DM365_BV DAVINCI_DM365_BV 3188 ag5evm MACH_AG5EVM AG5EVM 3189 +sc575plc MACH_SC575PLC SC575PLC 3190 +sc575hmi MACH_SC575IPC SC575IPC 3191 +omap3_tdm3730 MACH_OMAP3_TDM3730 OMAP3_TDM3730 3192 +top9000_eval MACH_TOP9000_EVAL TOP9000_EVAL 3194 +top9000_su MACH_TOP9000_SU TOP9000_SU 3195 +utm300 MACH_UTM300 UTM300 3196 tsunagi MACH_TSUNAGI TSUNAGI 3197 +ts75xx MACH_TS75XX TS75XX 3198 +ts47xx MACH_TS47XX TS47XX 3200 +da850_k5 MACH_DA850_K5 DA850_K5 3201 +ax502 MACH_AX502 AX502 3202 +igep0032 MACH_IGEP0032 IGEP0032 3203 +antero MACH_ANTERO ANTERO 3204 +synergy MACH_SYNERGY SYNERGY 3205 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 +punica MACH_PUNICA PUNICA 3208 trimslice MACH_TRIMSLICE TRIMSLICE 3209 +mx27_wmultra MACH_MX27_WMULTRA MX27_WMULTRA 3210 mackerel MACH_MACKEREL MACKEREL 3211 +fa9x27 MACH_FA9X27 FA9X27 3213 +ns2816tb MACH_NS2816TB NS2816TB 3214 +ns2816_ntpad MACH_NS2816_NTPAD NS2816_NTPAD 3215 +ns2816_ntnb MACH_NS2816_NTNB NS2816_NTNB 3216 kaen MACH_KAEN KAEN 3217 +nv1000 MACH_NV1000 NV1000 3218 +nuc950ts MACH_NUC950TS NUC950TS 3219 nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220 +ast2200 MACH_AST2200 AST2200 3221 +lead MACH_LEAD LEAD 3222 +unino1 MACH_UNINO1 UNINO1 3223 +greeco MACH_GREECO GREECO 3224 +verdi MACH_VERDI VERDI 3225 dm6446_adbox MACH_DM6446_ADBOX DM6446_ADBOX 3226 quad_salsa MACH_QUAD_SALSA QUAD_SALSA 3227 abb_gma_1_1 MACH_ABB_GMA_1_1 ABB_GMA_1_1 3228 @@ -603,7 +3251,9 @@ isc3 MACH_ISC3 ISC3 3291 rascal MACH_RASCAL RASCAL 3292 hrefv60 MACH_HREFV60 HREFV60 3293 tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 +pydtd MACH_PYRAMID_TD PYRAMID_TD 3295 splendor MACH_SPLENDOR SPLENDOR 3296 +guf_vincell MACH_GUF_PLANET GUF_PLANET 3297 msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 athene MACH_ATHENE ATHENE 3300 @@ -614,6 +3264,7 @@ rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 nmh MACH_NMH NMH 3305 wn802t MACH_WN802T WN802T 3306 dragonet MACH_DRAGONET DRAGONET 3307 +geneva_b4 MACH_GENEVA_B GENEVA_B 3308 at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 @@ -621,11 +3272,13 @@ koi MACH_KOI KOI 3312 ts4800 MACH_TS4800 TS4800 3313 tqma9263 MACH_TQMA9263 TQMA9263 3314 holiday MACH_HOLIDAY HOLIDAY 3315 +dma_6410 MACH_DMA6410 DMA6410 3316 pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317 hwgw6410 MACH_HWGW6410 HWGW6410 3318 shenzhou MACH_SHENZHOU SHENZHOU 3319 cwme9210 MACH_CWME9210 CWME9210 3320 cwme9210js MACH_CWME9210JS CWME9210JS 3321 +pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322 colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323 w21 MACH_W21 W21 3324 polysat1 MACH_POLYSAT1 POLYSAT1 3325 @@ -691,11 +3344,15 @@ viprinet MACH_VIPRINET VIPRINET 3385 bockw MACH_BOCKW BOCKW 3386 eva2000 MACH_EVA2000 EVA2000 3387 steelyard MACH_STEELYARD STEELYARD 3388 +ea2468devkit MACH_LPC2468OEM LPC2468OEM 3389 +sdh001 MACH_MACH_SDH001 MACH_SDH001 3390 +fe2478mblox MACH_LPC2478MICROBLOX LPC2478MICROBLOX 3391 nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392 geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393 spear1340 MACH_SPEAR1340 SPEAR1340 3394 rexmas MACH_REXMAS REXMAS 3395 msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396 +msm8960_mtp MACH_MSM8960_MDP MSM8960_MDP 3397 msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398 msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399 helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400 @@ -727,6 +3384,7 @@ gt_i5700 MACH_GT_I5700 GT_I5700 3425 ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426 marvelct MACH_MARVELCT MARVELCT 3427 ag11005 MACH_AG11005 AG11005 3428 +omap_tabletblaze MACH_OMAP_BLAZE OMAP_BLAZE 3429 vangogh MACH_VANGOGH VANGOGH 3430 matrix505 MACH_MATRIX505 MATRIX505 3431 oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432 @@ -766,6 +3424,7 @@ h1600 MACH_H1600 H1600 3465 mini210 MACH_MINI210 MINI210 3466 mini8168 MACH_MINI8168 MINI8168 3467 pc7308 MACH_PC7308 PC7308 3468 +ge863pro3 MACH_GE863 GE863 3469 kmm2m01 MACH_KMM2M01 KMM2M01 3470 mx51erebus MACH_MX51EREBUS MX51EREBUS 3471 wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472 @@ -802,6 +3461,7 @@ shooter_k MACH_SHOOTER_K SHOOTER_K 3502 nspire MACH_NSPIRE NSPIRE 3503 mickxx MACH_MICKXX MICKXX 3504 lxmb MACH_LXMB LXMB 3505 +tmdxscbp6618x MACH_TMDXSCBP6616X TMDXSCBP6616X 3506 adam MACH_ADAM ADAM 3507 b1004 MACH_B1004 B1004 3508 oboea MACH_OBOEA OBOEA 3509 @@ -879,6 +3539,7 @@ bct MACH_BCT BCT 3582 tuscan MACH_TUSCAN TUSCAN 3583 xbt_sam9g45 MACH_XBT_SAM9G45 XBT_SAM9G45 3584 enbw_cmc MACH_ENBW_CMC ENBW_CMC 3585 +msm8x60_dragon MACH_APQ8060_DRAGON APQ8060_DRAGON 3586 ch104mx257 MACH_CH104MX257 CH104MX257 3587 openpri MACH_OPENPRI OPENPRI 3588 am335xevm MACH_AM335XEVM AM335XEVM 3589 @@ -900,6 +3561,7 @@ cinema MACH_CINEMA CINEMA 3604 cinema_tea MACH_CINEMA_TEA CINEMA_TEA 3605 cinema_coffee MACH_CINEMA_COFFEE CINEMA_COFFEE 3606 cinema_juice MACH_CINEMA_JUICE CINEMA_JUICE 3607 +linux_pad MACH_THEPAD THEPAD 3608 mx53_mirage2 MACH_MX53_MIRAGE2 MX53_MIRAGE2 3609 mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 stm_b2000 MACH_STM_B2000 STM_B2000 3612 @@ -965,6 +3627,7 @@ pia_am35x MACH_PIA_AM35X PIA_AM35X 3671 cedar MACH_CEDAR CEDAR 3672 picasso_e MACH_PICASSO_E PICASSO_E 3673 samsung_e60 MACH_SAMSUNG_E60 SAMSUNG_E60 3674 +msm9615_cdp MACH_MDM9615 MDM9615 3675 sdvr_mini MACH_SDVR_MINI SDVR_MINI 3676 omap3_ij3k MACH_OMAP3_IJ3K OMAP3_IJ3K 3677 modasmc1 MACH_MODASMC1 MODASMC1 3678 @@ -992,6 +3655,8 @@ fmc_uic MACH_FMC_UIC FMC_UIC 3699 fmc_dcm MACH_FMC_DCM FMC_DCM 3700 batwm MACH_BATWM BATWM 3701 atlas6cb MACH_ATLAS6CB ATLAS6CB 3702 +quattro_f MACH_QUATTROF QUATTROF 3703 +quattro_u MACH_QUATTROU QUATTROU 3704 blue MACH_BLUE BLUE 3705 colorado MACH_COLORADO COLORADO 3706 popc MACH_POPC POPC 3707 @@ -999,15 +3664,19 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708 amp MACH_AMP AMP 3709 gnet_amp MACH_GNET_AMP GNET_AMP 3710 toques MACH_TOQUES TOQUES 3711 +apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712 dct_storm MACH_DCT_STORM DCT_STORM 3713 +dm8168z3 MACH_Z3 Z3 3714 owl MACH_OWL OWL 3715 cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716 +omap3_kiko MACH_OMAP3 OMAP3 3717 adillustra610 MACH_ADILLUSTRA610 ADILLUSTRA610 3718 ecafe_na04 MACH_ECAFE_NA04 ECAFE_NA04 3719 popct MACH_POPCT POPCT 3720 omap3_helena MACH_OMAP3_HELENA OMAP3_HELENA 3721 ach MACH_ACH ACH 3722 module_dtb MACH_MODULE_DTB MODULE_DTB 3723 +ratebox MACH_RACKBOX RACKBOX 3724 oslo_elisabeth MACH_OSLO_ELISABETH OSLO_ELISABETH 3725 tt01 MACH_TT01 TT01 3726 msm8930_cdp MACH_MSM8930_CDP MSM8930_CDP 3727 @@ -1038,6 +3707,7 @@ ptip_murnau MACH_PTIP_MURNAU PTIP_MURNAU 3752 ptip_classic MACH_PTIP_CLASSIC PTIP_CLASSIC 3753 mx53grb MACH_MX53GRB MX53GRB 3754 gagarin MACH_GAGARIN GAGARIN 3755 +msm7627a_qrd1 MACH_MSM7X27A_QRD1 MSM7X27A_QRD1 3756 nas2big MACH_NAS2BIG NAS2BIG 3757 superfemto MACH_SUPERFEMTO SUPERFEMTO 3758 teufel MACH_TEUFEL TEUFEL 3759 @@ -1087,6 +3757,7 @@ ubisys_g1 MACH_UBISYS_G1 UBISYS_G1 3802 mx53_pf1 MACH_MX53_PF1 MX53_PF1 3803 asanti MACH_ASANTI ASANTI 3804 volta MACH_VOLTA VOLTA 3805 +potenza MACH_S5P6450 S5P6450 3806 knight MACH_KNIGHT KNIGHT 3807 beaglebone MACH_BEAGLEBONE BEAGLEBONE 3808 becker MACH_BECKER BECKER 3809 @@ -1148,6 +3819,7 @@ primou MACH_PRIMOU PRIMOU 3864 primoc MACH_PRIMOC PRIMOC 3865 primoct MACH_PRIMOCT PRIMOCT 3866 a9500 MACH_A9500 A9500 3867 +pue_td MACH_PULSE_TD PULSE_TD 3868 pluto MACH_PLUTO PLUTO 3869 acfx100 MACH_ACFX100 ACFX100 3870 msm8625_rumi3 MACH_MSM8625_RUMI3 MSM8625_RUMI3 3871 @@ -1161,6 +3833,8 @@ valente_wx MACH_VALENTE_WX VALENTE_WX 3878 huangshans MACH_HUANGSHANS HUANGSHANS 3879 bosphorus1 MACH_BOSPHORUS1 BOSPHORUS1 3880 prima MACH_PRIMA PRIMA 3881 +meson3_skt MACH_M3_SKT M3_SKT 3882 +meson3_ref MACH_M3_REF M3_REF 3883 evita_ulk MACH_EVITA_ULK EVITA_ULK 3884 merisc600 MACH_MERISC600 MERISC600 3885 dolak MACH_DOLAK DOLAK 3886 @@ -1169,3 +3843,113 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888 pov2 MACH_POV2 POV2 3889 ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890 da850_pqab MACH_DA850_PQAB DA850_PQAB 3891 +fermi MACH_FERMI FERMI 3892 +ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893 +ccardmx28 MACH_CCARDMX28 CCARDMX28 3894 +fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895 +kinetis MACH_KINETIS KINETIS 3896 +kai MACH_KAI KAI 3897 +bcthb2 MACH_BCTHB2 BCTHB2 3898 +inels3_cu MACH_INELS3_CU INELS3_CU 3899 +da850_juniper MACH_JUNIPER JUNIPER 3900 +da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901 +tracnas MACH_TRACNAS TRACNAS 3902 +mityarm335x MACH_MITYARM335X MITYARM335X 3903 +xcgz7x MACH_XCGZ7X XCGZ7X 3904 +cubox MACH_CUBOX CUBOX 3905 +terminator MACH_TERMINATOR TERMINATOR 3906 +eye03 MACH_EYE03 EYE03 3907 +kota3 MACH_KOTA3 KOTA3 3908 +mx53_nitrogen_k MACH_MX5 MX5 3909 +pscpe MACH_PSCPE PSCPE 3910 +akt1100 MACH_AKT1100 AKT1100 3911 +pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912 +primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913 +nsbc MACH_NSBC NSBC 3914 +meson2_skt MACH_MESON2_SKT MESON2_SKT 3915 +meson2_ref MACH_MESON2_REF MESON2_REF 3916 +ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917 +ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918 +indico MACH_INDICO INDICO 3919 +msm8960dt MACH_MSM8960DT MSM8960DT 3920 +primods MACH_PRIMODS PRIMODS 3921 +beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922 +primotd MACH_PRIMOTD PRIMOTD 3923 +varan_master MACH_VARAN_MASTER VARAN_MASTER 3924 +primodd MACH_PRIMODD PRIMODD 3925 +jetduo MACH_JETDUO JETDUO 3926 +mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927 +trats MACH_TRATS TRATS 3928 +starcraft MACH_STARCRAFT STARCRAFT 3929 +qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930 +lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931 +movenow MACH_MOVENOW MOVENOW 3932 +golf_u MACH_GOLF_U GOLF_U 3933 +msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934 +rambo MACH_RAMBO RAMBO 3935 +golfu MACH_GOLFU GOLFU 3936 +mango310 MACH_MANGO310 MANGO310 3937 +dns343 MACH_DNS343 DNS343 3938 +var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939 +naon MACH_NAON NAON 3940 +vp4000 MACH_VP4000 VP4000 3941 +impcard MACH_IMPCARD IMPCARD 3942 +smoovcam MACH_SMOOVCAM SMOOVCAM 3943 +cobham3725 MACH_COBHAM3725 COBHAM3725 3944 +cobham3730 MACH_COBHAM3730 COBHAM3730 3945 +cobham3703 MACH_COBHAM3703 COBHAM3703 3946 +quetzal MACH_QUETZAL QUETZAL 3947 +apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948 +apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949 +apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950 +apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951 +mango210 MACH_MANGO210 MANGO210 3952 +mango100 MACH_MANGO100 MANGO100 3953 +mango24 MACH_MANGO24 MANGO24 3954 +mango64 MACH_MANGO64 MANGO64 3955 +nsa320 MACH_NSA320 NSA320 3956 +elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957 +triton_x00 MACH_TRITON_X00 TRITON_X00 3958 +triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959 +pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960 +venus_cl MACH_VENUS_CL VENUS_CL 3961 +vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962 +sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963 +stsv2 MACH_STSV2 STSV2 3964 +csb1724 MACH_CSB1724 CSB1724 3965 +omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966 +jel_dd MACH_JEWEL_DD JEWEL_DD 3967 +pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968 +meson6_skt MACH_MESON6_SKT MESON6_SKT 3969 +meson6_ref MACH_MESON6_REF MESON6_REF 3970 +pxm MACH_PXM PXM 3971 +stuttgart MACH_S3 S3 3972 +pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973 +mlp89626 MACH_MLP89626 MLP89626 3974 +iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975 +pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976 +bntv250 MACH_BNTV250 BNTV250 3977 +mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978 +gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979 +mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980 +mt4 MACH_MT4 MT4 3981 +jumbo_d MACH_JUMBO_D JUMBO_D 3982 +jumbo_i MACH_JUMBO_I JUMBO_I 3983 +fs20_dmp MACH_FS20_DMP FS20_DMP 3984 +dns320 MACH_DNS320 DNS320 3985 +mx28bacos MACH_MX28BACOS MX28BACOS 3986 +tl80 MACH_TL80 TL80 3987 +polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988 +tely MACH_TELY TELY 3989 +u8520 MACH_U8520 U8520 3990 +manta MACH_MANTA MANTA 3991 +spear1340_lcad MACH_SPEAR_EM_S900 SPEAR_EM_S900 3992 +mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993 +mpq8064_stb MACH_MPQ8064_STB MPQ8064_STB 3994 +mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995 +dm368som MACH_DM368SOM DM368SOM 3996 +gprisb2 MACH_GPRISB2 GPRISB2 3997 +chammid MACH_CHAMMID CHAMMID 3998 +seoul2 MACH_SEOUL2 SEOUL2 3999 +omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000 +aalto MACH_AALTO AALTO 4001 -- cgit v1.2.3 From 0addb09e8f40baa63e608fd21d16cc5372cd606d Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 6 Feb 2012 12:06:09 +0100 Subject: drivers: power: ab8500_charger: Remove pointless check Remove pointless check for NULL that didn't return a proper return value. (di can't be NULL, since then containerof would have failed.) ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ic3a725150c739e50e73d36255be4c3f02ae9bb6f Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47966 Reviewed-by: Johan BJORNSTEDT --- drivers/power/ab8500_charger.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 13f2975445f..6c599813d84 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -2429,9 +2429,6 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, else /* Should never occur */ bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; - if (di == NULL) - return; - dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", __func__, bm_usb_state, mA); -- cgit v1.2.3 From 960a61882213cc8f3cd17aa1cf9bf31302fb0efc Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 10 Jan 2012 09:53:35 +0100 Subject: ARM: configs: Add support for 9540 ST-Ericsson Linux next: NA ST-Ericsson ID: 398896 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I3962c34e9eb84e808f4d31dc0d9050bdac993abf Signed-off-by: Yann Gautier Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44916 Reviewed-by: QATOOLS Reviewed-by: Srinidhi KASAGAR --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 053b02ebc09..f3c8d116e38 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -23,6 +23,7 @@ CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_U9540=y CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_GPIO_KEYS=y -- cgit v1.2.3 From bfe8199e1a5686a1dd460d8a99ac862870f0f4fa Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 2 Feb 2012 11:36:49 +0100 Subject: config: ux500: Add U8520 machine ST-Ericsson ID: 371953 Signed-off-by: Bengt Jonsson --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index f3c8d116e38..0a8daf746fe 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -22,6 +22,7 @@ CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y +CONFIG_MACH_U8520=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U9540=y CONFIG_MACH_U8500_SNOWBALL=y -- cgit v1.2.3 From d2802da3a7a6c8445a53ec1dd07711f1e444ac9d Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Fri, 13 Jan 2012 17:25:33 +0100 Subject: mfd: ab8500: Configure AB8505 ST-Ericsson ID: 371953 Signed-off-by: Bengt Jonsson --- drivers/mfd/ab8500-core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 0542381185b..d4d5400e184 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1044,6 +1044,15 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ab8500->chip_id = value; + /* + * HACK: for AB8505 until drivers are updated, + * make it look like an AB8500 3.3. + */ + if (ab8500->version == AB8500_VERSION_AB8505) { + ab8500->version = AB8500_VERSION_AB8500; + ab8500->chip_id = AB8500_CUT3P3; + } + dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", ab8500_version_str[ab8500->version], ab8500->chip_id >> 4, -- cgit v1.2.3 From 8280c41dc2d47aa7291cad3256f87e073ea785f8 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 15 Dec 2011 10:49:09 +0100 Subject: ARM: kexec: Call the per cpu calls on crashing cpu as well Previous the per cpu callbacks where only executed on the none-crashing cpu. ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I0640f9121fb55e94f3939104d0a0fef224d35e7c Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42666 Reviewed-by: QABUILD Reviewed-by: Johan BJORNSTEDT --- arch/arm/kernel/machine_kexec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 7455ca0fc51..4f868fc5174 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -84,6 +84,8 @@ void machine_crash_shutdown(struct pt_regs *regs) local_irq_disable(); + atomic_notifier_call_chain(&crash_percpu_notifier_list, 0, NULL); + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); smp_call_function(machine_crash_nonpanic_core, NULL, false); msecs = 1000; /* Wait at most a second for the other cpus to stop */ -- cgit v1.2.3 From f56978457cd094f18fbb2d49a883921737d60b14 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 31 Jan 2012 14:36:20 +0530 Subject: tty: serial: amba-pl011: fix cancel_delayed_work() usage PL011 calls del_timer_sync() (via cancel_delayed_work()) from atomic context. Fix it. ====================================================== [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ] 3.0.8+ #1188 ------------------------------------------------------ kworker/u:0/5 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: (&(&uap->clk_off_work)->timer){+.-...}, at: [] del_timer_sync+0x0/0xc8 and this task is already holding: (&port_lock_key){-.-...}, at: [] pl011_clock_on+0x80/0xc4 which would create a new lock dependency: (&port_lock_key){-.-...} -> (&(&uap->clk_off_work)->timer){+.-...} but this new dependency connects a HARDIRQ-irq-safe lock: (&port_lock_key){-.-...} ... which became HARDIRQ-irq-safe at: [] mark_irqflags+0x68/0x170 [] __lock_acquire+0x598/0x788 [] lock_acquire+0x10c/0x130 [] _raw_spin_lock_irqsave+0x5c/0x98 [] pl011_int+0x10/0x128 [] handle_irq_event_percpu+0x98/0x1f4 [] handle_irq_event+0x3c/0x5c [] handle_fasteoi_irq+0xc8/0x100 [] generic_handle_irq+0x28/0x30 [] asm_do_IRQ+0x78/0xb8 [] __irq_svc+0x50/0xf4 [] enter_sleep+0x550/0x608 [] cpuidle_idle_call+0x1c4/0x33c [] cpu_idle+0xa4/0x10c [] start_kernel+0x228/0x27c [<00008040>] 0x8040 to a HARDIRQ-irq-unsafe lock: (&(&uap->clk_off_work)->timer){+.-...} ... which became HARDIRQ-irq-unsafe at: ... [] mark_irqflags+0xec/0x170 [] __lock_acquire+0x598/0x788 [] lock_acquire+0x10c/0x130 [] call_timer_fn+0x68/0x1e4 [] run_timer_softirq+0x1c8/0x224 [] __do_softirq+0x110/0x23c [] irq_exit+0x5c/0xc0 [] do_local_timer+0x50/0x80 [] __irq_svc+0x50/0xf4 [] __mutex_unlock_slowpath+0x150/0x17c [] sysfs_addrm_finish+0x10/0x74 [] sysfs_add_file_mode+0x70/0xb0 [] create_files+0x7c/0xb4 [] internal_create_group+0xb8/0x118 [] device_add_groups+0x1c/0x70 [] device_add_attrs+0x50/0xa8 [] device_add+0x110/0x2b4 [] hci_register_sysfs+0x54/0x114 [] hci_register_dev+0x378/0x4d8 [] register_bluetooth+0xb4/0x124 [] probe_common+0x7c/0xcc [] btcg2900_evt_probe+0x38/0x6c [] platform_drv_probe+0x18/0x1c [] really_probe+0x98/0x148 [] driver_probe_device+0x48/0x60 [] bus_for_each_drv+0x44/0x74 [] device_attach+0x78/0xa4 [] bus_probe_device+0x24/0x40 [] device_add+0x174/0x2b4 [] platform_device_add+0x104/0x160 [] mfd_add_device+0x194/0x1d4 [] mfd_add_devices+0x70/0xbc [] work_power_off_chip+0x11c/0x1c8 [] process_one_work+0x2ac/0x4c8 [] worker_thread+0x144/0x234 [] kthread+0x80/0x88 [] kernel_thread_exit+0x0/0x8 other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&(&uap->clk_off_work)->timer); local_irq_disable(); lock(&port_lock_key); lock(&(&uap->clk_off_work)->timer); lock(&port_lock_key); *** DEADLOCK *** Change-Id: I55d565d484baaee2dc76f258a5066aacbb6e6dee Signed-off-by: Rabin Vincent ST-Ericsson ID: 413918 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1a45effb0afeb4344f03ca500a5b0767bd760ec3 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/47174 Reviewed-by: QABUILD Reviewed-by: Shreshtha Kumar SAHU Reviewed-by: Rabin VINCENT Tested-by: Rabin VINCENT --- drivers/tty/serial/amba-pl011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index bed430df99e..d356b940382 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1306,7 +1306,7 @@ static void pl011_clock_on(struct uart_port *port) } /* fallthrough */ case PL011_CLK_REQUEST_OFF: - cancel_delayed_work(&uap->clk_off_work); + __cancel_delayed_work(&uap->clk_off_work); uap->clk_state = PL011_CLK_ON; break; default: @@ -1321,7 +1321,7 @@ static void pl011_clock_check(struct uart_amba_port *uap) /* Reshedule work during off request */ if (uap->clk_state == PL011_CLK_REQUEST_OFF) /* New TX - restart work */ - if (cancel_delayed_work(&uap->clk_off_work)) + if (__cancel_delayed_work(&uap->clk_off_work)) schedule_delayed_work(&uap->clk_off_work, uap->clk_off_delay); } -- cgit v1.2.3 From 22221424ee6bd9c279a11e02198935d57ebab4a6 Mon Sep 17 00:00:00 2001 From: Michel JAOUEN Date: Thu, 9 Feb 2012 12:06:47 +0100 Subject: ab8500: gpadc: Introduce new AB version detection Add support for AB8505 and AB9540 ST-Ericsson ID: 366316 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9021cce8a38ba70f025b95610c84b554c4ad59ac Signed-off-by: Maxime Coquelin Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49029 Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Rabin VINCENT --- drivers/mfd/ab8500-gpadc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 515e360fb09..8d3d257148d 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -102,10 +102,10 @@ struct adc_cal_data { /** * struct ab8500_gpadc - AB8500 GPADC device information - * @chip_id ABB chip id * @dev: pointer to the struct device * @node: a list of AB8500 GPADCs, hence prepared for reentrance + * @parent: pointer to the struct ab8500 * @ab8500_gpadc_complete: pointer to the struct completion, to indicate * the completion of gpadc conversion * @ab8500_gpadc_lock: structure of type mutex @@ -114,9 +114,9 @@ struct adc_cal_data { * @cal_data array of ADC calibration data structs */ struct ab8500_gpadc { - u8 chip_id; struct device *dev; struct list_head node; + struct ab8500 *parent; struct completion ab8500_gpadc_complete; struct mutex ab8500_gpadc_lock; struct regulator *regu; @@ -328,7 +328,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) EN_BUF | EN_ICHAR); break; case BTEMP_BALL: - if (gpadc->chip_id >= AB8500_CUT3P0) { + if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { /* Turn on btemp pull-up on ABB 3.0 */ ret = abx500_mask_and_set_register_interruptible( gpadc->dev, @@ -587,6 +587,7 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) } gpadc->dev = &pdev->dev; + gpadc->parent = dev_get_drvdata(pdev->dev.parent); mutex_init(&gpadc->ab8500_gpadc_lock); /* Initialize completion used to notify completion of conversion */ @@ -602,14 +603,6 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) goto fail; } - /* Get Chip ID of the ABB ASIC */ - ret = abx500_get_chip_id(gpadc->dev); - if (ret < 0) { - dev_err(gpadc->dev, "failed to get chip ID\n"); - goto fail_irq; - } - gpadc->chip_id = (u8) ret; - /* VTVout LDO used to power up ab8500-GPADC */ gpadc->regu = regulator_get(&pdev->dev, "vddadc"); if (IS_ERR(gpadc->regu)) { -- cgit v1.2.3 From 88eb63ee79dafce5ba11e8559799454b1f542273 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Tue, 14 Feb 2012 10:53:07 +0100 Subject: ab8500: rtc: Remove fix for AB8500 ED version AB8500 ED (Early Drop) is no longer supported. ST-Ericsson ID: 366316 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I51b860b71cf1485a202237a6962c89873b03add7 Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49030 Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Rabin VINCENT --- drivers/rtc/rtc-ab8500.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 587f593c17e..baae8548781 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -88,22 +88,17 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) if (retval < 0) return retval; - /* Early AB8500 chips will not clear the rtc read request bit */ - if (abx500_get_chip_id(dev) == 0) { - usleep_range(1000, 1000); - } else { - /* Wait for some cycles after enabling the rtc read in ab8500 */ - while (time_before(jiffies, timeout)) { - retval = abx500_get_register_interruptible(dev, - AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); - if (retval < 0) - return retval; - - if (!(value & RTC_READ_REQUEST)) - break; - - usleep_range(1000, 5000); - } + /* Wait for some cycles after enabling the rtc read in ab8500 */ + while (time_before(jiffies, timeout)) { + retval = abx500_get_register_interruptible(dev, + AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); + if (retval < 0) + return retval; + + if (!(value & RTC_READ_REQUEST)) + break; + + usleep_range(1000, 5000); } /* Read the Watchtime registers */ -- cgit v1.2.3 From 4cf150e81720126af51dce617e53266ebc6be727 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Tue, 14 Feb 2012 17:33:10 +0100 Subject: ab8500: mfd: Remove AB8505 detection hack ST-Ericsson ID: 366316 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I26aa50ff04843a53bddc147b7a5c501efe779f44 Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49034 Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Rabin VINCENT --- drivers/mfd/ab8500-core.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index d4d5400e184..0542381185b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1044,15 +1044,6 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ab8500->chip_id = value; - /* - * HACK: for AB8505 until drivers are updated, - * make it look like an AB8500 3.3. - */ - if (ab8500->version == AB8500_VERSION_AB8505) { - ab8500->version = AB8500_VERSION_AB8500; - ab8500->chip_id = AB8500_CUT3P3; - } - dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", ab8500_version_str[ab8500->version], ab8500->chip_id >> 4, -- cgit v1.2.3 From 34fce062ec003181a2c9a4648bc2e722c8fde847 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Tue, 14 Feb 2012 13:01:00 +0100 Subject: ab8500: mfd: Add interrupt debug This patch adds an entry in debugfs to check number of interrupts from the AB. ST-Ericsson ID: 366316 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I09d391e7d755773f7438fa1263371145ba91c1f1 Signed-off-by: Bengt Jonsson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49036 Reviewed-by: Rabin VINCENT --- drivers/mfd/ab8500-core.c | 1 + drivers/mfd/ab8500-debugfs.c | 49 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab8500.h | 2 ++ 3 files changed, 52 insertions(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 0542381185b..e92f51b1136 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -358,6 +358,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev) int line = i * 8 + bit; handle_nested_irq(ab8500->irq_base + line); + ab8500_debug_register_interrupt(line); value &= ~(1 << bit); } while (value); } diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 7f893aeba22..1db6bcff114 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -735,6 +735,35 @@ static ssize_t ab8500_val_write(struct file *file, return count; } +/* + * Interrupt status + */ +static u32 num_interrupts[AB8500_MAX_NR_IRQS]; +static int num_interrupt_lines; + +void ab8500_debug_register_interrupt(int line) +{ + if (line < num_interrupt_lines) + num_interrupts[line]++; +} + +static int ab8500_interrupts_print(struct seq_file *s, void *p) +{ + int line; + + seq_printf(s, "irq: number of\n"); + + for (line = 0; line < num_interrupt_lines; line++) + seq_printf(s, "%3i: %6i\n", line, num_interrupts[line]); + + return 0; +} + +static int ab8500_interrupts_open(struct inode *inode, struct file *file) +{ + return single_open(file, ab8500_interrupts_print, inode->i_private); +} + /* * - HWREG DB8500 formated routines */ @@ -1485,6 +1514,14 @@ static const struct file_operations ab8500_val_fops = { .owner = THIS_MODULE, }; +static const struct file_operations ab8500_interrupts_fops = { + .open = ab8500_interrupts_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static const struct file_operations ab8500_subscribe_fops = { .open = ab8500_subscribe_unsubscribe_open, .write = ab8500_subscribe_write, @@ -1588,6 +1625,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) if (!file) goto err; + if (is_ab8500(ab8500)) + num_interrupt_lines = AB8500_NR_IRQS; + else if (is_ab8505(ab8500)) + num_interrupt_lines = AB8505_NR_IRQS; + else if (is_ab9540(ab8500)) + num_interrupt_lines = AB9540_NR_IRQS; + + file = debugfs_create_file("interrupts", (S_IRUGO), + ab8500_dir, &plf->dev, &ab8500_interrupts_fops); + if (!file) + goto err; + file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_subscribe_fops); if (!file) diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 8d2a57e2fa7..7e056197b98 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -349,8 +349,10 @@ static inline int is_ab8500_2p0(struct ab8500 *ab) #ifdef CONFIG_AB8500_DEBUG void ab8500_dump_all_banks(struct device *dev); +void ab8500_debug_register_interrupt(int line); #else static inline void ab8500_dump_all_banks(struct device *dev) {} +static inline void ab8500_debug_register_interrupt(int line) {} #endif #endif /* MFD_AB8500_H */ -- cgit v1.2.3 From b7c30dfedc05fa3fd9e73ad9d56db4637824de6f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 21 Nov 2011 18:08:06 +0530 Subject: Revert "Revert "rtc-ab: set can_wake flag"" This reverts commit 3b2031017f342d0906f9e2ba7484bcb27cbb240d. Now that the real problem has been fixed (in the RTC core and AB5500 driver), bring this back. ST-Ericsson ID: 375473 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9e18d60fd26299e9a4c5709bdf0de7d850fba3a0 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/39116 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Arun MURTHY --- drivers/rtc/rtc-ab.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-ab.c b/drivers/rtc/rtc-ab.c index 393dd5a0e09..009409f39d7 100644 --- a/drivers/rtc/rtc-ab.c +++ b/drivers/rtc/rtc-ab.c @@ -410,6 +410,8 @@ static int __devinit ab_rtc_probe(struct platform_device *pdev) return err; } + device_init_wakeup(&pdev->dev, true); + rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { -- cgit v1.2.3 From b607377c36ff0efdc187e291d22df1835cd688cd Mon Sep 17 00:00:00 2001 From: Johan Bjornstedt Date: Wed, 18 Jan 2012 12:44:55 +0100 Subject: power: ab8500_bm: Charger current step-up/down There is no state machine in the AB to step up/down the charger current to avoid dips and spikes on VBUS and VBAT when charging is started. Instead this is implemented in SW ST-Ericsson ID: 409058, 410253 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: Ia21d8689c6894c3f62d9a2d7e7aacda6873aa79f Signed-off-by: Johan Bjornstedt Signed-off-by: Mattias Wallin Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45827 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Karl KOMIEROWSKI --- drivers/power/ab8500_charger.c | 175 +++++++++++++++++++++++++++++++---------- 1 file changed, 135 insertions(+), 40 deletions(-) diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 6c599813d84..a675765fc4f 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -78,6 +78,9 @@ /* Lowest charger voltage is 3.39V -> 0x4E */ #define LOW_VOLT_REG 0x4E +/* Step up/down delay in us */ +#define STEP_UDELAY 1000 + /* UsbLineStatus register - usb types */ enum ab8500_charger_link_status { USB_STAT_NOT_CONFIGURED, @@ -934,6 +937,88 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) return 0; } +/** + * ab8500_charger_set_current() - set charger current + * @di: pointer to the ab8500_charger structure + * @ich: charger current, in mA + * @reg: select what charger register to set + * + * Set charger current. + * There is no state machine in the AB to step up/down the charger + * current to avoid dips and spikes on MAIN, VBUS and VBAT when + * charging is started. Instead we need to implement + * this charger current step-up/down here. + * Returns error code in case of failure else 0(on success) + */ +static int ab8500_charger_set_current(struct ab8500_charger *di, + int ich, int reg) +{ + int ret, i; + int curr_index, prev_curr_index, shift_value; + u8 reg_value; + + switch (reg) { + case AB8500_MCH_IPT_CURLVL_REG: + shift_value = MAIN_CH_INPUT_CURR_SHIFT; + curr_index = ab8500_current_to_regval(ich); + break; + case AB8500_USBCH_IPT_CRNTLVL_REG: + shift_value = VBUS_IN_CURR_LIM_SHIFT; + curr_index = ab8500_vbus_in_curr_to_regval(ich); + break; + case AB8500_CH_OPT_CRNTLVL_REG: + shift_value = 0; + curr_index = ab8500_current_to_regval(ich); + break; + default: + dev_err(di->dev, "%s current register not valid\n", __func__); + return -ENXIO; + } + + if (curr_index < 0) { + dev_err(di->dev, "requested current limit out-of-range\n"); + return -ENXIO; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, + reg, ®_value); + if (ret < 0) { + dev_err(di->dev, "%s read failed\n", __func__); + return ret; + } + prev_curr_index = (reg_value >> shift_value); + + /* only update current if it's been changed */ + if (prev_curr_index == curr_index) + return 0; + + dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n", + __func__, ich, reg); + + if (prev_curr_index > curr_index) { + for (i = prev_curr_index - 1; i >= curr_index; i--) { + ret = abx500_set_register_interruptible(di->dev, + AB8500_CHARGER, reg, (u8) i << shift_value); + if (ret) { + dev_err(di->dev, "%s write failed\n", __func__); + return ret; + } + usleep_range(STEP_UDELAY, STEP_UDELAY * 2); + } + } else { + for (i = prev_curr_index + 1; i <= curr_index; i++) { + ret = abx500_set_register_interruptible(di->dev, + AB8500_CHARGER, reg, (u8) i << shift_value); + if (ret) { + dev_err(di->dev, "%s write failed\n", __func__); + return ret; + } + usleep_range(STEP_UDELAY, STEP_UDELAY * 2); + } + } + return ret; +} + /** * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit * @di: pointer to the ab8500_charger structure @@ -945,8 +1030,6 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, int ich_in) { - int ret; - int input_curr_index; int min_value; /* We should always use to lowest current limit */ @@ -965,19 +1048,38 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, break; } - input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); - if (input_curr_index < 0) { - dev_err(di->dev, "VBUS input current limit too high\n"); - return -ENXIO; - } + return ab8500_charger_set_current(di, min_value, + AB8500_USBCH_IPT_CRNTLVL_REG); +} - ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_USBCH_IPT_CRNTLVL_REG, - input_curr_index << VBUS_IN_CURR_LIM_SHIFT); - if (ret) - dev_err(di->dev, "%s write failed\n", __func__); +/** + * ab8500_charger_set_main_in_curr() - set main charger input current + * @di: pointer to the ab8500_charger structure + * @ich_in: input charger current, in mA + * + * Set main charger input current. + * Returns error code in case of failure else 0(on success) + */ +static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di, + int ich_in) +{ + return ab8500_charger_set_current(di, ich_in, + AB8500_MCH_IPT_CURLVL_REG); +} - return ret; +/** + * ab8500_charger_set_output_curr() - set charger output current + * @di: pointer to the ab8500_charger structure + * @ich_out: output charger current, in mA + * + * Set charger output current. + * Returns error code in case of failure else 0(on success) + */ +static int ab8500_charger_set_output_curr(struct ab8500_charger *di, + int ich_out) +{ + return ab8500_charger_set_current(di, ich_out, + AB8500_CH_OPT_CRNTLVL_REG); } /** @@ -1089,18 +1191,19 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, return ret; } /* MainChInputCurr: current that can be drawn from the charger*/ - ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_MCH_IPT_CURLVL_REG, - input_curr_index << MAIN_CH_INPUT_CURR_SHIFT); + ret = ab8500_charger_set_main_in_curr(di, + di->bat->chg_params->ac_curr_max); if (ret) { - dev_err(di->dev, "%s write failed\n", __func__); + dev_err(di->dev, "%s Failed to set MainChInputCurr\n", + __func__); return ret; } /* ChOutputCurentLevel: protected output current */ - ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); + ret = ab8500_charger_set_output_curr(di, iset); if (ret) { - dev_err(di->dev, "%s write failed\n", __func__); + dev_err(di->dev, "%s " + "Failed to set ChOutputCurentLevel\n", + __func__); return ret; } @@ -1157,12 +1260,11 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, return ret; } - ret = abx500_set_register_interruptible(di->dev, - AB8500_CHARGER, - AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1); + ret = ab8500_charger_set_output_curr(di, 0); if (ret) { - dev_err(di->dev, - "%s write failed\n", __func__); + dev_err(di->dev, "%s " + "Failed to set ChOutputCurentLevel\n", + __func__); return ret; } } else { @@ -1265,10 +1367,11 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, return ret; } /* ChOutputCurentLevel: protected output current */ - ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); + ret = ab8500_charger_set_output_curr(di, ich_out); if (ret) { - dev_err(di->dev, "%s write failed\n", __func__); + dev_err(di->dev, "%s " + "Failed to set ChOutputCurentLevel\n", + __func__); return ret; } /* Check if VBAT overshoot control should be enabled */ @@ -1365,7 +1468,6 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, int ich_out) { int ret; - int curr_index; struct ab8500_charger *di; if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) @@ -1375,18 +1477,11 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, else return -ENXIO; - curr_index = ab8500_current_to_regval(ich_out); - if (curr_index < 0) { - dev_err(di->dev, - "Charger current too high, " - "charging not started\n"); - return -ENXIO; - } - - ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); + ret = ab8500_charger_set_output_curr(di, ich_out); if (ret) { - dev_err(di->dev, "%s write failed\n", __func__); + dev_err(di->dev, "%s " + "Failed to set ChOutputCurentLevel\n", + __func__); return ret; } -- cgit v1.2.3 From a3f15a7ec440dbccb72f0da6bf65f5c21797a69c Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Fri, 10 Feb 2012 10:00:06 +0100 Subject: drivers: mfd: ab8500-gpadc: Add runtime pm support Add runtime pm support to speed up multiple ADC reads in a row. ST-Ericsson Linux next: - ST-Ericsson ID: 408044 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I8d868d31437f4560ec3328baecebc8a9265093d4 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49950 Reviewed-by: QABUILD Reviewed-by: Ulf HANSSON --- drivers/mfd/ab8500-gpadc.c | 70 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 8d3d257148d..20ab561b42e 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,9 @@ /* This is used to not lose precision when dividing to get gain and offset */ #define CALIB_SCALE 1000 +/* Time in ms before disabling regulator */ +#define GPADC_AUDOSUSPEND_DELAY 1 + enum cal_channels { ADC_INPUT_VMAIN = 0, ADC_INPUT_BTEMP, @@ -278,8 +282,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) return -ENODEV; mutex_lock(&gpadc->ab8500_gpadc_lock); + /* Enable VTVout LDO this is required for GPADC */ - regulator_enable(gpadc->regu); + pm_runtime_get_sync(gpadc->dev); /* Check if ADC is not busy, lock and proceed */ do { @@ -393,8 +398,10 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); goto out; } - /* Disable VTVout LDO this is required for GPADC */ - regulator_disable(gpadc->regu); + + pm_runtime_mark_last_busy(gpadc->dev); + pm_runtime_put_autosuspend(gpadc->dev); + mutex_unlock(&gpadc->ab8500_gpadc_lock); return (high_data << 8) | low_data; @@ -408,7 +415,9 @@ out: */ (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, AB8500_GPADC_CTRL1_REG, DIS_GPADC); - regulator_disable(gpadc->regu); + + pm_runtime_put(gpadc->dev); + mutex_unlock(&gpadc->ab8500_gpadc_lock); dev_err(gpadc->dev, "gpadc_conversion: Failed to AD convert channel %d\n", channel); @@ -567,6 +576,30 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) gpadc->cal_data[ADC_INPUT_VBAT].offset); } +static int ab8500_gpadc_runtime_suspend(struct device *dev) +{ + struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); + + regulator_disable(gpadc->regu); + return 0; +} + +static int ab8500_gpadc_runtime_resume(struct device *dev) +{ + struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); + + regulator_enable(gpadc->regu); + return 0; +} + +static int ab8500_gpadc_runtime_idle(struct device *dev) +{ + struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); + + pm_runtime_suspend(dev); + return 0; +} + static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) { int ret = 0; @@ -610,6 +643,16 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) dev_err(gpadc->dev, "failed to get vtvout LDO\n"); goto fail_irq; } + + platform_set_drvdata(pdev, gpadc); + + regulator_enable(gpadc->regu); + + pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); + pm_runtime_use_autosuspend(gpadc->dev); + pm_runtime_set_active(gpadc->dev); + pm_runtime_enable(gpadc->dev); + ab8500_gpadc_read_calibration_data(gpadc); list_add_tail(&gpadc->node, &ab8500_gpadc_list); dev_dbg(gpadc->dev, "probe success\n"); @@ -630,19 +673,34 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev) list_del(&gpadc->node); /* remove interrupt - completion of Sw ADC conversion */ free_irq(gpadc->irq, gpadc); - /* disable VTVout LDO that is being used by GPADC */ - regulator_put(gpadc->regu); + + pm_runtime_get_sync(gpadc->dev); + pm_runtime_disable(gpadc->dev); + + regulator_disable(gpadc->regu); + + pm_runtime_set_suspended(gpadc->dev); + + pm_runtime_put_noidle(gpadc->dev); + kfree(gpadc); gpadc = NULL; return 0; } +static const struct dev_pm_ops ab8500_gpadc_pm_ops = { + SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, + ab8500_gpadc_runtime_resume, + ab8500_gpadc_runtime_idle) +}; + static struct platform_driver ab8500_gpadc_driver = { .probe = ab8500_gpadc_probe, .remove = __devexit_p(ab8500_gpadc_remove), .driver = { .name = "ab8500-gpadc", .owner = THIS_MODULE, + .pm = &ab8500_gpadc_pm_ops, }, }; -- cgit v1.2.3 From 2ab2bbebe4ad7f2e6edef2f4fb11d275ec9b0737 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Tue, 17 Jan 2012 16:16:43 +0530 Subject: ab8500-pwm:AB8505:Enable support for PWMLED blink Enable support for PWM OUT LED blinking for AB8505.Instead of having 3 pwm instances from ab8500 core file add it as platform data. ST-Ericsson ID: 366316 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:I63cd5510d3c1071613871946f7c624d2e2026568 Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45669 Reviewed-by: QABUILD Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- drivers/mfd/ab8500-core.c | 8 ---- drivers/misc/ab8500-pwm.c | 96 +++++++++++++++++++++++++++++++++----- include/linux/mfd/ab8500/pwmleds.h | 20 ++++++++ include/linux/mfd/abx500/ab8500.h | 2 + 4 files changed, 106 insertions(+), 20 deletions(-) create mode 100644 include/linux/mfd/ab8500/pwmleds.h diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index e92f51b1136..8137ac22816 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -803,14 +803,6 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { .name = "ab8500-pwm", .id = 1, }, - { - .name = "ab8500-pwm", - .id = 2, - }, - { - .name = "ab8500-pwm", - .id = 3, - }, { .name = "ab8500-leds", }, { .name = "ab8500-denc", diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 7a928667169..d7a62767a58 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -12,7 +12,7 @@ #include #include #include - +#include /* * PWM Out generators * Bank: 0x10 @@ -20,6 +20,11 @@ #define AB8500_PWM_OUT_CTRL1_REG 0x60 #define AB8500_PWM_OUT_CTRL2_REG 0x61 #define AB8500_PWM_OUT_CTRL7_REG 0x66 +#define AB8505_PWM_OUT_BLINK_CTRL1_REG 0x68 +#define AB8505_PWM_OUT_BLINK_CTRL4_REG 0x6B +#define AB8505_PWM_OUT_BLINK_CTRL_DUTYBIT 4 +#define AB8505_PWM_OUT_BLINK_DUTYMASK (0x0F << AB8505_PWM_OUT_BLINK_CTRL_DUTYBIT) + /* backlight driver constants */ #define ENABLE_PWM 1 @@ -31,11 +36,67 @@ struct pwm_device { struct clk *clk; const char *label; unsigned int pwm_id; + unsigned int blink_en; + struct ab8500 *parent; bool clk_enabled; }; static LIST_HEAD(pwm_list); +int pwm_config_blink(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + int ret; + unsigned int value; + u8 reg; + if ((!is_ab8505(pwm->parent)) || (!pwm->blink_en)) { + dev_err(pwm->dev, "setting blinking for this " + "device not supported\n"); + return -EINVAL; + } + /* + * get the period value that is to be written to + * AB8500_PWM_OUT_BLINK_CTRL1 REGS[0:2] + */ + value = period_ns & 0x07; + /* + * get blink duty value to be written to + * AB8500_PWM_OUT_BLINK_CTRL REGS[7:4] + */ + value |= ((duty_ns << AB8505_PWM_OUT_BLINK_CTRL_DUTYBIT) & + AB8505_PWM_OUT_BLINK_DUTYMASK); + + reg = AB8505_PWM_OUT_BLINK_CTRL1_REG + (pwm->pwm_id - 1); + + ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC, + reg, (u8)value); + if (ret < 0) + dev_err(pwm->dev, "%s: Failed to config PWM blink,Error %d\n", + pwm->label, ret); + return ret; +} + +int pwm_blink_ctrl(struct pwm_device *pwm , int enable) +{ + int ret; + + if ((!is_ab8505(pwm->parent)) || (!pwm->blink_en)) { + dev_err(pwm->dev, "setting blinking for this " + "device not supported\n"); + return -EINVAL; + } + /* + * Enable/disable blinking feature for corresponding PWMOUT + * channel depending on value of enable. + */ + ret = abx500_mask_and_set_register_interruptible(pwm->dev, + AB8500_MISC, AB8505_PWM_OUT_BLINK_CTRL4_REG, + 1 << (pwm->pwm_id-1), enable << (pwm->pwm_id-1)); + if (ret < 0) + dev_err(pwm->dev, "%s: Failed to control PWM blink,Error %d\n", + pwm->label, ret); + return ret; +} + int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { int ret = 0; @@ -82,7 +143,7 @@ int pwm_enable(struct pwm_device *pwm) AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 1 << (pwm->pwm_id-1), 1 << (pwm->pwm_id-1)); if (ret < 0) - dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", + dev_err(pwm->dev, "%s: Failed to enable PWM, Error %d\n", pwm->label, ret); return ret; } @@ -123,7 +184,6 @@ EXPORT_SYMBOL(pwm_disable); struct pwm_device *pwm_request(int pwm_id, const char *label) { struct pwm_device *pwm; - list_for_each_entry(pwm, &pwm_list, node) { if (pwm->pwm_id == pwm_id) { pwm->label = label; @@ -144,38 +204,50 @@ EXPORT_SYMBOL(pwm_free); static int __devinit ab8500_pwm_probe(struct platform_device *pdev) { + struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent); + struct ab8500_platform_data *plat = dev_get_platdata(parent->dev); + struct ab8500_pwmled_platform_data *pdata = plat->pwmled; struct pwm_device *pwm; - int ret = 0; + int ret = 0 , i; /* * Nothing to be done in probe, this is required to get the * device which is required for ab8500 read and write */ - pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + pwm = kzalloc(((sizeof(struct pwm_device)) * pdata->num_pwm), + GFP_KERNEL); if (pwm == NULL) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } - pwm->dev = &pdev->dev; - pwm->pwm_id = pdev->id; - list_add_tail(&pwm->node, &pwm_list); - platform_set_drvdata(pdev, pwm); - + for (i = 0; i < pdata->num_pwm; i++) { + pwm[i].dev = &pdev->dev; + pwm[i].parent = parent; + pwm[i].blink_en = pdata->leds[i].blink_en; + pwm[i].pwm_id = pdata->leds[i].pwm_id; + list_add_tail(&pwm[i].node, &pwm_list); + } pwm->clk = clk_get(pwm->dev, NULL); if (IS_ERR(pwm->clk)) { dev_err(pwm->dev, "clock request failed\n"); ret = PTR_ERR(pwm->clk); - kfree(pwm); - return ret; + goto fail; } + platform_set_drvdata(pdev, pwm); pwm->clk_enabled = false; dev_dbg(pwm->dev, "pwm probe successful\n"); return ret; + +fail: + list_del(&pwm->node); + kfree(pwm); + return ret; } static int __devexit ab8500_pwm_remove(struct platform_device *pdev) { struct pwm_device *pwm = platform_get_drvdata(pdev); + list_del(&pwm->node); clk_put(pwm->clk); dev_dbg(&pdev->dev, "pwm driver removed\n"); diff --git a/include/linux/mfd/ab8500/pwmleds.h b/include/linux/mfd/ab8500/pwmleds.h new file mode 100644 index 00000000000..e31658280a0 --- /dev/null +++ b/include/linux/mfd/ab8500/pwmleds.h @@ -0,0 +1,20 @@ +/* + * Copyright ST-Ericsson 2012. + * + * Author: Naga Radhesh + * Licensed under GPLv2. + */ +#ifndef _AB8500_PWMLED_H +#define _AB8500_PWMLED_H + +struct ab8500_led_pwm { + int pwm_id; + int blink_en; +}; + +struct ab8500_pwmled_platform_data { + int num_pwm; + struct ab8500_led_pwm *leds; +}; + +#endif diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 7e056197b98..a51161222e1 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -278,6 +278,7 @@ struct ab8500_sysctrl_platform_data; * @battery: machine-specific battery management data * @charger: machine-specific charger data * @btemp: machine-specific battery temp data + * @pwmled: machine-specific pwmled data */ struct ab8500_platform_data { int irq_base; @@ -297,6 +298,7 @@ struct ab8500_platform_data { struct ab8500_chargalg_platform_data *chargalg; struct ab8500_gpio_platform_data *gpio; struct ab8500_sysctrl_platform_data *sysctrl; + struct ab8500_pwmled_platform_data *pwmled; }; extern int __devinit ab8500_init(struct ab8500 *ab8500, -- cgit v1.2.3 From 713724046af865d0650e430f2101693fd5947969 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Mon, 27 Feb 2012 12:41:16 +0530 Subject: ab8500-pwm: check for valid platform data pointer Before accessing platform data, check whether platform pointer is valid or not. ST-Ericsson ID: 366316 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Naga Radhesh Change-Id: I176dd81743d1c063f6814c35992cc8813ac57055 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50530 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Jonas ABERG --- drivers/misc/ab8500-pwm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index d7a62767a58..01d329ba76c 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -206,10 +206,16 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev) { struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *plat = dev_get_platdata(parent->dev); - struct ab8500_pwmled_platform_data *pdata = plat->pwmled; + struct ab8500_pwmled_platform_data *pdata; struct pwm_device *pwm; int ret = 0 , i; + /* get pwmled specific platform data */ + if (!plat->pwmled) { + dev_err(&pdev->dev, "no pwm platform data supplied\n"); + return -EINVAL; + } + pdata = plat->pwmled; /* * Nothing to be done in probe, this is required to get the * device which is required for ab8500 read and write -- cgit v1.2.3 From 84cefcf74c7b9291cbe3ce725ee912bc1f1412b7 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Thu, 23 Feb 2012 15:49:39 +0530 Subject: leds-pwm:Support HW blink functionality Support LED HW blink functionlity, by registering blink set function. ST-Ericsson ID: 366316 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:Ice4f7b786bd2acdd115ca920de6deb2e83d80ea3 Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50126 Reviewed-by: Srinidhi KASAGAR --- drivers/leds/leds-pwm.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/leds_pwm.h | 2 ++ include/linux/pwm.h | 10 +++++++++ 3 files changed, 65 insertions(+) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 4d086e87bc1..9c5f7136b37 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -29,8 +29,58 @@ struct led_pwm_data { unsigned int active_low; unsigned int lth_brightness; unsigned int period; + unsigned int dutycycle_steps; + unsigned int period_steps; }; +static int led_pwm_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct led_pwm_data *led_dat = + container_of(led_cdev, struct led_pwm_data, cdev); + int dutycycle_ms, period_sec; + int dutycycle, period; + /* + * If both the delays are zero set some sensible delay + */ + if (*delay_on == 0 && *delay_off == 0) { + *delay_on = 500; + *delay_off = 500; + } + /* + * calculate the duty cycle from on and off time + */ + dutycycle_ms = ((*delay_on * 1000)/(*delay_on + *delay_off)); + /* + * convert calculated value to write into the PWM out register + */ + if (led_dat->dutycycle_steps) + dutycycle = ((dutycycle_ms * led_dat->dutycycle_steps)/1000); + else + dutycycle = (dutycycle_ms/1000); + /* + * calculate period from on and off time(msec) + */ + period_sec = ((*delay_on + *delay_off)/1000); + /* + * convert calculated value to write into the PWM out register + */ + if (led_dat->period_steps) { + if ((*delay_on + *delay_off) == 500) + period = led_dat->period_steps; + else + period = led_dat->period_steps - period_sec; + } + else + period = period_sec; + /* + * configure the PWM registers and enable blink functionality + */ + pwm_config_blink(led_dat->pwm, dutycycle, period); + pwm_blink_ctrl(led_dat->pwm, 1); + return 0; +} + static void led_pwm_set(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -85,8 +135,11 @@ static int led_pwm_probe(struct platform_device *pdev) led_dat->period = cur_led->pwm_period_ns; led_dat->lth_brightness = cur_led->lth_brightness * (cur_led->pwm_period_ns / cur_led->max_brightness); + led_dat->dutycycle_steps = cur_led->dutycycle_steps; + led_dat->period_steps = cur_led->period_steps; led_dat->cdev.brightness_set = led_pwm_set; led_dat->cdev.brightness = LED_OFF; + led_dat->cdev.blink_set = led_pwm_blink_set; led_dat->cdev.max_brightness = cur_led->max_brightness; led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h index 9c5eab6e086..5128ffa43c3 100644 --- a/include/linux/leds_pwm.h +++ b/include/linux/leds_pwm.h @@ -12,6 +12,8 @@ struct led_pwm { unsigned max_brightness; unsigned pwm_period_ns; unsigned int lth_brightness; + unsigned int dutycycle_steps; + unsigned int period_steps; }; struct led_pwm_platform_data { diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7c775751392..792ed4a9240 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -28,4 +28,14 @@ int pwm_enable(struct pwm_device *pwm); */ void pwm_disable(struct pwm_device *pwm); +/* + * pwm_config_blink - configure PWM blinking + */ +int pwm_config_blink(struct pwm_device *pwm, int duty_ns, int period_ns); + +/* + * pwm_blink_ctrl - Enable/Disable PWM blinking + */ +int pwm_blink_ctrl(struct pwm_device *pwm , int enable); + #endif /* __LINUX_PWM_H */ -- cgit v1.2.3 From 04cc2eb1eb7da89ab871d279d8fb64807cee0053 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Thu, 23 Feb 2012 15:59:46 +0530 Subject: pm: mach-ux500: platform data for pwm driver platform data for pwm driver, which contains no.of supported pwm and pwm out led's ST-Ericsson ID: 366316 Signed-off-by: Naga Radhesh --- arch/arm/mach-ux500/board-mop500-bm.c | 21 +++++++++++++++++++++ arch/arm/mach-ux500/board-mop500-bm.h | 1 + 2 files changed, 22 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 400f89a85cc..6f380b45ad5 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -12,6 +12,7 @@ #include #include +#include #include "board-mop500-bm.h" #ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL @@ -402,6 +403,26 @@ struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data = { .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to), }; +static struct ab8500_led_pwm leds_pwm_data[] = { + [0] = { + .pwm_id = 1, + .blink_en = 1, + }, + [1] = { + .pwm_id = 2, + .blink_en = 0, + }, + [2] = { + .pwm_id = 3, + .blink_en = 0, + }, +}; + +struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data = { + .num_pwm = 3, + .leds = leds_pwm_data, +}; + static const struct ab8500_bm_capacity_levels cap_levels = { .critical = 2, .low = 10, diff --git a/arch/arm/mach-ux500/board-mop500-bm.h b/arch/arm/mach-ux500/board-mop500-bm.h index 74d44529fe6..6b6dcf43502 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.h +++ b/arch/arm/mach-ux500/board-mop500-bm.h @@ -20,5 +20,6 @@ extern struct ab8500_btemp_platform_data ab8500_btemp_plat_data; extern struct ab8500_fg_platform_data ab8500_fg_plat_data; extern struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data; extern struct ab8500_bm_data ab8500_bm_data; +extern struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data; #endif -- cgit v1.2.3 From dde2702b6dec26717c0badd0878144c5e3f23470 Mon Sep 17 00:00:00 2001 From: Ashok G Date: Tue, 28 Feb 2012 10:21:00 +0530 Subject: ab8500-debugfs: Sizeof mismatch St-Ericsson Linux next: NA St-Ericsson Id: 420118 St-Ericsson FOSS-OUT ID: Trivial Change-Id: I2acc2ceced2e22d6f432dbe2f6b8a448c410c99d Signed-off-by: Ashok G Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50651 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Mattias WALLIN --- drivers/mfd/ab8500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 1db6bcff114..595b41800b4 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -1563,7 +1563,7 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) ab8500 = dev_get_drvdata(plf->dev.parent); num_irqs = ab8500->mask_size; - irq_count = kzalloc(sizeof(irq_count)*num_irqs, GFP_KERNEL); + irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL); if (!irq_count) return -ENOMEM; -- cgit v1.2.3 From 5ef65ec433d008af4918114642ddfc207cf95af0 Mon Sep 17 00:00:00 2001 From: Naga Radhesh Date: Mon, 27 Feb 2012 20:44:33 +0530 Subject: ab8500-pwm:Add sysfs path to disable LED blinking Add sysfs path to disable LED blinking functionality ST-Ericsson ID: 366316 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id:I3f4c62525defe948459cf74c3ae18f4cf81945bf Signed-off-by: Naga Radhesh Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50621 Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- drivers/misc/ab8500-pwm.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 01d329ba76c..9d864e4db5a 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -36,6 +36,7 @@ struct pwm_device { struct clk *clk; const char *label; unsigned int pwm_id; + unsigned int num_pwm; unsigned int blink_en; struct ab8500 *parent; bool clk_enabled; @@ -74,6 +75,7 @@ int pwm_config_blink(struct pwm_device *pwm, int duty_ns, int period_ns) pwm->label, ret); return ret; } +EXPORT_SYMBOL(pwm_config_blink); int pwm_blink_ctrl(struct pwm_device *pwm , int enable) { @@ -96,6 +98,7 @@ int pwm_blink_ctrl(struct pwm_device *pwm , int enable) pwm->label, ret); return ret; } +EXPORT_SYMBOL(pwm_blink_ctrl); int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { @@ -202,6 +205,46 @@ void pwm_free(struct pwm_device *pwm) } EXPORT_SYMBOL(pwm_free); +static ssize_t store_blink_status(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct pwm_device *pwm; + unsigned long val; + + if (strict_strtoul(buf, 0, &val)) + return -EINVAL; + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == val) + break; + else { + /* check if PWM ID is valid*/ + if (val > pwm->num_pwm) { + dev_err(pwm->dev, "Invalid PWM ID\n"); + return -EINVAL; + } + } + } + if ((!is_ab8505(pwm->parent)) || (!pwm->blink_en)) { + dev_err(pwm->dev, "setting blinking for this " + "device not supported\n"); + return -EINVAL; + } + /*Disable blink functionlity */ + pwm_blink_ctrl(pwm, 0); + return count; +} + +static DEVICE_ATTR(disable_blink, S_IWUGO, NULL, store_blink_status); + +static struct attribute *pwmled_attributes[] = { + &dev_attr_disable_blink.attr, + NULL +}; + +static const struct attribute_group pwmled_attr_group = { + .attrs = pwmled_attributes, +}; + static int __devinit ab8500_pwm_probe(struct platform_device *pdev) { struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent); @@ -231,19 +274,42 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev) pwm[i].parent = parent; pwm[i].blink_en = pdata->leds[i].blink_en; pwm[i].pwm_id = pdata->leds[i].pwm_id; + pwm[i].num_pwm = pdata->num_pwm; list_add_tail(&pwm[i].node, &pwm_list); } + for (i = 0; i < pdata->num_pwm; i++) { + /*Implement sysfs only if blink is enabled*/ + if ((is_ab8505(pwm[i].parent)) && (pwm[i].blink_en)) { + /* sysfs implementation to disable the blink */ + ret = sysfs_create_group(&pdev->dev.kobj, + &pwmled_attr_group); + if (ret) { + dev_err(&pdev->dev, "failed to create" + " sysfs entries\n"); + goto fail; + } + break; + } + } pwm->clk = clk_get(pwm->dev, NULL); if (IS_ERR(pwm->clk)) { dev_err(pwm->dev, "clock request failed\n"); ret = PTR_ERR(pwm->clk); - goto fail; + goto err_clk; } platform_set_drvdata(pdev, pwm); pwm->clk_enabled = false; dev_dbg(pwm->dev, "pwm probe successful\n"); return ret; +err_clk: + for (i = 0; i < pdata->num_pwm; i++) { + if ((is_ab8505(pwm[i].parent)) && (pwm[i].blink_en)) { + sysfs_remove_group(&pdev->dev.kobj, + &pwmled_attr_group); + break; + } + } fail: list_del(&pwm->node); kfree(pwm); @@ -253,7 +319,15 @@ fail: static int __devexit ab8500_pwm_remove(struct platform_device *pdev) { struct pwm_device *pwm = platform_get_drvdata(pdev); + int i; + for (i = 0; i < pwm->num_pwm; i++) { + if ((is_ab8505(pwm[i].parent)) && (pwm[i].blink_en)) { + sysfs_remove_group(&pdev->dev.kobj, + &pwmled_attr_group); + break; + } + } list_del(&pwm->node); clk_put(pwm->clk); dev_dbg(&pdev->dev, "pwm driver removed\n"); -- cgit v1.2.3 From e270135cee441becbbb898360014605f21a12699 Mon Sep 17 00:00:00 2001 From: Kalle Komierowski Date: Thu, 2 Feb 2012 16:05:46 +0100 Subject: power: ab8500_bm: Don't clear the CCMuxOffset bit The CCMuxOffset bit is not kept set, this will force the columb counter of the AB8500 to use the measure offset calibration. This should increase the accuracy of the fuel gauge. ST-Ericsson ID: 414923 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I82649e0d6f07933a36f48d33a877e72c5a5aa50e Signed-off-by: Kalle Komierowski Signed-off-by: Marcus Cooper Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50913 Reviewed-by: Jonas ABERG --- drivers/power/ab8500_fg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index c22f2f05657..fc27153b562 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -485,8 +485,9 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) di->flags.fg_enabled = true; } else { /* Clear any pending read requests */ - ret = abx500_set_register_interruptible(di->dev, - AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0); + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + (RESET_ACCU | READ_REQ), 0); if (ret) goto cc_err; @@ -1404,8 +1405,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) sleep_time = di->bat->fg_params->init_timer; /* Discard the first [x] seconds */ - if (di->init_cnt > - di->bat->fg_params->init_discard_time) { + if (di->init_cnt > di->bat->fg_params->init_discard_time) { ab8500_fg_calc_cap_discharge_voltage(di, true); ab8500_fg_check_capacity_limits(di, true); -- cgit v1.2.3 From aea554e132718130c3e8fff5e37081733271d218 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 29 Feb 2012 08:47:22 +0100 Subject: drivers: ab8500-gpadc: Reduce conversion timeout Reduce the conversion timeout from 2s to 0.5s ST-Ericsson Linux next: - ST-Ericsson ID: 420077 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Icb18eef9b6c887f7817c2c1f7dd1b3876620a5b6 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50864 Reviewed-by: Karl KOMIEROWSKI --- drivers/mfd/ab8500-gpadc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 20ab561b42e..d4135706529 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -86,6 +86,8 @@ /* Time in ms before disabling regulator */ #define GPADC_AUDOSUSPEND_DELAY 1 +#define CONVERSION_TIME 500 /* ms */ + enum cal_channels { ADC_INPUT_VMAIN = 0, ADC_INPUT_BTEMP, @@ -368,7 +370,8 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) goto out; } /* wait for completion of conversion */ - if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) { + if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, + msecs_to_jiffies(CONVERSION_TIME))) { dev_err(gpadc->dev, "timeout: didn't receive GPADC conversion interrupt\n"); ret = -EINVAL; @@ -594,8 +597,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev) static int ab8500_gpadc_runtime_idle(struct device *dev) { - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); - pm_runtime_suspend(dev); return 0; } -- cgit v1.2.3 From 53223686faa189a61e71d1153671962ffb4c34ca Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 27 Feb 2012 11:02:44 +0100 Subject: power: ab8500_btemp: Detect battery type in workqueue Detect battery type in work queue instead of probe. This reduces the system boot time with 1.5s ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I6d21df2746a8a08940e18e793ec0e171eda67708 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50551 Reviewed-by: QABUILD Reviewed-by: Karl KOMIEROWSKI --- drivers/power/ab8500_btemp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index d8bb99394ac..6d4ece31413 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -83,6 +83,7 @@ struct ab8500_btemp_ranges { * @btemp_ranges: Battery temperature range structure * @btemp_wq: Work queue for measuring the temperature periodically * @btemp_periodic_work: Work for measuring the temperature periodically + * @initialized: True if battery id read. */ struct ab8500_btemp { struct device *dev; @@ -100,6 +101,7 @@ struct ab8500_btemp { struct ab8500_btemp_ranges btemp_ranges; struct workqueue_struct *btemp_wq; struct delayed_work btemp_periodic_work; + bool initialized; }; /* BTEMP power supply properties */ @@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work) struct ab8500_btemp *di = container_of(work, struct ab8500_btemp, btemp_periodic_work.work); + if (!di->initialized) { + di->initialized = true; + /* Identify the battery */ + if (ab8500_btemp_id(di) < 0) + dev_warn(di->dev, "failed to identify the battery\n"); + } + di->bat_temp = ab8500_btemp_measure_temp(di); if (di->bat_temp != di->prev_bat_temp) { @@ -976,6 +985,8 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->parent = dev_get_drvdata(pdev->dev.parent); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); + di->initialized = false; + /* get btemp specific platform data */ plat_data = pdev->dev.platform_data; di->pdata = plat_data->btemp; @@ -1017,10 +1028,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work, ab8500_btemp_periodic_work); - /* Identify the battery */ - if (ab8500_btemp_id(di) < 0) - dev_warn(di->dev, "failed to identify the battery\n"); - /* Set BTEMP thermal limits. Low and Med are fixed */ di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; -- cgit v1.2.3 From ec36b9e84dd62c2a6f4dfaca482732c2a76f9ce5 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 22 Feb 2012 10:57:17 +0100 Subject: ARM: configs: u8500: Enable lockup detection ST-Ericsson ID: 370799 Signed-off-by: Jonas Aaberg --- arch/arm/configs/u8500_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0a8daf746fe..5b6e8f5541c 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -305,6 +305,9 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_DETECT_HUNG_TASK=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y -- cgit v1.2.3 From ca3e4b25de74dabef162498ad464394c730c5873 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 6 Mar 2012 13:54:53 +0100 Subject: ARM: configs: u8500: Enable per UID net statistics Sets CONFIG_UID_STAT=y in u8500_defconfig to enable network usage statistics per UID. ST-Ericsson Linux next: - ST-Ericsson ID: 410876 ST-Ericsson FOSS-OUT ID: NA Change-Id: I812748a9997fb30a15810892b7a829f9e9c4cb7c Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50545 Reviewed-by: Dominik SLIWA Tested-by: Dominik SLIWA Reviewed-by: QABUILD Reviewed-by: Tomasz HLIWIAK Reviewed-by: Jonas ABERG --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 5b6e8f5541c..49512fe422b 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -325,3 +325,4 @@ CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y CONFIG_HIDRAW=y +CONFIG_UID_STAT=y -- cgit v1.2.3 From 84ed66f95d2e6cf9b9b175c1b3805377c04181f4 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 14 Nov 2011 15:19:15 +0100 Subject: config: u8500: power: idle test Add power module test. This test, in debugfs/pwr_test/idle shall pass when the screen is black, but suspend is not yet reached. This module test checks clocks, prcmu-regulators, db8500 regulators and ab8500 regulators. The reason why not adding this to LTP is that later this module test will contain tests for voicecall and low-power-audio, which require Android to run. ST-Ericsson ID: 367599 Signed-off-by: Jonas Aaberg --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 49512fe422b..ab8a18be30b 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -47,6 +47,7 @@ CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M in CONFIG_KEXEC=y CONFIG_CRASH_SWRESET=y CONFIG_CRASH_DUMP=y +CONFIG_DB8500_PWR_TEST=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -- cgit v1.2.3 From cb1a5c1823a07db65bdf14dcf175ebf3136ad811 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 29 Feb 2012 14:20:09 +0100 Subject: ARM: ux500: Remove unused include file ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9bb0d97f8562d6abef8b0a6d424ad38bf7f58a1c Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/50944 Reviewed-by: QABUILD Reviewed-by: Arun MURTHY Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/include/mach/ab8500_gpadc.h | 36 ------------------------- 1 file changed, 36 deletions(-) delete mode 100644 arch/arm/mach-ux500/include/mach/ab8500_gpadc.h diff --git a/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h b/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h deleted file mode 100644 index 4289dcfc0aa..00000000000 --- a/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ab8500_gpadc.c - AB8500 GPADC Driver - * - * Copyright (C) 2010 ST-Ericsson SA - * Licensed under GPLv2. - * - * Author: Arun R Murthy - */ - -#ifndef _AB8500_GPADC_H -#define _Ab8500_GPADC_H - -/* GPADC source: From datasheer(ADCSwSel[4:0] in GPADCCtrl2) */ -#define BAT_CTRL 0x01 -#define ACC_DETECT1 0x04 -#define ACC_DETECT2 0x05 -#define MAIN_BAT_V 0x08 -#define BK_BAT_V 0x0C -#define VBUS_V 0x09 -#define MAIN_CHARGER_V 0x03 -#define MAIN_CHARGER_C 0x0A -#define USB_CHARGER_C 0x0B -#define DIE_TEMP 0x0D -#define BTEMP_BALL 0x02 - -struct ab8500_gpadc_device_info { - struct completion ab8500_gpadc_complete; - struct mutex ab8500_gpadc_lock; -#if defined(CONFIG_REGULATOR) - struct regulator *regu; -#endif -}; - -int ab8500_gpadc_conversion(int input); - -#endif /* _AB8500_GPADC_H */ -- cgit v1.2.3 From 05f4e15da7ed2daf165d9472e1834e07ce44b9ab Mon Sep 17 00:00:00 2001 From: Marcin Mielczarczyk Date: Fri, 18 Jun 2010 10:04:45 +0200 Subject: u8500: Vibrator: Timed output vibrator driver ST-Ericsson vibrator driver which registers in Android specific timed output device class. Signed-off-by: Marcin Mielczarczyk Signed-off-by: Jerzy Kasenberg Signed-off-by: Mian Yousaf Kaukab Timed output vibrator: New functionality. This patch allows to form the vibration characteristic using few parameters defined in the platform data: - boost level and period for start condition - on level as moderate speed - off level and period for brake condition Detailed information can be found here: Documentation\DocBook\ste_timed_vibra.html Signed-off-by: Grzegorz Sygieda Signed-off-by: Krzysztof Antonowicz Signed-off-by: srinidhi kasagar vibrator: remove board specific control of vibrator Platform specific control of vibrator should be present in board file (here board-mop500.c). So, for example if GPIO pins are used to control the vibrator, its control function implemenation should be in board file. This patch provides the callback function support in the driver for the same. Signed-off-by: Shreshtha Kumar Sahu android: vibrator: dont directly access ktime_t members Use ktime helper functions for converting ktime values Signed-off-by: Mian Yousaf Kaukab u8500: vibra: linear vibrators using vibra-pwm Linear vibrators operate on thier required resonance frequency (for COPAL and AAC its ~150Hz). This can be provided using AUDIO DA5 path. This software *workaround* enables linear vibrators using AB8500 vibra-pwm by generating required resonace frequency using software. In addition this patch provides support for separate platform data for Linear and Rotarty vibrators. Signed-off-by: Shreshtha Kumar Sahu u8500: vibra: disable vibrator after vibration This patch disables vibrator i.e. configures the PWM duty cycle to zero after vibration duration is over. Signed-off-by: Philippe Langlais u8500: optimize: linear vibra drv using vibra-pwm This patch optimizes the current implementation of "linear vibrator driver using vibra-pwm". Current implementation is CPU intensive and uses 100% of a CPU for the time period vibrator is used. ST-Ericsson ID: ER 349958 Signed-off-by: Avinash A u8500: vibra: fix sleeping fn. in atomic context sleepable call - flush_workqueue called from atomic context of vibra_enable. ST-Ericsson ID: ER 351276 Signed-off-by: Avinash A u8500: vibra: remove race condition in timer operation In situation described below, vibra driver can hang. In a scenario where vibra_enable is called and vibrator is running i.e. vibra_work is scheduled and vibra_timer. Suppose vibra_timer is started and has not expired yet. At this moment if vibra_work starts executing and acquires the vibra_lock and just before hrtimer_cancel is called, if old timer expires and timer callback starts executing then it will try to acquire vibra_lock and hence it will wait for vibra_lock, as it is already acquired by vibra_work. Now vibra_work->hrtimer_cancel will wait for timer callback to complete and timer callback will wait for vibra_lock to be free so that it can complete. This result in recursive waiting for vibra_lock and hence deadlock. As timer callback is running in interrupt context so above deadlock may trigger watchdog. ST-Ericsson ID: 405366 Signed-off-by: Shreshtha Kumar Sahu u8500: vibra: remove race condition in open In situation described below, vibra driver can hang. vibra_enable takes the vibra_lock and timer expires then timer callback will spin for vibra_lock. If vibra_enable tries to do hrtimer_cancel then it will wait for timer callback to complete. In above situation hrtimer_cancel will wait for timer callback to complete and timer callback will wait for vibra_lock to be free so that it can complete. This result in recursive waiting for vibra_lock and hence deadlock. As timer callback is running in interrupt context so above deadlock may trigger watchdog. ST-Ericsson ID: 407253 Signed-off-by: Shreshtha Kumar Sahu vibra:Remove unnecessary assignment of dev->parent Remove unnecessary assignment of dev->parent, because of this during timed out class unregister it is trying to free resources of parent which does not exist Signed-off-by: Naga Radhesh --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/ste_timed_vibra.tmpl | 278 +++++++++++++++++++ drivers/staging/android/Kconfig | 8 + drivers/staging/android/Makefile | 1 + drivers/staging/android/ste_timed_vibra.c | 431 +++++++++++++++++++++++++++++ include/linux/ste_timed_vibra.h | 41 +++ 6 files changed, 760 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/ste_timed_vibra.tmpl create mode 100644 drivers/staging/android/ste_timed_vibra.c create mode 100644 include/linux/ste_timed_vibra.h diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index f0e9b64b910..ae3d4c348c1 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -19,7 +19,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ tc_keypad.xml prcmu-fw-api.xml cg2900_fm_radio.xml \ synaptics_rmi4_touchp.xml db5500_keypad.xml \ u5500_LogicalMailbox.xml cg2900.xml \ - lsm303dlh.xml ske_keypad.xml ste_ff_vibra.xml ux500_usb.xml + lsm303dlh.xml ske_keypad.xml ste_ff_vibra.xml ste_timed_vibra.xml ux500_usb.xml include $(srctree)/Documentation/DocBook/media/Makefile diff --git a/Documentation/DocBook/ste_timed_vibra.tmpl b/Documentation/DocBook/ste_timed_vibra.tmpl new file mode 100644 index 00000000000..ae9e62c9fb1 --- /dev/null +++ b/Documentation/DocBook/ste_timed_vibra.tmpl @@ -0,0 +1,278 @@ + + + + + Timed Output Vibrator Driver + + + + Marcin + Mielczarczyk + +
+ marcin.mielczarczyk@tieto.com +
+
+
+
+ + + 2010 + ST-Ericsson + + + + + Linux standard functions + + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + This documentation describes the implementation of ST-Ericsson's + Timed Output Vibrator driver for the ST-Ericsson Linux platforms. + + + + + Getting Started + + There are no special compilation flags needed to build the + Timed Output Vibrator driver. + + +
+ Basic Tutorial + + Before using this driver few parameters shall be defined in the platform data structure: + + Boost level - vibrator speed in the the startup stage + Boost time - vibrator startup period + On level - vibrator moderate speed + On time - vibrator moderate period + Off level - vibrator speed in the stop stage + Off time - vibrator stop period + + + + NOTE: If the time elapsing between the ON and OFF sequence is smaller than the 'boost' period, + then OFF is delayed until the 'boost' expires. If the time elapsing between the OFF and + ON sequence is smaller than the 'off' period, then ON is delayed until the 'off' period expires. + The ON request when vibrator is in 'boost' or 'on' stage is ignored. + The OFF request when vibrator is in the 'off' stage is ignored. + + + To enable the Timed Output Vibrator driver using Kconfig, go to + Device Drivers -> Staging -> Android + and enable the following: + + + ST-Ericsson Timed Output Vibrator driver + +
+ +
+ + + Concepts + + Vibrator driver registers as timed output class device (implemented for Android). + + + + + Tasks + + Timed Output Vibrator can be controlled from user space using following device: + + /sys/class/timed_output/vibrator/enable + + To turn on the vibrator for 1s, following command should be executed: + + echo 1000 > /sys/class/timed_output/vibrator/enable + + To turn off the vibrator if enabled, then the following command should be executed: + + echo 0 > /sys/class/timed_output/vibrator/enable + + To get the remaining time, the following command should be executed: + + cat /sys/class/timed_output/vibrator/enable + + + + + + + Driver Configuration and Interaction + + There are no configuration parameters for Timed Output Vibrator Driver. + +
+ Implemented operations in driver + + All available operations are provided by Timed Output class driver. + + + + Supported device driver operations + + enable Calls vibra_enable() function which controls timer and workqueue + get_time Calls vibra_get_time() function which returns time remaining to the end of vibration + +
+
+ +
+
+ Driver loading parameters + + Not Applicable. + +
+
+ Driver IO Control + + Not Applicable. + +
+ +
+ Driver Interaction with Sysfs + + Timed Output Vibrator driver is available in sysfs as /sys/class/timed_output/vibrator + + + + enable + + + + Direction + read-write + + + Attribute file type + + Text file + + + + File path + /sys/class/timed_output/vibrator/enable + + + + Description + + + Vibrator is enabled for given period of time on file write (in miliseconds). + + + When written 0, vibrator stops. + + + When file is read, it gives remaining time to disable vibrator (in miliseconds). + + + + + + + + +
+
+ Driver Interaction using /proc filesystem + + Not Applicable. + + +
+ +
+ Other means for Driver Interaction + + Not Applicable. + +
+ +
+ Driver Node File + + Not aplicable. + +
+ + +
+ + + + Known Bugs And Assumptions + + + + None. + + + + + + + + + + + + + Public Functions Provided + + Not Applicable. + + + + + Internal Functions Provided + + This chapter contains the autogenerated documentation of the internal functions. + +!Edrivers/staging/android/ste_timed_vibra.c + + +
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index eb1dee26bda..7823c2a19ed 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -53,6 +53,14 @@ config ANDROID_LOW_MEMORY_KILLER ---help--- Register processes to be killed when memory is low +config ANDROID_STE_TIMED_VIBRA + bool "ST-Ericsson Timed Output Vibrator" + depends on SND_SOC_AB8500 + depends on ANDROID_TIMED_OUTPUT + default y + help + ST-Ericsson's vibrator driver using timed output class device + source "drivers/staging/android/switch/Kconfig" config ANDROID_INTF_ALARM diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 9b6c9ed91f6..e529c63da57 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o +obj-$(CONFIG_ANDROID_STE_TIMED_VIBRA) += ste_timed_vibra.o obj-$(CONFIG_ANDROID_SWITCH) += switch/ obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o diff --git a/drivers/staging/android/ste_timed_vibra.c b/drivers/staging/android/ste_timed_vibra.c new file mode 100644 index 00000000000..4621b2fb441 --- /dev/null +++ b/drivers/staging/android/ste_timed_vibra.c @@ -0,0 +1,431 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Marcin Mielczarczyk + * for ST-Ericsson + * License Terms: GNU General Public License v2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "timed_output.h" + +/** + * struct vibra_info - Vibrator information structure + * @tdev: Pointer to timed output device structure + * @linear_workqueue: Pointer to linear vibrator workqueue structure + * @linear_work: Linear Vibrator work + * @linear_tick: Linear Vibrator high resolution timer + * @vibra_workqueue: Pointer to vibrator workqueue structure + * @vibra_work: Vibrator work + * @vibra_timer: Vibrator high resolution timer + * @vibra_lock: Vibrator lock + * @vibra_state: Actual vibrator state + * @state_force: Indicates if oppositive state is requested + * @timeout: Indicates how long time the vibrator will be enabled + * @time_passed: Total time passed in states + * @pdata: Local pointer to platform data with vibrator parameters + * + * Structure vibra_info holds vibrator information + **/ +struct vibra_info { + struct timed_output_dev tdev; + struct workqueue_struct *linear_workqueue; + struct work_struct linear_work; + struct hrtimer linear_tick; + struct workqueue_struct *vibra_workqueue; + struct work_struct vibra_work; + struct hrtimer vibra_timer; + spinlock_t vibra_lock; + enum ste_timed_vibra_states vibra_state; + bool state_force; + unsigned int timeout; + unsigned int time_passed; + struct ste_timed_vibra_platform_data *pdata; +}; + +/* + * Linear vibrator hardware operates on a particular resonance + * frequency. The resonance frequency (f) may also vary with h/w. + * This define is half time period (t) in micro seconds (us). + * For resonance frequency f = 150 Hz + * t = T/2 = ((1/150) / 2) = 3333 usec. + */ +#define LINEAR_RESONANCE 3333 + +/** + * linear_vibra_work() - Linear Vibrator work, turns on/off vibrator + * @work: Pointer to work structure + * + * This function is called from workqueue, turns on/off vibrator + **/ +static void linear_vibra_work(struct work_struct *work) +{ + struct vibra_info *vinfo = + container_of(work, struct vibra_info, linear_work); + unsigned char speed_pos = 0, speed_neg = 0; + ktime_t ktime; + static unsigned char toggle; + + if (toggle) { + speed_pos = vinfo->pdata->boost_level; + speed_neg = 0; + } else { + speed_neg = vinfo->pdata->boost_level; + speed_pos = 0; + } + + toggle = !toggle; + vinfo->pdata->timed_vibra_control(speed_pos, speed_neg, + speed_pos, speed_neg); + + if ((vinfo->vibra_state != STE_VIBRA_IDLE) && + (vinfo->vibra_state != STE_VIBRA_OFF)) { + ktime = ktime_set((LINEAR_RESONANCE / USEC_PER_SEC), + (LINEAR_RESONANCE % USEC_PER_SEC) * NSEC_PER_USEC); + hrtimer_start(&vinfo->linear_tick, ktime, HRTIMER_MODE_REL); + } +} + +/** + * vibra_control_work() - Vibrator work, turns on/off vibrator + * @work: Pointer to work structure + * + * This function is called from workqueue, turns on/off vibrator + **/ +static void vibra_control_work(struct work_struct *work) +{ + struct vibra_info *vinfo = + container_of(work, struct vibra_info, vibra_work); + unsigned val = 0; + unsigned char speed_pos = 0, speed_neg = 0; + unsigned long flags; + + /* + * Cancel scheduled timer if it has not started + * else it will wait for timer callback to complete. + * It should be done before taking vibra_lock to + * prevent race condition, as timer callback also + * takes same lock. + */ + hrtimer_cancel(&vinfo->vibra_timer); + + spin_lock_irqsave(&vinfo->vibra_lock, flags); + + switch (vinfo->vibra_state) { + case STE_VIBRA_BOOST: + /* Turn on both vibrators with boost speed */ + speed_pos = vinfo->pdata->boost_level; + val = vinfo->pdata->boost_time; + break; + case STE_VIBRA_ON: + /* Turn on both vibrators with speed */ + speed_pos = vinfo->pdata->on_level; + val = vinfo->timeout - vinfo->pdata->boost_time; + break; + case STE_VIBRA_OFF: + /* Turn on both vibrators with reversed speed */ + speed_neg = vinfo->pdata->off_level; + val = vinfo->pdata->off_time; + break; + case STE_VIBRA_IDLE: + vinfo->time_passed = 0; + break; + default: + break; + } + spin_unlock_irqrestore(&vinfo->vibra_lock, flags); + + /* Send new settings (only for rotary vibrators) */ + if (!vinfo->pdata->is_linear_vibra) + vinfo->pdata->timed_vibra_control(speed_pos, speed_neg, + speed_pos, speed_neg); + + if (vinfo->vibra_state != STE_VIBRA_IDLE) { + /* Start timer if it's not in IDLE state */ + ktime_t ktime; + ktime = ktime_set((val / MSEC_PER_SEC), + (val % MSEC_PER_SEC) * NSEC_PER_MSEC), + hrtimer_start(&vinfo->vibra_timer, ktime, HRTIMER_MODE_REL); + } else if (vinfo->pdata->is_linear_vibra) { + /* Cancel work and timers of linear vibrator in IDLE state */ + hrtimer_cancel(&vinfo->linear_tick); + flush_workqueue(vinfo->linear_workqueue); + vinfo->pdata->timed_vibra_control(0, 0, 0, 0); + } +} + +/** + * vibra_enable() - Enables vibrator + * @tdev: Pointer to timed output device structure + * @timeout: Time indicating how long vibrator will be enabled + * + * This function enables vibrator + **/ +static void vibra_enable(struct timed_output_dev *tdev, int timeout) +{ + struct vibra_info *vinfo = dev_get_drvdata(tdev->dev); + unsigned long flags; + + spin_lock_irqsave(&vinfo->vibra_lock, flags); + switch (vinfo->vibra_state) { + case STE_VIBRA_IDLE: + if (timeout) + vinfo->vibra_state = STE_VIBRA_BOOST; + else /* Already disabled */ + break; + + vinfo->state_force = false; + /* Trim timeout */ + vinfo->timeout = timeout < vinfo->pdata->boost_time ? + vinfo->pdata->boost_time : timeout; + + if (vinfo->pdata->is_linear_vibra) + queue_work(vinfo->linear_workqueue, + &vinfo->linear_work); + queue_work(vinfo->vibra_workqueue, &vinfo->vibra_work); + break; + case STE_VIBRA_BOOST: + /* Force only when user requested OFF while BOOST */ + if (!timeout) + vinfo->state_force = true; + break; + case STE_VIBRA_ON: + /* If user requested OFF */ + if (!timeout) { + if (vinfo->pdata->is_linear_vibra) + hrtimer_cancel(&vinfo->linear_tick); + /* Cancel timer if it has not expired yet. + * Else setting the vibra_state to STE_VIBRA_OFF + * will make take care that vibrator will move to + * STE_VIBRA_IDLE in timer callback just after + * this function call. + */ + hrtimer_try_to_cancel(&vinfo->vibra_timer); + vinfo->vibra_state = STE_VIBRA_OFF; + queue_work(vinfo->vibra_workqueue, &vinfo->vibra_work); + } + break; + case STE_VIBRA_OFF: + /* Force only when user requested ON while OFF */ + if (timeout) + vinfo->state_force = true; + break; + default: + break; + } + spin_unlock_irqrestore(&vinfo->vibra_lock, flags); +} + +/** + * linear_vibra_tick() - Generate resonance frequency waveform + * @hrtimer: Pointer to high resolution timer structure + * + * This function helps in generating the resonance frequency + * waveform required for linear vibrators + * + * Returns: + * Returns value which indicates whether hrtimer should be restarted + **/ +static enum hrtimer_restart linear_vibra_tick(struct hrtimer *hrtimer) +{ + struct vibra_info *vinfo = + container_of(hrtimer, struct vibra_info, linear_tick); + + if ((vinfo->vibra_state != STE_VIBRA_IDLE) && + (vinfo->vibra_state != STE_VIBRA_OFF)) { + queue_work(vinfo->linear_workqueue, &vinfo->linear_work); + } + + return HRTIMER_NORESTART; +} + +/** + * vibra_timer_expired() - Handles vibrator machine state + * @hrtimer: Pointer to high resolution timer structure + * + * This function handles vibrator machine state + * + * Returns: + * Returns value which indicates wether hrtimer should be restarted + **/ +static enum hrtimer_restart vibra_timer_expired(struct hrtimer *hrtimer) +{ + struct vibra_info *vinfo = + container_of(hrtimer, struct vibra_info, vibra_timer); + unsigned long flags; + + spin_lock_irqsave(&vinfo->vibra_lock, flags); + switch (vinfo->vibra_state) { + case STE_VIBRA_BOOST: + /* If BOOST finished and force, go to OFF */ + if (vinfo->state_force) + vinfo->vibra_state = STE_VIBRA_OFF; + else + vinfo->vibra_state = STE_VIBRA_ON; + vinfo->time_passed = vinfo->pdata->boost_time; + break; + case STE_VIBRA_ON: + vinfo->vibra_state = STE_VIBRA_OFF; + vinfo->time_passed = vinfo->timeout; + break; + case STE_VIBRA_OFF: + /* If OFF finished and force, go to ON */ + if (vinfo->state_force) + vinfo->vibra_state = STE_VIBRA_ON; + else + vinfo->vibra_state = STE_VIBRA_IDLE; + vinfo->time_passed += vinfo->pdata->off_time; + break; + case STE_VIBRA_IDLE: + break; + default: + break; + } + vinfo->state_force = false; + spin_unlock_irqrestore(&vinfo->vibra_lock, flags); + + queue_work(vinfo->vibra_workqueue, &vinfo->vibra_work); + + return HRTIMER_NORESTART; +} + +/** + * vibra_get_time() - Returns remaining time to disabling vibration + * @tdev: Pointer to timed output device structure + * + * This function returns time remaining to disabling vibration + * + * Returns: + * Returns remaining time to disabling vibration + **/ +static int vibra_get_time(struct timed_output_dev *tdev) +{ + struct vibra_info *vinfo = dev_get_drvdata(tdev->dev); + u32 ms; + + if (hrtimer_active(&vinfo->vibra_timer)) { + ktime_t remain = hrtimer_get_remaining(&vinfo->vibra_timer); + ms = (u32) ktime_to_ms(remain); + return ms + vinfo->time_passed; + } else + return 0; +} + +static int __devinit ste_timed_vibra_probe(struct platform_device *pdev) +{ + int ret; + struct vibra_info *vinfo; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -ENODEV; + } + + vinfo = kmalloc(sizeof *vinfo, GFP_KERNEL); + if (!vinfo) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + vinfo->tdev.name = "vibrator"; + vinfo->tdev.enable = vibra_enable; + vinfo->tdev.get_time = vibra_get_time; + vinfo->time_passed = 0; + vinfo->vibra_state = STE_VIBRA_IDLE; + vinfo->state_force = false; + vinfo->pdata = pdev->dev.platform_data; + + if (vinfo->pdata->is_linear_vibra) + dev_info(&pdev->dev, "Linear Type Vibrators\n"); + else + dev_info(&pdev->dev, "Rotary Type Vibrators\n"); + + ret = timed_output_dev_register(&vinfo->tdev); + if (ret) { + dev_err(&pdev->dev, "failed to register timed output device\n"); + goto exit_free_vinfo; + } + + dev_set_drvdata(vinfo->tdev.dev, vinfo); + + vinfo->linear_workqueue = + create_singlethread_workqueue("ste-timed-linear-vibra"); + if (!vinfo->linear_workqueue) { + dev_err(&pdev->dev, "failed to allocate workqueue\n"); + ret = -ENOMEM; + goto exit_timed_output_unregister; + } + + /* Create workqueue just for timed output vibrator */ + vinfo->vibra_workqueue = + create_singlethread_workqueue("ste-timed-output-vibra"); + if (!vinfo->vibra_workqueue) { + dev_err(&pdev->dev, "failed to allocate workqueue\n"); + ret = -ENOMEM; + goto exit_destroy_workqueue; + } + + INIT_WORK(&vinfo->linear_work, linear_vibra_work); + INIT_WORK(&vinfo->vibra_work, vibra_control_work); + spin_lock_init(&vinfo->vibra_lock); + hrtimer_init(&vinfo->linear_tick, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&vinfo->vibra_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + vinfo->linear_tick.function = linear_vibra_tick; + vinfo->vibra_timer.function = vibra_timer_expired; + + platform_set_drvdata(pdev, vinfo); + return 0; + +exit_destroy_workqueue: + destroy_workqueue(vinfo->linear_workqueue); +exit_timed_output_unregister: + timed_output_dev_unregister(&vinfo->tdev); +exit_free_vinfo: + kfree(vinfo); + return ret; +} + +static int __devexit ste_timed_vibra_remove(struct platform_device *pdev) +{ + struct vibra_info *vinfo = platform_get_drvdata(pdev); + + timed_output_dev_unregister(&vinfo->tdev); + destroy_workqueue(vinfo->linear_workqueue); + destroy_workqueue(vinfo->vibra_workqueue); + kfree(vinfo); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ste_timed_vibra_driver = { + .driver = { + .name = "ste_timed_output_vibra", + .owner = THIS_MODULE, + }, + .probe = ste_timed_vibra_probe, + .remove = __devexit_p(ste_timed_vibra_remove) +}; + +static int __init ste_timed_vibra_init(void) +{ + return platform_driver_register(&ste_timed_vibra_driver); +} +module_init(ste_timed_vibra_init); + +static void __exit ste_timed_vibra_exit(void) +{ + platform_driver_unregister(&ste_timed_vibra_driver); +} +module_exit(ste_timed_vibra_exit); + +MODULE_AUTHOR("Marcin Mielczarczyk "); +MODULE_DESCRIPTION("STE Timed Output Vibrator"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/ste_timed_vibra.h b/include/linux/ste_timed_vibra.h new file mode 100644 index 00000000000..24edf89aade --- /dev/null +++ b/include/linux/ste_timed_vibra.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Authors: + * Grzegorz Sygieda for ST-Ericsson. + * Krzysztof Antonowicz for ST-Ericsson. + * + * License Terms: GNU General Public License v2 + */ + +#ifndef _STE_TIMED_VIBRA_H_ +#define _STE_TIMED_VIBRA_H + +/* Vibrator states */ +enum ste_timed_vibra_states { + STE_VIBRA_IDLE = 0, + STE_VIBRA_BOOST, + STE_VIBRA_ON, + STE_VIBRA_OFF, +}; + +typedef void (*timed_vibra_control_fp)( + unsigned char speed_left_pos, + unsigned char speed_left_neg, + unsigned char speed_right_pos, + unsigned char speed_right_neg); + +/* + * Vibrator platform data structure + * For details check ste_timed_vibra docbook + */ +struct ste_timed_vibra_platform_data { + bool is_linear_vibra; + unsigned int boost_level; /* p1 */ + unsigned int boost_time; /* p2 */ + unsigned int on_level; /* p3 */ + unsigned int off_level; /* p4 */ + unsigned int off_time; /* p5 */ + timed_vibra_control_fp timed_vibra_control; +}; + +#endif /* _STE_TIMED_VIBRA_H_ */ -- cgit v1.2.3 From 4af8850368fc894f920e504e5569779d179940f6 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Tue, 30 Aug 2011 08:58:33 +0100 Subject: u5500: timed output driver for ab5500 vibrator Simple timed output vibrator driver for AB5500 MFD chips. This chip supports Rotary and Linear vibrator hardware types. Resonance frequency of 100-198 Hz is supported. ST-Ericsson ID: WP 256408 Signed-off-by: Avinash A Signed-off-by: Robert Marklund u5500: enable vibrator when new timeout is requested with this patch new timeout value will be accepted/updated even if vibrator is already executing. ST-Ericsson ID: 360178 Signed-off-by: Avinash A vibra:Remove unnecessary assignment of dev->parent Remove unnecessary assignment of dev->parent, because of this during timed out class unregister it is trying to free resources of parent which does not exist ST-Ericsson ID: 410065 Signed-off-by: Naga Radhesh u5500: Add vibra end of life support Detect and disable vibra when vibra end of life(eol) condition is detected at boot sequence. ST-Ericsson ID: 265890 Signed-off-by: Rajagopala V --- drivers/mfd/ab5500-gpadc.c | 15 + drivers/staging/android/Kconfig | 10 + drivers/staging/android/Makefile | 1 + drivers/staging/android/ab5500-timed-vibra.c | 490 +++++++++++++++++++++++++++ include/linux/ab5500-vibra.h | 57 ++++ include/linux/mfd/abx500/ab5500-gpadc.h | 1 + 6 files changed, 574 insertions(+) create mode 100644 drivers/staging/android/ab5500-timed-vibra.c create mode 100644 include/linux/ab5500-vibra.h diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index 4718e26bee8..fe05ffbadfd 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -99,6 +99,7 @@ #define MIN_INDEX 0x02 #define MAX_INDEX 0x03 #define CTRL_INDEX 0x01 +#define KELVIN_SCALE_VOL45 0x00 /* GPADC constants from AB5500 spec */ #define GPADC0_MIN 0 @@ -129,6 +130,8 @@ #define USBID_MAX 1800 #define KELVIN_MIN 0 #define KELVIN_MAX 4500 +#define VIBRA_MIN 0 +#define VIBRA_MAX 4500 /* This is used for calibration */ #define ADC_RESOLUTION 1023 @@ -253,7 +256,9 @@ struct adc_data adc_tab[] = { ADC_DATA(ACC_DETECT3, 0x19, ACCDET3_MIN, ACCDET3_MAX, 0), ADC_DATA(MAIN_BAT_V_TRIG_MIN, 0x0C, VBAT_MIN, VBAT_MAX, 0), ADC_DATA(MAIN_BAT_V_TXON_TRIG_MIN, 0x0C, VBAT_MIN, VBAT_MAX, 0), + ADC_DATA(VIBRA_KELVIN, 0x16, VIBRA_MIN, VIBRA_MAX, 0), }; + /** * ab5500_gpadc_get() - returns a reference to the primary AB5500 GPADC * (i.e. the first GPADC in the instance list) @@ -279,6 +284,7 @@ static int ab5500_gpadc_ad_to_voltage(struct ab5500_gpadc *gpadc, int res; switch (in) { + case VIBRA_KELVIN: case GPADC0_V: case PCB_TEMP: case BTEMP_BALL: @@ -404,6 +410,15 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) goto out; } break; + case VIBRA_KELVIN: + ret = abx500_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_KELVIN_CTRL, + KELVIN_SCALE_VOL45); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set kelv scale\n"); + goto out; + } + break; case USB_CHARGER_C: case VBUS_V: case BK_BAT_V: diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 7823c2a19ed..a4495997d1b 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -8,6 +8,16 @@ config ANDROID if ANDROID +config ANDROID_AB5500_TIMED_VIBRA + bool "AB5500 Timed Output Vibrator" + depends on AB5500_CORE + depends on ANDROID_TIMED_OUTPUT + default y + help + Say Y here to enable linear/rotary vibrator driver using timed + output class device for ST-Ericsson's based on ST-Ericsson's + AB5500 Mix-Sig PMIC + config ANDROID_BINDER_IPC bool "Android Binder IPC Driver" default n diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index e529c63da57..0d642936a0b 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_ANDROID_AB5500_TIMED_VIBRA) += ab5500-timed-vibra.o obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o diff --git a/drivers/staging/android/ab5500-timed-vibra.c b/drivers/staging/android/ab5500-timed-vibra.c new file mode 100644 index 00000000000..35c627a6285 --- /dev/null +++ b/drivers/staging/android/ab5500-timed-vibra.c @@ -0,0 +1,490 @@ +/* + * ab5500-vibra.c - driver for vibrator in ST-Ericsson AB5500 chip + * + * Copyright (C) 2011 ST-Ericsson SA. + * + * License Terms: GNU General Public License v2 + * + * Author: Shreshtha Kumar SAHU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "timed_output.h" + +#include /* abx500_* */ +#include +#include +#include + +#define AB5500_VIBRA_DEV_NAME "ab5500:vibra" +#define AB5500_VIBRA_DRV_NAME "ab5500-vibrator" + +/* Vibrator Register Address Offsets */ +#define AB5500_VIB_CTRL 0x10 +#define AB5500_VIB_VOLT 0x11 +#define AB5500_VIB_FUND_FREQ 0x12 /* Linear vibra resonance freq. */ +#define AB5500_VIB_FUND_DUTY 0x13 +#define AB5500_KELVIN_ANA 0xB1 +#define AB5500_VIBRA_KELVIN 0xFE + +/* Vibrator Control */ +#define AB5500_VIB_DISABLE (0x80) +#define AB5500_VIB_PWR_ON (0x40) +#define AB5500_VIB_FUND_EN (0x20) +#define AB5500_VIB_FREQ_SHIFT (0) +#define AB5500_VIB_DUTY_SHIFT (3) +#define AB5500_VIB_VOLT_SHIFT (0) +#define AB5500_VIB_PULSE_SHIFT (4) +#define VIBRA_KELVIN_ENABLE (0x90) +#define VIBRA_KELVIN_VOUT (0x20) + +/* Vibrator Freq. (in HZ) and Duty */ +enum ab5500_vibra_freq { + AB5500_VIB_FREQ_1HZ = 1, + AB5500_VIB_FREQ_2HZ, + AB5500_VIB_FREQ_4HZ, + AB5500_VIB_FREQ_8HZ, +}; + +enum ab5500_vibra_duty { + AB5500_VIB_DUTY_100 = 0, + AB5500_VIB_DUTY_75 = 8, + AB5500_VIB_DUTY_50 = 16, + AB5500_VIB_DUTY_25 = 24, +}; + +/* Linear vibrator resonance freq. duty */ +#define AB5500_VIB_RDUTY_50 (0x7F) + +/* Vibration magnitudes */ +#define AB5500_VIB_FREQ_MAX (4) +#define AB5500_VIB_DUTY_MAX (4) + +static u8 vib_freq[AB5500_VIB_FREQ_MAX] = { + AB5500_VIB_FREQ_1HZ, + AB5500_VIB_FREQ_2HZ, + AB5500_VIB_FREQ_4HZ, + AB5500_VIB_FREQ_8HZ, +}; + +static u8 vib_duty[AB5500_VIB_DUTY_MAX] = { + AB5500_VIB_DUTY_100, + AB5500_VIB_DUTY_75, + AB5500_VIB_DUTY_50, + AB5500_VIB_DUTY_25, +}; + +/** + * struct ab5500_vibra - Vibrator driver interal info. + * @tdev: Pointer to timed output device structure + * @dev: Reference to vibra device structure + * @vibra_workqueue: Pointer to vibrator workqueue structure + * @vibra_work: Vibrator work + * @gpadc: Gpadc instance + * @vibra_wait: Vibrator wait queue head + * @vibra_lock: Vibrator lock + * @timeout_ms: Indicates how long time the vibrator will be enabled + * @timeout_start: Start of vibrator in jiffies + * @pdata: Local pointer to platform data with vibrator parameters + * @magnitude: required vibration strength + * @enable: Vibrator running status + * @eol: Vibrator end of life(eol) status + **/ +struct ab5500_vibra { + struct timed_output_dev tdev; + struct device *dev; + struct workqueue_struct *vibra_workqueue; + struct work_struct vibra_work; + struct ab5500_gpadc *gpadc; + wait_queue_head_t vibra_wait; + spinlock_t vibra_lock; + unsigned int timeout_ms; + unsigned long timeout_start; + struct ab5500_vibra_platform_data *pdata; + u8 magnitude; + bool enable; + bool eol; +}; + +static inline u8 vibra_magnitude(u8 mag) +{ + mag /= (AB5500_VIB_FREQ_MAX * AB5500_VIB_DUTY_MAX); + mag = vib_freq[mag / AB5500_VIB_FREQ_MAX] << AB5500_VIB_FREQ_SHIFT; + mag |= vib_duty[mag % AB5500_VIB_DUTY_MAX] << AB5500_VIB_DUTY_SHIFT; + + return mag; +} + +static int ab5500_setup_vibra_kelvin(struct ab5500_vibra* vibra) +{ + int ret; + + /* Establish the kelvin IP connection to be measured */ + ret = abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + AB5500_KELVIN_ANA, VIBRA_KELVIN_ENABLE); + if (ret < 0) { + dev_err(vibra->dev, "failed to set kelvin network\n"); + return ret; + } + + /* Select vibra parameter to be measured */ + ret = abx500_set_register_interruptible(vibra->dev, AB5500_BANK_VIBRA, + AB5500_VIBRA_KELVIN, VIBRA_KELVIN_VOUT); + if (ret < 0) + dev_err(vibra->dev, "failed to select the kelvin param\n"); + + return ret; +} + +static int ab5500_vibra_start(struct ab5500_vibra* vibra) +{ + u8 ctrl = 0; + + ctrl = AB5500_VIB_PWR_ON | + vibra_magnitude(vibra->magnitude); + + if (vibra->pdata->type == AB5500_VIB_LINEAR) + ctrl |= AB5500_VIB_FUND_EN; + + return abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_CTRL, ctrl); +} + +static int ab5500_vibra_stop(struct ab5500_vibra* vibra) +{ + return abx500_mask_and_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_CTRL, + AB5500_VIB_PWR_ON, 0); +} + +static int ab5500_vibra_eol_check(struct ab5500_vibra* vibra) +{ + int ret, vout; + + ret = ab5500_setup_vibra_kelvin(vibra); + if (ret < 0) { + dev_err(vibra->dev, "failed to setup kelvin network\n"); + return ret; + } + + /* Start vibra to measure voltage */ + ret = ab5500_vibra_start(vibra); + if (ret < 0) { + dev_err(vibra->dev, "failed to start vibra\n"); + return ret; + } + /* 20ms delay required for voltage rampup */ + wait_event_interruptible_timeout(vibra->vibra_wait, + 0, msecs_to_jiffies(20)); + + vout = ab5500_gpadc_convert(vibra->gpadc, VIBRA_KELVIN); + if (vout < 0) { + dev_err(vibra->dev, "failed to read gpadc vibra\n"); + return vout; + } + + /* Stop vibra after measuring voltage */ + ret = ab5500_vibra_stop(vibra); + if (ret < 0) { + dev_err(vibra->dev, "failed to stop vibra\n"); + return ret; + } + /* Check for vibra eol condition */ + if (vout < vibra->pdata->eol_voltage) { + vibra->eol = true; + dev_err(vibra->dev, "Vibra eol detected. Disabling vibra!\n"); + } + + return ret; +} + +/** + * ab5500_vibra_work() - Vibrator work, turns on/off vibrator + * @work: Pointer to work structure + * + * This function is called from workqueue, turns on/off vibrator + **/ +static void ab5500_vibra_work(struct work_struct *work) +{ + struct ab5500_vibra *vibra = container_of(work, + struct ab5500_vibra, vibra_work); + unsigned long flags; + int ret; + + ret = ab5500_vibra_start(vibra); + if (ret < 0) + dev_err(vibra->dev, "reg[%d] w failed: %d\n", + AB5500_VIB_CTRL, ret); + + wait_event_interruptible_timeout(vibra->vibra_wait, + 0, msecs_to_jiffies(vibra->timeout_ms)); + + ret = ab5500_vibra_stop(vibra); + if (ret < 0) + dev_err(vibra->dev, "reg[%d] w failed: %d\n", + AB5500_VIB_CTRL, ret); + + spin_lock_irqsave(&vibra->vibra_lock, flags); + + vibra->timeout_start = 0; + vibra->enable = false; + + spin_unlock_irqrestore(&vibra->vibra_lock, flags); +} + +/** + * vibra_enable() - Enables vibrator + * @tdev: Pointer to timed output device structure + * @timeout: Time indicating how long vibrator will be enabled + * + * This function enables vibrator + **/ +static void vibra_enable(struct timed_output_dev *tdev, int timeout) +{ + struct ab5500_vibra *vibra = dev_get_drvdata(tdev->dev); + unsigned long flags; + + spin_lock_irqsave(&vibra->vibra_lock, flags); + + if ((!vibra->enable || timeout) && !vibra->eol) { + vibra->enable = true; + + vibra->timeout_ms = timeout; + vibra->timeout_start = jiffies; + queue_work(vibra->vibra_workqueue, &vibra->vibra_work); + } + + spin_unlock_irqrestore(&vibra->vibra_lock, flags); +} + +/** + * vibra_get_time() - Returns remaining time to disabling vibration + * @tdev: Pointer to timed output device structure + * + * This function returns time remaining to disabling vibration + * + * Returns: + * Returns remaining time to disabling vibration + **/ +static int vibra_get_time(struct timed_output_dev *tdev) +{ + struct ab5500_vibra *vibra = dev_get_drvdata(tdev->dev); + unsigned int ms; + unsigned long flags; + + spin_lock_irqsave(&vibra->vibra_lock, flags); + + if (vibra->enable) + ms = jiffies_to_msecs(vibra->timeout_start + + msecs_to_jiffies(vibra->timeout_ms) - jiffies); + else + ms = 0; + + spin_unlock_irqrestore(&vibra->vibra_lock, flags); + + return ms; +} + +static int ab5500_vibra_reg_init(struct ab5500_vibra *vibra) +{ + int ret = 0; + u8 ctrl = 0; + u8 pulse = 0; + + ctrl = (AB5500_VIB_DUTY_50 << AB5500_VIB_DUTY_SHIFT) | + (AB5500_VIB_FREQ_8HZ << AB5500_VIB_FREQ_SHIFT); + + if (vibra->pdata->type == AB5500_VIB_LINEAR) { + ctrl |= AB5500_VIB_FUND_EN; + + if (vibra->pdata->voltage > AB5500_VIB_VOLT_MAX) + vibra->pdata->voltage = AB5500_VIB_VOLT_MAX; + + pulse = (vibra->pdata->pulse << AB5500_VIB_PULSE_SHIFT) | + (vibra->pdata->voltage << AB5500_VIB_VOLT_SHIFT); + ret = abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_VOLT, + pulse); + if (ret < 0) { + dev_err(vibra->dev, + "reg[%#x] w %#x failed: %d\n", + AB5500_VIB_VOLT, vibra->pdata->voltage, ret); + return ret; + } + + ret = abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_FUND_FREQ, + vibra->pdata->res_freq); + if (ret < 0) { + dev_err(vibra->dev, "reg[%#x] w %#x failed: %d\n", + AB5500_VIB_FUND_FREQ, + vibra->pdata->res_freq, ret); + return ret; + } + + ret = abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_FUND_DUTY, + AB5500_VIB_RDUTY_50); + if (ret < 0) { + dev_err(vibra->dev, "reg[%#x] w %#x failed: %d\n", + AB5500_VIB_FUND_DUTY, + AB5500_VIB_RDUTY_50, ret); + return ret; + } + } + + ret = abx500_set_register_interruptible(vibra->dev, + AB5500_BANK_VIBRA, AB5500_VIB_CTRL, ctrl); + if (ret < 0) { + dev_err(vibra->dev, "reg[%#x] w %#x failed: %d\n", + AB5500_VIB_CTRL, ctrl, ret); + return ret; + } + + return ret; +} + +static int ab5500_vibra_register_dev(struct ab5500_vibra *vibra, + struct platform_device *pdev) +{ + int ret = 0; + + ret = timed_output_dev_register(&vibra->tdev); + if (ret) { + dev_err(&pdev->dev, "failed to register timed output device\n"); + goto err_out; + } + + dev_set_drvdata(vibra->tdev.dev, vibra); + + + /* Create workqueue just for timed output vibrator */ + vibra->vibra_workqueue = + create_singlethread_workqueue("ste-timed-output-vibra"); + if (!vibra->vibra_workqueue) { + dev_err(&pdev->dev, "failed to allocate workqueue\n"); + ret = -ENOMEM; + goto exit_output_unregister; + } + + init_waitqueue_head(&vibra->vibra_wait); + INIT_WORK(&vibra->vibra_work, ab5500_vibra_work); + spin_lock_init(&vibra->vibra_lock); + + platform_set_drvdata(pdev, vibra); + + return ret; + +exit_output_unregister: + timed_output_dev_unregister(&vibra->tdev); +err_out: + return ret; +} + +static int __devinit ab5500_vibra_probe(struct platform_device *pdev) +{ + struct ab5500_vibra_platform_data *pdata = pdev->dev.platform_data; + struct ab5500_vibra *vibra = NULL; + int ret = 0; + + if (pdata == NULL) { + dev_err(&pdev->dev, "platform data required. Quitting...\n"); + return -ENODEV; + } + + vibra = kzalloc(sizeof(struct ab5500_vibra), GFP_KERNEL); + if (vibra == NULL) + return -ENOMEM; + + vibra->tdev.name = "vibrator"; + vibra->tdev.enable = vibra_enable; + vibra->tdev.get_time = vibra_get_time; + vibra->timeout_start = 0; + vibra->enable = false; + vibra->magnitude = pdata->magnitude; + vibra->pdata = pdata; + vibra->dev = &pdev->dev; + + if (vibra->pdata->eol_voltage) { + vibra->gpadc = ab5500_gpadc_get("ab5500-adc.0"); + if (IS_ERR(vibra->gpadc)) + goto err_alloc; + } + + if (vibra->pdata->type == AB5500_VIB_LINEAR) + dev_info(&pdev->dev, "Linear Type Vibrators\n"); + else + dev_info(&pdev->dev, "Rotary Type Vibrators\n"); + + ret = ab5500_vibra_reg_init(vibra); + if (ret < 0) + goto err_alloc; + + ret = ab5500_vibra_register_dev(vibra, pdev); + if (ret < 0) + goto err_alloc; + + /* Perform vibra eol diagnostics if eol_voltage is set */ + if (vibra->pdata->eol_voltage) { + ret = ab5500_vibra_eol_check(vibra); + if (ret < 0) + dev_warn(&pdev->dev, "EOL check failed\n"); + } + + dev_info(&pdev->dev, "initialization success\n"); + + return ret; + +err_alloc: + kfree(vibra); + + return ret; +} + +static int __devexit ab5500_vibra_remove(struct platform_device *pdev) +{ + struct ab5500_vibra *vibra = platform_get_drvdata(pdev); + + timed_output_dev_unregister(&vibra->tdev); + destroy_workqueue(vibra->vibra_workqueue); + kfree(vibra); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ab5500_vibra_driver = { + .probe = ab5500_vibra_probe, + .remove = __devexit_p(ab5500_vibra_remove), + .driver = { + .name = AB5500_VIBRA_DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_vibra_module_init(void) +{ + return platform_driver_register(&ab5500_vibra_driver); +} + +static void __exit ab5500_vibra_module_exit(void) +{ + platform_driver_unregister(&ab5500_vibra_driver); +} + +module_init(ab5500_vibra_module_init); +module_exit(ab5500_vibra_module_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Shreshtha Kumar SAHU "); +MODULE_DESCRIPTION("Timed Output Driver for AB5500 Vibrator"); + diff --git a/include/linux/ab5500-vibra.h b/include/linux/ab5500-vibra.h new file mode 100644 index 00000000000..e85048dd801 --- /dev/null +++ b/include/linux/ab5500-vibra.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------------------------- + * ab5500-vibra.h header file for ab5500 vibrator driver + * + * Copyright (C) 2011 ST-Ericsson SA. + * + * License Terms: GNU General Public License v2 + * + * Author: Shreshtha Kumar SAHU + * + */ + +#ifndef __AB5500_VIBRA_H__ +#define __AB5500_VIBRA_H__ + +enum ab5500_vibra_type { + AB5500_VIB_ROTARY, + AB5500_VIB_LINEAR, +}; + +/* Vibrator Voltage */ +#define AB5500_VIB_VOLT_MIN (0x00) /* 1.3 Volt */ +#define AB5500_VIB_VOLT_MAX (0x0A) /* 3.5 Volt */ +#define AB5500_VIB_VOLT_STEP (0x01) /* 0.2 Volt */ + + +/* Linear Vibrator Resonance Frequncy */ +#define AB5500_VIB_RFREQ_100HZ (0xFB) +#define AB5500_VIB_RFREQ_150HZ (0x52) +#define AB5500_VIB_RFREQ_196HZ (0x03) + +/* Vibrator pulse duration in milliseconds */ +enum ab5500_vibra_pulse { + AB5500_VIB_PULSE_OFF, + AB5500_VIB_PULSE_20ms, + AB5500_VIB_PULSE_75ms, + AB5500_VIB_PULSE_130ms, + AB5500_VIB_PULSE_170ms, +}; + +/** + * struct ab5500_vibra_platform_data + * @voltage: Vibra output voltage + * @res_freq: Linear vibra resonance freq. + * @type: Vibra HW type + * @pulse: Vibra pulse duration in ms + * @eol_voltage: EOL voltage in mV + */ +struct ab5500_vibra_platform_data { + u8 voltage; + u8 res_freq; + u8 magnitude; + enum ab5500_vibra_type type; + enum ab5500_vibra_pulse pulse; + int eol_voltage; +}; + +#endif /* __AB5500_VIBRA_H__ */ diff --git a/include/linux/mfd/abx500/ab5500-gpadc.h b/include/linux/mfd/abx500/ab5500-gpadc.h index 67dc3cc9034..8bddafc7f79 100644 --- a/include/linux/mfd/abx500/ab5500-gpadc.h +++ b/include/linux/mfd/abx500/ab5500-gpadc.h @@ -34,6 +34,7 @@ /* VBAT with TX off only min trigger */ #define MAIN_BAT_V_TRIG_MIN 14 #define GPADC0_V 15 +#define VIBRA_KELVIN 16 /* * Frequency of auto adc conversion -- cgit v1.2.3 From 7aec3be3a38705f74df761d8ccaa802580024d84 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 19 Mar 2012 15:50:02 +0100 Subject: config: ux500: android: Disable UX500_SUSPEND_DBG, needs STE cpuidle Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index c5ed034a99e..3a4bcd4b252 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -35,8 +35,6 @@ CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y # CONFIG_UX500_USECASE_GOVERNOR is not set CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DB8500_MLOADER=y -- cgit v1.2.3 From 40414757c5922848053657fe223fc4c39e21b295 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 29 Mar 2012 11:42:05 +0200 Subject: mach_ux500:config:Removed suspend flag By disbaling the suspend we could avoid the hangs in suspend and resume. This workaround will be removed once the power management supports for all other peripheral drivers. Signed-off-by: Naveen Kumar Gaddipati Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 3 --- arch/arm/configs/u8500_defconfig | 5 ----- 2 files changed, 8 deletions(-) mode change 100755 => 100644 arch/arm/configs/u8500_defconfig diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index 3a4bcd4b252..71cb1932811 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -32,9 +32,6 @@ CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_STANDBY=y -CONFIG_UX500_SUSPEND_MEM=y # CONFIG_UX500_USECASE_GOVERNOR is not set CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DB8500_MLOADER=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig old mode 100755 new mode 100644 index ab8a18be30b..50ade0d1a14 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -29,11 +29,6 @@ CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_GPIO_KEYS=y CONFIG_DBX500_PRCMU_DEBUG=y -CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_STANDBY=y -CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -- cgit v1.2.3 From 9e11f7158058c88ab6639427b6d7649002836b66 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 6 Apr 2012 10:36:11 +0200 Subject: ux500: configs: u8500 defconfigs cleanup and alignment Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 30 ++++++++++++++++++-------- arch/arm/configs/u8500_defconfig | 36 ++++++++++++++------------------ 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index 71cb1932811..ff7f2289e1c 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -30,8 +30,12 @@ CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y +CONFIG_MACH_U8520=y CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_U9540=y +CONFIG_UX500_GPIO_KEYS=y CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_DB8500_PWR_TEST=y # CONFIG_UX500_USECASE_GOVERNOR is not set CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DB8500_MLOADER=y @@ -78,12 +82,16 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_IPV6_SIT is not set +CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_TPROXY=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y @@ -91,17 +99,16 @@ CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_ULOG=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y CONFIG_PHONET=y CONFIG_NET_SCHED=y -CONFIG_BT_L2CAP=y -CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y -CONFIG_BT_HCIUART=y CONFIG_CFG80211=y CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_REG_DEBUG=y @@ -124,6 +131,7 @@ CONFIG_STE_TRACE_MODEM=y CONFIG_DISPDEV=y CONFIG_U8500_SIM_DETECT=y CONFIG_STM_TRACE=y +CONFIG_STM_DEFAULT_MASTERS_MODES=0x20 CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_MD=y @@ -144,11 +152,10 @@ CONFIG_PPP_ASYNC=y CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_STMPE=y +CONFIG_KEYBOARD_NOMADIK_SKE=y CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_BU21013=y CONFIG_TOUCHSCREEN_CYTTSP_CORE=y CONFIG_TOUCHSCREEN_CYTTSP_SPI=y CONFIG_INPUT_MISC=y @@ -174,19 +181,20 @@ CONFIG_GPIO_AB8500=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_SENSORS_AB8500=y +CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y CONFIG_THERMAL=y CONFIG_WATCHDOG=y -CONFIG_U8500_WATCHDOG_DEBUG=y -CONFIG_TPS6105X=y -CONFIG_MFD_STMPE=y +CONFIG_UX500_WATCHDOG_DEBUG=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_MFD_DB8500_PRCMU=y +CONFIG_REGULATOR=y CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_DB8500_PRCMU=y @@ -217,6 +225,7 @@ CONFIG_SND_SOC_UX500_AB5500=y CONFIG_SND_SOC_UX500_AB8500=y CONFIG_SND_SOC_UX500_CG29XX=y CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_HIDRAW=y CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_SUSPEND=y @@ -233,7 +242,7 @@ CONFIG_USB_G_ANDROID=y CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_UNSAFE_RESUME=y -CONFIG_MMC_CLKGATE=y +CONFIG_MMC_BLOCK_MINORS=32 # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y @@ -273,6 +282,7 @@ CONFIG_CW1200_DEBUGFS=y CONFIG_U8500_MMIO=y CONFIG_U8500_CM=y CONFIG_U8500_FLASH=y +CONFIG_HSEM_U8500=y CONFIG_MODEM_U8500=y CONFIG_U8500_SHRM=y CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y @@ -310,6 +320,8 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_UNUSED_SYMBOLS=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_DETECT_HUNG_TASK=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 50ade0d1a14..83374053a01 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -18,6 +18,14 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_BLKDEV_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y @@ -29,10 +37,12 @@ CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y CONFIG_UX500_GPIO_KEYS=y CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_DB8500_PWR_TEST=y CONFIG_DB8500_MLOADER=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y +CONFIG_SCHED_MC=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y @@ -42,7 +52,6 @@ CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M in CONFIG_KEXEC=y CONFIG_CRASH_SWRESET=y CONFIG_CRASH_DUMP=y -CONFIG_DB8500_PWR_TEST=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y @@ -65,8 +74,6 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP6_NF_IPTABLES=y # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set @@ -78,21 +85,20 @@ CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_TPROXY=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_SOCKET=y -CONFIG_NETFILTER_TPROXY=y +CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_ULOG=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y CONFIG_PHONET=y CONFIG_NET_SCHED=y -CONFIG_BT_L2CAP=y -CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=y @@ -159,7 +165,6 @@ CONFIG_HW_RANDOM_NOMADIK=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_NOMADIK=y CONFIG_SPI=y -CONFIG_STM_MSP_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_TC3589X=y @@ -172,6 +177,7 @@ CONFIG_SENSORS_DBX500=y CONFIG_SENSORS_LSM303DLH=y CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y +CONFIG_THERMAL=y CONFIG_WATCHDOG=y CONFIG_UX500_WATCHDOG_DEBUG=y CONFIG_MFD_TC3589X=y @@ -210,6 +216,7 @@ CONFIG_SND_SOC_UX500_AB5500=y CONFIG_SND_SOC_UX500_AB8500=y CONFIG_SND_SOC_UX500_CG29XX=y CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_HIDRAW=y CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_SUSPEND=y @@ -288,20 +295,11 @@ CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_9P_FS=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_BLKDEV_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -CONFIG_SGI_PARTITION=y -CONFIG_SUN_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_KERNEL=y CONFIG_LOCKUP_DETECTOR=y CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_DETECT_HUNG_TASK=y @@ -320,5 +318,3 @@ CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEV_UX500=y CONFIG_CRYPTO_DEV_UX500_HASH=y CONFIG_CRC7=y -CONFIG_HIDRAW=y -CONFIG_UID_STAT=y -- cgit v1.2.3 From e4032a05be2e8680fc45e97166696b32c065b5d7 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 18 Apr 2012 13:20:33 +0200 Subject: ux500: bm: Update board mop500 battery management to 3.4 bm drivers Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-mop500-bm.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index 6f380b45ad5..b55de182953 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -11,7 +11,8 @@ */ #include -#include +#include +#include #include #include "board-mop500-bm.h" @@ -22,7 +23,7 @@ * Note that the res_to_temp table must be strictly sorted by falling resistance * values to work. */ -static struct res_to_temp temp_tbl_A[] = { +static struct abx500_res_to_temp temp_tbl_A[] = { {-5, 53407}, { 0, 48594}, { 5, 43804}, @@ -39,7 +40,7 @@ static struct res_to_temp temp_tbl_A[] = { {60, 13437}, {65, 12500}, }; -static struct res_to_temp temp_tbl_B[] = { +static struct abx500_res_to_temp temp_tbl_B[] = { {-5, 165418}, { 0, 159024}, { 5, 151921}, @@ -56,7 +57,7 @@ static struct res_to_temp temp_tbl_B[] = { {60, 85461}, {65, 82869}, }; -static struct v_to_cap cap_tbl_A[] = { +static struct abx500_v_to_cap cap_tbl_A[] = { {4171, 100}, {4114, 95}, {4009, 83}, @@ -78,7 +79,7 @@ static struct v_to_cap cap_tbl_A[] = { {3408, 1}, {3247, 0}, }; -static struct v_to_cap cap_tbl_B[] = { +static struct abx500_v_to_cap cap_tbl_B[] = { {4161, 100}, {4124, 98}, {4044, 90}, @@ -101,7 +102,7 @@ static struct v_to_cap cap_tbl_B[] = { {3250, 0}, }; #endif -static struct v_to_cap cap_tbl[] = { +static struct abx500_v_to_cap cap_tbl[] = { {4186, 100}, {4163, 99}, {4114, 95}, @@ -132,7 +133,7 @@ static struct v_to_cap cap_tbl[] = { * Note that the res_to_temp table must be strictly sorted by falling * resistance values to work. */ -static struct res_to_temp temp_tbl[] = { +static struct abx500_res_to_temp temp_tbl[] = { {-5, 214834}, { 0, 162943}, { 5, 124820}, @@ -184,7 +185,7 @@ static struct batres_vs_temp temp_to_batres_tbl[] = { {-20, BATRES}, }; #endif -static const struct battery_type bat_type[] = { +static const struct abx500_battery_type bat_type[] = { [BATTERY_UNKNOWN] = { /* First element always represent the UNKNOWN battery */ .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, @@ -224,6 +225,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, #ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL @@ -251,6 +254,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl_A, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A), .v_to_cap_tbl = cap_tbl_A, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, { @@ -277,6 +282,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl_B, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B), .v_to_cap_tbl = cap_tbl_B, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, #else /* @@ -308,6 +315,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, { .name = POWER_SUPPLY_TECHNOLOGY_LION, @@ -333,6 +342,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, { .name = POWER_SUPPLY_TECHNOLOGY_LION, @@ -358,6 +369,8 @@ static const struct battery_type bat_type[] = { .r_to_t_tbl = temp_tbl, .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, }, #endif }; @@ -479,9 +492,9 @@ struct ab8500_bm_data ab8500_bm_data = { .no_maintenance = false, #endif #ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL - .adc_therm = ADC_THERM_BATCTRL, + .adc_therm = ABx500_ADC_THERM_BATCTRL, #else - .adc_therm = ADC_THERM_BATTEMP, + .adc_therm = ABx500_ADC_THERM_BATTEMP, #endif #ifdef CONFIG_AB8500_9100_LI_ION_BATTERY .chg_unknown_bat = true, -- cgit v1.2.3 From c5030b1731024660f643f8481237fddf1770248d Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 18 Apr 2012 13:23:26 +0200 Subject: mfd ab8500: bm: Fix the bat_type field lack in ab8500_bm_data Signed-off-by: Philippe Langlais --- include/linux/mfd/abx500/ab8500-bm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h index 44310c98ee6..c92c297fd3f 100644 --- a/include/linux/mfd/abx500/ab8500-bm.h +++ b/include/linux/mfd/abx500/ab8500-bm.h @@ -395,6 +395,7 @@ struct ab8500_bm_data { int gnd_lift_resistance; const struct ab8500_maxim_parameters *maxi; const struct ab8500_bm_capacity_levels *cap_levels; + const struct abx500_battery_type *bat_type; const struct ab8500_bm_charger_parameters *chg_params; const struct ab8500_fg_parameters *fg_params; }; -- cgit v1.2.3 From 3fc05771a4957963c8108ecbdc0308f02e21a935 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 18 Apr 2012 15:52:59 +0200 Subject: ab8500: gpadc: Use new mainline ab8500_gpadc_get() with name parameter Signed-off-by: Philippe Langlais --- drivers/hwmon/ab8500.c | 2 +- drivers/mfd/ab8500-debugfs.c | 26 +++++++++++++------------- drivers/mfd/ab8500-gpadc.c | 10 +++++++--- include/linux/mfd/abx500/ab8500-gpadc.h | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c index 8204af594a9..65a0f381d01 100644 --- a/drivers/hwmon/ab8500.c +++ b/drivers/hwmon/ab8500.c @@ -139,7 +139,7 @@ static int ab8500_temp_irq_handler(int irq, struct abx500_temp *data) int __init ab8500_hwmon_init(struct abx500_temp *data) { - data->ab8500_gpadc = ab8500_gpadc_get(); + data->ab8500_gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); if (IS_ERR(data->ab8500_gpadc)) return PTR_ERR(data->ab8500_gpadc); diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 595b41800b4..7b912afd664 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -805,7 +805,7 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) int bat_ctrl_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL); bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL, bat_ctrl_raw); @@ -833,7 +833,7 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) int btemp_ball_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL); btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, btemp_ball_raw); @@ -862,7 +862,7 @@ static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) int main_charger_v_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V); main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_CHARGER_V, main_charger_v_raw); @@ -892,7 +892,7 @@ static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) int acc_detect1_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1); acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, acc_detect1_raw); @@ -922,7 +922,7 @@ static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) int acc_detect2_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2); acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT2, acc_detect2_raw); @@ -952,7 +952,7 @@ static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) int aux1_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1); aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, aux1_raw); @@ -980,7 +980,7 @@ static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) int aux2_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2); aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, aux2_raw); @@ -1008,7 +1008,7 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) int main_bat_v_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V); main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, main_bat_v_raw); @@ -1037,7 +1037,7 @@ static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) int vbus_v_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V); vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, vbus_v_raw); @@ -1065,7 +1065,7 @@ static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) int main_charger_c_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C); main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_CHARGER_C, main_charger_c_raw); @@ -1095,7 +1095,7 @@ static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) int usb_charger_c_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C); usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_CHARGER_C, usb_charger_c_raw); @@ -1125,7 +1125,7 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) int bk_bat_v_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V); bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, BK_BAT_V, bk_bat_v_raw); @@ -1153,7 +1153,7 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) int die_temp_convert; struct ab8500_gpadc *gpadc; - gpadc = ab8500_gpadc_get(); + gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP); die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, die_temp_raw); diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index d4135706529..d06f4826619 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -136,12 +136,16 @@ static LIST_HEAD(ab8500_gpadc_list); * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC * (i.e. the first GPADC in the instance list) */ -struct ab8500_gpadc *ab8500_gpadc_get(void) +struct ab8500_gpadc *ab8500_gpadc_get(char *name) { struct ab8500_gpadc *gpadc; - gpadc = list_first_entry(&ab8500_gpadc_list, struct ab8500_gpadc, node); - return gpadc; + list_for_each_entry(gpadc, &ab8500_gpadc_list, node) { + if (!strcmp(name, dev_name(gpadc->dev))) + return gpadc; + } + + return ERR_PTR(-ENOENT); } EXPORT_SYMBOL(ab8500_gpadc_get); diff --git a/include/linux/mfd/abx500/ab8500-gpadc.h b/include/linux/mfd/abx500/ab8500-gpadc.h index fa706c5a04a..252966769d9 100644 --- a/include/linux/mfd/abx500/ab8500-gpadc.h +++ b/include/linux/mfd/abx500/ab8500-gpadc.h @@ -26,7 +26,7 @@ struct ab8500_gpadc; -struct ab8500_gpadc *ab8500_gpadc_get(void); +struct ab8500_gpadc *ab8500_gpadc_get(char *name); int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel); int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel); int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, -- cgit v1.2.3 From 169b92e33260f1616046880de89ee8103dcdf156 Mon Sep 17 00:00:00 2001 From: supriya karanth Date: Fri, 13 Apr 2012 16:10:34 +0200 Subject: Enable USB Video in Snowball kernel config Enable the USB VIDEO CLASS for android https://bugs.launchpad.net/igloocommunity/+bug/975593 Signed-off-by: supriya karanth --- arch/arm/configs/u8500_android_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index ff7f2289e1c..5dbbd2aa130 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -202,7 +202,8 @@ CONFIG_REGULATOR_AB8500_DEBUG=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set -# CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y CONFIG_RADIO_CG2900=y CONFIG_GPU_MALI=y CONFIG_FB=y -- cgit v1.2.3 From 88ee8490ab4f6401fe4d60533161a0266680543d Mon Sep 17 00:00:00 2001 From: "ramesh.chandrasekaran" Date: Mon, 23 Apr 2012 07:55:42 +0200 Subject: RTC: Fix to correct improper implementation of clock update irq (RTC_UIE) and enable UIE Emulation Signed-off-by: ramesh.chandrasekaran --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-ab8500.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 595d02b1117..3e47885660e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -722,6 +722,7 @@ config RTC_DRV_AB3100 config RTC_DRV_AB8500 tristate "ST-Ericsson AB8500 RTC" depends on AB8500_CORE + select RTC_INTF_DEV_UIE_EMUL help Select this to enable the ST-Ericsson AB8500 power management IC RTC support. This chip contains a battery- and capacitor-backed RTC. diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index baae8548781..63b3a672a17 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -219,8 +219,8 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { int retval, i; unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; - unsigned long mins, secs = 0; - + unsigned long mins, secs = 0, cursec=0; + struct rtc_time curtm; if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { dev_dbg(dev, "year should be equal to or greater than %d\n", AB8500_RTC_EPOCH); @@ -230,6 +230,17 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) /* Get the number of seconds since 1970 */ rtc_tm_to_time(&alarm->time, &secs); + /* Check whether alarm is set less than 1min. + * Since our RTC doesn't support alarm resolution less than 1min, + * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON + */ + ab8500_rtc_read_time(dev, &curtm); /* Read current time */ + rtc_tm_to_time(&curtm, &cursec); + if ((secs - cursec) < 59) { + dev_dbg(dev, "Alarm less than 1 minute not supported\n"); + return -EINVAL; + } + /* * Convert it to the number of seconds since 01-01-2000 00:00:00, since * we only have a small counter in the RTC. -- cgit v1.2.3 From addfa027e67c7241938e88c96e1b2abe6ea4149e Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 24 Apr 2012 13:04:34 +0200 Subject: power: ab8500: bm: Temporary workaround to reuse old ab8500 platform data managment Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-mop500-bm.c | 18 +++++++++--------- arch/arm/mach-ux500/board-mop500-bm.h | 10 +++++----- drivers/power/ab8500_btemp.c | 4 ++-- drivers/power/ab8500_charger.c | 5 +++-- drivers/power/ab8500_fg.c | 4 ++-- drivers/power/abx500_chargalg.c | 7 ++++--- include/linux/mfd/abx500/ab8500.h | 10 +++++----- 7 files changed, 30 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c index b55de182953..afdc6ee59a3 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.c +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -395,23 +395,23 @@ static char *ab8500_chargalg_supplied_to[] = { "ab8500_fg", }; -struct ab8500_charger_platform_data ab8500_charger_plat_data = { +struct abx500_charger_platform_data ab8500_charger_plat_data = { .supplied_to = ab8500_charger_supplied_to, .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to), .autopower_cfg = false, }; -struct ab8500_btemp_platform_data ab8500_btemp_plat_data = { +struct abx500_btemp_platform_data ab8500_btemp_plat_data = { .supplied_to = ab8500_btemp_supplied_to, .num_supplicants = ARRAY_SIZE(ab8500_btemp_supplied_to), }; -struct ab8500_fg_platform_data ab8500_fg_plat_data = { +struct abx500_fg_platform_data ab8500_fg_plat_data = { .supplied_to = ab8500_fg_supplied_to, .num_supplicants = ARRAY_SIZE(ab8500_fg_supplied_to), }; -struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data = { +struct abx500_chargalg_platform_data ab8500_chargalg_plat_data = { .supplied_to = ab8500_chargalg_supplied_to, .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to), }; @@ -436,7 +436,7 @@ struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data = { .leds = leds_pwm_data, }; -static const struct ab8500_bm_capacity_levels cap_levels = { +static const struct abx500_bm_capacity_levels cap_levels = { .critical = 2, .low = 10, .normal = 70, @@ -444,7 +444,7 @@ static const struct ab8500_bm_capacity_levels cap_levels = { .full = 100, }; -static const struct ab8500_fg_parameters fg = { +static const struct abx500_fg_parameters fg = { .recovery_sleep_timer = 10, .recovery_total_time = 100, .init_timer = 1, @@ -461,21 +461,21 @@ static const struct ab8500_fg_parameters fg = { .maint_thres = 97, }; -static const struct ab8500_maxim_parameters maxi_params = { +static const struct abx500_maxim_parameters maxi_params = { .ena_maxi = true, .chg_curr = 910, .wait_cycles = 10, .charger_curr_step = 100, }; -static const struct ab8500_bm_charger_parameters chg = { +static const struct abx500_bm_charger_parameters chg = { .usb_volt_max = 5500, .usb_curr_max = 1500, .ac_volt_max = 7500, .ac_curr_max = 1500, }; -struct ab8500_bm_data ab8500_bm_data = { +struct abx500_bm_data ab8500_bm_data = { .temp_under = 3, .temp_low = 8, .temp_high = 43, diff --git a/arch/arm/mach-ux500/board-mop500-bm.h b/arch/arm/mach-ux500/board-mop500-bm.h index 6b6dcf43502..61d6bc71cc3 100644 --- a/arch/arm/mach-ux500/board-mop500-bm.h +++ b/arch/arm/mach-ux500/board-mop500-bm.h @@ -15,11 +15,11 @@ #include -extern struct ab8500_charger_platform_data ab8500_charger_plat_data; -extern struct ab8500_btemp_platform_data ab8500_btemp_plat_data; -extern struct ab8500_fg_platform_data ab8500_fg_plat_data; -extern struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data; -extern struct ab8500_bm_data ab8500_bm_data; +extern struct abx500_charger_platform_data ab8500_charger_plat_data; +extern struct abx500_btemp_platform_data ab8500_btemp_plat_data; +extern struct abx500_fg_platform_data ab8500_fg_plat_data; +extern struct abx500_chargalg_platform_data ab8500_chargalg_plat_data; +extern struct abx500_bm_data ab8500_bm_data; extern struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data; #endif diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 6d4ece31413..5e5700cf24a 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -973,7 +973,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { int irq, i, ret = 0; u8 val; - struct abx500_bm_plat_data *plat_data; + struct ab8500_platform_data *plat_data; struct ab8500_btemp *di = kzalloc(sizeof(struct ab8500_btemp), GFP_KERNEL); @@ -988,7 +988,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->initialized = false; /* get btemp specific platform data */ - plat_data = pdev->dev.platform_data; + plat_data = dev_get_platdata(di->parent->dev); di->pdata = plat_data->btemp; if (!di->pdata) { dev_err(di->dev, "no btemp platform data supplied\n"); diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index a675765fc4f..19f62729a0a 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -2637,7 +2637,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) static int __devinit ab8500_charger_probe(struct platform_device *pdev) { int irq, i, charger_status, ret = 0; - struct abx500_bm_plat_data *plat_data; + struct ab8500_platform_data *plat_data; struct ab8500_charger *di = kzalloc(sizeof(struct ab8500_charger), GFP_KERNEL); @@ -2653,7 +2653,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) spin_lock_init(&di->usb_state.usb_lock); /* get charger specific platform data */ - plat_data = pdev->dev.platform_data; + plat_data = dev_get_platdata(di->parent->dev); + di->pdata = plat_data->charger; if (!di->pdata) { diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index fc27153b562..798f5f7cef4 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -2446,7 +2446,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) { int i, irq; int ret = 0; - struct abx500_bm_plat_data *plat_data; + struct ab8500_platform_data *plat_data; struct ab8500_fg *di = kzalloc(sizeof(struct ab8500_fg), GFP_KERNEL); @@ -2461,7 +2461,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); /* get fg specific platform data */ - plat_data = pdev->dev.platform_data; + plat_data = dev_get_platdata(di->parent->dev); di->pdata = plat_data->fg; if (!di->pdata) { dev_err(di->dev, "no fg platform data supplied\n"); diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 804b88c760d..032b27d35bf 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -220,6 +220,7 @@ enum maxim_ret { */ struct abx500_chargalg { struct device *dev; + struct ab8500 *parent; int charge_status; int eoc_cnt; int rch_cnt; @@ -1802,7 +1803,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev) static int __devinit abx500_chargalg_probe(struct platform_device *pdev) { - struct abx500_bm_plat_data *plat_data; + struct ab8500_platform_data *plat_data; int ret = 0; struct abx500_chargalg *di = @@ -1812,8 +1813,8 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev) /* get device struct */ di->dev = &pdev->dev; - - plat_data = pdev->dev.platform_data; + di->parent = dev_get_drvdata(pdev->dev.parent); + plat_data = dev_get_platdata(di->parent->dev); di->pdata = plat_data->chargalg; di->bat = plat_data->battery; diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index a51161222e1..30435405c07 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -289,13 +289,13 @@ struct ab8500_platform_data { void (*init) (struct ab8500 *); struct ab8500_regulator_platform_data *regulator; struct abx500_accdet_platform_data *accdet; - struct ab8500_bm_data *battery; + struct abx500_bm_data *battery; struct ab8500_denc_platform_data *denc; struct ab8500_audio_platform_data *audio; - struct ab8500_charger_platform_data *charger; - struct ab8500_btemp_platform_data *btemp; - struct ab8500_fg_platform_data *fg; - struct ab8500_chargalg_platform_data *chargalg; + struct abx500_charger_platform_data *charger; + struct abx500_btemp_platform_data *btemp; + struct abx500_fg_platform_data *fg; + struct abx500_chargalg_platform_data *chargalg; struct ab8500_gpio_platform_data *gpio; struct ab8500_sysctrl_platform_data *sysctrl; struct ab8500_pwmled_platform_data *pwmled; -- cgit v1.2.3 From ec3e8a328c763998e45e2a3115a07298221f77ba Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 25 Apr 2012 16:29:54 +0200 Subject: config: Enable PCCARD to set IO_SPACE_LIMIT to 0xffff to avoid failure in IORESOURCE_IO allocation This is a temporary workaround until cg2900-uart & cw1200 drivers change their way to manage the GPIO reservations Signed-off-by: Philippe Langlais --- arch/arm/configs/u8500_android_defconfig | 2 ++ arch/arm/configs/u8500_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig index 5dbbd2aa130..62d360df4f4 100644 --- a/arch/arm/configs/u8500_android_defconfig +++ b/arch/arm/configs/u8500_android_defconfig @@ -39,6 +39,8 @@ CONFIG_DB8500_PWR_TEST=y # CONFIG_UX500_USECASE_GOVERNOR is not set CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DB8500_MLOADER=y +CONFIG_PCCARD=y +# CONFIG_PCMCIA is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 83374053a01..30e88eb8985 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -39,6 +39,8 @@ CONFIG_UX500_GPIO_KEYS=y CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_DB8500_PWR_TEST=y CONFIG_DB8500_MLOADER=y +CONFIG_PCCARD=y +# CONFIG_PCMCIA is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y -- cgit v1.2.3 From f0bfbaaec3d8dfb06790c59bc5d6c848f0bbd5f8 Mon Sep 17 00:00:00 2001 From: "ramesh.chandrasekaran" Date: Thu, 17 May 2012 13:27:00 +0200 Subject: core: Fix for Basic Suspend/Resume to work Signed-off-by: ramesh.chandrasekaran --- drivers/amba/bus.c | 12 ++++++------ include/linux/amba/bus.h | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index cc273226dbd..e98838a060e 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -117,7 +117,7 @@ static int amba_legacy_resume(struct device *dev) #ifdef CONFIG_SUSPEND -static int amba_pm_suspend(struct device *dev) +int amba_pm_suspend(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; @@ -135,7 +135,7 @@ static int amba_pm_suspend(struct device *dev) return ret; } -static int amba_pm_resume(struct device *dev) +int amba_pm_resume(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; @@ -162,7 +162,7 @@ static int amba_pm_resume(struct device *dev) #ifdef CONFIG_HIBERNATE_CALLBACKS -static int amba_pm_freeze(struct device *dev) +int amba_pm_freeze(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; @@ -180,7 +180,7 @@ static int amba_pm_freeze(struct device *dev) return ret; } -static int amba_pm_thaw(struct device *dev) +int amba_pm_thaw(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; @@ -198,7 +198,7 @@ static int amba_pm_thaw(struct device *dev) return ret; } -static int amba_pm_poweroff(struct device *dev) +int amba_pm_poweroff(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; @@ -216,7 +216,7 @@ static int amba_pm_poweroff(struct device *dev) return ret; } -static int amba_pm_restore(struct device *dev) +int amba_pm_restore(struct device *dev) { struct device_driver *drv = dev->driver; int ret = 0; diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 8d54f79457b..affea2229c4 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -128,3 +128,23 @@ struct amba_device name##_device = { \ module_driver(__amba_drv, amba_driver_register, amba_driver_unregister) #endif + +#ifdef CONFIG_SUSPEND +extern int amba_pm_suspend(struct device *dev); +extern int amba_pm_resume(struct device *dev); +#else +#define amba_pm_suspend NULL +#define amba_pm_resume NULL +#endif + +#ifdef CONFIG_HIBERNATE_CALLBACKS +extern int amba_pm_freeze(struct device *dev); +extern int amba_pm_thaw(struct device *dev); +extern int amba_pm_poweroff(struct device *dev); +extern int amba_pm_restore(struct device *dev); +#else +#define amba_pm_freeze NULL +#define amba_pm_thaw NULL +#define amba_pm_poweroff NULL +#define amba_pm_restore NULL +#endif -- cgit v1.2.3