Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932476Ab0FOVLW (ORCPT ); Tue, 15 Jun 2010 17:11:22 -0400 Received: from wolverine02.qualcomm.com ([199.106.114.251]:34948 "EHLO wolverine02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758471Ab0FOVLS (ORCPT ); Tue, 15 Jun 2010 17:11:18 -0400 X-IronPort-AV: E=McAfee;i="5400,1158,6014"; a="44404154" From: Gregory Bean To: akpm@linux-foundation.org Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Gregory Bean , Joe Perches , "David S. Miller" , Samuel Ortiz , Mark Brown , Randy Dunlap , Michael Hennerich , Mike Frysinger , David Brown , Daniel Walker , Bryan Huntsman Subject: [PATCH 1/2 v4] gpio: msm7200a: Add gpiolib support for MSM chips. Date: Tue, 15 Jun 2010 14:11:07 -0700 Message-Id: <1276636268-4891-2-git-send-email-gbean@codeaurora.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1276636268-4891-1-git-send-email-gbean@codeaurora.org> References: <1276636268-4891-1-git-send-email-gbean@codeaurora.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10666 Lines: 332 Add support for uniprocessor MSM chips whose TLMM/GPIO design is the same as the MSM7200A. This includes, but is not necessarily limited to, the: MSM7200A, MSM7x25, MSM7x27, MSM7x30, QSD8x50, QSD8x50A Signed-off-by: Gregory Bean --- MAINTAINERS | 2 + drivers/gpio/Kconfig | 8 ++ drivers/gpio/Makefile | 1 + drivers/gpio/msm7200a-gpio.c | 187 +++++++++++++++++++++++++++++++++++++++++ include/linux/msm7200a-gpio.h | 62 ++++++++++++++ 5 files changed, 260 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/msm7200a-gpio.c create mode 100644 include/linux/msm7200a-gpio.h diff --git a/MAINTAINERS b/MAINTAINERS index 6d119c9..bdfd31d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -819,6 +819,8 @@ F: drivers/mmc/host/msm_sdcc.c F: drivers/mmc/host/msm_sdcc.h F: drivers/serial/msm_serial.h F: drivers/serial/msm_serial.c +F: drivers/gpio/msm7200a-gpio.c +F: include/linux/msm7200a-gpio.h T: git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git S: Maintained diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 724038d..557738a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -76,6 +76,14 @@ config GPIO_IT8761E help Say yes here to support GPIO functionality of IT8761E super I/O chip. +config GPIO_MSM7200A + tristate "Qualcomm MSM7200A SoC GPIO support" + depends on GPIOLIB + help + Say yes here to support GPIO functionality on Qualcomm's + MSM chipsets which descend from the MSM7200a: + MSM7x01(a), MSM7x25, MSM7x27, MSM7x30, QSD8x50(a). + config GPIO_PL061 bool "PrimeCell PL061 GPIO support" depends on ARM_AMBA diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 51c3cdd..2389c29 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_MAX7301) += max7301.o obj-$(CONFIG_GPIO_MAX732X) += max732x.o obj-$(CONFIG_GPIO_MC33880) += mc33880.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o +obj-$(CONFIG_GPIO_MSM7200A) += msm7200a-gpio.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PL061) += pl061.o diff --git a/drivers/gpio/msm7200a-gpio.c b/drivers/gpio/msm7200a-gpio.c new file mode 100644 index 0000000..22ae631 --- /dev/null +++ b/drivers/gpio/msm7200a-gpio.c @@ -0,0 +1,187 @@ +/* + * Driver for Qualcomm MSM7200a and related SoC GPIO. + * Supported chipset families include: + * MSM7x01(a), MSM7x25, MSM7x27, MSM7x30, QSD8x50(a) + * + * Copyright (C) 2007 Google, Inc. + * 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 +#include +#include +#include +#include +#include +#include + +struct msm_gpio_dev { + struct gpio_chip gpio_chip; + spinlock_t lock; + struct msm7200a_gpio_regs regs; +}; + +static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip) +{ + return container_of(chip, struct msm_gpio_dev, gpio_chip); +} + +/* + * This function assumes that msm_gpio_dev::lock is held. + */ +static inline void set_gpio_bit(unsigned n, void __iomem *reg) +{ + writel(readl(reg) | BIT(n), reg); +} + +/* + * This function assumes that msm_gpio_dev::lock is held. + */ +static inline void clr_gpio_bit(unsigned n, void __iomem *reg) +{ + writel(readl(reg) & ~BIT(n), reg); +} + +/* + * This function assumes that msm_gpio_dev::lock is held. + */ +static inline void +msm_gpio_write(struct msm_gpio_dev *dev, unsigned n, unsigned on) +{ + if (on) + set_gpio_bit(n, dev->regs.out); + else + clr_gpio_bit(n, dev->regs.out); +} + +static int gpio_chip_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct msm_gpio_dev *msm_gpio = to_msm_gpio_dev(chip); + unsigned long irq_flags; + + spin_lock_irqsave(&msm_gpio->lock, irq_flags); + clr_gpio_bit(offset, msm_gpio->regs.oe); + spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); + + return 0; +} + +static int +gpio_chip_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msm_gpio_dev *msm_gpio = to_msm_gpio_dev(chip); + unsigned long irq_flags; + + spin_lock_irqsave(&msm_gpio->lock, irq_flags); + msm_gpio_write(msm_gpio, offset, value); + set_gpio_bit(offset, msm_gpio->regs.oe); + spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); + + return 0; +} + +static int gpio_chip_get(struct gpio_chip *chip, unsigned offset) +{ + struct msm_gpio_dev *msm_gpio = to_msm_gpio_dev(chip); + + return readl(msm_gpio->regs.in) & BIT(offset) ? 1 : 0; +} + +static void gpio_chip_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msm_gpio_dev *msm_gpio = to_msm_gpio_dev(chip); + unsigned long irq_flags; + + spin_lock_irqsave(&msm_gpio->lock, irq_flags); + msm_gpio_write(msm_gpio, offset, value); + spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); +} + +static int msm_gpio_probe(struct platform_device *dev) +{ + struct msm_gpio_dev *msm_gpio; + struct msm7200a_gpio_platform_data *pdata = dev->dev.platform_data; + int ret; + + if (!pdata) + return -EINVAL; + + msm_gpio = kzalloc(sizeof(struct msm_gpio_dev), GFP_KERNEL); + if (!msm_gpio) + return -ENOMEM; + + spin_lock_init(&msm_gpio->lock); + platform_set_drvdata(dev, msm_gpio); + + msm_gpio->regs = pdata->regs; + msm_gpio->gpio_chip.label = dev->name; + msm_gpio->gpio_chip.base = pdata->gpio_base; + msm_gpio->gpio_chip.ngpio = pdata->ngpio; + msm_gpio->gpio_chip.direction_input = gpio_chip_direction_input; + msm_gpio->gpio_chip.direction_output = gpio_chip_direction_output; + msm_gpio->gpio_chip.get = gpio_chip_get; + msm_gpio->gpio_chip.set = gpio_chip_set; + + ret = gpiochip_add(&msm_gpio->gpio_chip); + if (ret < 0) + goto err_post_malloc; + + return ret; +err_post_malloc: + platform_set_drvdata(dev, NULL); + kfree(msm_gpio); + return ret; +} + +static int msm_gpio_remove(struct platform_device *dev) +{ + struct msm_gpio_dev *msm_gpio = platform_get_drvdata(dev); + int ret = gpiochip_remove(&msm_gpio->gpio_chip); + + if (ret < 0) + return ret; + + kfree(msm_gpio); + + return 0; +} + +static struct platform_driver msm_gpio_driver = { + .probe = msm_gpio_probe, + .remove = msm_gpio_remove, + .driver = { + .name = "msm7200a-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init msm_gpio_init(void) +{ + return platform_driver_register(&msm_gpio_driver); +} + +static void __exit msm_gpio_exit(void) +{ + platform_driver_unregister(&msm_gpio_driver); +} + +postcore_initcall(msm_gpio_init); +module_exit(msm_gpio_exit); + +MODULE_AUTHOR("Gregory Bean "); +MODULE_DESCRIPTION("Driver for Qualcomm MSM 7200a-family SoC GPIOs"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:msm7200a-gpio"); diff --git a/include/linux/msm7200a-gpio.h b/include/linux/msm7200a-gpio.h new file mode 100644 index 0000000..c44d16b --- /dev/null +++ b/include/linux/msm7200a-gpio.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LINUX_MSM7200A_GPIO_H +#define __LINUX_MSM7200A_GPIO_H + +/** + * struct msm7200a_gpio_regs - addresess of iomapped GPIO registers + * @in: GPIO_IN_n + * @out: GPIO_OUT_n + * @oe: GPIO_OE_n + * + * Registers are not guaranteed to be packed in memory, or even + * located in a predictable pattern. + */ +struct msm7200a_gpio_regs { + void __iomem *in; + void __iomem *out; + void __iomem *oe; +}; + +/** + * struct msm7200a_gpio_platform_data - configuration for msm7200a-gpio + * @gpio_base: The first gpio to be assigned to the device. Corresponds + * directly to gpio_chip.base. + * @ngpio: The number of gpio lines to be managed by the device. + * Must be <= 32. Corresponds directly to gpio_chip.ngpio. + * @regs: Addresses of the registers which control the gpios + * to be managed by the device. + */ +struct msm7200a_gpio_platform_data { + unsigned gpio_base; + unsigned ngpio; + struct msm7200a_gpio_regs regs; +}; + +#endif -- 1.7.0.4 -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/