From 6f2384c4bdd4be3dc1e5d22ed5e6f0c3076fda60 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 20 Jun 2008 11:02:19 +0200 Subject: mfd: asic3 gpiolib support ASIC3 is, among other things, a GPIO extender. We should thus have it supporting the current gpiolib API. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 224 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index ef8a492766a7..c70e7a5a5a90 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -9,7 +9,7 @@ * * Copyright 2001 Compaq Computer Corporation. * Copyright 2004-2005 Phil Blundell - * Copyright 2007 OpenedHand Ltd. + * Copyright 2007-2008 OpenedHand Ltd. * * Authors: Phil Blundell , * Samuel Ortiz @@ -19,12 +19,26 @@ #include #include #include +#include #include #include #include #include +struct asic3 { + void __iomem *mapping; + unsigned int bus_shift; + unsigned int irq_nr; + unsigned int irq_base; + spinlock_t lock; + u16 irq_bothedge[4]; + struct gpio_chip gpio; + struct device *dev; +}; + +static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); + static inline void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value) { @@ -251,7 +265,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) edge &= ~bit; } else if (type == IRQT_BOTHEDGE) { trigger |= bit; - if (asic3_gpio_get_value(asic, irq - asic->irq_base)) + if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base)) edge &= ~bit; else edge |= bit; @@ -350,6 +364,107 @@ static void asic3_irq_remove(struct platform_device *pdev) } /* GPIOs */ +static int asic3_gpio_direction(struct gpio_chip *chip, + unsigned offset, int out) +{ + u32 mask = ASIC3_GPIO_TO_MASK(offset), out_reg; + unsigned int gpio_base; + unsigned long flags; + struct asic3 *asic; + + asic = container_of(chip, struct asic3, gpio); + gpio_base = ASIC3_GPIO_TO_BASE(offset); + + if (gpio_base > ASIC3_GPIO_D_Base) { + printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); + return -EINVAL; + } + + spin_lock_irqsave(&asic->lock, flags); + + out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_Direction); + + /* Input is 0, Output is 1 */ + if (out) + out_reg |= mask; + else + out_reg &= ~mask; + + asic3_write_register(asic, gpio_base + ASIC3_GPIO_Direction, out_reg); + + spin_unlock_irqrestore(&asic->lock, flags); + + return 0; + +} + +static int asic3_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + return asic3_gpio_direction(chip, offset, 0); +} + +static int asic3_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + return asic3_gpio_direction(chip, offset, 1); +} + +static int asic3_gpio_get(struct gpio_chip *chip, + unsigned offset) +{ + unsigned int gpio_base; + u32 mask = ASIC3_GPIO_TO_MASK(offset); + struct asic3 *asic; + + asic = container_of(chip, struct asic3, gpio); + gpio_base = ASIC3_GPIO_TO_BASE(offset); + + if (gpio_base > ASIC3_GPIO_D_Base) { + printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); + return -EINVAL; + } + + return asic3_read_register(asic, gpio_base + ASIC3_GPIO_Status) & mask; +} + +static void asic3_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + u32 mask, out_reg; + unsigned int gpio_base; + unsigned long flags; + struct asic3 *asic; + + asic = container_of(chip, struct asic3, gpio); + gpio_base = ASIC3_GPIO_TO_BASE(offset); + + if (gpio_base > ASIC3_GPIO_D_Base) { + printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); + return; + } + + mask = ASIC3_GPIO_TO_MASK(offset); + + spin_lock_irqsave(&asic->lock, flags); + + out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_Out); + + if (value) + out_reg |= mask; + else + out_reg &= ~mask; + + asic3_write_register(asic, gpio_base + ASIC3_GPIO_Out, out_reg); + + spin_unlock_irqrestore(&asic->lock, flags); + + return; +} + static inline u32 asic3_get_gpio(struct asic3 *asic, unsigned int base, unsigned int function) { @@ -368,15 +483,6 @@ static void asic3_set_gpio(struct asic3 *asic, unsigned int base, spin_unlock_irqrestore(&asic->lock, flags); } -#define asic3_get_gpio_a(asic, fn) \ - asic3_get_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn) -#define asic3_get_gpio_b(asic, fn) \ - asic3_get_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn) -#define asic3_get_gpio_c(asic, fn) \ - asic3_get_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn) -#define asic3_get_gpio_d(asic, fn) \ - asic3_get_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn) - #define asic3_set_gpio_a(asic, fn, bits, val) \ asic3_set_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn, bits, val) #define asic3_set_gpio_b(asic, fn, bits, val) \ @@ -394,54 +500,6 @@ static void asic3_set_gpio(struct asic3 *asic, unsigned int base, asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ } while (0) -int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) -{ - u32 mask = ASIC3_GPIO_bit(gpio); - - switch (gpio >> 4) { - case ASIC3_GPIO_BANK_A: - return asic3_get_gpio_a(asic, Status) & mask; - case ASIC3_GPIO_BANK_B: - return asic3_get_gpio_b(asic, Status) & mask; - case ASIC3_GPIO_BANK_C: - return asic3_get_gpio_c(asic, Status) & mask; - case ASIC3_GPIO_BANK_D: - return asic3_get_gpio_d(asic, Status) & mask; - default: - printk(KERN_ERR "%s: invalid GPIO value 0x%x", - __func__, gpio); - return -EINVAL; - } -} -EXPORT_SYMBOL(asic3_gpio_get_value); - -void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) -{ - u32 mask = ASIC3_GPIO_bit(gpio); - u32 bitval = 0; - if (val) - bitval = mask; - - switch (gpio >> 4) { - case ASIC3_GPIO_BANK_A: - asic3_set_gpio_a(asic, Out, mask, bitval); - return; - case ASIC3_GPIO_BANK_B: - asic3_set_gpio_b(asic, Out, mask, bitval); - return; - case ASIC3_GPIO_BANK_C: - asic3_set_gpio_c(asic, Out, mask, bitval); - return; - case ASIC3_GPIO_BANK_D: - asic3_set_gpio_d(asic, Out, mask, bitval); - return; - default: - printk(KERN_ERR "%s: invalid GPIO value 0x%x", - __func__, gpio); - return; - } -} -EXPORT_SYMBOL(asic3_gpio_set_value); static int asic3_gpio_probe(struct platform_device *pdev) { @@ -472,12 +530,14 @@ static int asic3_gpio_probe(struct platform_device *pdev) alt_function); } - return 0; + return gpiochip_add(&asic->gpio); } -static void asic3_gpio_remove(struct platform_device *pdev) +static int asic3_gpio_remove(struct platform_device *pdev) { - return; + struct asic3 *asic = platform_get_drvdata(pdev); + + return gpiochip_remove(&asic->gpio); } @@ -488,11 +548,13 @@ static int asic3_probe(struct platform_device *pdev) struct asic3 *asic; struct resource *mem; unsigned long clksel; - int ret; + int ret = 0; asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); - if (!asic) + if (asic == NULL) { + printk(KERN_ERR "kzalloc failed\n"); return -ENOMEM; + } spin_lock_init(&asic->lock); platform_set_drvdata(pdev, asic); @@ -502,14 +564,15 @@ static int asic3_probe(struct platform_device *pdev) if (!mem) { ret = -ENOMEM; printk(KERN_ERR "asic3: no MEM resource\n"); - goto err_out_1; + goto out_free; } + asic->mapping = ioremap(mem->start, PAGE_SIZE); if (!asic->mapping) { ret = -ENOMEM; printk(KERN_ERR "asic3: couldn't ioremap\n"); - goto err_out_1; + goto out_free; } asic->irq_base = pdata->irq_base; @@ -525,9 +588,21 @@ static int asic3_probe(struct platform_device *pdev) ret = asic3_irq_probe(pdev); if (ret < 0) { printk(KERN_ERR "asic3: couldn't probe IRQs\n"); - goto err_out_2; + goto out_unmap; + } + + asic->gpio.base = pdata->gpio_base; + asic->gpio.ngpio = ASIC3_NUM_GPIOS; + asic->gpio.get = asic3_gpio_get; + asic->gpio.set = asic3_gpio_set; + asic->gpio.direction_input = asic3_gpio_direction_input; + asic->gpio.direction_output = asic3_gpio_direction_output; + + ret = asic3_gpio_probe(pdev); + if (ret < 0) { + printk(KERN_ERR "GPIO probe failed\n"); + goto out_irq; } - asic3_gpio_probe(pdev); if (pdata->children) { int i; @@ -541,9 +616,13 @@ static int asic3_probe(struct platform_device *pdev) return 0; - err_out_2: + out_irq: + asic3_irq_remove(pdev); + + out_unmap: iounmap(asic->mapping); - err_out_1: + + out_free: kfree(asic); return ret; @@ -551,9 +630,12 @@ static int asic3_probe(struct platform_device *pdev) static int asic3_remove(struct platform_device *pdev) { + int ret; struct asic3 *asic = platform_get_drvdata(pdev); - asic3_gpio_remove(pdev); + ret = asic3_gpio_remove(pdev); + if (ret < 0) + return ret; asic3_irq_remove(pdev); asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); -- cgit v1.2.1 From 1effe5bc6cfbac4506d7944d68dadbd29ad62645 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 20 Jun 2008 11:07:39 +0200 Subject: mfd: asic3 children platform data removal Platform devices should be dynamically allocated, and each supported device should have its own platform data. For now we just remove this buggy code. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c70e7a5a5a90..dfee0a2ba167 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -604,14 +604,6 @@ static int asic3_probe(struct platform_device *pdev) goto out_irq; } - if (pdata->children) { - int i; - for (i = 0; i < pdata->n_children; i++) { - pdata->children[i]->dev.parent = &pdev->dev; - platform_device_register(pdata->children[i]); - } - } - printk(KERN_INFO "ASIC3 Core driver\n"); return 0; -- cgit v1.2.1 From 3b26bf17226f66bfd6cd4e36ac81f83fe994043a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 20 Jun 2008 11:09:51 +0200 Subject: mfd: New asic3 gpio configuration code The ASIC3 GPIO configuration code is a bit obscure and hardly readable. This patch changes it so that it is now more readable and understandable, by being more explicit. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 99 +++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index dfee0a2ba167..36b46ded1bff 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -465,69 +465,54 @@ static void asic3_gpio_set(struct gpio_chip *chip, return; } -static inline u32 asic3_get_gpio(struct asic3 *asic, unsigned int base, - unsigned int function) +static int asic3_gpio_probe(struct platform_device *pdev, + u16 *gpio_config, int num) { - return asic3_read_register(asic, base + function); -} - -static void asic3_set_gpio(struct asic3 *asic, unsigned int base, - unsigned int function, u32 bits, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&asic->lock, flags); - val |= (asic3_read_register(asic, base + function) & ~bits); - - asic3_write_register(asic, base + function, val); - spin_unlock_irqrestore(&asic->lock, flags); -} - -#define asic3_set_gpio_a(asic, fn, bits, val) \ - asic3_set_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn, bits, val) -#define asic3_set_gpio_b(asic, fn, bits, val) \ - asic3_set_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn, bits, val) -#define asic3_set_gpio_c(asic, fn, bits, val) \ - asic3_set_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn, bits, val) -#define asic3_set_gpio_d(asic, fn, bits, val) \ - asic3_set_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn, bits, val) - -#define asic3_set_gpio_banks(asic, fn, bits, pdata, field) \ - do { \ - asic3_set_gpio_a((asic), fn, (bits), (pdata)->gpio_a.field); \ - asic3_set_gpio_b((asic), fn, (bits), (pdata)->gpio_b.field); \ - asic3_set_gpio_c((asic), fn, (bits), (pdata)->gpio_c.field); \ - asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ - } while (0) - - -static int asic3_gpio_probe(struct platform_device *pdev) -{ - struct asic3_platform_data *pdata = pdev->dev.platform_data; struct asic3 *asic = platform_get_drvdata(pdev); + u16 alt_reg[ASIC3_NUM_GPIO_BANKS]; + u16 out_reg[ASIC3_NUM_GPIO_BANKS]; + u16 dir_reg[ASIC3_NUM_GPIO_BANKS]; + int i; + memset(alt_reg, 0, ASIC3_NUM_GPIO_BANKS); + memset(out_reg, 0, ASIC3_NUM_GPIO_BANKS); + memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS); + + /* Enable all GPIOs */ asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff); asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, Mask), 0xffff); asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, Mask), 0xffff); - asic3_set_gpio_a(asic, SleepMask, 0xffff, 0xffff); - asic3_set_gpio_b(asic, SleepMask, 0xffff, 0xffff); - asic3_set_gpio_c(asic, SleepMask, 0xffff, 0xffff); - asic3_set_gpio_d(asic, SleepMask, 0xffff, 0xffff); - - if (pdata) { - asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init); - asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir); - asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata, - sleep_mask); - asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out); - asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata, - batt_fault_out); - asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata, - sleep_conf); - asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata, - alt_function); + for (i = 0; i < num; i++) { + u8 alt, pin, dir, init, bank_num, bit_num; + u16 config = gpio_config[i]; + + pin = ASIC3_CONFIG_GPIO_PIN(config); + alt = ASIC3_CONFIG_GPIO_ALT(config); + dir = ASIC3_CONFIG_GPIO_DIR(config); + init = ASIC3_CONFIG_GPIO_INIT(config); + + bank_num = ASIC3_GPIO_TO_BANK(pin); + bit_num = ASIC3_GPIO_TO_BIT(pin); + + alt_reg[bank_num] |= (alt << bit_num); + out_reg[bank_num] |= (init << bit_num); + dir_reg[bank_num] |= (dir << bit_num); + } + + for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) { + asic3_write_register(asic, + ASIC3_BANK_TO_BASE(i) + + ASIC3_GPIO_Direction, + dir_reg[i]); + asic3_write_register(asic, + ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_Out, + out_reg[i]); + asic3_write_register(asic, + ASIC3_BANK_TO_BASE(i) + + ASIC3_GPIO_AltFunction, + alt_reg[i]); } return gpiochip_add(&asic->gpio); @@ -598,7 +583,9 @@ static int asic3_probe(struct platform_device *pdev) asic->gpio.direction_input = asic3_gpio_direction_input; asic->gpio.direction_output = asic3_gpio_direction_output; - ret = asic3_gpio_probe(pdev); + ret = asic3_gpio_probe(pdev, + pdata->gpio_config, + pdata->gpio_config_num); if (ret < 0) { printk(KERN_ERR "GPIO probe failed\n"); goto out_irq; -- cgit v1.2.1 From 24f4f2eef2714bddd6fdb823be53fc2ee69699e0 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 20 Jun 2008 11:11:19 +0200 Subject: mfd: use dev_* macros for asic3 debugging We replace the various printks, and use the dev_* macros instead. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 36b46ded1bff..1924eb01cc8c 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -145,8 +145,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) } if (iter >= MAX_ASIC_ISR_LOOPS) - printk(KERN_ERR "%s: interrupt processing overrun\n", - __func__); + dev_err(asic->dev, "interrupt processing overrun\n"); } static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) @@ -282,7 +281,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) * be careful to not unmask them if mask was also called. * Probably need internal state for mask. */ - printk(KERN_NOTICE "asic3: irq type not changed.\n"); + dev_notice(asic->dev, "irq type not changed\n"); } asic3_write_register(asic, bank + ASIC3_GPIO_LevelTrigger, level); @@ -376,8 +375,8 @@ static int asic3_gpio_direction(struct gpio_chip *chip, gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_Base) { - printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", - gpio_base, offset); + dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); return -EINVAL; } @@ -422,8 +421,8 @@ static int asic3_gpio_get(struct gpio_chip *chip, gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_Base) { - printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", - gpio_base, offset); + dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); return -EINVAL; } @@ -442,8 +441,8 @@ static void asic3_gpio_set(struct gpio_chip *chip, gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_Base) { - printk(KERN_ERR "Invalid base (0x%x) for gpio %d\n", - gpio_base, offset); + dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", + gpio_base, offset); return; } @@ -548,7 +547,7 @@ static int asic3_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { ret = -ENOMEM; - printk(KERN_ERR "asic3: no MEM resource\n"); + dev_err(asic->dev, "no MEM resource\n"); goto out_free; } @@ -556,7 +555,7 @@ static int asic3_probe(struct platform_device *pdev) asic->mapping = ioremap(mem->start, PAGE_SIZE); if (!asic->mapping) { ret = -ENOMEM; - printk(KERN_ERR "asic3: couldn't ioremap\n"); + dev_err(asic->dev, "Couldn't ioremap\n"); goto out_free; } @@ -572,7 +571,7 @@ static int asic3_probe(struct platform_device *pdev) ret = asic3_irq_probe(pdev); if (ret < 0) { - printk(KERN_ERR "asic3: couldn't probe IRQs\n"); + dev_err(asic->dev, "Couldn't probe IRQs\n"); goto out_unmap; } @@ -587,11 +586,11 @@ static int asic3_probe(struct platform_device *pdev) pdata->gpio_config, pdata->gpio_config_num); if (ret < 0) { - printk(KERN_ERR "GPIO probe failed\n"); + dev_err(asic->dev, "GPIO probe failed\n"); goto out_irq; } - printk(KERN_INFO "ASIC3 Core driver\n"); + dev_info(asic->dev, "ASIC3 Core driver\n"); return 0; -- cgit v1.2.1 From 3b8139f8b1457af7b5295d97050b3f9a2545a17a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 20 Jun 2008 11:12:21 +0200 Subject: mfd: Use uppercase only for asic3 macros and defines Let's be consistent and use uppercase only, for both macro and defines. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 88 ++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 1924eb01cc8c..9931581b08a1 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -55,8 +55,8 @@ static inline u32 asic3_read_register(struct asic3 *asic, /* IRQs */ #define MAX_ASIC_ISR_LOOPS 20 -#define ASIC3_GPIO_Base_INCR \ - (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base) +#define ASIC3_GPIO_BASE_INCR \ + (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE) static void asic3_irq_flip_edge(struct asic3 *asic, u32 base, int bit) @@ -66,10 +66,10 @@ static void asic3_irq_flip_edge(struct asic3 *asic, spin_lock_irqsave(&asic->lock, flags); edge = asic3_read_register(asic, - base + ASIC3_GPIO_EdgeTrigger); + base + ASIC3_GPIO_EDGE_TRIGGER); edge ^= bit; asic3_write_register(asic, - base + ASIC3_GPIO_EdgeTrigger, edge); + base + ASIC3_GPIO_EDGE_TRIGGER, edge); spin_unlock_irqrestore(&asic->lock, flags); } @@ -89,7 +89,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) spin_lock_irqsave(&asic->lock, flags); status = asic3_read_register(asic, - ASIC3_OFFSET(INTR, PIntStat)); + ASIC3_OFFSET(INTR, P_INT_STAT)); spin_unlock_irqrestore(&asic->lock, flags); /* Check all ten register bits */ @@ -101,17 +101,17 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) if (status & (1 << bank)) { unsigned long base, istat; - base = ASIC3_GPIO_A_Base - + bank * ASIC3_GPIO_Base_INCR; + base = ASIC3_GPIO_A_BASE + + bank * ASIC3_GPIO_BASE_INCR; spin_lock_irqsave(&asic->lock, flags); istat = asic3_read_register(asic, base + - ASIC3_GPIO_IntStatus); + ASIC3_GPIO_INT_STATUS); /* Clearing IntStatus */ asic3_write_register(asic, base + - ASIC3_GPIO_IntStatus, 0); + ASIC3_GPIO_INT_STATUS, 0); spin_unlock_irqrestore(&asic->lock, flags); for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { @@ -154,7 +154,7 @@ static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) n = (irq - asic->irq_base) >> 4; - return (n * (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base)); + return (n * (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE)); } static inline int asic3_irq_to_index(struct asic3 *asic, int irq) @@ -172,9 +172,9 @@ static void asic3_mask_gpio_irq(unsigned int irq) index = asic3_irq_to_index(asic, irq); spin_lock_irqsave(&asic->lock, flags); - val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); + val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); val |= 1 << index; - asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); + asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); spin_unlock_irqrestore(&asic->lock, flags); } @@ -186,15 +186,15 @@ static void asic3_mask_irq(unsigned int irq) spin_lock_irqsave(&asic->lock, flags); regval = asic3_read_register(asic, - ASIC3_INTR_Base + - ASIC3_INTR_IntMask); + ASIC3_INTR_BASE + + ASIC3_INTR_INT_MASK); regval &= ~(ASIC3_INTMASK_MASK0 << (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); asic3_write_register(asic, - ASIC3_INTR_Base + - ASIC3_INTR_IntMask, + ASIC3_INTR_BASE + + ASIC3_INTR_INT_MASK, regval); spin_unlock_irqrestore(&asic->lock, flags); } @@ -209,9 +209,9 @@ static void asic3_unmask_gpio_irq(unsigned int irq) index = asic3_irq_to_index(asic, irq); spin_lock_irqsave(&asic->lock, flags); - val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); + val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); val &= ~(1 << index); - asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); + asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); spin_unlock_irqrestore(&asic->lock, flags); } @@ -223,15 +223,15 @@ static void asic3_unmask_irq(unsigned int irq) spin_lock_irqsave(&asic->lock, flags); regval = asic3_read_register(asic, - ASIC3_INTR_Base + - ASIC3_INTR_IntMask); + ASIC3_INTR_BASE + + ASIC3_INTR_INT_MASK); regval |= (ASIC3_INTMASK_MASK0 << (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); asic3_write_register(asic, - ASIC3_INTR_Base + - ASIC3_INTR_IntMask, + ASIC3_INTR_BASE + + ASIC3_INTR_INT_MASK, regval); spin_unlock_irqrestore(&asic->lock, flags); } @@ -249,11 +249,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) spin_lock_irqsave(&asic->lock, flags); level = asic3_read_register(asic, - bank + ASIC3_GPIO_LevelTrigger); + bank + ASIC3_GPIO_LEVEL_TRIGGER); edge = asic3_read_register(asic, - bank + ASIC3_GPIO_EdgeTrigger); + bank + ASIC3_GPIO_EDGE_TRIGGER); trigger = asic3_read_register(asic, - bank + ASIC3_GPIO_TriggerType); + bank + ASIC3_GPIO_TRIGGER_TYPE); asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; if (type == IRQT_RISING) { @@ -283,11 +283,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) */ dev_notice(asic->dev, "irq type not changed\n"); } - asic3_write_register(asic, bank + ASIC3_GPIO_LevelTrigger, + asic3_write_register(asic, bank + ASIC3_GPIO_LEVEL_TRIGGER, level); - asic3_write_register(asic, bank + ASIC3_GPIO_EdgeTrigger, + asic3_write_register(asic, bank + ASIC3_GPIO_EDGE_TRIGGER, edge); - asic3_write_register(asic, bank + ASIC3_GPIO_TriggerType, + asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE, trigger); spin_unlock_irqrestore(&asic->lock, flags); return 0; @@ -336,7 +336,7 @@ static int asic3_irq_probe(struct platform_device *pdev) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - asic3_write_register(asic, ASIC3_OFFSET(INTR, IntMask), + asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK), ASIC3_INTMASK_GINTMASK); set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); @@ -374,7 +374,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip, asic = container_of(chip, struct asic3, gpio); gpio_base = ASIC3_GPIO_TO_BASE(offset); - if (gpio_base > ASIC3_GPIO_D_Base) { + if (gpio_base > ASIC3_GPIO_D_BASE) { dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", gpio_base, offset); return -EINVAL; @@ -382,7 +382,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip, spin_lock_irqsave(&asic->lock, flags); - out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_Direction); + out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION); /* Input is 0, Output is 1 */ if (out) @@ -390,7 +390,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip, else out_reg &= ~mask; - asic3_write_register(asic, gpio_base + ASIC3_GPIO_Direction, out_reg); + asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg); spin_unlock_irqrestore(&asic->lock, flags); @@ -420,13 +420,13 @@ static int asic3_gpio_get(struct gpio_chip *chip, asic = container_of(chip, struct asic3, gpio); gpio_base = ASIC3_GPIO_TO_BASE(offset); - if (gpio_base > ASIC3_GPIO_D_Base) { + if (gpio_base > ASIC3_GPIO_D_BASE) { dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", gpio_base, offset); return -EINVAL; } - return asic3_read_register(asic, gpio_base + ASIC3_GPIO_Status) & mask; + return asic3_read_register(asic, gpio_base + ASIC3_GPIO_STATUS) & mask; } static void asic3_gpio_set(struct gpio_chip *chip, @@ -440,7 +440,7 @@ static void asic3_gpio_set(struct gpio_chip *chip, asic = container_of(chip, struct asic3, gpio); gpio_base = ASIC3_GPIO_TO_BASE(offset); - if (gpio_base > ASIC3_GPIO_D_Base) { + if (gpio_base > ASIC3_GPIO_D_BASE) { dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", gpio_base, offset); return; @@ -450,14 +450,14 @@ static void asic3_gpio_set(struct gpio_chip *chip, spin_lock_irqsave(&asic->lock, flags); - out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_Out); + out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT); if (value) out_reg |= mask; else out_reg &= ~mask; - asic3_write_register(asic, gpio_base + ASIC3_GPIO_Out, out_reg); + asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg); spin_unlock_irqrestore(&asic->lock, flags); @@ -478,10 +478,10 @@ static int asic3_gpio_probe(struct platform_device *pdev, memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS); /* Enable all GPIOs */ - asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); - asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff); - asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, Mask), 0xffff); - asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, Mask), 0xffff); + asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff); + asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, MASK), 0xffff); + asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, MASK), 0xffff); + asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, MASK), 0xffff); for (i = 0; i < num; i++) { u8 alt, pin, dir, init, bank_num, bit_num; @@ -503,14 +503,14 @@ static int asic3_gpio_probe(struct platform_device *pdev, for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) { asic3_write_register(asic, ASIC3_BANK_TO_BASE(i) + - ASIC3_GPIO_Direction, + ASIC3_GPIO_DIRECTION, dir_reg[i]); asic3_write_register(asic, - ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_Out, + ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_OUT, out_reg[i]); asic3_write_register(asic, ASIC3_BANK_TO_BASE(i) + - ASIC3_GPIO_AltFunction, + ASIC3_GPIO_ALT_FUNCTION, alt_reg[i]); } -- cgit v1.2.1 From 065032f61bd9acdb843766da3149de12eaf87c0b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 21 Jun 2008 00:51:38 +0200 Subject: mfd: move asic3 probe functions into __init section Potentially free some memory by moving the _probe functions into __init. Signed-off-by: Philipp Zabel Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 9931581b08a1..80dc3334e82f 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -308,7 +308,7 @@ static struct irq_chip asic3_irq_chip = { .unmask = asic3_unmask_irq, }; -static int asic3_irq_probe(struct platform_device *pdev) +static int __init asic3_irq_probe(struct platform_device *pdev) { struct asic3 *asic = platform_get_drvdata(pdev); unsigned long clksel = 0; @@ -464,8 +464,8 @@ static void asic3_gpio_set(struct gpio_chip *chip, return; } -static int asic3_gpio_probe(struct platform_device *pdev, - u16 *gpio_config, int num) +static __init int asic3_gpio_probe(struct platform_device *pdev, + u16 *gpio_config, int num) { struct asic3 *asic = platform_get_drvdata(pdev); u16 alt_reg[ASIC3_NUM_GPIO_BANKS]; @@ -526,7 +526,7 @@ static int asic3_gpio_remove(struct platform_device *pdev) /* Core */ -static int asic3_probe(struct platform_device *pdev) +static int __init asic3_probe(struct platform_device *pdev) { struct asic3_platform_data *pdata = pdev->dev.platform_data; struct asic3 *asic; @@ -633,7 +633,6 @@ static struct platform_driver asic3_device_driver = { .driver = { .name = "asic3", }, - .probe = asic3_probe, .remove = __devexit_p(asic3_remove), .shutdown = asic3_shutdown, }; @@ -641,7 +640,7 @@ static struct platform_driver asic3_device_driver = { static int __init asic3_init(void) { int retval = 0; - retval = platform_driver_register(&asic3_device_driver); + retval = platform_driver_probe(&asic3_device_driver, asic3_probe); return retval; } -- cgit v1.2.1 From 786bef3768a6ea1070526983b20e316c4eacd854 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 24 Jun 2008 01:31:24 +0200 Subject: mfd: fix asic3 config array initialisation Our memset length was incorrect. Tested-by: Philipp Zabel Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 80dc3334e82f..50c773c4d60a 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -473,9 +473,9 @@ static __init int asic3_gpio_probe(struct platform_device *pdev, u16 dir_reg[ASIC3_NUM_GPIO_BANKS]; int i; - memset(alt_reg, 0, ASIC3_NUM_GPIO_BANKS); - memset(out_reg, 0, ASIC3_NUM_GPIO_BANKS); - memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS); + memzero(alt_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); + memzero(out_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); + memzero(dir_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); /* Enable all GPIOs */ asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff); -- cgit v1.2.1 From 30250b457f30ca655d37ad1a1587221ff6eefc91 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 24 Jun 2008 23:37:09 +0200 Subject: mfd: asic3 should depend on gpiolib Now that asic3 implements the gpiolib API, it should depend on it at build time. Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ae96bd6242f2..260bade0a5ec 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -17,7 +17,7 @@ config MFD_SM501 config MFD_ASIC3 bool "Support for Compaq ASIC3" - depends on GENERIC_HARDIRQS && ARM + depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM ---help--- This driver supports the ASIC3 multifunction chip found on many PDAs (mainly iPAQ and HTC based ones) -- cgit v1.2.1 From de0d23c12c42317c273919b597f6822af2102e55 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 3 Jul 2008 11:08:27 +0200 Subject: mfd: fix the asic3 irq demux code Wrong irq numbers were given to desc->handle_irq, which on some devices caused endless loops (asic3_irq_demux calling itself, basically). Signed-off-by: Philipp Zabel Signed-off-by: Samuel Ortiz Signed-off-by: Andrew Morton --- drivers/mfd/asic3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 50c773c4d60a..f2fb233b0ff3 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -137,7 +137,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { /* They start at bit 4 and go up */ if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { - desc = irq_desc + + i; + desc = irq_desc + asic->irq_base + i; desc->handle_irq(asic->irq_base + i, desc); } -- cgit v1.2.1 From 99cdb0c8c5e0e43652d25951a85bac82a1231591 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 10 Jul 2008 02:17:02 +0200 Subject: mfd: let asic3 use mem resource instead of bus_shift The bus_shift parameter in platform_data is not needed as we can tell the driver with the IOMEM_RESOURCE whether the ASIC is located on a 16bit or 32bit memory bus. The htc-egpio driver uses a more descriptive bus_width parameter, but for drivers where the register map size fixed, we don't even need this. Signed-off-by: Philipp Zabel Signed-off-by: Samuel Ortiz --- drivers/mfd/asic3.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index f2fb233b0ff3..3b870e7fb3e1 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -313,6 +313,7 @@ static int __init asic3_irq_probe(struct platform_device *pdev) struct asic3 *asic = platform_get_drvdata(pdev); unsigned long clksel = 0; unsigned int irq, irq_base; + int map_size; asic->irq_nr = platform_get_irq(pdev, 0); if (asic->irq_nr < 0) @@ -551,8 +552,8 @@ static int __init asic3_probe(struct platform_device *pdev) goto out_free; } - - asic->mapping = ioremap(mem->start, PAGE_SIZE); + map_size = mem->end - mem->start + 1; + asic->mapping = ioremap(mem->start, map_size); if (!asic->mapping) { ret = -ENOMEM; dev_err(asic->dev, "Couldn't ioremap\n"); @@ -561,10 +562,8 @@ static int __init asic3_probe(struct platform_device *pdev) asic->irq_base = pdata->irq_base; - if (pdata && pdata->bus_shift) - asic->bus_shift = 2 - pdata->bus_shift; - else - asic->bus_shift = 0; + /* calculate bus shift from mem resource */ + asic->bus_shift = 2 - (map_size >> 12); clksel = 0; asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); -- cgit v1.2.1