From 7e3f7e59ccc6ed8b243de9941ffd09d2ad7a5b9c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Sep 2010 11:28:05 +0100 Subject: ARM: 6353/1: nomadik-gpio: add SLPM register handing for DB8500v2 The SLPM register enables/disables wakeup detection on DB8500v2. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 30 ++++++++++++++++++++++++++--- arch/arm/plat-nomadik/include/plat/gpio.h | 2 ++ arch/arm/plat-nomadik/include/plat/pincfg.h | 5 ++++- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-nomadik') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 977c8f9a07a2..014da39b6a88 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -118,8 +118,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, [3] /* illegal */ = "??" }; static const char *slpmnames[] = { - [NMK_GPIO_SLPM_INPUT] = "input", - [NMK_GPIO_SLPM_NOCHANGE] = "no-change", + [NMK_GPIO_SLPM_INPUT] = "input/wakeup", + [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; int pin = PIN_NUM(cfg); @@ -200,6 +200,10 @@ EXPORT_SYMBOL(nmk_config_pins); * changed to an input (with pullup/down enabled) in sleep and deep sleep. If * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was * configured even when in sleep and deep sleep. + * + * On DB8500v2 onwards, this setting loses the previous meaning and instead + * indicates if wakeup detection is enabled on the pin. Note that + * enable_irq_wake() will automatically enable wakeup detection. */ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) { @@ -367,7 +371,27 @@ static void nmk_gpio_irq_unmask(unsigned int irq) static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) { - return nmk_gpio_irq_modify(irq, WAKE, on); + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + int gpio; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); +#ifdef CONFIG_ARCH_U8500 + if (cpu_is_u8500v2()) { + __nmk_gpio_set_slpm(nmk_chip, gpio, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } +#endif + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; } static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index aba355101f49..67b113d639d8 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -65,7 +65,9 @@ enum nmk_gpio_pull { /* 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); diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 7eed11c1038d..432a201b3b41 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -24,7 +24,7 @@ * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled - * sleep mode = input + * sleep mode = input/wakeup * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -55,6 +55,9 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) #define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) +/* These two replace the above in DB8500v2+ */ +#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) -- cgit v1.2.3 From 6720db7cc592b2148e0d88a7d76dc0532f3d266c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Sep 2010 11:28:48 +0100 Subject: ARM: 6354/1: nomadik-gpio: allow control of sleep mode direction and pull up DB8500v2 allows control of direction and pull up/down configuration in sleep mode, instead of switching the pin to input with pull up/down enabled. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 42 +++++++++++++++++++++-------- arch/arm/plat-nomadik/include/plat/pincfg.h | 31 ++++++++++++++++++++- 2 files changed, 61 insertions(+), 12 deletions(-) (limited to 'arch/arm/plat-nomadik') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 014da39b6a88..7afc7e8850b6 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -102,6 +102,22 @@ static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); } +static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + if (val) + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC); +} + +static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + __nmk_gpio_set_output(nmk_chip, offset, val); +} + static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg) { @@ -126,12 +142,21 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int slpm = PIN_SLPM(cfg); + int output = PIN_DIR(cfg); + int val = PIN_VAL(cfg); - dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n", - pin, afnames[af], pullnames[pull], slpmnames[slpm]); + dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", + pin, afnames[af], pullnames[pull], slpmnames[slpm], + output ? "output " : "input", + output ? (val ? "high" : "low") : ""); + + if (output) + __nmk_gpio_make_output(nmk_chip, offset, val); + else { + __nmk_gpio_make_input(nmk_chip, offset); + __nmk_gpio_set_pull(nmk_chip, offset, pull); + } - __nmk_gpio_make_input(nmk_chip, offset); - __nmk_gpio_set_pull(nmk_chip, offset, pull); __nmk_gpio_set_slpm(nmk_chip, offset, slpm); __nmk_gpio_set_mode(nmk_chip, offset, af); } @@ -519,12 +544,8 @@ 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); - u32 bit = 1 << offset; - if (val) - writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - else - writel(bit, nmk_chip->addr + NMK_GPIO_DATC); + __nmk_gpio_set_output(nmk_chip, offset, val); } static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, @@ -533,8 +554,7 @@ 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); - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); - nmk_gpio_set_output(chip, offset, val); + __nmk_gpio_make_output(nmk_chip, offset, val); return 0; } diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 432a201b3b41..8c5ae3f2acf8 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -19,12 +19,16 @@ * bit 9..10 - Alternate Function Selection * bit 11..12 - Pull up/down state * bit 13 - Sleep mode behaviour + * bit 14 - (sleep mode) Direction + * bit 15 - (sleep mode) Value (if output) * * to facilitate the definition, the following macros are provided * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled * sleep mode = input/wakeup + * (sleep mode) direction = input + * (sleep mode) value = low * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -53,12 +57,37 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_SHIFT 13 #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) -#define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) +#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) /* These two replace the above in DB8500v2+ */ #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_DIR_SHIFT 14 +#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) +#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) +#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) +#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) + +#define PIN_VAL_SHIFT 15 +#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) +#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) +#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) +#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) + +/* Shortcuts. Use these instead of separate DIR and VAL. */ +#define PIN_INPUT PIN_DIR_INPUT +#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) +#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) + +/* + * These are the same as the ones above, but should make more sense to the + * reader when seen along with a setting a pin to AF mode. + */ +#define PIN_SLPM_INPUT PIN_INPUT +#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW +#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH + #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) #define PIN_CFG(num, alt) \ -- cgit v1.2.3 From fd0d67d62def64ed5aa57f99d247e2b3d5eff8c5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 2 Sep 2010 16:13:35 +0100 Subject: ARM: 6347/2: nomadik: move nmk_gpio_probe to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a section mismatch reported by modpost: WARNING: arch/arm/plat-nomadik/built-in.o(.data+0x100): Section mismatch in reference from the variable nmk_gpio_driver to the function .init.text:nmk_gpio_probe() The variable nmk_gpio_driver references the function __init nmk_gpio_probe() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, According to Rabin VINCENT the alternative to use platform_driver_probe won't work because the "platform devices are not yet registered when nmk_gpio_init() is called." Acked-by: Rabin Vincent Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/plat-nomadik/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-nomadik') diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 7afc7e8850b6..85e6fd212a41 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -578,7 +578,7 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; -static int __init nmk_gpio_probe(struct platform_device *dev) +static int __devinit nmk_gpio_probe(struct platform_device *dev) { struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; struct nmk_gpio_chip *nmk_chip; -- cgit v1.2.3 From 99f76891a33d130776da3b01935d978b1e75fe68 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Sep 2010 13:38:55 +0100 Subject: ARM: 6375/1: plat-nomadik: MTU timer trivial bug fix timer0 to 3 are all on mtu block 0, so don't calculate the clock event rate based upon mtu block 1's clock speed. Acked-by: Alessandro Rubini Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-nomadik/timer.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch/arm/plat-nomadik') diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index ea3ca86c5283..d673888af18e 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -131,17 +131,12 @@ void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; - struct clk *clk1; u32 cr; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); - clk1 = clk_get_sys("mtu1", NULL); - BUG_ON(IS_ERR(clk1)); - clk_enable(clk0); - clk_enable(clk1); /* * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: @@ -170,15 +165,8 @@ void __init nmdk_timer_init(void) pr_err("timer: failed to initialize clock source %s\n", nmdk_clksrc.name); - /* Timer 1 is used for events, fix according to rate */ - cr = MTU_CRn_32BITS; - rate = clk_get_rate(clk1); - if (rate > 16 << 20) { - rate /= 16; - cr |= MTU_CRn_PRESCALE_16; - } else { - cr |= MTU_CRn_PRESCALE_1; - } + /* Timer 1 is used for events */ + clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ -- cgit v1.2.3 From a0719f52d90aed5b82ecf2f3ed14bc4ced3d1a8a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Sep 2010 13:40:04 +0100 Subject: ARM: 6376/1: plat-nomadik: MTU: Change prescaler limit and comment updates The prescaler 16 is now used only when the timer runs at 32 MHz or more. Some comment updates as well. Acked-by: Alessandro Rubini Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-nomadik/timer.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'arch/arm/plat-nomadik') diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index d673888af18e..aedf9c1d645e 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-nomadik/timer.c + * linux/arch/arm/plat-nomadik/timer.c * * Copyright (C) 2008 STMicroelectronics * Copyright (C) 2010 Alessandro Rubini @@ -75,7 +75,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, cr = readl(mtu_base + MTU_CR(1)); writel(0, mtu_base + MTU_LR(1)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1)); - writel(0x2, mtu_base + MTU_IMSC); + writel(1 << 1, mtu_base + MTU_IMSC); break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: @@ -131,7 +131,7 @@ void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; - u32 cr; + u32 cr = MTU_CRn_32BITS; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); @@ -139,12 +139,15 @@ void __init nmdk_timer_init(void) clk_enable(clk0); /* - * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: - * use a divide-by-16 counter if it's more than 16MHz + * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz + * for ux500. + * Use a divide-by-16 counter if the tick rate is more than 32MHz. + * At 32 MHz, the timer (with 32 bit counter) can be programmed + * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer + * with 16 gives too low timer resolution. */ - cr = MTU_CRn_32BITS;; rate = clk_get_rate(clk0); - if (rate > 16 << 20) { + if (rate > 32000000) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { -- cgit v1.2.3