From 41039506a7ad313405bf26858e2a0cf2230f7a82 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 11:47:14 +0100 Subject: gpio/nomadik: move the Nomadik GPIO header This takes the Nomadik GPIO header out of the plat-nomadik directory and pushes it down into where it belongs. Signed-off-by: Linus Walleij --- include/linux/gpio/nomadik.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 include/linux/gpio/nomadik.h (limited to 'include') diff --git a/include/linux/gpio/nomadik.h b/include/linux/gpio/nomadik.h new file mode 100644 index 00000000000..0cfe96ece47 --- /dev/null +++ b/include/linux/gpio/nomadik.h @@ -0,0 +1,84 @@ +/* + * Structures and registers for GPIO access in the Nomadik SoC + * + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini + * + * 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. + */ +#ifndef __GPIO_NOMADIK_H +#define __GPIO_NOMADIK_H + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +/* Pull up/down values */ +enum nmk_gpio_pull { + NMK_GPIO_PULL_NONE, + NMK_GPIO_PULL_UP, + NMK_GPIO_PULL_DOWN, +}; + +/* Sleep mode */ +enum nmk_gpio_slpm { + NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, +}; + +extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); +extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); +extern int nmk_gpio_set_mode(int gpio, int gpio_mode); +extern int nmk_gpio_get_mode(int gpio); + +extern void nmk_gpio_wakeups_suspend(void); +extern void nmk_gpio_wakeups_resume(void); + +extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int num_gpio; + u32 (*get_secondary_status)(unsigned int bank); + void (*set_ioforce)(bool enable); + bool supports_sleepmode; +}; + +#endif -- cgit v1.2.3 From d3e1ba36c61189658ef967d3f3101d69fae088c2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 16 Mar 2011 15:25:23 +0530 Subject: gpio/nomadik: disable clocks when unused The GPIO clock is required for register access and interrupt detection. When interrupt detection is not required on any of the pin in a block, the block's clock can be disabled when the registers are not being accessed. Signed-off-by: Rabin Vincent Reviewed-by: Rickard Andersson Reviewed-by: Jonas Aberg [Adjust for new IRQ chip core code, use only local functions] Signed-off-by: Linus Walleij --- drivers/gpio/gpio-nomadik.c | 120 ++++++++++++++++++++++++++++++++++++++++--- include/linux/gpio/nomadik.h | 3 ++ 2 files changed, 116 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index efc75605b64..4300b9fb4e8 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -276,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) if (!chip) break; + clk_enable(chip->clk); + slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); writel(temp, chip->addr + NMK_GPIO_SLPC); } @@ -292,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) break; writel(slpm[i], chip->addr + NMK_GPIO_SLPC); + + clk_disable(chip->clk); } } @@ -336,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) break; } + clk_enable(nmk_chip->clk); spin_lock(&nmk_chip->lock); __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, cfgs[i], sleep, glitch ? slpm : NULL); spin_unlock(&nmk_chip->lock); + clk_disable(nmk_chip->clk); } if (glitch) @@ -424,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) if (!nmk_chip) return -EINVAL; + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); @@ -431,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + clk_disable(nmk_chip->clk); return 0; } @@ -457,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) if (!nmk_chip) return -EINVAL; + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_chip->lock, flags); __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); spin_unlock_irqrestore(&nmk_chip->lock, flags); + clk_disable(nmk_chip->clk); return 0; } @@ -483,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) if (!nmk_chip) return -EINVAL; + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_chip->lock, flags); __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); spin_unlock_irqrestore(&nmk_chip->lock, flags); + clk_disable(nmk_chip->clk); return 0; } @@ -502,9 +514,13 @@ int nmk_gpio_get_mode(int gpio) bit = 1 << (gpio - nmk_chip->chip.base); + clk_enable(nmk_chip->clk); + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; + clk_disable(nmk_chip->clk); + return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); } EXPORT_SYMBOL(nmk_gpio_get_mode); @@ -525,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d) nmk_chip = irq_data_get_irq_chip_data(d); if (!nmk_chip) return; + + clk_enable(nmk_chip->clk); writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); + clk_disable(nmk_chip->clk); } enum nmk_gpio_irq_type { @@ -591,6 +610,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) else nmk_chip->enabled &= ~bitmask; + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); @@ -601,6 +621,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + clk_disable(nmk_chip->clk); return 0; } @@ -628,6 +649,7 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) return -EINVAL; bitmask = nmk_gpio_get_bitmask(gpio); + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); @@ -641,13 +663,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + clk_disable(nmk_chip->clk); return 0; } static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) { - bool enabled, wake = irqd_is_wakeup_set(d); + bool enabled; + bool wake = irqd_is_wakeup_set(d); int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; @@ -664,10 +688,10 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) if (type & IRQ_TYPE_LEVEL_LOW) return -EINVAL; - enabled = nmk_chip->enabled & bitmask; - + clk_enable(nmk_chip->clk); spin_lock_irqsave(&nmk_chip->lock, flags); + enabled = !!(nmk_chip->enabled & bitmask); if (enabled) __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); @@ -689,10 +713,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); spin_unlock_irqrestore(&nmk_chip->lock, flags); + clk_disable(nmk_chip->clk); + + return 0; +} + +static unsigned int nmk_gpio_irq_startup(struct irq_data *d) +{ + struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); + clk_enable(nmk_chip->clk); + nmk_gpio_irq_unmask(d); return 0; } +static void nmk_gpio_irq_shutdown(struct irq_data *d) +{ + struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); + + nmk_gpio_irq_mask(d); + clk_disable(nmk_chip->clk); +} + static struct irq_chip nmk_gpio_irq_chip = { .name = "Nomadik-GPIO", .irq_ack = nmk_gpio_irq_ack, @@ -700,6 +742,8 @@ static struct irq_chip nmk_gpio_irq_chip = { .irq_unmask = nmk_gpio_irq_unmask, .irq_set_type = nmk_gpio_irq_set_type, .irq_set_wake = nmk_gpio_irq_set_wake, + .irq_startup = nmk_gpio_irq_startup, + .irq_shutdown = nmk_gpio_irq_shutdown, }; static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, @@ -726,7 +770,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); - u32 status = readl(nmk_chip->addr + NMK_GPIO_IS); + u32 status; + + clk_enable(nmk_chip->clk); + status = readl(nmk_chip->addr + NMK_GPIO_IS); + clk_disable(nmk_chip->clk); __nmk_gpio_irq_handler(irq, desc, status); } @@ -772,7 +820,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + clk_enable(nmk_chip->clk); + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); + + clk_disable(nmk_chip->clk); + return 0; } @@ -781,8 +834,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); u32 bit = 1 << offset; + int value; + + clk_enable(nmk_chip->clk); + + value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; - return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; + clk_disable(nmk_chip->clk); + + return value; } static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, @@ -791,7 +851,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + clk_enable(nmk_chip->clk); + __nmk_gpio_set_output(nmk_chip, offset, val); + + clk_disable(nmk_chip->clk); } static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, @@ -800,8 +864,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + clk_enable(nmk_chip->clk); + __nmk_gpio_make_output(nmk_chip, offset, val); + clk_disable(nmk_chip->clk); + return 0; } @@ -832,6 +900,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) [NMK_GPIO_ALT_C] = "altC", }; + clk_enable(nmk_chip->clk); + for (i = 0; i < chip->ngpio; i++, gpio++) { const char *label = gpiochip_is_requested(chip, i); bool pull; @@ -876,6 +946,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) seq_printf(s, "\n"); } + + clk_disable(nmk_chip->clk); } #else @@ -893,6 +965,34 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; +void nmk_gpio_clocks_enable(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + continue; + + clk_enable(chip->clk); + } +} + +void nmk_gpio_clocks_disable(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + continue; + + clk_disable(chip->clk); + } +} + /* * Called from the suspend/resume path to only keep the real wakeup interrupts * (those that have had set_irq_wake() called on them) as wakeup interrupts, @@ -912,6 +1012,8 @@ void nmk_gpio_wakeups_suspend(void) if (!chip) break; + clk_enable(chip->clk); + chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); @@ -926,6 +1028,8 @@ void nmk_gpio_wakeups_suspend(void) /* 0 -> wakeup enable */ writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); } + + clk_disable(chip->clk); } } @@ -939,11 +1043,15 @@ void nmk_gpio_wakeups_resume(void) if (!chip) break; + clk_enable(chip->clk); + writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); if (chip->sleepmode) writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); + + clk_disable(chip->clk); } } @@ -1010,8 +1118,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) goto out_release; } - clk_enable(clk); - nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { ret = -ENOMEM; diff --git a/include/linux/gpio/nomadik.h b/include/linux/gpio/nomadik.h index 0cfe96ece47..cc956d1eb81 100644 --- a/include/linux/gpio/nomadik.h +++ b/include/linux/gpio/nomadik.h @@ -66,6 +66,9 @@ extern int nmk_gpio_get_mode(int gpio); extern void nmk_gpio_wakeups_suspend(void); extern void nmk_gpio_wakeups_resume(void); +extern void nmk_gpio_clocks_enable(void); +extern void nmk_gpio_clocks_disable(void); + extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); /* -- cgit v1.2.3 From db98895008316a0b7f88e7d8d0f397306acbdd1a Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Thu, 15 Sep 2011 15:51:15 +0200 Subject: gpio: ab8500: make pins configurable Make it possible to set the pin configuration either as gpio or specific functionality. Change-Id: I884dc5f17d17b3d5352d6035648417cd83d50a62 Signed-off-by: Bengt Jonsson Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32098 Tested-by: Jonas ABERG --- drivers/gpio/gpio-ab8500.c | 63 +++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/ab8500/gpio.h | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c index db40acb9c3e..c3c7c5a86ba 100644 --- a/drivers/gpio/gpio-ab8500.c +++ b/drivers/gpio/gpio-ab8500.c @@ -495,6 +495,69 @@ static int __devexit ab8500_gpio_remove(struct platform_device *pdev) return 0; } +/* + * ab8500_gpio_config_select() + * + * Configure functionality of pin, either specific use or GPIO. + * @dev: device pointer + * @gpio: gpio number + * @gpio_select: true if the pin should be used as GPIO + */ +int ab8500_gpio_config_select(struct device *dev, + enum ab8500_pin gpio, bool gpio_select) +{ + u8 offset = gpio - AB8500_PIN_GPIO1; + u8 reg = AB8500_GPIO_SEL1_REG + (offset / 8); + u8 pos = offset % 8; + u8 val = gpio_select ? 1 : 0; + int ret; + + ret = abx500_mask_and_set_register_interruptible(dev, + AB8500_MISC, reg, 1 << pos, val << pos); + if (ret < 0) + dev_err(dev, "%s write failed\n", __func__); + + dev_vdbg(dev, "%s (bank, addr, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + __func__, AB8500_MISC, reg, 1 << pos, val << pos); + + return ret; +} + +/* + * ab8500_gpio_config_get_select() + * + * Read currently configured functionality, either specific use or GPIO. + * @dev: device pointer + * @gpio: gpio number + * @gpio_select: pointer to pin selection status + */ +int ab8500_gpio_config_get_select(struct device *dev, + enum ab8500_pin gpio, bool *gpio_select) +{ + u8 offset = gpio - AB8500_PIN_GPIO1; + u8 reg = AB8500_GPIO_SEL1_REG + (offset / 8); + u8 pos = offset % 8; + u8 val; + int ret; + + ret = abx500_get_register_interruptible(dev, + AB8500_MISC, reg, &val); + if (ret < 0) { + dev_err(dev, "%s read failed\n", __func__); + return ret; + } + + if (val & (1 << pos)) + *gpio_select = true; + else + *gpio_select = false; + + dev_vdbg(dev, "%s (bank, addr, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + __func__, AB8500_MISC, reg, 1 << pos, val); + + return 0; +} + static struct platform_driver ab8500_gpio_driver = { .driver = { .name = "ab8500-gpio", diff --git a/include/linux/mfd/ab8500/gpio.h b/include/linux/mfd/ab8500/gpio.h index 488a8c920a2..df49f2d6036 100644 --- a/include/linux/mfd/ab8500/gpio.h +++ b/include/linux/mfd/ab8500/gpio.h @@ -18,4 +18,55 @@ struct ab8500_gpio_platform_data { u8 config_reg[7]; }; +enum ab8500_pin { + AB8500_PIN_GPIO1 = 0, + AB8500_PIN_GPIO2, + AB8500_PIN_GPIO3, + AB8500_PIN_GPIO4, + AB8500_PIN_GPIO5, + AB8500_PIN_GPIO6, + AB8500_PIN_GPIO7, + AB8500_PIN_GPIO8, + AB8500_PIN_GPIO9, + AB8500_PIN_GPIO10, + AB8500_PIN_GPIO11, + AB8500_PIN_GPIO12, + AB8500_PIN_GPIO13, + AB8500_PIN_GPIO14, + AB8500_PIN_GPIO15, + AB8500_PIN_GPIO16, + AB8500_PIN_GPIO17, + AB8500_PIN_GPIO18, + AB8500_PIN_GPIO19, + AB8500_PIN_GPIO20, + AB8500_PIN_GPIO21, + AB8500_PIN_GPIO22, + AB8500_PIN_GPIO23, + AB8500_PIN_GPIO24, + AB8500_PIN_GPIO25, + AB8500_PIN_GPIO26, + AB8500_PIN_GPIO27, + AB8500_PIN_GPIO28, + AB8500_PIN_GPIO29, + AB8500_PIN_GPIO30, + AB8500_PIN_GPIO31, + AB8500_PIN_GPIO32, + AB8500_PIN_GPIO33, + AB8500_PIN_GPIO34, + AB8500_PIN_GPIO35, + AB8500_PIN_GPIO36, + AB8500_PIN_GPIO37, + AB8500_PIN_GPIO38, + AB8500_PIN_GPIO39, + AB8500_PIN_GPIO40, + AB8500_PIN_GPIO41, + AB8500_PIN_GPIO42, +}; + +int ab8500_gpio_config_select(struct device *dev, + enum ab8500_pin gpio, bool gpio_select); + +int ab8500_gpio_config_get_select(struct device *dev, + enum ab8500_pin gpio, bool *gpio_select); + #endif /* _AB8500_GPIO_H */ -- cgit v1.2.3 From bb42437bc56efa219b8159845809ad3ce26a7cf2 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Mon, 19 Sep 2011 15:38:51 +0200 Subject: gpio: ab8500: allow direction and pullups configuration This patch extends the the platform data to include gpio direction and pullups configurations. These configurations are applied during probe(). Change-Id: I0c742615cb31ff83671489cce5fb742bc0e10902 Signed-off-by: Bibek Basu Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32113 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- drivers/gpio/gpio-ab8500.c | 12 ++++++++++++ include/linux/mfd/ab8500/gpio.h | 2 ++ 2 files changed, 14 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c index 77fe1d765ef..dd95cb3c32d 100644 --- a/drivers/gpio/gpio-ab8500.c +++ b/drivers/gpio/gpio-ab8500.c @@ -445,6 +445,18 @@ static int __devinit ab8500_gpio_probe(struct platform_device *pdev) pdata->config_reg[i]); if (ret < 0) goto out_free; + + ret = abx500_set_register_interruptible(ab8500_gpio->dev, + AB8500_MISC, i + AB8500_GPIO_DIR1_REG, + pdata->config_direction[i]); + if (ret < 0) + goto out_free; + + ret = abx500_set_register_interruptible(ab8500_gpio->dev, + AB8500_MISC, i + AB8500_GPIO_PUD1_REG, + pdata->config_pullups[i]); + if (ret < 0) + goto out_free; } ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC, AB8500_GPIO_ALTFUN_REG, diff --git a/include/linux/mfd/ab8500/gpio.h b/include/linux/mfd/ab8500/gpio.h index df49f2d6036..20b841ab81e 100644 --- a/include/linux/mfd/ab8500/gpio.h +++ b/include/linux/mfd/ab8500/gpio.h @@ -16,6 +16,8 @@ struct ab8500_gpio_platform_data { int gpio_base; u32 irq_base; u8 config_reg[7]; + u8 config_direction[6]; + u8 config_pullups[6]; }; enum ab8500_pin { -- cgit v1.2.3 From dab7d58def763dda0dcc9965e77e86dea46d8d55 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Mon, 19 Sep 2011 16:15:11 +0200 Subject: gpio: ab8500: add api to enable pulldown Change-Id: Ia8c31da2cbfef4f8cb5f6e0ccd5b70dcf0bbd9de Signed-off-by: Bibek Basu Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32114 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- drivers/gpio/gpio-ab8500.c | 17 +++++++++++++++++ include/linux/mfd/ab8500/gpio.h | 3 +++ 2 files changed, 20 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c index dd95cb3c32d..b71bb723c0e 100644 --- a/drivers/gpio/gpio-ab8500.c +++ b/drivers/gpio/gpio-ab8500.c @@ -507,6 +507,23 @@ static int __devexit ab8500_gpio_remove(struct platform_device *pdev) return 0; } +int ab8500_config_pulldown(struct device *dev, + enum ab8500_pin gpio, bool enable) +{ + u8 offset = gpio - AB8500_PIN_GPIO1; + u8 pos = offset % 8; + u8 val = enable ? 0 : 1; + u8 reg = AB8500_GPIO_PUD1_REG + (offset / 8); + int ret; + + ret = abx500_mask_and_set_register_interruptible(dev, + AB8500_MISC, reg, 1 << pos, val << pos); + if (ret < 0) + dev_err(dev, "%s write failed\n", __func__); + return ret; +} +EXPORT_SYMBOL(ab8500_config_pulldown); + /* * ab8500_gpio_config_select() * diff --git a/include/linux/mfd/ab8500/gpio.h b/include/linux/mfd/ab8500/gpio.h index 20b841ab81e..e5779b7418e 100644 --- a/include/linux/mfd/ab8500/gpio.h +++ b/include/linux/mfd/ab8500/gpio.h @@ -65,6 +65,9 @@ enum ab8500_pin { AB8500_PIN_GPIO42, }; +int ab8500_config_pulldown(struct device *dev, + enum ab8500_pin gpio, bool enable); + int ab8500_gpio_config_select(struct device *dev, enum ab8500_pin gpio, bool gpio_select); -- cgit v1.2.3 From 905490fc2f97a9b7465d453e629670841097550b Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 27 Sep 2011 18:00:35 +0200 Subject: gpio: ab8500: use gpio base number defined for the platform Change-Id: I84da2cbc3a482d0c54ec489874fc040d8c79eda8 Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32347 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- include/linux/mfd/ab8500/gpio.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mfd/ab8500/gpio.h b/include/linux/mfd/ab8500/gpio.h index e5779b7418e..d88e3025317 100644 --- a/include/linux/mfd/ab8500/gpio.h +++ b/include/linux/mfd/ab8500/gpio.h @@ -8,6 +8,8 @@ #ifndef _AB8500_GPIO_H #define _AB8500_GPIO_H +#include + /* * Platform data to register a block: only the initial gpio/irq number. */ @@ -21,7 +23,7 @@ struct ab8500_gpio_platform_data { }; enum ab8500_pin { - AB8500_PIN_GPIO1 = 0, + AB8500_PIN_GPIO1 = AB8500_GPIO_BASE, AB8500_PIN_GPIO2, AB8500_PIN_GPIO3, AB8500_PIN_GPIO4, -- cgit v1.2.3 From a88b42179a216f54ea9150b239b65f84e81079fd Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 28 Sep 2011 15:49:11 +0530 Subject: gpio: nomadik: support low EMI mode ST-Ericsson ID: 345488 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I88f6c92f199e52186acf6899e14ed399aba657ac Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32354 Reviewed-by: Srinidhi KASAGAR --- drivers/gpio/gpio-nomadik.c | 25 +++++++++++++++++++++++++ include/linux/gpio/nomadik.h | 1 + 2 files changed, 26 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 284d696a21f..e7512b6cd1f 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -61,6 +61,7 @@ struct nmk_gpio_chip { u32 rimsc; u32 fimsc; u32 pull_up; + u32 lowemi; }; static struct nmk_gpio_chip * @@ -125,6 +126,24 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, } } +static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip, + unsigned offset, bool lowemi) +{ + u32 bit = BIT(offset); + bool enabled = nmk_chip->lowemi & bit; + + if (lowemi == enabled) + return; + + if (lowemi) + nmk_chip->lowemi |= bit; + else + nmk_chip->lowemi &= ~bit; + + writel_relaxed(nmk_chip->lowemi, + nmk_chip->addr + NMK_GPIO_LOWEMI); +} + static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, unsigned offset) { @@ -269,6 +288,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, __nmk_gpio_set_pull(nmk_chip, offset, pull); } + __nmk_gpio_set_lowemi(nmk_chip, offset, PIN_LOWEMI(cfg)); + /* * If the pin is switching to altfunc, and there was an interrupt * installed on it which has been lazy disabled, actually mask the @@ -1181,6 +1202,10 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) chip->dev = &dev->dev; chip->owner = THIS_MODULE; + clk_enable(nmk_chip->clk); + nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); + clk_disable(nmk_chip->clk); + ret = gpiochip_add(&nmk_chip->chip); if (ret) goto out_free; diff --git a/include/linux/gpio/nomadik.h b/include/linux/gpio/nomadik.h index cc956d1eb81..6b094d5e404 100644 --- a/include/linux/gpio/nomadik.h +++ b/include/linux/gpio/nomadik.h @@ -28,6 +28,7 @@ #define NMK_GPIO_SLPC 0x1c #define NMK_GPIO_AFSLA 0x20 #define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 #define NMK_GPIO_RIMSC 0x40 #define NMK_GPIO_FIMSC 0x44 -- cgit v1.2.3