diff options
author | Gregory Bean <gbean@codeaurora.org> | 2010-11-24 11:53:51 -0800 |
---|---|---|
committer | Daniel Walker <dwalker@codeaurora.org> | 2010-11-30 13:51:17 -0800 |
commit | 0cc2fc1f2f5f1fcf6699b43d73ca3e753ef63582 (patch) | |
tree | 9c64db8da8095fd0021497ad6196aec010464876 /arch/arm/mach-msm/gpio-v2.c | |
parent | 4916a1083290edfb6cc53aa134f00597447de1ce (diff) | |
download | op-kernel-dev-0cc2fc1f2f5f1fcf6699b43d73ca3e753ef63582.zip op-kernel-dev-0cc2fc1f2f5f1fcf6699b43d73ca3e753ef63582.tar.gz |
msm: gpio: Add v2 gpio support to MSM SoCs.
Beginning with the MSM8x60, the hardware block responsible for gpio
support changes. Provide gpiolib support for the new v2 architecture.
Cc: Baruch Siach <baruch@tkos.co.il>
Cc: Pavan Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm/gpio-v2.c')
-rw-r--r-- | arch/arm/mach-msm/gpio-v2.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c new file mode 100644 index 0000000..d907af6 --- /dev/null +++ b/arch/arm/mach-msm/gpio-v2.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#include <linux/gpio.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <mach/msm_iomap.h> +#include "gpiomux.h" + +/* Bits of interest in the GPIO_IN_OUT register. + */ +enum { + GPIO_IN_BIT = 0, + GPIO_OUT_BIT = 1 +}; + +/* Bits of interest in the GPIO_CFG register. + */ +enum { + GPIO_OE_BIT = 9, +}; + +#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio))) +#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio))) + +static DEFINE_SPINLOCK(tlmm_lock); + +static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN_BIT); +} + +static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +{ + writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(offset)); +} + +static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&tlmm_lock, irq_flags); + writel(readl(GPIO_CONFIG(offset)) & ~BIT(GPIO_OE_BIT), + GPIO_CONFIG(offset)); + spin_unlock_irqrestore(&tlmm_lock, irq_flags); + return 0; +} + +static int msm_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, + int val) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&tlmm_lock, irq_flags); + msm_gpio_set(chip, offset, val); + writel(readl(GPIO_CONFIG(offset)) | BIT(GPIO_OE_BIT), + GPIO_CONFIG(offset)); + spin_unlock_irqrestore(&tlmm_lock, irq_flags); + return 0; +} + +static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return msm_gpiomux_get(chip->base + offset); +} + +static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + msm_gpiomux_put(chip->base + offset); +} + +static struct gpio_chip msm_gpio = { + .base = 0, + .ngpio = NR_GPIO_IRQS, + .direction_input = msm_gpio_direction_input, + .direction_output = msm_gpio_direction_output, + .get = msm_gpio_get, + .set = msm_gpio_set, + .request = msm_gpio_request, + .free = msm_gpio_free, +}; + +static int __devinit msm_gpio_probe(struct platform_device *dev) +{ + int ret; + + msm_gpio.label = dev->name; + ret = gpiochip_add(&msm_gpio); + + return ret; +} + +static int __devexit msm_gpio_remove(struct platform_device *dev) +{ + int ret = gpiochip_remove(&msm_gpio); + + if (ret < 0) + return ret; + + set_irq_handler(TLMM_SCSS_SUMMARY_IRQ, NULL); + + return 0; +} + +static struct platform_driver msm_gpio_driver = { + .probe = msm_gpio_probe, + .remove = __devexit_p(msm_gpio_remove), + .driver = { + .name = "msmgpio", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device msm_device_gpio = { + .name = "msmgpio", + .id = -1, +}; + +static int __init msm_gpio_init(void) +{ + int rc; + + rc = platform_driver_register(&msm_gpio_driver); + if (!rc) { + rc = platform_device_register(&msm_device_gpio); + if (rc) + platform_driver_unregister(&msm_gpio_driver); + } + + return rc; +} + +static void __exit msm_gpio_exit(void) +{ + platform_device_unregister(&msm_device_gpio); + platform_driver_unregister(&msm_gpio_driver); +} + +postcore_initcall(msm_gpio_init); +module_exit(msm_gpio_exit); + +MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); +MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:msmgpio"); |