diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-03 14:31:24 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-03 14:31:24 -0700 |
commit | be82ae0238b0453afcf4a76f0512b7dde34ba500 (patch) | |
tree | aaa3f5f11fd51fd73365ee1a2164aad9a03de060 /arch/arm/plat-nomadik | |
parent | 4b4fd27c0b5ec638a1f06ced9226fd95229dbbf0 (diff) | |
parent | 7b70c4275f28702b76b273c8534c38f8313812e9 (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (291 commits)
ARM: AMBA: Add pclk support to AMBA bus infrastructure
ARM: 6278/2: fix regression in RealView after the introduction of pclk
ARM: 6277/1: mach-shmobile: Allow users to select HZ, default to 128
ARM: 6276/1: mach-shmobile: remove duplicate NR_IRQS_LEGACY
ARM: 6246/1: mmci: support larger MMCIDATALENGTH register
ARM: 6245/1: mmci: enable hardware flow control on Ux500 variants
ARM: 6244/1: mmci: add variant data and default MCICLOCK support
ARM: 6243/1: mmci: pass power_mode to the translate_vdd callback
ARM: 6274/1: add global control registers definition header file for nuc900
mx2_camera: fix type of dma buffer virtual address pointer
mx2_camera: Add soc_camera support for i.MX25/i.MX27
arm/imx/gpio: add spinlock protection
ARM: Add support for the LPC32XX arch
ARM: LPC32XX: Arch config menu supoport and makefiles
ARM: LPC32XX: Phytec 3250 platform support
ARM: LPC32XX: Misc support functions
ARM: LPC32XX: Serial support code
ARM: LPC32XX: System suspend support
ARM: LPC32XX: GPIO, timer, and IRQ drivers
ARM: LPC32XX: Clock driver
...
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 316 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 15 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/mtu.h | 6 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/pincfg.h | 72 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/timer.c | 14 |
5 files changed, 365 insertions, 58 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 5a6ef252c38b..977c8f9a07a2 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -23,6 +23,7 @@ #include <linux/irq.h> #include <linux/slab.h> +#include <plat/pincfg.h> #include <mach/hardware.h> #include <mach/gpio.h> @@ -46,28 +47,217 @@ struct nmk_gpio_chip { u32 edge_falling; }; +static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int gpio_mode) +{ + u32 bit = 1 << offset; + u32 afunc, bfunc; + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; + if (gpio_mode & NMK_GPIO_ALT_A) + afunc |= bit; + if (gpio_mode & NMK_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); + writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); +} + +static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, + unsigned offset, enum nmk_gpio_slpm mode) +{ + u32 bit = 1 << offset; + u32 slpm; + + slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC); + if (mode == NMK_GPIO_SLPM_NOCHANGE) + slpm |= bit; + else + slpm &= ~bit; + writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC); +} + +static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, + unsigned offset, enum nmk_gpio_pull pull) +{ + u32 bit = 1 << offset; + u32 pdis; + + pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS); + if (pull == NMK_GPIO_PULL_NONE) + pdis |= bit; + else + pdis &= ~bit; + writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); + + if (pull == NMK_GPIO_PULL_UP) + writel(bit, nmk_chip->addr + NMK_GPIO_DATS); + else if (pull == NMK_GPIO_PULL_DOWN) + writel(bit, nmk_chip->addr + NMK_GPIO_DATC); +} + +static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, + unsigned offset) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); +} + +static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, + pin_cfg_t cfg) +{ + static const char *afnames[] = { + [NMK_GPIO_ALT_GPIO] = "GPIO", + [NMK_GPIO_ALT_A] = "A", + [NMK_GPIO_ALT_B] = "B", + [NMK_GPIO_ALT_C] = "C" + }; + static const char *pullnames[] = { + [NMK_GPIO_PULL_NONE] = "none", + [NMK_GPIO_PULL_UP] = "up", + [NMK_GPIO_PULL_DOWN] = "down", + [3] /* illegal */ = "??" + }; + static const char *slpmnames[] = { + [NMK_GPIO_SLPM_INPUT] = "input", + [NMK_GPIO_SLPM_NOCHANGE] = "no-change", + }; + + int pin = PIN_NUM(cfg); + int pull = PIN_PULL(cfg); + int af = PIN_ALT(cfg); + int slpm = PIN_SLPM(cfg); + + dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n", + pin, afnames[af], pullnames[pull], slpmnames[slpm]); + + __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); +} + +/** + * nmk_config_pin - configure a pin's mux attributes + * @cfg: pin confguration + * + * 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/<soc>-pins.h. These + * are constructed using, and can be further enhanced with, the macros in + * plat/pincfg.h. + * + * If a pin's mode is set to GPIO, it is configured as an input to avoid + * side-effects. The gpio can be manipulated later using standard GPIO API + * calls. + */ +int nmk_config_pin(pin_cfg_t cfg) +{ + struct nmk_gpio_chip *nmk_chip; + int gpio = PIN_NUM(cfg); + unsigned long flags; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); + __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; +} +EXPORT_SYMBOL(nmk_config_pin); + +/** + * nmk_config_pins - configure several pins at once + * @cfgs: array of pin configurations + * @num: number of elments in the array + * + * Configures several pins using nmk_config_pin(). Refer to that function for + * further information. + */ +int nmk_config_pins(pin_cfg_t *cfgs, int num) +{ + int ret = 0; + int i; + + for (i = 0; i < num; i++) { + int ret = nmk_config_pin(cfgs[i]); + if (ret) + break; + } + + return ret; +} +EXPORT_SYMBOL(nmk_config_pins); + +/** + * nmk_gpio_set_slpm() - configure the sleep mode of a pin + * @gpio: pin number + * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE, + * + * Sets the sleep mode of a pin. If @mode is NMK_GPIO_SLPM_INPUT, the pin is + * 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. + */ +int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; +} + +/** + * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio + * @gpio: pin number + * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE + * + * Enables/disables pull up/down on a specified pin. This only takes effect if + * the pin is configured as an input (either explicitly or by the alternate + * function). + * + * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is + * configured as an input. Otherwise, due to the way the controller registers + * work, this function will change the value output on the pin. + */ +int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + 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); + + return 0; +} + /* Mode functions */ int nmk_gpio_set_mode(int gpio, int gpio_mode) { struct nmk_gpio_chip *nmk_chip; unsigned long flags; - u32 afunc, bfunc, bit; nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); if (!nmk_chip) return -EINVAL; - bit = 1 << (gpio - nmk_chip->chip.base); - spin_lock_irqsave(&nmk_chip->lock, flags); - afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; - bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; - if (gpio_mode & NMK_GPIO_ALT_A) - afunc |= bit; - if (gpio_mode & NMK_GPIO_ALT_B) - bfunc |= bit; - writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); - writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); + __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); spin_unlock_irqrestore(&nmk_chip->lock, flags); return 0; @@ -111,32 +301,41 @@ static void nmk_gpio_irq_ack(unsigned int irq) writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); } +enum nmk_gpio_irq_type { + NORMAL, + WAKE, +}; + static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, - int gpio, bool enable) + int gpio, enum nmk_gpio_irq_type which, + bool enable) { + u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC; + u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC; u32 bitmask = nmk_gpio_get_bitmask(gpio); u32 reg; /* we must individually set/clear the two edges */ if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); + reg = readl(nmk_chip->addr + rimsc); if (enable) reg |= bitmask; else reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); + writel(reg, nmk_chip->addr + rimsc); } if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); + reg = readl(nmk_chip->addr + fimsc); if (enable) reg |= bitmask; else reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); + writel(reg, nmk_chip->addr + fimsc); } } -static void nmk_gpio_irq_modify(unsigned int irq, bool enable) +static int nmk_gpio_irq_modify(unsigned int irq, enum nmk_gpio_irq_type which, + bool enable) { int gpio; struct nmk_gpio_chip *nmk_chip; @@ -147,26 +346,35 @@ static void nmk_gpio_irq_modify(unsigned int irq, bool enable) nmk_chip = get_irq_chip_data(irq); bitmask = nmk_gpio_get_bitmask(gpio); if (!nmk_chip) - return; + return -EINVAL; spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_gpio_irq_modify(nmk_chip, gpio, enable); + __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; } static void nmk_gpio_irq_mask(unsigned int irq) { - nmk_gpio_irq_modify(irq, false); -}; + nmk_gpio_irq_modify(irq, NORMAL, false); +} static void nmk_gpio_irq_unmask(unsigned int irq) { - nmk_gpio_irq_modify(irq, true); + nmk_gpio_irq_modify(irq, NORMAL, true); +} + +static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) +{ + return nmk_gpio_irq_modify(irq, WAKE, on); } static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) { - bool enabled = !(irq_to_desc(irq)->status & IRQ_DISABLED); + struct irq_desc *desc = irq_to_desc(irq); + bool enabled = !(desc->status & IRQ_DISABLED); + bool wake = desc->wake_depth; int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; @@ -186,7 +394,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) spin_lock_irqsave(&nmk_chip->lock, flags); if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, false); + __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); + + if (wake) + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); nmk_chip->edge_rising &= ~bitmask; if (type & IRQ_TYPE_EDGE_RISING) @@ -197,7 +408,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) nmk_chip->edge_falling |= bitmask; if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, true); + __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); + + if (wake) + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); spin_unlock_irqrestore(&nmk_chip->lock, flags); @@ -210,6 +424,7 @@ static struct irq_chip nmk_gpio_irq_chip = { .mask = nmk_gpio_irq_mask, .unmask = nmk_gpio_irq_unmask, .set_type = nmk_gpio_irq_set_type, + .set_wake = nmk_gpio_irq_set_wake, }; static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) @@ -266,16 +481,6 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) return 0; } -static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); - return 0; -} - static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) { struct nmk_gpio_chip *nmk_chip = @@ -298,12 +503,33 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, writel(bit, nmk_chip->addr + NMK_GPIO_DATC); } +static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + 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); + + return 0; +} + +static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; +} + /* This structure is replicated for each GPIO block allocated at probe time */ static struct gpio_chip nmk_gpio_template = { .direction_input = nmk_gpio_make_input, .get = nmk_gpio_get_input, .direction_output = nmk_gpio_make_output, .set = nmk_gpio_set_output, + .to_irq = nmk_gpio_to_irq, .ngpio = NMK_GPIO_PER_CHIP, .can_sleep = 0, }; @@ -393,30 +619,12 @@ out: return ret; } -static int __exit nmk_gpio_remove(struct platform_device *dev) -{ - struct nmk_gpio_chip *nmk_chip; - struct resource *res; - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - - nmk_chip = platform_get_drvdata(dev); - gpiochip_remove(&nmk_chip->chip); - clk_disable(nmk_chip->clk); - clk_put(nmk_chip->clk); - kfree(nmk_chip); - release_mem_region(res->start, resource_size(res)); - return 0; -} - - static struct platform_driver nmk_gpio_driver = { .driver = { .owner = THIS_MODULE, .name = "gpio", }, .probe = nmk_gpio_probe, - .remove = __exit_p(nmk_gpio_remove), .suspend = NULL, /* to be done */ .resume = NULL, }; @@ -426,7 +634,7 @@ static int __init nmk_gpio_init(void) return platform_driver_register(&nmk_gpio_driver); } -arch_initcall(nmk_gpio_init); +core_initcall(nmk_gpio_init); MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); MODULE_DESCRIPTION("Nomadik GPIO Driver"); diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 4200811249ca..aba355101f49 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -55,6 +55,21 @@ #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_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); diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h index 42c907258b14..65704a3d4241 100644 --- a/arch/arm/plat-nomadik/include/plat/mtu.h +++ b/arch/arm/plat-nomadik/include/plat/mtu.h @@ -1,6 +1,12 @@ #ifndef __PLAT_MTU_H #define __PLAT_MTU_H +/* + * Guaranteed runtime conversion range in seconds for + * the clocksource and clockevent. + */ +#define MTU_MIN_RANGE 4 + /* should be set by the platform code */ extern void __iomem *mtu_base; diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h new file mode 100644 index 000000000000..7eed11c1038d --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License, version 2 + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * + * Based on arch/arm/mach-pxa/include/mach/mfp.h: + * Copyright (C) 2007 Marvell International Ltd. + * eric miao <eric.miao@marvell.com> + */ + +#ifndef __PLAT_PINCFG_H +#define __PLAT_PINCFG_H + +/* + * pin configurations are represented by 32-bit integers: + * + * bit 0.. 8 - Pin Number (512 Pins Maximum) + * bit 9..10 - Alternate Function Selection + * bit 11..12 - Pull up/down state + * bit 13 - Sleep mode behaviour + * + * to facilitate the definition, the following macros are provided + * + * PIN_CFG_DEFAULT - default config (0): + * pull up/down = disabled + * sleep mode = input + * + * PIN_CFG - default config with alternate function + * PIN_CFG_PULL - default config with alternate function and pull up/down + */ + +typedef unsigned long pin_cfg_t; + +#define PIN_NUM_MASK 0x1ff +#define PIN_NUM(x) ((x) & PIN_NUM_MASK) + +#define PIN_ALT_SHIFT 9 +#define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) +#define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) +#define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) +#define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) +#define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) +#define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) + +#define PIN_PULL_SHIFT 11 +#define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) +#define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) +#define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) +#define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) +#define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) + +#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_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) + +#define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) + +#define PIN_CFG(num, alt) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt)) + +#define PIN_CFG_PULL(num, alt, pull) \ + ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ + (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) + +extern int nmk_config_pin(pin_cfg_t cfg); +extern int nmk_config_pins(pin_cfg_t *cfgs, int num); + +#endif diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 08aaa4a7f65f..ea3ca86c5283 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -42,7 +42,6 @@ static struct clocksource nmdk_clksrc = { .rating = 200, .read = nmdk_read_timer_dummy, .mask = CLOCKSOURCE_MASK(32), - .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -82,6 +81,12 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: /* disable irq */ writel(0, mtu_base + MTU_IMSC); + /* disable timer */ + cr = readl(mtu_base + MTU_CR(1)); + cr &= ~MTU_CRn_ENA; + writel(cr, mtu_base + MTU_CR(1)); + /* load some high default value */ + writel(0xffffffff, mtu_base + MTU_LR(1)); break; case CLOCK_EVT_MODE_RESUME: break; @@ -98,7 +103,6 @@ static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) static struct clock_event_device nmdk_clkevt = { .name = "mtu_1", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 200, .set_mode = nmdk_clkevt_mode, .set_next_event = nmdk_clkevt_next, @@ -151,6 +155,7 @@ void __init nmdk_timer_init(void) } else { cr |= MTU_CRn_PRESCALE_1; } + clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); /* Timer 0 is the free running clocksource */ writel(cr, mtu_base + MTU_CR(0)); @@ -158,7 +163,6 @@ void __init nmdk_timer_init(void) writel(0, mtu_base + MTU_BGLR(0)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); - nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); /* Now the scheduling clock is ready */ nmdk_clksrc.read = nmdk_read_timer; @@ -175,8 +179,10 @@ void __init nmdk_timer_init(void) } else { cr |= MTU_CRn_PRESCALE_1; } + clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); + writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ - nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); + nmdk_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff, &nmdk_clkevt); nmdk_clkevt.min_delta_ns = |