diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-12 16:00:54 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-12 16:00:54 -0800 |
commit | dca1d9f6d7ae428c193f32bd3e9a4ca13176648b (patch) | |
tree | 02de8c3503c1c811754423d2fa3f3b4978044f6e /arch/arm/plat-samsung/gpio.c | |
parent | 9ff99339447de403a46be5e3f23d0c794d540b06 (diff) | |
parent | 91e013827c0bcbb187ecf02213c5446b6f62d445 (diff) | |
download | linux-3.10-dca1d9f6d7ae428c193f32bd3e9a4ca13176648b.tar.gz linux-3.10-dca1d9f6d7ae428c193f32bd3e9a4ca13176648b.tar.bz2 linux-3.10-dca1d9f6d7ae428c193f32bd3e9a4ca13176648b.zip |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (370 commits)
ARM: S3C2443: Add set_rate and round_rate calls for armdiv clock
ARM: S3C2443: Remove #if 0 for clk_mpll
ARM: S3C2443: Update notes on MPLLREF clock
ARM: S3C2443: Further clksrc-clk conversions
ARM: S3C2443: Change to using plat-samsung clksrc-clk implementation
USB: Fix s3c-hsotg build following Samsung platform header moves
ARM: S3C64XX: Reintroduce unconditional build of audio device
ARM: 5961/1: ux500: fix CLKRST addresses
ARM: 5977/1: arm: Enable backtrace printing on oops when PC is corrupted
ASoC: Fix S3C64xx IIS driver for Samsung header reorg
ARM: S3C2440: Fix plat-s3c24xx move of s3c2440/s3c2442 support
[ARM] pxa: fix typo in mxm8x10.h
[ARM] pxa/raumfeld: set GPIO drive bits for LED pins
[ARM] pxa/zeus: Add support for mcp2515 CAN bus
[ARM] pxa/zeus: Add support for onboard max6369 watchdog
[ARM] pxa/zeus: Add Eurotech as the manufacturer
[ARM] pxa/zeus: Correct the USB host initialisation flags
[ARM] pxa/zeus: Allow usage of 8250-compatible UART in uncompress
[ARM] pxa: refactor uncompress.h for non-PXA uarts
[ARM] mmp2: fix incorrect calling of chip->mask_ack() for 2nd level cascaded IRQs
...
Diffstat (limited to 'arch/arm/plat-samsung/gpio.c')
-rw-r--r-- | arch/arm/plat-samsung/gpio.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c new file mode 100644 index 00000000000..28d2ab8a08d --- /dev/null +++ b/arch/arm/plat-samsung/gpio.c @@ -0,0 +1,156 @@ +/* linux/arch/arm/plat-s3c/gpio.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series GPIO core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <plat/gpio-core.h> + +#ifdef CONFIG_S3C_GPIO_TRACK +struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; + +static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip) +{ + unsigned int gpn; + int i; + + gpn = chip->chip.base; + for (i = 0; i < chip->chip.ngpio; i++, gpn++) { + BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios)); + s3c_gpios[gpn] = chip; + } +} +#endif /* CONFIG_S3C_GPIO_TRACK */ + +/* Default routines for controlling GPIO, based on the original S3C24XX + * GPIO functions which deal with the case where each gpio bank of the + * chip is as following: + * + * base + 0x00: Control register, 2 bits per gpio + * gpio n: 2 bits starting at (2*n) + * 00 = input, 01 = output, others mean special-function + * base + 0x04: Data register, 1 bit per gpio + * bit n: data bit n +*/ + +static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long con; + + local_irq_save(flags); + + con = __raw_readl(base + 0x00); + con &= ~(3 << (offset * 2)); + + __raw_writel(con, base + 0x00); + + local_irq_restore(flags); + return 0; +} + +static int s3c_gpiolib_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long dat; + unsigned long con; + + local_irq_save(flags); + + dat = __raw_readl(base + 0x04); + dat &= ~(1 << offset); + if (value) + dat |= 1 << offset; + __raw_writel(dat, base + 0x04); + + con = __raw_readl(base + 0x00); + con &= ~(3 << (offset * 2)); + con |= 1 << (offset * 2); + + __raw_writel(con, base + 0x00); + __raw_writel(dat, base + 0x04); + + local_irq_restore(flags); + return 0; +} + +static void s3c_gpiolib_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long dat; + + local_irq_save(flags); + + dat = __raw_readl(base + 0x04); + dat &= ~(1 << offset); + if (value) + dat |= 1 << offset; + __raw_writel(dat, base + 0x04); + + local_irq_restore(flags); +} + +static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + unsigned long val; + + val = __raw_readl(ourchip->base + 0x04); + val >>= offset; + val &= 1; + + return val; +} + +__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) +{ + struct gpio_chip *gc = &chip->chip; + int ret; + + BUG_ON(!chip->base); + BUG_ON(!gc->label); + BUG_ON(!gc->ngpio); + + if (!gc->direction_input) + gc->direction_input = s3c_gpiolib_input; + if (!gc->direction_output) + gc->direction_output = s3c_gpiolib_output; + if (!gc->set) + gc->set = s3c_gpiolib_set; + if (!gc->get) + gc->get = s3c_gpiolib_get; + +#ifdef CONFIG_PM + if (chip->pm != NULL) { + if (!chip->pm->save || !chip->pm->resume) + printk(KERN_ERR "gpio: %s has missing PM functions\n", + gc->label); + } else + printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); +#endif + + /* gpiochip_add() prints own failure message on error. */ + ret = gpiochip_add(gc); + if (ret >= 0) + s3c_gpiolib_track(chip); +} |