diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/gpio')
62 files changed, 0 insertions, 28833 deletions
diff --git a/ANDROID_3.4.5/drivers/gpio/Kconfig b/ANDROID_3.4.5/drivers/gpio/Kconfig deleted file mode 100644 index e03653d6..00000000 --- a/ANDROID_3.4.5/drivers/gpio/Kconfig +++ /dev/null @@ -1,517 +0,0 @@ -# -# GPIO infrastructure and drivers -# - -config ARCH_WANT_OPTIONAL_GPIOLIB - bool - help - Select this config option from the architecture Kconfig, if - it is possible to use gpiolib on the architecture, but let the - user decide whether to actually build it or not. - Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does - not depend on GPIOs being available, but rather let the user - decide whether he needs it or not. - -config ARCH_REQUIRE_GPIOLIB - bool - select GPIOLIB - help - Platforms select gpiolib if they use this infrastructure - for all their GPIOs, usually starting with ones integrated - into SOC processors. - Selecting this from the architecture code will cause the gpiolib - code to always get built in. - - - -menuconfig GPIOLIB - bool "GPIO Support" - depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO - help - This enables GPIO support through the generic GPIO library. - You only need to enable this, if you also want to enable - one or more of the GPIO drivers below. - - If unsure, say N. - -if GPIOLIB - -config DEBUG_GPIO - bool "Debug GPIO calls" - depends on DEBUG_KERNEL - help - Say Y here to add some extra checks and diagnostics to GPIO calls. - These checks help ensure that GPIOs have been properly initialized - before they are used, and that sleeping calls are not made from - non-sleeping contexts. They can make bitbanged serial protocols - slower. The diagnostics help catch the type of setup errors - that are most common when setting up new platforms or boards. - -config GPIO_SYSFS - bool "/sys/class/gpio/... (sysfs interface)" - depends on SYSFS && EXPERIMENTAL - help - Say Y here to add a sysfs interface for GPIOs. - - This is mostly useful to work around omissions in a system's - kernel support. Those are common in custom and semicustom - hardware assembled using standard kernels with a minimum of - custom patches. In those cases, userspace code may import - a given GPIO from the kernel, if no kernel driver requested it. - - Kernel drivers may also request that a particular GPIO be - exported to userspace; this can be useful when debugging. - -config GPIO_GENERIC - tristate - -# put drivers in the right section, in alphabetical order - -config GPIO_DA9052 - tristate "Dialog DA9052 GPIO" - depends on PMIC_DA9052 && BROKEN - help - Say yes here to enable the GPIO driver for the DA9052 chip. - -config GPIO_MAX730X - tristate - -comment "Memory mapped GPIO drivers:" - -config GPIO_GENERIC_PLATFORM - tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" - select GPIO_GENERIC - help - Say yes here to support basic platform_device memory-mapped GPIO controllers. - -config GPIO_IT8761E - tristate "IT8761E GPIO support" - depends on X86 # unconditional access to IO space. - help - Say yes here to support GPIO functionality of IT8761E super I/O chip. - -config GPIO_EP93XX - def_bool y - depends on ARCH_EP93XX - select GPIO_GENERIC - -config GPIO_MPC5200 - def_bool y - depends on PPC_MPC52xx - -config GPIO_MPC8XXX - bool "MPC512x/MPC8xxx GPIO support" - depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ - FSL_SOC_BOOKE || PPC_86xx - help - Say Y here if you're going to use hardware that connects to the - MPC512x/831x/834x/837x/8572/8610 GPIOs. - -config GPIO_MSM_V1 - tristate "Qualcomm MSM GPIO v1" - depends on GPIOLIB && ARCH_MSM - help - Say yes here to support the GPIO interface on ARM v6 based - Qualcomm MSM chips. Most of the pins on the MSM can be - selected for GPIO, and are controlled by this driver. - -config GPIO_MSM_V2 - tristate "Qualcomm MSM GPIO v2" - depends on GPIOLIB && ARCH_MSM - help - Say yes here to support the GPIO interface on ARM v7 based - Qualcomm MSM chips. Most of the pins on the MSM can be - selected for GPIO, and are controlled by this driver. - -config GPIO_MXC - def_bool y - depends on ARCH_MXC - select GPIO_GENERIC - select GENERIC_IRQ_CHIP - -config GPIO_MXS - def_bool y - depends on ARCH_MXS - select GPIO_GENERIC - select GENERIC_IRQ_CHIP - -config GPIO_PL061 - bool "PrimeCell PL061 GPIO support" - depends on ARM_AMBA - select GENERIC_IRQ_CHIP - help - Say yes here to support the PrimeCell PL061 GPIO device - -config GPIO_PXA - bool "PXA GPIO support" - depends on ARCH_PXA || ARCH_MMP - help - Say yes here to support the PXA GPIO device - -config GPIO_XILINX - bool "Xilinx GPIO support" - depends on PPC_OF || MICROBLAZE - help - Say yes here to support the Xilinx FPGA GPIO device - -config GPIO_VR41XX - tristate "NEC VR4100 series General-purpose I/O Uint support" - depends on CPU_VR41XX - help - Say yes here to support the NEC VR4100 series General-purpose I/O Uint - -config GPIO_SCH - tristate "Intel SCH/TunnelCreek GPIO" - depends on PCI && X86 - select MFD_CORE - select LPC_SCH - help - Say yes here to support GPIO interface on Intel Poulsbo SCH - or Intel Tunnel Creek processor. - The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are - powered by the core power rail and are turned off during sleep - modes (S3 and higher). The remaining four GPIOs are powered by - the Intel SCH suspend power supply. These GPIOs remain - active during S3. The suspend powered GPIOs can be used to wake the - system from the Suspend-to-RAM state. - The Intel Tunnel Creek processor has 5 GPIOs powered by the - core power rail and 9 from suspend power supply. - -config GPIO_VX855 - tristate "VIA VX855/VX875 GPIO" - depends on PCI - select MFD_CORE - select MFD_VX855 - help - Support access to the VX855/VX875 GPIO lines through the gpio library. - - This driver provides common support for accessing the device, - additional drivers must be enabled in order to use the - functionality of the device. - -config GPIO_GE_FPGA - bool "GE FPGA based GPIO" - depends on GE_FPGA - help - Support for common GPIO functionality provided on some GE Single Board - Computers. - - This driver provides basic support (configure as input or output, read - and write pin state) for GPIO implemented in a number of GE single - board computers. - -comment "I2C GPIO expanders:" - -config GPIO_MAX7300 - tristate "Maxim MAX7300 GPIO expander" - depends on I2C - select GPIO_MAX730X - help - GPIO driver for Maxim MAX7301 I2C-based GPIO expander. - -config GPIO_MAX732X - tristate "MAX7319, MAX7320-7327 I2C Port Expanders" - depends on I2C - help - Say yes here to support the MAX7319, MAX7320-7327 series of I2C - Port Expanders. Each IO port on these chips has a fixed role of - Input (designated by 'I'), Push-Pull Output ('O'), or Open-Drain - Input and Output (designed by 'P'). The combinations are listed - below: - - 8 bits: max7319 (8I), max7320 (8O), max7321 (8P), - max7322 (4I4O), max7323 (4P4O) - - 16 bits: max7324 (8I8O), max7325 (8P8O), - max7326 (4I12O), max7327 (4P12O) - - Board setup code must specify the model to use, and the start - number for these GPIOs. - -config GPIO_MAX732X_IRQ - bool "Interrupt controller support for MAX732x" - depends on GPIO_MAX732X=y && GENERIC_HARDIRQS - help - Say yes here to enable the max732x to be used as an interrupt - controller. It requires the driver to be built in the kernel. - -config GPIO_MC9S08DZ60 - bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" - depends on I2C && MACH_MX35_3DS - help - Select this to enable the MC9S08DZ60 GPIO driver - -config GPIO_PCA953X - tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" - depends on I2C - help - Say yes here to provide access to several register-oriented - SMBus I/O expanders, made mostly by NXP or TI. Compatible - models include: - - 4 bits: pca9536, pca9537 - - 8 bits: max7310, pca9534, pca9538, pca9554, pca9557, - tca6408 - - 16 bits: pca9535, pca9539, pca9555, tca6416 - -config GPIO_PCA953X_IRQ - bool "Interrupt controller support for PCA953x" - depends on GPIO_PCA953X=y - help - Say yes here to enable the pca953x to be used as an interrupt - controller. It requires the driver to be built in the kernel. - -config GPIO_PCF857X - tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" - depends on I2C - help - Say yes here to provide access to most "quasi-bidirectional" I2C - GPIO expanders used for additional digital outputs or inputs. - Most of these parts are from NXP, though TI is a second source for - some of them. Compatible models include: - - 8 bits: pcf8574, pcf8574a, pca8574, pca8574a, - pca9670, pca9672, pca9674, pca9674a, - max7328, max7329 - - 16 bits: pcf8575, pcf8575c, pca8575, - pca9671, pca9673, pca9675 - - Your board setup code will need to declare the expanders in - use, and assign numbers to the GPIOs they expose. Those GPIOs - can then be used from drivers and other kernel code, just like - other GPIOs, but only accessible from task contexts. - - This driver provides an in-kernel interface to those GPIOs using - platform-neutral GPIO calls. - -config GPIO_SX150X - bool "Semtech SX150x I2C GPIO expander" - depends on I2C=y - default n - help - Say yes here to provide support for Semtech SX150-series I2C - GPIO expanders. Compatible models include: - - 8 bits: sx1508q - 16 bits: sx1509q - -config GPIO_STMPE - bool "STMPE GPIOs" - depends on MFD_STMPE - help - This enables support for the GPIOs found on the STMPE I/O - Expanders. - -config GPIO_TC3589X - bool "TC3589X GPIOs" - depends on MFD_TC3589X - help - This enables support for the GPIOs found on the TC3589X - I/O Expander. - -config GPIO_TPS65912 - tristate "TI TPS65912 GPIO" - depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI) - help - This driver supports TPS65912 gpio chip - -config GPIO_TWL4030 - tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" - depends on TWL4030_CORE - help - Say yes here to access the GPIO signals of various multi-function - power management chips from Texas Instruments. - -config GPIO_WM831X - tristate "WM831x GPIOs" - depends on MFD_WM831X - help - Say yes here to access the GPIO signals of WM831x power management - chips from Wolfson Microelectronics. - -config GPIO_WM8350 - tristate "WM8350 GPIOs" - depends on MFD_WM8350 - help - Say yes here to access the GPIO signals of WM8350 power management - chips from Wolfson Microelectronics. - -config GPIO_WM8994 - tristate "WM8994 GPIOs" - depends on MFD_WM8994 - help - Say yes here to access the GPIO signals of WM8994 audio hub - CODECs from Wolfson Microelectronics. - -config GPIO_ADP5520 - tristate "GPIO Support for ADP5520 PMIC" - depends on PMIC_ADP5520 - help - This option enables support for on-chip GPIO found - on Analog Devices ADP5520 PMICs. - -config GPIO_ADP5588 - tristate "ADP5588 I2C GPIO expander" - depends on I2C - help - This option enables support for 18 GPIOs found - on Analog Devices ADP5588 GPIO Expanders. - -config GPIO_ADP5588_IRQ - bool "Interrupt controller support for ADP5588" - depends on GPIO_ADP5588=y - help - Say yes here to enable the adp5588 to be used as an interrupt - controller. It requires the driver to be built in the kernel. - -comment "PCI GPIO expanders:" - -config GPIO_CS5535 - tristate "AMD CS5535/CS5536 GPIO support" - depends on PCI && X86 && MFD_CS5535 - help - The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that - can be used for quite a number of things. The CS5535/6 is found on - AMD Geode and Lemote Yeeloong devices. - - If unsure, say N. - -config GPIO_BT8XX - tristate "BT8XX GPIO abuser" - depends on PCI && VIDEO_BT848=n - help - The BT8xx frame grabber chip has 24 GPIO pins than can be abused - as a cheap PCI GPIO card. - - This chip can be found on Miro, Hauppauge and STB TV-cards. - - The card needs to be physically altered for using it as a - GPIO card. For more information on how to build a GPIO card - from a BT8xx TV card, see the documentation file at - Documentation/bt8xxgpio.txt - - If unsure, say N. - -config GPIO_LANGWELL - bool "Intel Langwell/Penwell GPIO support" - depends on PCI && X86 - help - Say Y here to support Intel Langwell/Penwell GPIO. - -config GPIO_PCH - tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO" - depends on PCI && X86 - select GENERIC_IRQ_CHIP - help - This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff - which is an IOH(Input/Output Hub) for x86 embedded processor. - This driver can access PCH GPIO device. - - This driver also can be used for LAPIS Semiconductor IOH(Input/ - Output Hub), ML7223 and ML7831. - ML7223 IOH is for MP(Media Phone) use. - ML7831 IOH is for general purpose use. - ML7223/ML7831 is companion chip for Intel Atom E6xx series. - ML7223/ML7831 is completely compatible for Intel EG20T PCH. - -config GPIO_ML_IOH - tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" - depends on PCI - select GENERIC_IRQ_CHIP - help - ML7213 is companion chip for Intel Atom E6xx series. - This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output - Hub) which is for IVI(In-Vehicle Infotainment) use. - This driver can access the IOH's GPIO device. - -config GPIO_SODAVILLE - bool "Intel Sodaville GPIO support" - depends on X86 && PCI && OF - select GPIO_GENERIC - select GENERIC_IRQ_CHIP - help - Say Y here to support Intel Sodaville GPIO. - -config GPIO_TIMBERDALE - bool "Support for timberdale GPIO IP" - depends on MFD_TIMBERDALE && HAS_IOMEM - ---help--- - Add support for the GPIO IP in the timberdale FPGA. - -config GPIO_RDC321X - tristate "RDC R-321x GPIO support" - depends on PCI - select MFD_CORE - select MFD_RDC321X - help - Support for the RDC R321x SoC GPIOs over southbridge - PCI configuration space. - -comment "SPI GPIO expanders:" - -config GPIO_MAX7301 - tristate "Maxim MAX7301 GPIO expander" - depends on SPI_MASTER - select GPIO_MAX730X - help - GPIO driver for Maxim MAX7301 SPI-based GPIO expander. - -config GPIO_MCP23S08 - tristate "Microchip MCP23xxx I/O expander" - depends on SPI_MASTER || I2C - help - SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 - I/O expanders. - This provides a GPIO interface supporting inputs and outputs. - -config GPIO_MC33880 - tristate "Freescale MC33880 high-side/low-side switch" - depends on SPI_MASTER - help - SPI driver for Freescale MC33880 high-side/low-side switch. - This provides GPIO interface supporting inputs and outputs. - -config GPIO_74X164 - tristate "74x164 serial-in/parallel-out 8-bits shift register" - depends on SPI_MASTER - help - Platform driver for 74x164 compatible serial-in/parallel-out - 8-outputs shift registers. This driver can be used to provide access - to more gpio outputs. - -comment "AC97 GPIO expanders:" - -config GPIO_UCB1400 - bool "Philips UCB1400 GPIO" - depends on UCB1400_CORE - help - This enables support for the Philips UCB1400 GPIO pins. - The UCB1400 is an AC97 audio codec. - -comment "MODULbus GPIO expanders:" - -config GPIO_JANZ_TTL - tristate "Janz VMOD-TTL Digital IO Module" - depends on MFD_JANZ_CMODIO - help - This enables support for the Janz VMOD-TTL Digital IO module. - This driver provides support for driving the pins in output - mode only. Input mode is not supported. - -config GPIO_AB8500 - bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions" - depends on AB8500_CORE && BROKEN - help - Select this to enable the AB8500 IC GPIO driver - -config GPIO_TPS65910 - bool "TPS65910 GPIO" - depends on MFD_TPS65910 - help - Select this option to enable GPIO driver for the TPS65910 - chip family. -endif diff --git a/ANDROID_3.4.5/drivers/gpio/Makefile b/ANDROID_3.4.5/drivers/gpio/Makefile deleted file mode 100644 index 007f54bd..00000000 --- a/ANDROID_3.4.5/drivers/gpio/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# generic gpio support: platform drivers, dedicated expander chips, etc - -ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG - -obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o - -# Device drivers. Generally keep list sorted alphabetically -obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o - -obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o -obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o -obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o -obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o -obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o -obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o -obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o -obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o -obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o -obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o -obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o -obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o -obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o -obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o -obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o -obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o -obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o -obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o -obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o -obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o -obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o -obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o -obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o -obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o -obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o -obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o -obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o -obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o -obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o -obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o -obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o -obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o -obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o -obj-$(CONFIG_GPIO_PCH) += gpio-pch.o -obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o -obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o -obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o -obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o -obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o -obj-$(CONFIG_GPIO_SCH) += gpio-sch.o -obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o -obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o -obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o -obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o -obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o -obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o -obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o -obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o -obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o -obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o -obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o -obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o -obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o -obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o -obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o -obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o -obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o diff --git a/ANDROID_3.4.5/drivers/gpio/devres.c b/ANDROID_3.4.5/drivers/gpio/devres.c deleted file mode 100644 index 3dd29399..00000000 --- a/ANDROID_3.4.5/drivers/gpio/devres.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * drivers/gpio/devres.c - managed gpio resources - * - * 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. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This file is based on kernel/irq/devres.c - * - * Copyright (c) 2011 John Crispin <blogic@openwrt.org> - */ - -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/device.h> -#include <linux/gfp.h> - -static void devm_gpio_release(struct device *dev, void *res) -{ - unsigned *gpio = res; - - gpio_free(*gpio); -} - -static int devm_gpio_match(struct device *dev, void *res, void *data) -{ - unsigned *this = res, *gpio = data; - - return *this == *gpio; -} - -/** - * devm_gpio_request - request a gpio for a managed device - * @dev: device to request the gpio for - * @gpio: gpio to allocate - * @label: the name of the requested gpio - * - * Except for the extra @dev argument, this function takes the - * same arguments and performs the same function as - * gpio_request(). GPIOs requested with this function will be - * automatically freed on driver detach. - * - * If an GPIO allocated with this function needs to be freed - * separately, devm_gpio_free() must be used. - */ - -int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) -{ - unsigned *dr; - int rc; - - dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - rc = gpio_request(gpio, label); - if (rc) { - devres_free(dr); - return rc; - } - - *dr = gpio; - devres_add(dev, dr); - - return 0; -} -EXPORT_SYMBOL(devm_gpio_request); - -/** - * devm_gpio_free - free an interrupt - * @dev: device to free gpio for - * @gpio: gpio to free - * - * Except for the extra @dev argument, this function takes the - * same arguments and performs the same function as gpio_free(). - * This function instead of gpio_free() should be used to manually - * free GPIOs allocated with devm_gpio_request(). - */ -void devm_gpio_free(struct device *dev, unsigned int gpio) -{ - - WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match, - &gpio)); - gpio_free(gpio); -} -EXPORT_SYMBOL(devm_gpio_free); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-74x164.c b/ANDROID_3.4.5/drivers/gpio/gpio-74x164.c deleted file mode 100644 index a31ad6f5..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-74x164.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver - * - * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> - * Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com> - * - * 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/init.h> -#include <linux/mutex.h> -#include <linux/spi/spi.h> -#include <linux/spi/74x164.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/module.h> - -struct gen_74x164_chip { - struct spi_device *spi; - struct gpio_chip gpio_chip; - struct mutex lock; - u8 port_config; -}; - -static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) -{ - return container_of(gc, struct gen_74x164_chip, gpio_chip); -} - -static int __gen_74x164_write_config(struct gen_74x164_chip *chip) -{ - return spi_write(chip->spi, - &chip->port_config, sizeof(chip->port_config)); -} - -static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) -{ - struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); - int ret; - - mutex_lock(&chip->lock); - ret = (chip->port_config >> offset) & 0x1; - mutex_unlock(&chip->lock); - - return ret; -} - -static void gen_74x164_set_value(struct gpio_chip *gc, - unsigned offset, int val) -{ - struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); - - mutex_lock(&chip->lock); - if (val) - chip->port_config |= (1 << offset); - else - chip->port_config &= ~(1 << offset); - - __gen_74x164_write_config(chip); - mutex_unlock(&chip->lock); -} - -static int gen_74x164_direction_output(struct gpio_chip *gc, - unsigned offset, int val) -{ - gen_74x164_set_value(gc, offset, val); - return 0; -} - -static int __devinit gen_74x164_probe(struct spi_device *spi) -{ - struct gen_74x164_chip *chip; - struct gen_74x164_chip_platform_data *pdata; - int ret; - - pdata = spi->dev.platform_data; - if (!pdata || !pdata->base) { - dev_dbg(&spi->dev, "incorrect or missing platform data\n"); - return -EINVAL; - } - - /* - * bits_per_word cannot be configured in platform data - */ - spi->bits_per_word = 8; - - ret = spi_setup(spi); - if (ret < 0) - return ret; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - mutex_init(&chip->lock); - - dev_set_drvdata(&spi->dev, chip); - - chip->spi = spi; - - chip->gpio_chip.label = spi->modalias; - chip->gpio_chip.direction_output = gen_74x164_direction_output; - chip->gpio_chip.get = gen_74x164_get_value; - chip->gpio_chip.set = gen_74x164_set_value; - chip->gpio_chip.base = pdata->base; - chip->gpio_chip.ngpio = 8; - chip->gpio_chip.can_sleep = 1; - chip->gpio_chip.dev = &spi->dev; - chip->gpio_chip.owner = THIS_MODULE; - - ret = __gen_74x164_write_config(chip); - if (ret) { - dev_err(&spi->dev, "Failed writing: %d\n", ret); - goto exit_destroy; - } - - ret = gpiochip_add(&chip->gpio_chip); - if (ret) - goto exit_destroy; - - return ret; - -exit_destroy: - dev_set_drvdata(&spi->dev, NULL); - mutex_destroy(&chip->lock); - kfree(chip); - return ret; -} - -static int __devexit gen_74x164_remove(struct spi_device *spi) -{ - struct gen_74x164_chip *chip; - int ret; - - chip = dev_get_drvdata(&spi->dev); - if (chip == NULL) - return -ENODEV; - - dev_set_drvdata(&spi->dev, NULL); - - ret = gpiochip_remove(&chip->gpio_chip); - if (!ret) { - mutex_destroy(&chip->lock); - kfree(chip); - } else - dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", - ret); - - return ret; -} - -static struct spi_driver gen_74x164_driver = { - .driver = { - .name = "74x164", - .owner = THIS_MODULE, - }, - .probe = gen_74x164_probe, - .remove = __devexit_p(gen_74x164_remove), -}; - -static int __init gen_74x164_init(void) -{ - return spi_register_driver(&gen_74x164_driver); -} -subsys_initcall(gen_74x164_init); - -static void __exit gen_74x164_exit(void) -{ - spi_unregister_driver(&gen_74x164_driver); -} -module_exit(gen_74x164_exit); - -MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); -MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); -MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ab8500.c b/ANDROID_3.4.5/drivers/gpio/gpio-ab8500.c deleted file mode 100644 index 050c05d9..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ab8500.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: BIBEK BASU <bibek.basu@stericsson.com> - * License terms: GNU General Public License (GPL) version 2 - * - * 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/types.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/mfd/ab8500.h> -#include <linux/mfd/abx500.h> -#include <linux/mfd/ab8500/gpio.h> - -/* - * GPIO registers offset - * Bank: 0x10 - */ -#define AB8500_GPIO_SEL1_REG 0x00 -#define AB8500_GPIO_SEL2_REG 0x01 -#define AB8500_GPIO_SEL3_REG 0x02 -#define AB8500_GPIO_SEL4_REG 0x03 -#define AB8500_GPIO_SEL5_REG 0x04 -#define AB8500_GPIO_SEL6_REG 0x05 - -#define AB8500_GPIO_DIR1_REG 0x10 -#define AB8500_GPIO_DIR2_REG 0x11 -#define AB8500_GPIO_DIR3_REG 0x12 -#define AB8500_GPIO_DIR4_REG 0x13 -#define AB8500_GPIO_DIR5_REG 0x14 -#define AB8500_GPIO_DIR6_REG 0x15 - -#define AB8500_GPIO_OUT1_REG 0x20 -#define AB8500_GPIO_OUT2_REG 0x21 -#define AB8500_GPIO_OUT3_REG 0x22 -#define AB8500_GPIO_OUT4_REG 0x23 -#define AB8500_GPIO_OUT5_REG 0x24 -#define AB8500_GPIO_OUT6_REG 0x25 - -#define AB8500_GPIO_PUD1_REG 0x30 -#define AB8500_GPIO_PUD2_REG 0x31 -#define AB8500_GPIO_PUD3_REG 0x32 -#define AB8500_GPIO_PUD4_REG 0x33 -#define AB8500_GPIO_PUD5_REG 0x34 -#define AB8500_GPIO_PUD6_REG 0x35 - -#define AB8500_GPIO_IN1_REG 0x40 -#define AB8500_GPIO_IN2_REG 0x41 -#define AB8500_GPIO_IN3_REG 0x42 -#define AB8500_GPIO_IN4_REG 0x43 -#define AB8500_GPIO_IN5_REG 0x44 -#define AB8500_GPIO_IN6_REG 0x45 -#define AB8500_GPIO_ALTFUN_REG 0x45 -#define ALTFUN_REG_INDEX 6 -#define AB8500_NUM_GPIO 42 -#define AB8500_NUM_VIR_GPIO_IRQ 16 - -enum ab8500_gpio_action { - NONE, - STARTUP, - SHUTDOWN, - MASK, - UNMASK -}; - -struct ab8500_gpio { - struct gpio_chip chip; - struct ab8500 *parent; - struct device *dev; - struct mutex lock; - u32 irq_base; - enum ab8500_gpio_action irq_action; - u16 rising; - u16 falling; -}; -/** - * to_ab8500_gpio() - get the pointer to ab8500_gpio - * @chip: Member of the structure ab8500_gpio - */ -static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct ab8500_gpio, chip); -} - -static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg, - unsigned offset, int val) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - u8 pos = offset % 8; - int ret; - - reg = reg + (offset / 8); - ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev, - AB8500_MISC, reg, 1 << pos, val << pos); - if (ret < 0) - dev_err(ab8500_gpio->dev, "%s write failed\n", __func__); - return ret; -} -/** - * ab8500_gpio_get() - Get the particular GPIO value - * @chip: Gpio device - * @offset: GPIO number to read - */ -static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - u8 mask = 1 << (offset % 8); - u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8); - int ret; - u8 data; - ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC, - reg, &data); - if (ret < 0) { - dev_err(ab8500_gpio->dev, "%s read failed\n", __func__); - return ret; - } - return (data & mask) >> (offset % 8); -} - -static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - int ret; - /* Write the data */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1); - if (ret < 0) - dev_err(ab8500_gpio->dev, "%s write failed\n", __func__); -} - -static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - int ret; - /* set direction as output */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1); - if (ret < 0) - return ret; - /* disable pull down */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1); - if (ret < 0) - return ret; - /* set the output as 1 or 0 */ - return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); - -} - -static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - /* set the register as input */ - return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0); -} - -static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - /* - * Only some GPIOs are interrupt capable, and they are - * organized in discontiguous clusters: - * - * GPIO6 to GPIO13 - * GPIO24 and GPIO25 - * GPIO36 to GPIO41 - */ - static struct ab8500_gpio_irq_cluster { - int start; - int end; - } clusters[] = { - {.start = 6, .end = 13}, - {.start = 24, .end = 25}, - {.start = 36, .end = 41}, - }; - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - int base = ab8500_gpio->irq_base; - int i; - - for (i = 0; i < ARRAY_SIZE(clusters); i++) { - struct ab8500_gpio_irq_cluster *cluster = &clusters[i]; - - if (offset >= cluster->start && offset <= cluster->end) - return base + offset - cluster->start; - - /* Advance by the number of gpios in this cluster */ - base += cluster->end - cluster->start + 1; - } - - return -EINVAL; -} - -static struct gpio_chip ab8500gpio_chip = { - .label = "ab8500_gpio", - .owner = THIS_MODULE, - .direction_input = ab8500_gpio_direction_input, - .get = ab8500_gpio_get, - .direction_output = ab8500_gpio_direction_output, - .set = ab8500_gpio_set, - .to_irq = ab8500_gpio_to_irq, -}; - -static unsigned int irq_to_rising(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - int new_irq = offset + AB8500_INT_GPIO6R - + ab8500_gpio->parent->irq_base; - return new_irq; -} - -static unsigned int irq_to_falling(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - int new_irq = offset + AB8500_INT_GPIO6F - + ab8500_gpio->parent->irq_base; - return new_irq; - -} - -static unsigned int rising_to_irq(unsigned int irq, void *dev) -{ - struct ab8500_gpio *ab8500_gpio = dev; - int offset = irq - AB8500_INT_GPIO6R - - ab8500_gpio->parent->irq_base ; - int new_irq = offset + ab8500_gpio->irq_base; - return new_irq; -} - -static unsigned int falling_to_irq(unsigned int irq, void *dev) -{ - struct ab8500_gpio *ab8500_gpio = dev; - int offset = irq - AB8500_INT_GPIO6F - - ab8500_gpio->parent->irq_base ; - int new_irq = offset + ab8500_gpio->irq_base; - return new_irq; - -} - -/* - * IRQ handler - */ - -static irqreturn_t handle_rising(int irq, void *dev) -{ - - handle_nested_irq(rising_to_irq(irq , dev)); - return IRQ_HANDLED; -} - -static irqreturn_t handle_falling(int irq, void *dev) -{ - - handle_nested_irq(falling_to_irq(irq, dev)); - return IRQ_HANDLED; -} - -static void ab8500_gpio_irq_lock(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - mutex_lock(&ab8500_gpio->lock); -} - -static void ab8500_gpio_irq_sync_unlock(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - bool rising = ab8500_gpio->rising & BIT(offset); - bool falling = ab8500_gpio->falling & BIT(offset); - int ret; - - switch (ab8500_gpio->irq_action) { - case STARTUP: - if (rising) - ret = request_threaded_irq(irq_to_rising(irq), - NULL, handle_rising, - IRQF_TRIGGER_RISING, - "ab8500-gpio-r", ab8500_gpio); - if (falling) - ret = request_threaded_irq(irq_to_falling(irq), - NULL, handle_falling, - IRQF_TRIGGER_FALLING, - "ab8500-gpio-f", ab8500_gpio); - break; - case SHUTDOWN: - if (rising) - free_irq(irq_to_rising(irq), ab8500_gpio); - if (falling) - free_irq(irq_to_falling(irq), ab8500_gpio); - break; - case MASK: - if (rising) - disable_irq(irq_to_rising(irq)); - if (falling) - disable_irq(irq_to_falling(irq)); - break; - case UNMASK: - if (rising) - enable_irq(irq_to_rising(irq)); - if (falling) - enable_irq(irq_to_falling(irq)); - break; - case NONE: - break; - } - ab8500_gpio->irq_action = NONE; - ab8500_gpio->rising &= ~(BIT(offset)); - ab8500_gpio->falling &= ~(BIT(offset)); - mutex_unlock(&ab8500_gpio->lock); -} - - -static void ab8500_gpio_irq_mask(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = MASK; -} - -static void ab8500_gpio_irq_unmask(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = UNMASK; -} - -static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - - if (type == IRQ_TYPE_EDGE_BOTH) { - ab8500_gpio->rising = BIT(offset); - ab8500_gpio->falling = BIT(offset); - } else if (type == IRQ_TYPE_EDGE_RISING) { - ab8500_gpio->rising = BIT(offset); - } else { - ab8500_gpio->falling = BIT(offset); - } - return 0; -} - -unsigned int ab8500_gpio_irq_startup(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = STARTUP; - return 0; -} - -void ab8500_gpio_irq_shutdown(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = SHUTDOWN; -} - -static struct irq_chip ab8500_gpio_irq_chip = { - .name = "ab8500-gpio", - .startup = ab8500_gpio_irq_startup, - .shutdown = ab8500_gpio_irq_shutdown, - .bus_lock = ab8500_gpio_irq_lock, - .bus_sync_unlock = ab8500_gpio_irq_sync_unlock, - .mask = ab8500_gpio_irq_mask, - .unmask = ab8500_gpio_irq_unmask, - .set_type = ab8500_gpio_irq_set_type, -}; - -static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio) -{ - u32 base = ab8500_gpio->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) { - set_irq_chip_data(irq, ab8500_gpio); - set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip, - handle_simple_irq); - set_irq_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - set_irq_noprobe(irq); -#endif - } - - return 0; -} - -static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio) -{ - int base = ab8500_gpio->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - set_irq_chip_and_handler(irq, NULL, NULL); - set_irq_chip_data(irq, NULL); - } -} - -static int __devinit ab8500_gpio_probe(struct platform_device *pdev) -{ - struct ab8500_platform_data *ab8500_pdata = - dev_get_platdata(pdev->dev.parent); - struct ab8500_gpio_platform_data *pdata; - struct ab8500_gpio *ab8500_gpio; - int ret; - int i; - - pdata = ab8500_pdata->gpio; - if (!pdata) { - dev_err(&pdev->dev, "gpio platform data missing\n"); - return -ENODEV; - } - - ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL); - if (ab8500_gpio == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - ab8500_gpio->dev = &pdev->dev; - ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent); - ab8500_gpio->chip = ab8500gpio_chip; - ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO; - ab8500_gpio->chip.dev = &pdev->dev; - ab8500_gpio->chip.base = pdata->gpio_base; - ab8500_gpio->irq_base = pdata->irq_base; - /* initialize the lock */ - mutex_init(&ab8500_gpio->lock); - /* - * AB8500 core will handle and clear the IRQ - * configre GPIO based on config-reg value. - * These values are for selecting the PINs as - * GPIO or alternate function - */ - for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++) { - ret = abx500_set_register_interruptible(ab8500_gpio->dev, - AB8500_MISC, i, - pdata->config_reg[i]); - if (ret < 0) - goto out_free; - } - ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC, - AB8500_GPIO_ALTFUN_REG, - pdata->config_reg[ALTFUN_REG_INDEX]); - if (ret < 0) - goto out_free; - - ret = ab8500_gpio_irq_init(ab8500_gpio); - if (ret) - goto out_free; - ret = gpiochip_add(&ab8500_gpio->chip); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", - ret); - goto out_rem_irq; - } - platform_set_drvdata(pdev, ab8500_gpio); - return 0; - -out_rem_irq: - ab8500_gpio_irq_remove(ab8500_gpio); -out_free: - mutex_destroy(&ab8500_gpio->lock); - kfree(ab8500_gpio); - return ret; -} - -/* - * ab8500_gpio_remove() - remove Ab8500-gpio driver - * @pdev : Platform device registered - */ -static int __devexit ab8500_gpio_remove(struct platform_device *pdev) -{ - struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&ab8500_gpio->chip); - if (ret < 0) { - dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, NULL); - mutex_destroy(&ab8500_gpio->lock); - kfree(ab8500_gpio); - - return 0; -} - -static struct platform_driver ab8500_gpio_driver = { - .driver = { - .name = "ab8500-gpio", - .owner = THIS_MODULE, - }, - .probe = ab8500_gpio_probe, - .remove = __devexit_p(ab8500_gpio_remove), -}; - -static int __init ab8500_gpio_init(void) -{ - return platform_driver_register(&ab8500_gpio_driver); -} -arch_initcall(ab8500_gpio_init); - -static void __exit ab8500_gpio_exit(void) -{ - platform_driver_unregister(&ab8500_gpio_driver); -} -module_exit(ab8500_gpio_exit); - -MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>"); -MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO"); -MODULE_ALIAS("platform:ab8500-gpio"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-adp5520.c b/ANDROID_3.4.5/drivers/gpio/gpio-adp5520.c deleted file mode 100644 index 2f263cc3..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-adp5520.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * GPIO driver for Analog Devices ADP5520 MFD PMICs - * - * Copyright 2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mfd/adp5520.h> - -#include <linux/gpio.h> - -struct adp5520_gpio { - struct device *master; - struct gpio_chip gpio_chip; - unsigned char lut[ADP5520_MAXGPIOS]; - unsigned long output; -}; - -static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) -{ - struct adp5520_gpio *dev; - uint8_t reg_val; - - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - /* - * There are dedicated registers for GPIO IN/OUT. - * Make sure we return the right value, even when configured as output - */ - - if (test_bit(off, &dev->output)) - adp5520_read(dev->master, ADP5520_GPIO_OUT, ®_val); - else - adp5520_read(dev->master, ADP5520_GPIO_IN, ®_val); - - return !!(reg_val & dev->lut[off]); -} - -static void adp5520_gpio_set_value(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5520_gpio *dev; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - if (val) - adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); - else - adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); -} - -static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) -{ - struct adp5520_gpio *dev; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - clear_bit(off, &dev->output); - - return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2, - dev->lut[off]); -} - -static int adp5520_gpio_direction_output(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5520_gpio *dev; - int ret = 0; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - set_bit(off, &dev->output); - - if (val) - ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, - dev->lut[off]); - else - ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, - dev->lut[off]); - - ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2, - dev->lut[off]); - - return ret; -} - -static int __devinit adp5520_gpio_probe(struct platform_device *pdev) -{ - struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data; - struct adp5520_gpio *dev; - struct gpio_chip *gc; - int ret, i, gpios; - unsigned char ctl_mask = 0; - - if (pdata == NULL) { - dev_err(&pdev->dev, "missing platform data\n"); - return -ENODEV; - } - - if (pdev->id != ID_ADP5520) { - dev_err(&pdev->dev, "only ADP5520 supports GPIO\n"); - return -ENODEV; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&pdev->dev, "failed to alloc memory\n"); - return -ENOMEM; - } - - dev->master = pdev->dev.parent; - - for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++) - if (pdata->gpio_en_mask & (1 << i)) - dev->lut[gpios++] = 1 << i; - - if (gpios < 1) { - ret = -EINVAL; - goto err; - } - - gc = &dev->gpio_chip; - gc->direction_input = adp5520_gpio_direction_input; - gc->direction_output = adp5520_gpio_direction_output; - gc->get = adp5520_gpio_get_value; - gc->set = adp5520_gpio_set_value; - gc->can_sleep = 1; - - gc->base = pdata->gpio_start; - gc->ngpio = gpios; - gc->label = pdev->name; - gc->owner = THIS_MODULE; - - ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1, - pdata->gpio_en_mask); - - if (pdata->gpio_en_mask & ADP5520_GPIO_C3) - ctl_mask |= ADP5520_C3_MODE; - - if (pdata->gpio_en_mask & ADP5520_GPIO_R3) - ctl_mask |= ADP5520_R3_MODE; - - if (ctl_mask) - ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, - ctl_mask); - - ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, - pdata->gpio_pullup_mask); - - if (ret) { - dev_err(&pdev->dev, "failed to write\n"); - goto err; - } - - ret = gpiochip_add(&dev->gpio_chip); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - kfree(dev); - return ret; -} - -static int __devexit adp5520_gpio_remove(struct platform_device *pdev) -{ - struct adp5520_gpio *dev; - int ret; - - dev = platform_get_drvdata(pdev); - ret = gpiochip_remove(&dev->gpio_chip); - if (ret) { - dev_err(&pdev->dev, "%s failed, %d\n", - "gpiochip_remove()", ret); - return ret; - } - - kfree(dev); - return 0; -} - -static struct platform_driver adp5520_gpio_driver = { - .driver = { - .name = "adp5520-gpio", - .owner = THIS_MODULE, - }, - .probe = adp5520_gpio_probe, - .remove = __devexit_p(adp5520_gpio_remove), -}; - -module_platform_driver(adp5520_gpio_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("GPIO ADP5520 Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:adp5520-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-adp5588.c b/ANDROID_3.4.5/drivers/gpio/gpio-adp5588.c deleted file mode 100644 index ae5d7f12..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-adp5588.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * GPIO Chip driver for Analog Devices - * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller - * - * Copyright 2009-2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/irq.h> - -#include <linux/i2c/adp5588.h> - -#define DRV_NAME "adp5588-gpio" - -/* - * Early pre 4.0 Silicon required to delay readout by at least 25ms, - * since the Event Counter Register updated 25ms after the interrupt - * asserted. - */ -#define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4) - -struct adp5588_gpio { - struct i2c_client *client; - struct gpio_chip gpio_chip; - struct mutex lock; /* protect cached dir, dat_out */ - /* protect serialized access to the interrupt controller bus */ - struct mutex irq_lock; - unsigned gpio_start; - unsigned irq_base; - uint8_t dat_out[3]; - uint8_t dir[3]; - uint8_t int_lvl[3]; - uint8_t int_en[3]; - uint8_t irq_mask[3]; - uint8_t irq_stat[3]; -}; - -static int adp5588_gpio_read(struct i2c_client *client, u8 reg) -{ - int ret = i2c_smbus_read_byte_data(client, reg); - - if (ret < 0) - dev_err(&client->dev, "Read Error\n"); - - return ret; -} - -static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val) -{ - int ret = i2c_smbus_write_byte_data(client, reg, val); - - if (ret < 0) - dev_err(&client->dev, "Write Error\n"); - - return ret; -} - -static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) -{ - struct adp5588_gpio *dev = - container_of(chip, struct adp5588_gpio, gpio_chip); - - return !!(adp5588_gpio_read(dev->client, - GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off)); -} - -static void adp5588_gpio_set_value(struct gpio_chip *chip, - unsigned off, int val) -{ - unsigned bank, bit; - struct adp5588_gpio *dev = - container_of(chip, struct adp5588_gpio, gpio_chip); - - bank = ADP5588_BANK(off); - bit = ADP5588_BIT(off); - - mutex_lock(&dev->lock); - if (val) - dev->dat_out[bank] |= bit; - else - dev->dat_out[bank] &= ~bit; - - adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank, - dev->dat_out[bank]); - mutex_unlock(&dev->lock); -} - -static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) -{ - int ret; - unsigned bank; - struct adp5588_gpio *dev = - container_of(chip, struct adp5588_gpio, gpio_chip); - - bank = ADP5588_BANK(off); - - mutex_lock(&dev->lock); - dev->dir[bank] &= ~ADP5588_BIT(off); - ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]); - mutex_unlock(&dev->lock); - - return ret; -} - -static int adp5588_gpio_direction_output(struct gpio_chip *chip, - unsigned off, int val) -{ - int ret; - unsigned bank, bit; - struct adp5588_gpio *dev = - container_of(chip, struct adp5588_gpio, gpio_chip); - - bank = ADP5588_BANK(off); - bit = ADP5588_BIT(off); - - mutex_lock(&dev->lock); - dev->dir[bank] |= bit; - - if (val) - dev->dat_out[bank] |= bit; - else - dev->dat_out[bank] &= ~bit; - - ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank, - dev->dat_out[bank]); - ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, - dev->dir[bank]); - mutex_unlock(&dev->lock); - - return ret; -} - -#ifdef CONFIG_GPIO_ADP5588_IRQ -static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off) -{ - struct adp5588_gpio *dev = - container_of(chip, struct adp5588_gpio, gpio_chip); - return dev->irq_base + off; -} - -static void adp5588_irq_bus_lock(struct irq_data *d) -{ - struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); - - mutex_lock(&dev->irq_lock); -} - - /* - * genirq core code can issue chip->mask/unmask from atomic context. - * This doesn't work for slow busses where an access needs to sleep. - * bus_sync_unlock() is therefore called outside the atomic context, - * syncs the current irq mask state with the slow external controller - * and unlocks the bus. - */ - -static void adp5588_irq_bus_sync_unlock(struct irq_data *d) -{ - struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); - int i; - - for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) - if (dev->int_en[i] ^ dev->irq_mask[i]) { - dev->int_en[i] = dev->irq_mask[i]; - adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i, - dev->int_en[i]); - } - - mutex_unlock(&dev->irq_lock); -} - -static void adp5588_irq_mask(struct irq_data *d) -{ - struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); - unsigned gpio = d->irq - dev->irq_base; - - dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio); -} - -static void adp5588_irq_unmask(struct irq_data *d) -{ - struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); - unsigned gpio = d->irq - dev->irq_base; - - dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); -} - -static int adp5588_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); - uint16_t gpio = d->irq - dev->irq_base; - unsigned bank, bit; - - if ((type & IRQ_TYPE_EDGE_BOTH)) { - dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", - d->irq, type); - return -EINVAL; - } - - bank = ADP5588_BANK(gpio); - bit = ADP5588_BIT(gpio); - - if (type & IRQ_TYPE_LEVEL_HIGH) - dev->int_lvl[bank] |= bit; - else if (type & IRQ_TYPE_LEVEL_LOW) - dev->int_lvl[bank] &= ~bit; - else - return -EINVAL; - - adp5588_gpio_direction_input(&dev->gpio_chip, gpio); - adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank, - dev->int_lvl[bank]); - - return 0; -} - -static struct irq_chip adp5588_irq_chip = { - .name = "adp5588", - .irq_mask = adp5588_irq_mask, - .irq_unmask = adp5588_irq_unmask, - .irq_bus_lock = adp5588_irq_bus_lock, - .irq_bus_sync_unlock = adp5588_irq_bus_sync_unlock, - .irq_set_type = adp5588_irq_set_type, -}; - -static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf) -{ - int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf); - - if (ret < 0) - dev_err(&client->dev, "Read INT_STAT Error\n"); - - return ret; -} - -static irqreturn_t adp5588_irq_handler(int irq, void *devid) -{ - struct adp5588_gpio *dev = devid; - unsigned status, bank, bit, pending; - int ret; - status = adp5588_gpio_read(dev->client, INT_STAT); - - if (status & ADP5588_GPI_INT) { - ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat); - if (ret < 0) - memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat)); - - for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO); - bank++, bit = 0) { - pending = dev->irq_stat[bank] & dev->irq_mask[bank]; - - while (pending) { - if (pending & (1 << bit)) { - handle_nested_irq(dev->irq_base + - (bank << 3) + bit); - pending &= ~(1 << bit); - - } - bit++; - } - } - } - - adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */ - - return IRQ_HANDLED; -} - -static int adp5588_irq_setup(struct adp5588_gpio *dev) -{ - struct i2c_client *client = dev->client; - struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; - unsigned gpio; - int ret; - - adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC); - adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */ - adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */ - - dev->irq_base = pdata->irq_base; - mutex_init(&dev->irq_lock); - - for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) { - int irq = gpio + dev->irq_base; - irq_set_chip_data(irq, dev); - irq_set_chip_and_handler(irq, &adp5588_irq_chip, - handle_level_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - /* - * ARM needs us to explicitly flag the IRQ as VALID, - * once we do so, it will also set the noprobe. - */ - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - ret = request_threaded_irq(client->irq, - NULL, - adp5588_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(&client->dev), dev); - if (ret) { - dev_err(&client->dev, "failed to request irq %d\n", - client->irq); - goto out; - } - - dev->gpio_chip.to_irq = adp5588_gpio_to_irq; - adp5588_gpio_write(client, CFG, - ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT); - - return 0; - -out: - dev->irq_base = 0; - return ret; -} - -static void adp5588_irq_teardown(struct adp5588_gpio *dev) -{ - if (dev->irq_base) - free_irq(dev->client->irq, dev); -} - -#else -static int adp5588_irq_setup(struct adp5588_gpio *dev) -{ - struct i2c_client *client = dev->client; - dev_warn(&client->dev, "interrupt support not compiled in\n"); - - return 0; -} - -static void adp5588_irq_teardown(struct adp5588_gpio *dev) -{ -} -#endif /* CONFIG_GPIO_ADP5588_IRQ */ - -static int __devinit adp5588_gpio_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; - struct adp5588_gpio *dev; - struct gpio_chip *gc; - int ret, i, revid; - - if (pdata == NULL) { - dev_err(&client->dev, "missing platform data\n"); - return -ENODEV; - } - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); - return -EIO; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&client->dev, "failed to alloc memory\n"); - return -ENOMEM; - } - - dev->client = client; - - gc = &dev->gpio_chip; - gc->direction_input = adp5588_gpio_direction_input; - gc->direction_output = adp5588_gpio_direction_output; - gc->get = adp5588_gpio_get_value; - gc->set = adp5588_gpio_set_value; - gc->can_sleep = 1; - - gc->base = pdata->gpio_start; - gc->ngpio = ADP5588_MAXGPIO; - gc->label = client->name; - gc->owner = THIS_MODULE; - - mutex_init(&dev->lock); - - ret = adp5588_gpio_read(dev->client, DEV_ID); - if (ret < 0) - goto err; - - revid = ret & ADP5588_DEVICE_ID_MASK; - - for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { - dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i); - dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); - ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); - ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, - (pdata->pullup_dis_mask >> (8 * i)) & 0xFF); - ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0); - if (ret) - goto err; - } - - if (pdata->irq_base) { - if (WA_DELAYED_READOUT_REVID(revid)) { - dev_warn(&client->dev, "GPIO int not supported\n"); - } else { - ret = adp5588_irq_setup(dev); - if (ret) - goto err; - } - } - - ret = gpiochip_add(&dev->gpio_chip); - if (ret) - goto err_irq; - - dev_info(&client->dev, "IRQ Base: %d Rev.: %d\n", - pdata->irq_base, revid); - - if (pdata->setup) { - ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - i2c_set_clientdata(client, dev); - - return 0; - -err_irq: - adp5588_irq_teardown(dev); -err: - kfree(dev); - return ret; -} - -static int __devexit adp5588_gpio_remove(struct i2c_client *client) -{ - struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; - struct adp5588_gpio *dev = i2c_get_clientdata(client); - int ret; - - if (pdata->teardown) { - ret = pdata->teardown(client, - dev->gpio_chip.base, dev->gpio_chip.ngpio, - pdata->context); - if (ret < 0) { - dev_err(&client->dev, "teardown failed %d\n", ret); - return ret; - } - } - - if (dev->irq_base) - free_irq(dev->client->irq, dev); - - ret = gpiochip_remove(&dev->gpio_chip); - if (ret) { - dev_err(&client->dev, "gpiochip_remove failed %d\n", ret); - return ret; - } - - kfree(dev); - return 0; -} - -static const struct i2c_device_id adp5588_gpio_id[] = { - {DRV_NAME, 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id); - -static struct i2c_driver adp5588_gpio_driver = { - .driver = { - .name = DRV_NAME, - }, - .probe = adp5588_gpio_probe, - .remove = __devexit_p(adp5588_gpio_remove), - .id_table = adp5588_gpio_id, -}; - -static int __init adp5588_gpio_init(void) -{ - return i2c_add_driver(&adp5588_gpio_driver); -} - -module_init(adp5588_gpio_init); - -static void __exit adp5588_gpio_exit(void) -{ - i2c_del_driver(&adp5588_gpio_driver); -} - -module_exit(adp5588_gpio_exit); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("GPIO ADP5588 Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-bt8xx.c b/ANDROID_3.4.5/drivers/gpio/gpio-bt8xx.c deleted file mode 100644 index 5ca4098b..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-bt8xx.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - - bt8xx GPIO abuser - - Copyright (C) 2008 Michael Buesch <m@bues.ch> - - Please do _only_ contact the people listed _above_ with issues related to this driver. - All the other people listed below are not related to this driver. Their names - are only here, because this driver is derived from the bt848 driver. - - - Derived from the bt848 driver: - - Copyright (C) 1996,97,98 Ralph Metzler - & Marcus Metzler - (c) 1999-2002 Gerd Knorr - - some v4l2 code lines are taken from Justin's bttv2 driver which is - (c) 2000 Justin Schoeman - - V4L1 removal from: - (c) 2005-2006 Nickolay V. Shmyrev - - Fixes to be fully V4L2 compliant by - (c) 2006 Mauro Carvalho Chehab - - Cropping and overscan support - Copyright (C) 2005, 2006 Michael H. Schimek - Sponsored by OPQ Systems AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/spinlock.h> -#include <linux/gpio.h> -#include <linux/slab.h> - -/* Steal the hardware definitions from the bttv driver. */ -#include "../media/video/bt8xx/bt848.h" - - -#define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */ - - -struct bt8xxgpio { - spinlock_t lock; - - void __iomem *mmio; - struct pci_dev *pdev; - struct gpio_chip gpio; - -#ifdef CONFIG_PM - u32 saved_outen; - u32 saved_data; -#endif -}; - -#define bgwrite(dat, adr) writel((dat), bg->mmio+(adr)) -#define bgread(adr) readl(bg->mmio+(adr)) - - -static int modparam_gpiobase = -1/* dynamic */; -module_param_named(gpiobase, modparam_gpiobase, int, 0444); -MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default."); - - -static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) -{ - struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); - unsigned long flags; - u32 outen, data; - - spin_lock_irqsave(&bg->lock, flags); - - data = bgread(BT848_GPIO_DATA); - data &= ~(1 << nr); - bgwrite(data, BT848_GPIO_DATA); - - outen = bgread(BT848_GPIO_OUT_EN); - outen &= ~(1 << nr); - bgwrite(outen, BT848_GPIO_OUT_EN); - - spin_unlock_irqrestore(&bg->lock, flags); - - return 0; -} - -static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) -{ - struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); - unsigned long flags; - u32 val; - - spin_lock_irqsave(&bg->lock, flags); - val = bgread(BT848_GPIO_DATA); - spin_unlock_irqrestore(&bg->lock, flags); - - return !!(val & (1 << nr)); -} - -static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, - unsigned nr, int val) -{ - struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); - unsigned long flags; - u32 outen, data; - - spin_lock_irqsave(&bg->lock, flags); - - outen = bgread(BT848_GPIO_OUT_EN); - outen |= (1 << nr); - bgwrite(outen, BT848_GPIO_OUT_EN); - - data = bgread(BT848_GPIO_DATA); - if (val) - data |= (1 << nr); - else - data &= ~(1 << nr); - bgwrite(data, BT848_GPIO_DATA); - - spin_unlock_irqrestore(&bg->lock, flags); - - return 0; -} - -static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, - unsigned nr, int val) -{ - struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&bg->lock, flags); - - data = bgread(BT848_GPIO_DATA); - if (val) - data |= (1 << nr); - else - data &= ~(1 << nr); - bgwrite(data, BT848_GPIO_DATA); - - spin_unlock_irqrestore(&bg->lock, flags); -} - -static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) -{ - struct gpio_chip *c = &bg->gpio; - - c->label = dev_name(&bg->pdev->dev); - c->owner = THIS_MODULE; - c->direction_input = bt8xxgpio_gpio_direction_input; - c->get = bt8xxgpio_gpio_get; - c->direction_output = bt8xxgpio_gpio_direction_output; - c->set = bt8xxgpio_gpio_set; - c->dbg_show = NULL; - c->base = modparam_gpiobase; - c->ngpio = BT8XXGPIO_NR_GPIOS; - c->can_sleep = 0; -} - -static int bt8xxgpio_probe(struct pci_dev *dev, - const struct pci_device_id *pci_id) -{ - struct bt8xxgpio *bg; - int err; - - bg = kzalloc(sizeof(*bg), GFP_KERNEL); - if (!bg) - return -ENOMEM; - - bg->pdev = dev; - spin_lock_init(&bg->lock); - - err = pci_enable_device(dev); - if (err) { - printk(KERN_ERR "bt8xxgpio: Can't enable device.\n"); - goto err_freebg; - } - if (!request_mem_region(pci_resource_start(dev, 0), - pci_resource_len(dev, 0), - "bt8xxgpio")) { - printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n", - (unsigned long long)pci_resource_start(dev, 0)); - err = -EBUSY; - goto err_disable; - } - pci_set_master(dev); - pci_set_drvdata(dev, bg); - - bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000); - if (!bg->mmio) { - printk(KERN_ERR "bt8xxgpio: ioremap() failed\n"); - err = -EIO; - goto err_release_mem; - } - - /* Disable interrupts */ - bgwrite(0, BT848_INT_MASK); - - /* gpio init */ - bgwrite(0, BT848_GPIO_DMA_CTL); - bgwrite(0, BT848_GPIO_REG_INP); - bgwrite(0, BT848_GPIO_OUT_EN); - - bt8xxgpio_gpio_setup(bg); - err = gpiochip_add(&bg->gpio); - if (err) { - printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n"); - goto err_release_mem; - } - - return 0; - -err_release_mem: - release_mem_region(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); - pci_set_drvdata(dev, NULL); -err_disable: - pci_disable_device(dev); -err_freebg: - kfree(bg); - - return err; -} - -static void bt8xxgpio_remove(struct pci_dev *pdev) -{ - struct bt8xxgpio *bg = pci_get_drvdata(pdev); - - gpiochip_remove(&bg->gpio); - - bgwrite(0, BT848_INT_MASK); - bgwrite(~0x0, BT848_INT_STAT); - bgwrite(0x0, BT848_GPIO_OUT_EN); - - iounmap(bg->mmio); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - pci_disable_device(pdev); - - pci_set_drvdata(pdev, NULL); - kfree(bg); -} - -#ifdef CONFIG_PM -static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct bt8xxgpio *bg = pci_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&bg->lock, flags); - - bg->saved_outen = bgread(BT848_GPIO_OUT_EN); - bg->saved_data = bgread(BT848_GPIO_DATA); - - bgwrite(0, BT848_INT_MASK); - bgwrite(~0x0, BT848_INT_STAT); - bgwrite(0x0, BT848_GPIO_OUT_EN); - - spin_unlock_irqrestore(&bg->lock, flags); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int bt8xxgpio_resume(struct pci_dev *pdev) -{ - struct bt8xxgpio *bg = pci_get_drvdata(pdev); - unsigned long flags; - int err; - - pci_set_power_state(pdev, 0); - err = pci_enable_device(pdev); - if (err) - return err; - pci_restore_state(pdev); - - spin_lock_irqsave(&bg->lock, flags); - - bgwrite(0, BT848_INT_MASK); - bgwrite(0, BT848_GPIO_DMA_CTL); - bgwrite(0, BT848_GPIO_REG_INP); - bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN); - bgwrite(bg->saved_data & bg->saved_outen, - BT848_GPIO_DATA); - - spin_unlock_irqrestore(&bg->lock, flags); - - return 0; -} -#else -#define bt8xxgpio_suspend NULL -#define bt8xxgpio_resume NULL -#endif /* CONFIG_PM */ - -static struct pci_device_id bt8xxgpio_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl); - -static struct pci_driver bt8xxgpio_pci_driver = { - .name = "bt8xxgpio", - .id_table = bt8xxgpio_pci_tbl, - .probe = bt8xxgpio_probe, - .remove = bt8xxgpio_remove, - .suspend = bt8xxgpio_suspend, - .resume = bt8xxgpio_resume, -}; - -static int __init bt8xxgpio_init(void) -{ - return pci_register_driver(&bt8xxgpio_pci_driver); -} -module_init(bt8xxgpio_init) - -static void __exit bt8xxgpio_exit(void) -{ - pci_unregister_driver(&bt8xxgpio_pci_driver); -} -module_exit(bt8xxgpio_exit) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-cs5535.c b/ANDROID_3.4.5/drivers/gpio/gpio-cs5535.c deleted file mode 100644 index 19eda1bb..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-cs5535.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * AMD CS5535/CS5536 GPIO driver - * Copyright (C) 2006 Advanced Micro Devices, Inc. - * Copyright (C) 2007-2009 Andres Salomon <dilinger@collabora.co.uk> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/spinlock.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/io.h> -#include <linux/cs5535.h> -#include <asm/msr.h> - -#define DRV_NAME "cs5535-gpio" - -/* - * Some GPIO pins - * 31-29,23 : reserved (always mask out) - * 28 : Power Button - * 26 : PME# - * 22-16 : LPC - * 14,15 : SMBus - * 9,8 : UART1 - * 7 : PCI INTB - * 3,4 : UART2/DDC - * 2 : IDE_IRQ0 - * 1 : AC_BEEP - * 0 : PCI INTA - * - * If a mask was not specified, allow all except - * reserved and Power Button - */ -#define GPIO_DEFAULT_MASK 0x0F7FFFFF - -static ulong mask = GPIO_DEFAULT_MASK; -module_param_named(mask, mask, ulong, 0444); -MODULE_PARM_DESC(mask, "GPIO channel mask."); - -static struct cs5535_gpio_chip { - struct gpio_chip chip; - resource_size_t base; - - struct platform_device *pdev; - spinlock_t lock; -} cs5535_gpio_chip; - -/* - * The CS5535/CS5536 GPIOs support a number of extra features not defined - * by the gpio_chip API, so these are exported. For a full list of the - * registers, see include/linux/cs5535.h. - */ - -static void errata_outl(struct cs5535_gpio_chip *chip, u32 val, - unsigned int reg) -{ - unsigned long addr = chip->base + 0x80 + reg; - - /* - * According to the CS5536 errata (#36), after suspend - * a write to the high bank GPIO register will clear all - * non-selected bits; the recommended workaround is a - * read-modify-write operation. - * - * Don't apply this errata to the edge status GPIOs, as writing - * to their lower bits will clear them. - */ - if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) { - if (val & 0xffff) - val |= (inl(addr) & 0xffff); /* ignore the high bits */ - else - val |= (inl(addr) ^ (val >> 16)); - } - outl(val, addr); -} - -static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, - unsigned int reg) -{ - if (offset < 16) - /* low bank register */ - outl(1 << offset, chip->base + reg); - else - /* high bank register */ - errata_outl(chip, 1 << (offset - 16), reg); -} - -void cs5535_gpio_set(unsigned offset, unsigned int reg) -{ - struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - __cs5535_gpio_set(chip, offset, reg); - spin_unlock_irqrestore(&chip->lock, flags); -} -EXPORT_SYMBOL_GPL(cs5535_gpio_set); - -static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset, - unsigned int reg) -{ - if (offset < 16) - /* low bank register */ - outl(1 << (offset + 16), chip->base + reg); - else - /* high bank register */ - errata_outl(chip, 1 << offset, reg); -} - -void cs5535_gpio_clear(unsigned offset, unsigned int reg) -{ - struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - __cs5535_gpio_clear(chip, offset, reg); - spin_unlock_irqrestore(&chip->lock, flags); -} -EXPORT_SYMBOL_GPL(cs5535_gpio_clear); - -int cs5535_gpio_isset(unsigned offset, unsigned int reg) -{ - struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; - unsigned long flags; - long val; - - spin_lock_irqsave(&chip->lock, flags); - if (offset < 16) - /* low bank register */ - val = inl(chip->base + reg); - else { - /* high bank register */ - val = inl(chip->base + 0x80 + reg); - offset -= 16; - } - spin_unlock_irqrestore(&chip->lock, flags); - - return (val & (1 << offset)) ? 1 : 0; -} -EXPORT_SYMBOL_GPL(cs5535_gpio_isset); - -int cs5535_gpio_set_irq(unsigned group, unsigned irq) -{ - uint32_t lo, hi; - - if (group > 7 || irq > 15) - return -EINVAL; - - rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi); - - lo &= ~(0xF << (group * 4)); - lo |= (irq & 0xF) << (group * 4); - - wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi); - return 0; -} -EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq); - -void cs5535_gpio_setup_event(unsigned offset, int pair, int pme) -{ - struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; - uint32_t shift = (offset % 8) * 4; - unsigned long flags; - uint32_t val; - - if (offset >= 24) - offset = GPIO_MAP_W; - else if (offset >= 16) - offset = GPIO_MAP_Z; - else if (offset >= 8) - offset = GPIO_MAP_Y; - else - offset = GPIO_MAP_X; - - spin_lock_irqsave(&chip->lock, flags); - val = inl(chip->base + offset); - - /* Clear whatever was there before */ - val &= ~(0xF << shift); - - /* Set the new value */ - val |= ((pair & 7) << shift); - - /* Set the PME bit if this is a PME event */ - if (pme) - val |= (1 << (shift + 3)); - - outl(val, chip->base + offset); - spin_unlock_irqrestore(&chip->lock, flags); -} -EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event); - -/* - * Generic gpio_chip API support. - */ - -static int chip_gpio_request(struct gpio_chip *c, unsigned offset) -{ - struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - /* check if this pin is available */ - if ((mask & (1 << offset)) == 0) { - dev_info(&chip->pdev->dev, - "pin %u is not available (check mask)\n", offset); - spin_unlock_irqrestore(&chip->lock, flags); - return -EINVAL; - } - - /* disable output aux 1 & 2 on this pin */ - __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1); - __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2); - - /* disable input aux 1 on this pin */ - __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1); - - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return cs5535_gpio_isset(offset, GPIO_READ_BACK); -} - -static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - if (val) - cs5535_gpio_set(offset, GPIO_OUTPUT_VAL); - else - cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL); -} - -static int chip_direction_input(struct gpio_chip *c, unsigned offset) -{ - struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); - __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) -{ - struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); - __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE); - if (val) - __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL); - else - __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL); - - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static const char * const cs5535_gpio_names[] = { - "GPIO0", "GPIO1", "GPIO2", "GPIO3", - "GPIO4", "GPIO5", "GPIO6", "GPIO7", - "GPIO8", "GPIO9", "GPIO10", "GPIO11", - "GPIO12", "GPIO13", "GPIO14", "GPIO15", - "GPIO16", "GPIO17", "GPIO18", "GPIO19", - "GPIO20", "GPIO21", "GPIO22", NULL, - "GPIO24", "GPIO25", "GPIO26", "GPIO27", - "GPIO28", NULL, NULL, NULL, -}; - -static struct cs5535_gpio_chip cs5535_gpio_chip = { - .chip = { - .owner = THIS_MODULE, - .label = DRV_NAME, - - .base = 0, - .ngpio = 32, - .names = cs5535_gpio_names, - .request = chip_gpio_request, - - .get = chip_gpio_get, - .set = chip_gpio_set, - - .direction_input = chip_direction_input, - .direction_output = chip_direction_output, - }, -}; - -static int __devinit cs5535_gpio_probe(struct platform_device *pdev) -{ - struct resource *res; - int err = -EIO; - ulong mask_orig = mask; - - /* There are two ways to get the GPIO base address; one is by - * fetching it from MSR_LBAR_GPIO, the other is by reading the - * PCI BAR info. The latter method is easier (especially across - * different architectures), so we'll stick with that for now. If - * it turns out to be unreliable in the face of crappy BIOSes, we - * can always go back to using MSRs.. */ - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - goto done; - } - - if (!request_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "can't request region\n"); - goto done; - } - - /* set up the driver-specific struct */ - cs5535_gpio_chip.base = res->start; - cs5535_gpio_chip.pdev = pdev; - spin_lock_init(&cs5535_gpio_chip.lock); - - dev_info(&pdev->dev, "reserved resource region %pR\n", res); - - /* mask out reserved pins */ - mask &= 0x1F7FFFFF; - - /* do not allow pin 28, Power Button, as there's special handling - * in the PMC needed. (note 12, p. 48) */ - mask &= ~(1 << 28); - - if (mask_orig != mask) - dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n", - mask_orig, mask); - - /* finally, register with the generic GPIO API */ - err = gpiochip_add(&cs5535_gpio_chip.chip); - if (err) - goto release_region; - - return 0; - -release_region: - release_region(res->start, resource_size(res)); -done: - return err; -} - -static int __devexit cs5535_gpio_remove(struct platform_device *pdev) -{ - struct resource *r; - int err; - - err = gpiochip_remove(&cs5535_gpio_chip.chip); - if (err) { - /* uhh? */ - dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); - return err; - } - - r = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(r->start, resource_size(r)); - return 0; -} - -static struct platform_driver cs5535_gpio_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = cs5535_gpio_probe, - .remove = __devexit_p(cs5535_gpio_remove), -}; - -module_platform_driver(cs5535_gpio_driver); - -MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); -MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-da9052.c b/ANDROID_3.4.5/drivers/gpio/gpio-da9052.c deleted file mode 100644 index 56dd047d..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-da9052.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * GPIO Driver for Dialog DA9052 PMICs. - * - * Copyright(c) 2011 Dialog Semiconductor Ltd. - * - * Author: David Dajun Chen <dchen@diasemi.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/uaccess.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/syscalls.h> -#include <linux/seq_file.h> - -#include <linux/mfd/da9052/da9052.h> -#include <linux/mfd/da9052/reg.h> -#include <linux/mfd/da9052/pdata.h> - -#define DA9052_INPUT 1 -#define DA9052_OUTPUT_OPENDRAIN 2 -#define DA9052_OUTPUT_PUSHPULL 3 - -#define DA9052_SUPPLY_VDD_IO1 0 - -#define DA9052_DEBOUNCING_OFF 0 -#define DA9052_DEBOUNCING_ON 1 - -#define DA9052_OUTPUT_LOWLEVEL 0 - -#define DA9052_ACTIVE_LOW 0 -#define DA9052_ACTIVE_HIGH 1 - -#define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8 -#define DA9052_GPIO_SHIFT_COUNT(no) (no%8) -#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0 -#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F -#define DA9052_GPIO_NIBBLE_SHIFT 4 -#define DA9052_IRQ_GPI0 16 -#define DA9052_GPIO_ODD_SHIFT 7 -#define DA9052_GPIO_EVEN_SHIFT 3 - -struct da9052_gpio { - struct da9052 *da9052; - struct gpio_chip gp; -}; - -static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct da9052_gpio, gp); -} - -static unsigned char da9052_gpio_port_odd(unsigned offset) -{ - return offset % 2; -} - -static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct da9052_gpio *gpio = to_da9052_gpio(gc); - int da9052_port_direction = 0; - int ret; - - ret = da9052_reg_read(gpio->da9052, - DA9052_GPIO_0_1_REG + (offset >> 1)); - if (ret < 0) - return ret; - - if (da9052_gpio_port_odd(offset)) { - da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN; - da9052_port_direction >>= 4; - } else { - da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN; - } - - switch (da9052_port_direction) { - case DA9052_INPUT: - if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER) - ret = da9052_reg_read(gpio->da9052, - DA9052_STATUS_C_REG); - else - ret = da9052_reg_read(gpio->da9052, - DA9052_STATUS_D_REG); - if (ret < 0) - return ret; - if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset))) - return 1; - else - return 0; - case DA9052_OUTPUT_PUSHPULL: - if (da9052_gpio_port_odd(offset)) - return ret & DA9052_GPIO_ODD_PORT_MODE; - else - return ret & DA9052_GPIO_EVEN_PORT_MODE; - default: - return -EINVAL; - } -} - -static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value) -{ - struct da9052_gpio *gpio = to_da9052_gpio(gc); - int ret; - - if (da9052_gpio_port_odd(offset)) { - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_ODD_PORT_MODE, - value << DA9052_GPIO_ODD_SHIFT); - if (ret != 0) - dev_err(gpio->da9052->dev, - "Failed to updated gpio odd reg,%d", - ret); - } else { - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_EVEN_PORT_MODE, - value << DA9052_GPIO_EVEN_SHIFT); - if (ret != 0) - dev_err(gpio->da9052->dev, - "Failed to updated gpio even reg,%d", - ret); - } -} - -static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct da9052_gpio *gpio = to_da9052_gpio(gc); - unsigned char register_value; - int ret; - - /* Format: function - 2 bits type - 1 bit mode - 1 bit */ - register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 | - DA9052_DEBOUNCING_ON << 3; - - if (da9052_gpio_port_odd(offset)) - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_MASK_UPPER_NIBBLE, - (register_value << - DA9052_GPIO_NIBBLE_SHIFT)); - else - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_MASK_LOWER_NIBBLE, - register_value); - - return ret; -} - -static int da9052_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, int value) -{ - struct da9052_gpio *gpio = to_da9052_gpio(gc); - unsigned char register_value; - int ret; - - /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */ - register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 | - value << 3; - - if (da9052_gpio_port_odd(offset)) - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_MASK_UPPER_NIBBLE, - (register_value << - DA9052_GPIO_NIBBLE_SHIFT)); - else - ret = da9052_reg_update(gpio->da9052, (offset >> 1) + - DA9052_GPIO_0_1_REG, - DA9052_GPIO_MASK_LOWER_NIBBLE, - register_value); - - return ret; -} - -static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset) -{ - struct da9052_gpio *gpio = to_da9052_gpio(gc); - struct da9052 *da9052 = gpio->da9052; - - return da9052->irq_base + DA9052_IRQ_GPI0 + offset; -} - -static struct gpio_chip reference_gp __devinitdata = { - .label = "da9052-gpio", - .owner = THIS_MODULE, - .get = da9052_gpio_get, - .set = da9052_gpio_set, - .direction_input = da9052_gpio_direction_input, - .direction_output = da9052_gpio_direction_output, - .to_irq = da9052_gpio_to_irq, - .can_sleep = 1, - .ngpio = 16, - .base = -1, -}; - -static int __devinit da9052_gpio_probe(struct platform_device *pdev) -{ - struct da9052_gpio *gpio; - struct da9052_pdata *pdata; - int ret; - - gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); - if (gpio == NULL) - return -ENOMEM; - - gpio->da9052 = dev_get_drvdata(pdev->dev.parent); - pdata = gpio->da9052->dev->platform_data; - - gpio->gp = reference_gp; - if (pdata && pdata->gpio_base) - gpio->gp.base = pdata->gpio_base; - - ret = gpiochip_add(&gpio->gp); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - goto err_mem; - } - - platform_set_drvdata(pdev, gpio); - - return 0; - -err_mem: - kfree(gpio); - return ret; -} - -static int __devexit da9052_gpio_remove(struct platform_device *pdev) -{ - struct da9052_gpio *gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&gpio->gp); - if (ret == 0) - kfree(gpio); - - return ret; -} - -static struct platform_driver da9052_gpio_driver = { - .probe = da9052_gpio_probe, - .remove = __devexit_p(da9052_gpio_remove), - .driver = { - .name = "da9052-gpio", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(da9052_gpio_driver); - -MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); -MODULE_DESCRIPTION("DA9052 GPIO Device Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:da9052-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-davinci.c b/ANDROID_3.4.5/drivers/gpio/gpio-davinci.c deleted file mode 100644 index 3d000169..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-davinci.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * TI DaVinci GPIO Support - * - * Copyright (c) 2006-2007 David Brownell - * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include <linux/gpio.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> - -#include <asm/mach/irq.h> - -struct davinci_gpio_regs { - u32 dir; - u32 out_data; - u32 set_data; - u32 clr_data; - u32 in_data; - u32 set_rising; - u32 clr_rising; - u32 set_falling; - u32 clr_falling; - u32 intstat; -}; - -#define chip2controller(chip) \ - container_of(chip, struct davinci_gpio_controller, chip) - -static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; -static void __iomem *gpio_base; - -static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) -{ - void __iomem *ptr; - - if (gpio < 32 * 1) - ptr = gpio_base + 0x10; - else if (gpio < 32 * 2) - ptr = gpio_base + 0x38; - else if (gpio < 32 * 3) - ptr = gpio_base + 0x60; - else if (gpio < 32 * 4) - ptr = gpio_base + 0x88; - else if (gpio < 32 * 5) - ptr = gpio_base + 0xb0; - else - ptr = NULL; - return ptr; -} - -static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) -{ - struct davinci_gpio_regs __iomem *g; - - g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq); - - return g; -} - -static int __init davinci_gpio_irq_setup(void); - -/*--------------------------------------------------------------------------*/ - -/* board setup code *MUST* setup pinmux and enable the GPIO clock. */ -static inline int __davinci_direction(struct gpio_chip *chip, - unsigned offset, bool out, int value) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - unsigned long flags; - u32 temp; - u32 mask = 1 << offset; - - spin_lock_irqsave(&d->lock, flags); - temp = __raw_readl(&g->dir); - if (out) { - temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); - } else { - temp |= mask; - } - __raw_writel(temp, &g->dir); - spin_unlock_irqrestore(&d->lock, flags); - - return 0; -} - -static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) -{ - return __davinci_direction(chip, offset, false, 0); -} - -static int -davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) -{ - return __davinci_direction(chip, offset, true, value); -} - -/* - * Read the pin's value (works even if it's set up as output); - * returns zero/nonzero. - * - * Note that changes are synched to the GPIO clock, so reading values back - * right after you've set them may give old values. - */ -static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - - return (1 << offset) & __raw_readl(&g->in_data); -} - -/* - * Assuming the pin is muxed as a gpio output, set its output value. - */ -static void -davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; - - __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); -} - -static int __init davinci_gpio_setup(void) -{ - int i, base; - unsigned ngpio; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs *regs; - - if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) - return 0; - - /* - * The gpio banks conceptually expose a segmented bitmap, - * and "ngpio" is one more than the largest zero-based - * bit index that's valid. - */ - ngpio = soc_info->gpio_num; - if (ngpio == 0) { - pr_err("GPIO setup: how many GPIOs?\n"); - return -EINVAL; - } - - if (WARN_ON(DAVINCI_N_GPIO < ngpio)) - ngpio = DAVINCI_N_GPIO; - - gpio_base = ioremap(soc_info->gpio_base, SZ_4K); - if (WARN_ON(!gpio_base)) - return -ENOMEM; - - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - chips[i].chip.label = "DaVinci"; - - chips[i].chip.direction_input = davinci_direction_in; - chips[i].chip.get = davinci_gpio_get; - chips[i].chip.direction_output = davinci_direction_out; - chips[i].chip.set = davinci_gpio_set; - - chips[i].chip.base = base; - chips[i].chip.ngpio = ngpio - base; - if (chips[i].chip.ngpio > 32) - chips[i].chip.ngpio = 32; - - spin_lock_init(&chips[i].lock); - - regs = gpio2regs(base); - chips[i].regs = regs; - chips[i].set_data = ®s->set_data; - chips[i].clr_data = ®s->clr_data; - chips[i].in_data = ®s->in_data; - - gpiochip_add(&chips[i].chip); - } - - soc_info->gpio_ctlrs = chips; - soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - - davinci_gpio_irq_setup(); - return 0; -} -pure_initcall(davinci_gpio_setup); - -/*--------------------------------------------------------------------------*/ -/* - * We expect irqs will normally be set up as input pins, but they can also be - * used as output pins ... which is convenient for testing. - * - * NOTE: The first few GPIOs also have direct INTC hookups in addition - * to their GPIOBNK0 irq, with a bit less overhead. - * - * All those INTC hookups (direct, plus several IRQ banks) can also - * serve as EDMA event triggers. - */ - -static void gpio_irq_disable(struct irq_data *d) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - - __raw_writel(mask, &g->clr_falling); - __raw_writel(mask, &g->clr_rising); -} - -static void gpio_irq_enable(struct irq_data *d) -{ - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); - unsigned status = irqd_get_trigger_type(d); - - status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; - if (!status) - status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; - - if (status & IRQ_TYPE_EDGE_FALLING) - __raw_writel(mask, &g->set_falling); - if (status & IRQ_TYPE_EDGE_RISING) - __raw_writel(mask, &g->set_rising); -} - -static int gpio_irq_type(struct irq_data *d, unsigned trigger) -{ - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - return -EINVAL; - - return 0; -} - -static struct irq_chip gpio_irqchip = { - .name = "GPIO", - .irq_enable = gpio_irq_enable, - .irq_disable = gpio_irq_disable, - .irq_set_type = gpio_irq_type, - .flags = IRQCHIP_SET_TYPE_MASKED, -}; - -static void -gpio_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct davinci_gpio_regs __iomem *g; - u32 mask = 0xffff; - struct davinci_gpio_controller *d; - - d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc); - g = (struct davinci_gpio_regs __iomem *)d->regs; - - /* we only care about one bank */ - if (irq & 1) - mask <<= 16; - - /* temporarily mask (level sensitive) parent IRQ */ - desc->irq_data.chip->irq_mask(&desc->irq_data); - desc->irq_data.chip->irq_ack(&desc->irq_data); - while (1) { - u32 status; - int n; - int res; - - /* ack any irqs */ - status = __raw_readl(&g->intstat) & mask; - if (!status) - break; - __raw_writel(status, &g->intstat); - - /* now demux them to the right lowlevel handler */ - n = d->irq_base; - if (irq & 1) { - n += 16; - status >>= 16; - } - - while (status) { - res = ffs(status); - n += res; - generic_handle_irq(n - 1); - status >>= res; - } - } - desc->irq_data.chip->irq_unmask(&desc->irq_data); - /* now it may re-trigger */ -} - -static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *d = chip2controller(chip); - - if (d->irq_base >= 0) - return d->irq_base + offset; - else - return -ENODEV; -} - -static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - - /* NOTE: we assume for now that only irqs in the first gpio_chip - * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). - */ - if (offset < soc_info->gpio_unbanked) - return soc_info->gpio_irq + offset; - else - return -ENODEV; -} - -static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) -{ - struct davinci_gpio_controller *d; - struct davinci_gpio_regs __iomem *g; - struct davinci_soc_info *soc_info = &davinci_soc_info; - u32 mask; - - d = (struct davinci_gpio_controller *)data->handler_data; - g = (struct davinci_gpio_regs __iomem *)d->regs; - mask = __gpio_mask(data->irq - soc_info->gpio_irq); - - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - return -EINVAL; - - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) - ? &g->set_falling : &g->clr_falling); - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) - ? &g->set_rising : &g->clr_rising); - - return 0; -} - -/* - * NOTE: for suspend/resume, probably best to make a platform_device with - * suspend_late/resume_resume calls hooking into results of the set_wake() - * calls ... so if no gpios are wakeup events the clock can be disabled, - * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 - * (dm6446) can be set appropriately for GPIOV33 pins. - */ - -static int __init davinci_gpio_irq_setup(void) -{ - unsigned gpio, irq, bank; - struct clk *clk; - u32 binten = 0; - unsigned ngpio, bank_irq; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs __iomem *g; - - ngpio = soc_info->gpio_num; - - bank_irq = soc_info->gpio_irq; - if (bank_irq == 0) { - printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); - return -EINVAL; - } - - clk = clk_get(NULL, "gpio"); - if (IS_ERR(clk)) { - printk(KERN_ERR "Error %ld getting gpio clock?\n", - PTR_ERR(clk)); - return PTR_ERR(clk); - } - clk_enable(clk); - - /* Arrange gpio_to_irq() support, handling either direct IRQs or - * banked IRQs. Having GPIOs in the first GPIO bank use direct - * IRQs, while the others use banked IRQs, would need some setup - * tweaks to recognize hardware which can do that. - */ - for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { - chips[bank].chip.to_irq = gpio_to_irq_banked; - chips[bank].irq_base = soc_info->gpio_unbanked - ? -EINVAL - : (soc_info->intc_irq_num + gpio); - } - - /* - * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO - * controller only handling trigger modes. We currently assume no - * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. - */ - if (soc_info->gpio_unbanked) { - static struct irq_chip_type gpio_unbanked; - - /* pass "bank 0" GPIO IRQs to AINTC */ - chips[0].chip.to_irq = gpio_to_irq_unbanked; - binten = BIT(0); - - /* AINTC handles mask/unmask; GPIO handles triggering */ - irq = bank_irq; - gpio_unbanked = *container_of(irq_get_chip(irq), - struct irq_chip_type, chip); - gpio_unbanked.chip.name = "GPIO-AINTC"; - gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked; - - /* default trigger: both edges */ - g = gpio2regs(0); - __raw_writel(~0, &g->set_falling); - __raw_writel(~0, &g->set_rising); - - /* set the direct IRQs up to use that irqchip */ - for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { - irq_set_chip(irq, &gpio_unbanked.chip); - irq_set_handler_data(irq, &chips[gpio / 32]); - irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); - } - - goto done; - } - - /* - * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we - * then chain through our own handler. - */ - for (gpio = 0, irq = gpio_to_irq(0), bank = 0; - gpio < ngpio; - bank++, bank_irq++) { - unsigned i; - - /* disabled by default, enabled only as needed */ - g = gpio2regs(gpio); - __raw_writel(~0, &g->clr_falling); - __raw_writel(~0, &g->clr_rising); - - /* set up all irqs in this bank */ - irq_set_chained_handler(bank_irq, gpio_irq_handler); - - /* - * Each chip handles 32 gpios, and each irq bank consists of 16 - * gpio irqs. Pass the irq bank's corresponding controller to - * the chained irq handler. - */ - irq_set_handler_data(bank_irq, &chips[gpio / 32]); - - for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { - irq_set_chip(irq, &gpio_irqchip); - irq_set_chip_data(irq, (__force void *)g); - irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); - irq_set_handler(irq, handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); - } - - binten |= BIT(bank); - } - -done: - /* BINTEN -- per-bank interrupt enable. genirq would also let these - * bits be set/cleared dynamically. - */ - __raw_writel(binten, gpio_base + 0x08); - - printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); - - return 0; -} diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ep93xx.c b/ANDROID_3.4.5/drivers/gpio/gpio-ep93xx.c deleted file mode 100644 index 776b7725..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ep93xx.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Generic EP93xx GPIO handling - * - * Copyright (c) 2008 Ryan Mallon - * Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com> - * - * Based on code originally from: - * linux/arch/arm/mach-ep93xx/core.c - * - * 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/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/slab.h> -#include <linux/basic_mmio_gpio.h> - -#include <mach/hardware.h> -#include <mach/gpio-ep93xx.h> - -#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0)) - -struct ep93xx_gpio { - void __iomem *mmio_base; - struct bgpio_chip bgc[8]; -}; - -/************************************************************************* - * Interrupt handling for EP93xx on-chip GPIOs - *************************************************************************/ -static unsigned char gpio_int_unmasked[3]; -static unsigned char gpio_int_enabled[3]; -static unsigned char gpio_int_type1[3]; -static unsigned char gpio_int_type2[3]; -static unsigned char gpio_int_debounce[3]; - -/* Port ordering is: A B F */ -static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; -static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; -static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; -static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 }; -static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 }; - -static void ep93xx_gpio_update_int_params(unsigned port) -{ - BUG_ON(port > 2); - - __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); - - __raw_writeb(gpio_int_type2[port], - EP93XX_GPIO_REG(int_type2_register_offset[port])); - - __raw_writeb(gpio_int_type1[port], - EP93XX_GPIO_REG(int_type1_register_offset[port])); - - __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], - EP93XX_GPIO_REG(int_en_register_offset[port])); -} - -static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable) -{ - int line = irq_to_gpio(irq); - int port = line >> 3; - int port_mask = 1 << (line & 7); - - if (enable) - gpio_int_debounce[port] |= port_mask; - else - gpio_int_debounce[port] &= ~port_mask; - - __raw_writeb(gpio_int_debounce[port], - EP93XX_GPIO_REG(int_debounce_register_offset[port])); -} - -static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - unsigned char status; - int i; - - status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); - for (i = 0; i < 8; i++) { - if (status & (1 << i)) { - int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; - generic_handle_irq(gpio_irq); - } - } - - status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); - for (i = 0; i < 8; i++) { - if (status & (1 << i)) { - int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; - generic_handle_irq(gpio_irq); - } - } -} - -static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - /* - * map discontiguous hw irq range to continuous sw irq range: - * - * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) - */ - int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ - int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; - - generic_handle_irq(gpio_irq); -} - -static void ep93xx_gpio_irq_ack(struct irq_data *d) -{ - int line = irq_to_gpio(d->irq); - int port = line >> 3; - int port_mask = 1 << (line & 7); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - gpio_int_type2[port] ^= port_mask; /* switch edge direction */ - ep93xx_gpio_update_int_params(port); - } - - __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); -} - -static void ep93xx_gpio_irq_mask_ack(struct irq_data *d) -{ - int line = irq_to_gpio(d->irq); - int port = line >> 3; - int port_mask = 1 << (line & 7); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) - gpio_int_type2[port] ^= port_mask; /* switch edge direction */ - - gpio_int_unmasked[port] &= ~port_mask; - ep93xx_gpio_update_int_params(port); - - __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); -} - -static void ep93xx_gpio_irq_mask(struct irq_data *d) -{ - int line = irq_to_gpio(d->irq); - int port = line >> 3; - - gpio_int_unmasked[port] &= ~(1 << (line & 7)); - ep93xx_gpio_update_int_params(port); -} - -static void ep93xx_gpio_irq_unmask(struct irq_data *d) -{ - int line = irq_to_gpio(d->irq); - int port = line >> 3; - - gpio_int_unmasked[port] |= 1 << (line & 7); - ep93xx_gpio_update_int_params(port); -} - -/* - * gpio_int_type1 controls whether the interrupt is level (0) or - * edge (1) triggered, while gpio_int_type2 controls whether it - * triggers on low/falling (0) or high/rising (1). - */ -static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - const int gpio = irq_to_gpio(d->irq); - const int port = gpio >> 3; - const int port_mask = 1 << (gpio & 7); - irq_flow_handler_t handler; - - gpio_direction_input(gpio); - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - gpio_int_type1[port] |= port_mask; - gpio_int_type2[port] |= port_mask; - handler = handle_edge_irq; - break; - case IRQ_TYPE_EDGE_FALLING: - gpio_int_type1[port] |= port_mask; - gpio_int_type2[port] &= ~port_mask; - handler = handle_edge_irq; - break; - case IRQ_TYPE_LEVEL_HIGH: - gpio_int_type1[port] &= ~port_mask; - gpio_int_type2[port] |= port_mask; - handler = handle_level_irq; - break; - case IRQ_TYPE_LEVEL_LOW: - gpio_int_type1[port] &= ~port_mask; - gpio_int_type2[port] &= ~port_mask; - handler = handle_level_irq; - break; - case IRQ_TYPE_EDGE_BOTH: - gpio_int_type1[port] |= port_mask; - /* set initial polarity based on current input level */ - if (gpio_get_value(gpio)) - gpio_int_type2[port] &= ~port_mask; /* falling */ - else - gpio_int_type2[port] |= port_mask; /* rising */ - handler = handle_edge_irq; - break; - default: - return -EINVAL; - } - - __irq_set_handler_locked(d->irq, handler); - - gpio_int_enabled[port] |= port_mask; - - ep93xx_gpio_update_int_params(port); - - return 0; -} - -static struct irq_chip ep93xx_gpio_irq_chip = { - .name = "GPIO", - .irq_ack = ep93xx_gpio_irq_ack, - .irq_mask_ack = ep93xx_gpio_irq_mask_ack, - .irq_mask = ep93xx_gpio_irq_mask, - .irq_unmask = ep93xx_gpio_irq_unmask, - .irq_set_type = ep93xx_gpio_irq_type, -}; - -static void ep93xx_gpio_init_irq(void) -{ - int gpio_irq; - - for (gpio_irq = gpio_to_irq(0); - gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { - irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip, - handle_level_irq); - set_irq_flags(gpio_irq, IRQF_VALID); - } - - irq_set_chained_handler(IRQ_EP93XX_GPIO_AB, - ep93xx_gpio_ab_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX, - ep93xx_gpio_f_irq_handler); - irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX, - ep93xx_gpio_f_irq_handler); -} - - -/************************************************************************* - * gpiolib interface for EP93xx on-chip GPIOs - *************************************************************************/ -struct ep93xx_gpio_bank { - const char *label; - int data; - int dir; - int base; - bool has_debounce; -}; - -#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce) \ - { \ - .label = _label, \ - .data = _data, \ - .dir = _dir, \ - .base = _base, \ - .has_debounce = _debounce, \ - } - -static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = { - EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true), - EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true), - EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false), - EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false), - EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false), - EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true), - EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false), - EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false), -}; - -static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, - unsigned offset, unsigned debounce) -{ - int gpio = chip->base + offset; - int irq = gpio_to_irq(gpio); - - if (irq < 0) - return -EINVAL; - - ep93xx_gpio_int_debounce(irq, debounce ? true : false); - - return 0; -} - -/* - * Map GPIO A0..A7 (0..7) to irq 64..71, - * B0..B7 (7..15) to irq 72..79, and - * F0..F7 (16..24) to irq 80..87. - */ -static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - if (gpio > EP93XX_GPIO_LINE_MAX_IRQ) - return -EINVAL; - - return 64 + gpio; -} - -static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev, - void __iomem *mmio_base, struct ep93xx_gpio_bank *bank) -{ - void __iomem *data = mmio_base + bank->data; - void __iomem *dir = mmio_base + bank->dir; - int err; - - err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false); - if (err) - return err; - - bgc->gc.label = bank->label; - bgc->gc.base = bank->base; - - if (bank->has_debounce) { - bgc->gc.set_debounce = ep93xx_gpio_set_debounce; - bgc->gc.to_irq = ep93xx_gpio_to_irq; - } - - return gpiochip_add(&bgc->gc); -} - -static int __devinit ep93xx_gpio_probe(struct platform_device *pdev) -{ - struct ep93xx_gpio *ep93xx_gpio; - struct resource *res; - void __iomem *mmio; - int i; - int ret; - - ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL); - if (!ep93xx_gpio) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENXIO; - goto exit_free; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - ret = -EBUSY; - goto exit_free; - } - - mmio = ioremap(res->start, resource_size(res)); - if (!mmio) { - ret = -ENXIO; - goto exit_release; - } - ep93xx_gpio->mmio_base = mmio; - - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) { - struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i]; - struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; - - if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank)) - dev_warn(&pdev->dev, "Unable to add gpio bank %s\n", - bank->label); - } - - ep93xx_gpio_init_irq(); - - return 0; - -exit_release: - release_mem_region(res->start, resource_size(res)); -exit_free: - kfree(ep93xx_gpio); - dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret); - return ret; -} - -static struct platform_driver ep93xx_gpio_driver = { - .driver = { - .name = "gpio-ep93xx", - .owner = THIS_MODULE, - }, - .probe = ep93xx_gpio_probe, -}; - -static int __init ep93xx_gpio_init(void) -{ - return platform_driver_register(&ep93xx_gpio_driver); -} -postcore_initcall(ep93xx_gpio_init); - -MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> " - "H Hartley Sweeten <hsweeten@visionengravers.com>"); -MODULE_DESCRIPTION("EP93XX GPIO driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ge.c b/ANDROID_3.4.5/drivers/gpio/gpio-ge.c deleted file mode 100644 index 7b95a4a8..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ge.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Driver for GE FPGA based GPIO - * - * Author: Martyn Welch <martyn.welch@ge.com> - * - * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -/* TODO - * - * Configuration of output modes (totem-pole/open-drain) - * Interrupt configuration - interrupts are always generated the FPGA relies on - * the I/O interrupt controllers mask to stop them propergating - */ - -#include <linux/kernel.h> -#include <linux/compiler.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#include <linux/of_gpio.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/module.h> - -#define GEF_GPIO_DIRECT 0x00 -#define GEF_GPIO_IN 0x04 -#define GEF_GPIO_OUT 0x08 -#define GEF_GPIO_TRIG 0x0C -#define GEF_GPIO_POLAR_A 0x10 -#define GEF_GPIO_POLAR_B 0x14 -#define GEF_GPIO_INT_STAT 0x18 -#define GEF_GPIO_OVERRUN 0x1C -#define GEF_GPIO_MODE 0x20 - -static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value) -{ - unsigned int data; - - data = ioread32be(reg); - /* value: 0=low; 1=high */ - if (value & 0x1) - data = data | (0x1 << offset); - else - data = data & ~(0x1 << offset); - - iowrite32be(data, reg); -} - - -static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset) -{ - unsigned int data; - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); - - data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); - data = data | (0x1 << offset); - iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT); - - return 0; -} - -static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) -{ - unsigned int data; - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); - - /* Set direction before switching to input */ - _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); - - data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); - data = data & ~(0x1 << offset); - iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT); - - return 0; -} - -static int gef_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - unsigned int data; - int state = 0; - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); - - data = ioread32be(mmchip->regs + GEF_GPIO_IN); - state = (int)((data >> offset) & 0x1); - - return state; -} - -static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); - - _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); -} - -static int __init gef_gpio_init(void) -{ - struct device_node *np; - int retval; - struct of_mm_gpio_chip *gef_gpio_chip; - - for_each_compatible_node(np, NULL, "gef,sbc610-gpio") { - - pr_debug("%s: Initialising GEF GPIO\n", np->full_name); - - /* Allocate chip structure */ - gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); - if (!gef_gpio_chip) { - pr_err("%s: Unable to allocate structure\n", - np->full_name); - continue; - } - - /* Setup pointers to chip functions */ - gef_gpio_chip->gc.of_gpio_n_cells = 2; - gef_gpio_chip->gc.ngpio = 19; - gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; - gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; - gef_gpio_chip->gc.get = gef_gpio_get; - gef_gpio_chip->gc.set = gef_gpio_set; - - /* This function adds a memory mapped GPIO chip */ - retval = of_mm_gpiochip_add(np, gef_gpio_chip); - if (retval) { - kfree(gef_gpio_chip); - pr_err("%s: Unable to add GPIO\n", np->full_name); - } - } - - for_each_compatible_node(np, NULL, "gef,sbc310-gpio") { - - pr_debug("%s: Initialising GEF GPIO\n", np->full_name); - - /* Allocate chip structure */ - gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); - if (!gef_gpio_chip) { - pr_err("%s: Unable to allocate structure\n", - np->full_name); - continue; - } - - /* Setup pointers to chip functions */ - gef_gpio_chip->gc.of_gpio_n_cells = 2; - gef_gpio_chip->gc.ngpio = 6; - gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; - gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; - gef_gpio_chip->gc.get = gef_gpio_get; - gef_gpio_chip->gc.set = gef_gpio_set; - - /* This function adds a memory mapped GPIO chip */ - retval = of_mm_gpiochip_add(np, gef_gpio_chip); - if (retval) { - kfree(gef_gpio_chip); - pr_err("%s: Unable to add GPIO\n", np->full_name); - } - } - - for_each_compatible_node(np, NULL, "ge,imp3a-gpio") { - - pr_debug("%s: Initialising GE GPIO\n", np->full_name); - - /* Allocate chip structure */ - gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); - if (!gef_gpio_chip) { - pr_err("%s: Unable to allocate structure\n", - np->full_name); - continue; - } - - /* Setup pointers to chip functions */ - gef_gpio_chip->gc.of_gpio_n_cells = 2; - gef_gpio_chip->gc.ngpio = 16; - gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; - gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; - gef_gpio_chip->gc.get = gef_gpio_get; - gef_gpio_chip->gc.set = gef_gpio_set; - - /* This function adds a memory mapped GPIO chip */ - retval = of_mm_gpiochip_add(np, gef_gpio_chip); - if (retval) { - kfree(gef_gpio_chip); - pr_err("%s: Unable to add GPIO\n", np->full_name); - } - } - - return 0; -}; -arch_initcall(gef_gpio_init); - -MODULE_DESCRIPTION("GE I/O FPGA GPIO driver"); -MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-generic.c b/ANDROID_3.4.5/drivers/gpio/gpio-generic.c deleted file mode 100644 index e38dd0c3..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-generic.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Generic driver for memory-mapped GPIO controllers. - * - * Copyright 2008 MontaVista Software, Inc. - * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... - * ...`` ```````.. - * ..The simplest form of a GPIO controller that the driver supports is`` - * `.just a single "data" register, where GPIO state can be read and/or ` - * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` - * ````````` - ___ -_/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... -__________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . -o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` - `....trivial..'~`.```.``` - * ``````` - * .```````~~~~`..`.``.``. - * . The driver supports `... ,..```.`~~~```````````````....````.``,, - * . big-endian notation, just`. .. A bit more sophisticated controllers , - * . register the device with -be`. .with a pair of set/clear-bit registers , - * `.. suffix. ```~~`````....`.` . affecting the data register and the .` - * ``.`.``...``` ```.. output pins are also supported.` - * ^^ `````.`````````.,``~``~``~~`````` - * . ^^ - * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. - * .. The expectation is that in at least some cases . ,-~~~-, - * .this will be used with roll-your-own ASIC/FPGA .` \ / - * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / - * ..````````......``````````` \o_ - * | - * ^^ / \ - * - * ...`````~~`.....``.`..........``````.`.``.```........``. - * ` 8, 16, 32 and 64 bits registers are supported, and``. - * . the number of GPIOs is determined by the width of ~ - * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ - * `.......````.``` - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/bug.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/compiler.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/log2.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/mod_devicetable.h> -#include <linux/basic_mmio_gpio.h> - -static void bgpio_write8(void __iomem *reg, unsigned long data) -{ - writeb(data, reg); -} - -static unsigned long bgpio_read8(void __iomem *reg) -{ - return readb(reg); -} - -static void bgpio_write16(void __iomem *reg, unsigned long data) -{ - writew(data, reg); -} - -static unsigned long bgpio_read16(void __iomem *reg) -{ - return readw(reg); -} - -static void bgpio_write32(void __iomem *reg, unsigned long data) -{ - writel(data, reg); -} - -static unsigned long bgpio_read32(void __iomem *reg) -{ - return readl(reg); -} - -#if BITS_PER_LONG >= 64 -static void bgpio_write64(void __iomem *reg, unsigned long data) -{ - writeq(data, reg); -} - -static unsigned long bgpio_read64(void __iomem *reg) -{ - return readq(reg); -} -#endif /* BITS_PER_LONG >= 64 */ - -static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) -{ - return 1 << pin; -} - -static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc, - unsigned int pin) -{ - return 1 << (bgc->bits - 1 - pin); -} - -static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - - return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio); -} - -static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - if (val) - bgc->data |= mask; - else - bgc->data &= ~mask; - - bgc->write_reg(bgc->reg_dat, bgc->data); - - spin_unlock_irqrestore(&bgc->lock, flags); -} - -static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); - - if (val) - bgc->write_reg(bgc->reg_set, mask); - else - bgc->write_reg(bgc->reg_clr, mask); -} - -static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - if (val) - bgc->data |= mask; - else - bgc->data &= ~mask; - - bgc->write_reg(bgc->reg_set, bgc->data); - - spin_unlock_irqrestore(&bgc->lock, flags); -} - -static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - return 0; -} - -static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - gc->set(gc, gpio, val); - - return 0; -} - -static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir &= ~bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir |= bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir |= bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir &= ~bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_setup_accessors(struct device *dev, - struct bgpio_chip *bgc, - bool be) -{ - - switch (bgc->bits) { - case 8: - bgc->read_reg = bgpio_read8; - bgc->write_reg = bgpio_write8; - break; - case 16: - bgc->read_reg = bgpio_read16; - bgc->write_reg = bgpio_write16; - break; - case 32: - bgc->read_reg = bgpio_read32; - bgc->write_reg = bgpio_write32; - break; -#if BITS_PER_LONG >= 64 - case 64: - bgc->read_reg = bgpio_read64; - bgc->write_reg = bgpio_write64; - break; -#endif /* BITS_PER_LONG >= 64 */ - default: - dev_err(dev, "unsupported data width %u bits\n", bgc->bits); - return -EINVAL; - } - - bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask; - - return 0; -} - -/* - * Create the device and allocate the resources. For setting GPIO's there are - * three supported configurations: - * - * - single input/output register resource (named "dat"). - * - set/clear pair (named "set" and "clr"). - * - single output register resource and single input resource ("set" and - * dat"). - * - * For the single output register, this drives a 1 by setting a bit and a zero - * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit - * in the set register and clears it by setting a bit in the clear register. - * The configuration is detected by which resources are present. - * - * For setting the GPIO direction, there are three supported configurations: - * - * - simple bidirection GPIO that requires no configuration. - * - an output direction register (named "dirout") where a 1 bit - * indicates the GPIO is an output. - * - an input direction register (named "dirin") where a 1 bit indicates - * the GPIO is an input. - */ -static int bgpio_setup_io(struct bgpio_chip *bgc, - void __iomem *dat, - void __iomem *set, - void __iomem *clr) -{ - - bgc->reg_dat = dat; - if (!bgc->reg_dat) - return -EINVAL; - - if (set && clr) { - bgc->reg_set = set; - bgc->reg_clr = clr; - bgc->gc.set = bgpio_set_with_clear; - } else if (set && !clr) { - bgc->reg_set = set; - bgc->gc.set = bgpio_set_set; - } else { - bgc->gc.set = bgpio_set; - } - - bgc->gc.get = bgpio_get; - - return 0; -} - -static int bgpio_setup_direction(struct bgpio_chip *bgc, - void __iomem *dirout, - void __iomem *dirin) -{ - if (dirout && dirin) { - return -EINVAL; - } else if (dirout) { - bgc->reg_dir = dirout; - bgc->gc.direction_output = bgpio_dir_out; - bgc->gc.direction_input = bgpio_dir_in; - } else if (dirin) { - bgc->reg_dir = dirin; - bgc->gc.direction_output = bgpio_dir_out_inv; - bgc->gc.direction_input = bgpio_dir_in_inv; - } else { - bgc->gc.direction_output = bgpio_simple_dir_out; - bgc->gc.direction_input = bgpio_simple_dir_in; - } - - return 0; -} - -int bgpio_remove(struct bgpio_chip *bgc) -{ - int err = gpiochip_remove(&bgc->gc); - - kfree(bgc); - - return err; -} -EXPORT_SYMBOL_GPL(bgpio_remove); - -int bgpio_init(struct bgpio_chip *bgc, struct device *dev, - unsigned long sz, void __iomem *dat, void __iomem *set, - void __iomem *clr, void __iomem *dirout, void __iomem *dirin, - bool big_endian) -{ - int ret; - - if (!is_power_of_2(sz)) - return -EINVAL; - - bgc->bits = sz * 8; - if (bgc->bits > BITS_PER_LONG) - return -EINVAL; - - spin_lock_init(&bgc->lock); - bgc->gc.dev = dev; - bgc->gc.label = dev_name(dev); - bgc->gc.base = -1; - bgc->gc.ngpio = bgc->bits; - - ret = bgpio_setup_io(bgc, dat, set, clr); - if (ret) - return ret; - - ret = bgpio_setup_accessors(dev, bgc, big_endian); - if (ret) - return ret; - - ret = bgpio_setup_direction(bgc, dirout, dirin); - if (ret) - return ret; - - bgc->data = bgc->read_reg(bgc->reg_dat); - - return ret; -} -EXPORT_SYMBOL_GPL(bgpio_init); - -#ifdef CONFIG_GPIO_GENERIC_PLATFORM - -static void __iomem *bgpio_map(struct platform_device *pdev, - const char *name, - resource_size_t sane_sz, - int *err) -{ - struct device *dev = &pdev->dev; - struct resource *r; - resource_size_t start; - resource_size_t sz; - void __iomem *ret; - - *err = 0; - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!r) - return NULL; - - sz = resource_size(r); - if (sz != sane_sz) { - *err = -EINVAL; - return NULL; - } - - start = r->start; - if (!devm_request_mem_region(dev, start, sz, r->name)) { - *err = -EBUSY; - return NULL; - } - - ret = devm_ioremap(dev, start, sz); - if (!ret) { - *err = -ENOMEM; - return NULL; - } - - return ret; -} - -static int __devinit bgpio_pdev_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *r; - void __iomem *dat; - void __iomem *set; - void __iomem *clr; - void __iomem *dirout; - void __iomem *dirin; - unsigned long sz; - bool be; - int err; - struct bgpio_chip *bgc; - struct bgpio_pdata *pdata = dev_get_platdata(dev); - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); - if (!r) - return -EINVAL; - - sz = resource_size(r); - - dat = bgpio_map(pdev, "dat", sz, &err); - if (!dat) - return err ? err : -EINVAL; - - set = bgpio_map(pdev, "set", sz, &err); - if (err) - return err; - - clr = bgpio_map(pdev, "clr", sz, &err); - if (err) - return err; - - dirout = bgpio_map(pdev, "dirout", sz, &err); - if (err) - return err; - - dirin = bgpio_map(pdev, "dirin", sz, &err); - if (err) - return err; - - be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"); - - bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); - if (!bgc) - return -ENOMEM; - - err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be); - if (err) - return err; - - if (pdata) { - bgc->gc.base = pdata->base; - if (pdata->ngpio > 0) - bgc->gc.ngpio = pdata->ngpio; - } - - platform_set_drvdata(pdev, bgc); - - return gpiochip_add(&bgc->gc); -} - -static int __devexit bgpio_pdev_remove(struct platform_device *pdev) -{ - struct bgpio_chip *bgc = platform_get_drvdata(pdev); - - return bgpio_remove(bgc); -} - -static const struct platform_device_id bgpio_id_table[] = { - { "basic-mmio-gpio", }, - { "basic-mmio-gpio-be", }, - {}, -}; -MODULE_DEVICE_TABLE(platform, bgpio_id_table); - -static struct platform_driver bgpio_driver = { - .driver = { - .name = "basic-mmio-gpio", - }, - .id_table = bgpio_id_table, - .probe = bgpio_pdev_probe, - .remove = __devexit_p(bgpio_pdev_remove), -}; - -module_platform_driver(bgpio_driver); - -#endif /* CONFIG_GPIO_GENERIC_PLATFORM */ - -MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); -MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-it8761e.c b/ANDROID_3.4.5/drivers/gpio/gpio-it8761e.c deleted file mode 100644 index 278b8131..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-it8761e.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * GPIO interface for IT8761E Super I/O chip - * - * Author: Denis Turischev <denis@compulab.co.il> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/errno.h> -#include <linux/ioport.h> - -#include <linux/gpio.h> - -#define SIO_CHIP_ID 0x8761 -#define CHIP_ID_HIGH_BYTE 0x20 -#define CHIP_ID_LOW_BYTE 0x21 - -static u8 ports[2] = { 0x2e, 0x4e }; -static u8 port; - -static DEFINE_SPINLOCK(sio_lock); - -#define GPIO_NAME "it8761-gpio" -#define GPIO_BA_HIGH_BYTE 0x60 -#define GPIO_BA_LOW_BYTE 0x61 -#define GPIO_IOSIZE 4 -#define GPIO1X_IO 0xf0 -#define GPIO2X_IO 0xf1 - -static u16 gpio_ba; - -static u8 read_reg(u8 addr, u8 port) -{ - outb(addr, port); - return inb(port + 1); -} - -static void write_reg(u8 data, u8 addr, u8 port) -{ - outb(addr, port); - outb(data, port + 1); -} - -static void enter_conf_mode(u8 port) -{ - outb(0x87, port); - outb(0x61, port); - outb(0x55, port); - outb((port == 0x2e) ? 0x55 : 0xaa, port); -} - -static void exit_conf_mode(u8 port) -{ - outb(0x2, port); - outb(0x2, port + 1); -} - -static void enter_gpio_mode(u8 port) -{ - write_reg(0x2, 0x7, port); -} - -static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) -{ - u16 reg; - u8 bit; - - bit = gpio_num % 8; - reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; - - return !!(inb(reg) & (1 << bit)); -} - -static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) -{ - u8 curr_dirs; - u8 io_reg, bit; - - bit = gpio_num % 8; - io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; - - spin_lock(&sio_lock); - - enter_conf_mode(port); - enter_gpio_mode(port); - - curr_dirs = read_reg(io_reg, port); - - if (curr_dirs & (1 << bit)) - write_reg(curr_dirs & ~(1 << bit), io_reg, port); - - exit_conf_mode(port); - - spin_unlock(&sio_lock); - return 0; -} - -static void it8761e_gpio_set(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_vals, bit; - u16 reg; - - bit = gpio_num % 8; - reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; - - spin_lock(&sio_lock); - - curr_vals = inb(reg); - if (val) - outb(curr_vals | (1 << bit) , reg); - else - outb(curr_vals & ~(1 << bit), reg); - - spin_unlock(&sio_lock); -} - -static int it8761e_gpio_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_dirs, io_reg, bit; - - bit = gpio_num % 8; - io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; - - it8761e_gpio_set(gc, gpio_num, val); - - spin_lock(&sio_lock); - - enter_conf_mode(port); - enter_gpio_mode(port); - - curr_dirs = read_reg(io_reg, port); - - if (!(curr_dirs & (1 << bit))) - write_reg(curr_dirs | (1 << bit), io_reg, port); - - exit_conf_mode(port); - - spin_unlock(&sio_lock); - return 0; -} - -static struct gpio_chip it8761e_gpio_chip = { - .label = GPIO_NAME, - .owner = THIS_MODULE, - .get = it8761e_gpio_get, - .direction_input = it8761e_gpio_direction_in, - .set = it8761e_gpio_set, - .direction_output = it8761e_gpio_direction_out, -}; - -static int __init it8761e_gpio_init(void) -{ - int i, id, err; - - /* chip and port detection */ - for (i = 0; i < ARRAY_SIZE(ports); i++) { - spin_lock(&sio_lock); - enter_conf_mode(ports[i]); - - id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) + - read_reg(CHIP_ID_LOW_BYTE, ports[i]); - - exit_conf_mode(ports[i]); - spin_unlock(&sio_lock); - - if (id == SIO_CHIP_ID) { - port = ports[i]; - break; - } - } - - if (!port) - return -ENODEV; - - /* fetch GPIO base address */ - enter_conf_mode(port); - enter_gpio_mode(port); - gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) + - read_reg(GPIO_BA_LOW_BYTE, port); - exit_conf_mode(port); - - if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME)) - return -EBUSY; - - it8761e_gpio_chip.base = -1; - it8761e_gpio_chip.ngpio = 16; - - err = gpiochip_add(&it8761e_gpio_chip); - if (err < 0) - goto gpiochip_add_err; - - return 0; - -gpiochip_add_err: - release_region(gpio_ba, GPIO_IOSIZE); - gpio_ba = 0; - return err; -} - -static void __exit it8761e_gpio_exit(void) -{ - if (gpio_ba) { - int ret = gpiochip_remove(&it8761e_gpio_chip); - - WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n", - __func__, ret); - - release_region(gpio_ba, GPIO_IOSIZE); - gpio_ba = 0; - } -} -module_init(it8761e_gpio_init); -module_exit(it8761e_gpio_exit); - -MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); -MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-janz-ttl.c b/ANDROID_3.4.5/drivers/gpio/gpio-janz-ttl.c deleted file mode 100644 index f2f000dd..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-janz-ttl.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Janz MODULbus VMOD-TTL GPIO Driver - * - * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/slab.h> - -#include <linux/mfd/janz.h> - -#define DRV_NAME "janz-ttl" - -#define PORTA_DIRECTION 0x23 -#define PORTB_DIRECTION 0x2B -#define PORTC_DIRECTION 0x06 -#define PORTA_IOCTL 0x24 -#define PORTB_IOCTL 0x2C -#define PORTC_IOCTL 0x07 - -#define MASTER_INT_CTL 0x00 -#define MASTER_CONF_CTL 0x01 - -#define CONF_PAE (1 << 2) -#define CONF_PBE (1 << 7) -#define CONF_PCE (1 << 4) - -struct ttl_control_regs { - __be16 portc; - __be16 portb; - __be16 porta; - __be16 control; -}; - -struct ttl_module { - struct gpio_chip gpio; - - /* base address of registers */ - struct ttl_control_regs __iomem *regs; - - u8 portc_shadow; - u8 portb_shadow; - u8 porta_shadow; - - spinlock_t lock; -}; - -static int ttl_get_value(struct gpio_chip *gpio, unsigned offset) -{ - struct ttl_module *mod = dev_get_drvdata(gpio->dev); - u8 *shadow; - int ret; - - if (offset < 8) { - shadow = &mod->porta_shadow; - } else if (offset < 16) { - shadow = &mod->portb_shadow; - offset -= 8; - } else { - shadow = &mod->portc_shadow; - offset -= 16; - } - - spin_lock(&mod->lock); - ret = *shadow & (1 << offset); - spin_unlock(&mod->lock); - return ret; -} - -static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value) -{ - struct ttl_module *mod = dev_get_drvdata(gpio->dev); - void __iomem *port; - u8 *shadow; - - if (offset < 8) { - port = &mod->regs->porta; - shadow = &mod->porta_shadow; - } else if (offset < 16) { - port = &mod->regs->portb; - shadow = &mod->portb_shadow; - offset -= 8; - } else { - port = &mod->regs->portc; - shadow = &mod->portc_shadow; - offset -= 16; - } - - spin_lock(&mod->lock); - if (value) - *shadow |= (1 << offset); - else - *shadow &= ~(1 << offset); - - iowrite16be(*shadow, port); - spin_unlock(&mod->lock); -} - -static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val) -{ - iowrite16be(reg, &mod->regs->control); - iowrite16be(val, &mod->regs->control); -} - -static void __devinit ttl_setup_device(struct ttl_module *mod) -{ - /* reset the device to a known state */ - iowrite16be(0x0000, &mod->regs->control); - iowrite16be(0x0001, &mod->regs->control); - iowrite16be(0x0000, &mod->regs->control); - - /* put all ports in open-drain mode */ - ttl_write_reg(mod, PORTA_IOCTL, 0x00ff); - ttl_write_reg(mod, PORTB_IOCTL, 0x00ff); - ttl_write_reg(mod, PORTC_IOCTL, 0x000f); - - /* set all ports as outputs */ - ttl_write_reg(mod, PORTA_DIRECTION, 0x0000); - ttl_write_reg(mod, PORTB_DIRECTION, 0x0000); - ttl_write_reg(mod, PORTC_DIRECTION, 0x0000); - - /* set all ports to drive zeroes */ - iowrite16be(0x0000, &mod->regs->porta); - iowrite16be(0x0000, &mod->regs->portb); - iowrite16be(0x0000, &mod->regs->portc); - - /* enable all ports */ - ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE); -} - -static int __devinit ttl_probe(struct platform_device *pdev) -{ - struct janz_platform_data *pdata; - struct device *dev = &pdev->dev; - struct ttl_module *mod; - struct gpio_chip *gpio; - struct resource *res; - int ret; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data\n"); - ret = -ENXIO; - goto out_return; - } - - mod = kzalloc(sizeof(*mod), GFP_KERNEL); - if (!mod) { - dev_err(dev, "unable to allocate private data\n"); - ret = -ENOMEM; - goto out_return; - } - - platform_set_drvdata(pdev, mod); - spin_lock_init(&mod->lock); - - /* get access to the MODULbus registers for this module */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "MODULbus registers not found\n"); - ret = -ENODEV; - goto out_free_mod; - } - - mod->regs = ioremap(res->start, resource_size(res)); - if (!mod->regs) { - dev_err(dev, "MODULbus registers not ioremap\n"); - ret = -ENOMEM; - goto out_free_mod; - } - - ttl_setup_device(mod); - - /* Initialize the GPIO data structures */ - gpio = &mod->gpio; - gpio->dev = &pdev->dev; - gpio->label = pdev->name; - gpio->get = ttl_get_value; - gpio->set = ttl_set_value; - gpio->owner = THIS_MODULE; - - /* request dynamic allocation */ - gpio->base = -1; - gpio->ngpio = 20; - - ret = gpiochip_add(gpio); - if (ret) { - dev_err(dev, "unable to add GPIO chip\n"); - goto out_iounmap_regs; - } - - return 0; - -out_iounmap_regs: - iounmap(mod->regs); -out_free_mod: - kfree(mod); -out_return: - return ret; -} - -static int __devexit ttl_remove(struct platform_device *pdev) -{ - struct ttl_module *mod = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - int ret; - - ret = gpiochip_remove(&mod->gpio); - if (ret) { - dev_err(dev, "unable to remove GPIO chip\n"); - return ret; - } - - iounmap(mod->regs); - kfree(mod); - return 0; -} - -static struct platform_driver ttl_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = ttl_probe, - .remove = __devexit_p(ttl_remove), -}; - -module_platform_driver(ttl_driver); - -MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); -MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:janz-ttl"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ks8695.c b/ANDROID_3.4.5/drivers/gpio/gpio-ks8695.c deleted file mode 100644 index a3ac66ea..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ks8695.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * arch/arm/mach-ks8695/gpio.c - * - * Copyright (C) 2006 Andrew Victor - * Updated to GPIOLIB, Copyright 2008 Simtec Electronics - * Daniel Silverstone <dsilvers@simtec.co.uk> - * - * 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. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/gpio.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/module.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/mach/irq.h> - -#include <mach/regs-gpio.h> -#include <mach/gpio-ks8695.h> - -/* - * Configure a GPIO line for either GPIO function, or its internal - * function (Interrupt, Timer, etc). - */ -static void ks8695_gpio_mode(unsigned int pin, short gpio) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned long x, flags; - - if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ - return; - - local_irq_save(flags); - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - if (gpio) /* GPIO: set bit to 0 */ - x &= ~enable[pin]; - else /* Internal function: set bit to 1 */ - x |= enable[pin]; - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); - - local_irq_restore(flags); -} - - -static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; - -/* - * Configure GPIO pin as external interrupt source. - */ -int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - /* Set IRQ triggering type */ - irq_set_irq_type(gpio_irq[pin], type); - - /* enable interrupt mode */ - ks8695_gpio_mode(pin, 0); - - return 0; -} -EXPORT_SYMBOL(ks8695_gpio_interrupt); - - - -/* .... Generic GPIO interface .............................................. */ - -/* - * Configure the GPIO line as an input. - */ -static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Configure the GPIO line as an output, with default state. - */ -static int ks8695_gpio_direction_output(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - /* set pin as output */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x |= IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Set the state of an output GPIO line. - */ -static void ks8695_gpio_set_value(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return; - - local_irq_save(flags); - - /* set output line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - local_irq_restore(flags); -} - - -/* - * Read the state of a GPIO line. - */ -static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - return (x & IOPD(pin)) != 0; -} - - -/* - * Map GPIO line to IRQ number. - */ -static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) -{ - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - return gpio_irq[pin]; -} - -/* - * Map IRQ number to GPIO line. - */ -int irq_to_gpio(unsigned int irq) -{ - if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3)) - return -EINVAL; - - return (irq - KS8695_IRQ_EXTERN0); -} -EXPORT_SYMBOL(irq_to_gpio); - -/* GPIOLIB interface */ - -static struct gpio_chip ks8695_gpio_chip = { - .label = "KS8695", - .direction_input = ks8695_gpio_direction_input, - .direction_output = ks8695_gpio_direction_output, - .get = ks8695_gpio_get_value, - .set = ks8695_gpio_set_value, - .to_irq = ks8695_gpio_to_irq, - .base = 0, - .ngpio = 16, - .can_sleep = 0, -}; - -/* Register the GPIOs */ -void ks8695_register_gpios(void) -{ - if (gpiochip_add(&ks8695_gpio_chip)) - printk(KERN_ERR "Unable to register core GPIOs\n"); -} - -/* .... Debug interface ..................................................... */ - -#ifdef CONFIG_DEBUG_FS - -static int ks8695_gpio_show(struct seq_file *s, void *unused) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; - unsigned long mode, ctrl, data; - int i; - - mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - - seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); - - for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { - seq_printf(s, "%i:\t", i); - - seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); - - if (i <= KS8695_GPIO_3) { - if (ctrl & enable[i]) { - seq_printf(s, "EXT%i ", i); - - switch ((ctrl & intmask[i]) >> (4 * i)) { - case IOPC_TM_LOW: - seq_printf(s, "(Low)"); break; - case IOPC_TM_HIGH: - seq_printf(s, "(High)"); break; - case IOPC_TM_RISING: - seq_printf(s, "(Rising)"); break; - case IOPC_TM_FALLING: - seq_printf(s, "(Falling)"); break; - case IOPC_TM_EDGE: - seq_printf(s, "(Edges)"); break; - } - } - else - seq_printf(s, "GPIO\t"); - } - else if (i <= KS8695_GPIO_5) { - if (ctrl & enable[i]) - seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); - else - seq_printf(s, "GPIO\t"); - } - else - seq_printf(s, "GPIO\t"); - - seq_printf(s, "\t"); - - seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); - } - return 0; -} - -static int ks8695_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, ks8695_gpio_show, NULL); -} - -static const struct file_operations ks8695_gpio_operations = { - .open = ks8695_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init ks8695_gpio_debugfs_init(void) -{ - /* /sys/kernel/debug/ks8695_gpio */ - (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations); - return 0; -} -postcore_initcall(ks8695_gpio_debugfs_init); - -#endif diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-langwell.c b/ANDROID_3.4.5/drivers/gpio/gpio-langwell.c deleted file mode 100644 index 00692e89..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-langwell.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Moorestown platform Langwell chip GPIO driver - * - * Copyright (c) 2008 - 2009, Intel Corporation. - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Moorestown platform Langwell chip. - * Medfield platform Penwell chip. - * Whitney point. - */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/pm_runtime.h> - -/* - * Langwell chip has 64 pins and thus there are 2 32bit registers to control - * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit - * registers to control them, so we only define the order here instead of a - * structure, to get a bit offset for a pin (use GPDR as an example): - * - * nreg = ngpio / 32; - * reg = offset / 32; - * bit = offset % 32; - * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; - * - * so the bit of reg_addr is to control pin offset's GPDR feature -*/ - -enum GPIO_REG { - GPLR = 0, /* pin level read-only */ - GPDR, /* pin direction */ - GPSR, /* pin set */ - GPCR, /* pin clear */ - GRER, /* rising edge detect */ - GFER, /* falling edge detect */ - GEDR, /* edge detect result */ - GAFR, /* alt function */ -}; - -struct lnw_gpio { - struct gpio_chip chip; - void *reg_base; - spinlock_t lock; - unsigned irq_base; - struct pci_dev *pdev; -}; - -static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, - enum GPIO_REG reg_type) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - unsigned nreg = chip->ngpio / 32; - u8 reg = offset / 32; - void __iomem *ptr; - - ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); - return ptr; -} - -static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset, - enum GPIO_REG reg_type) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - unsigned nreg = chip->ngpio / 32; - u8 reg = offset / 16; - void __iomem *ptr; - - ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); - return ptr; -} - -static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR); - u32 value = readl(gafr); - int shift = (offset % 16) << 1, af = (value >> shift) & 3; - - if (af) { - value &= ~(3 << shift); - writel(value, gafr); - } - return 0; -} - -static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *gplr = gpio_reg(chip, offset, GPLR); - - return readl(gplr) & BIT(offset % 32); -} - -static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - void __iomem *gpsr, *gpcr; - - if (value) { - gpsr = gpio_reg(chip, offset, GPSR); - writel(BIT(offset % 32), gpsr); - } else { - gpcr = gpio_reg(chip, offset, GPCR); - writel(BIT(offset % 32), gpcr); - } -} - -static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - u32 value; - unsigned long flags; - - if (lnw->pdev) - pm_runtime_get(&lnw->pdev->dev); - - spin_lock_irqsave(&lnw->lock, flags); - value = readl(gpdr); - value &= ~BIT(offset % 32); - writel(value, gpdr); - spin_unlock_irqrestore(&lnw->lock, flags); - - if (lnw->pdev) - pm_runtime_put(&lnw->pdev->dev); - - return 0; -} - -static int lnw_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - unsigned long flags; - - lnw_gpio_set(chip, offset, value); - - if (lnw->pdev) - pm_runtime_get(&lnw->pdev->dev); - - spin_lock_irqsave(&lnw->lock, flags); - value = readl(gpdr); - value |= BIT(offset % 32); - writel(value, gpdr); - spin_unlock_irqrestore(&lnw->lock, flags); - - if (lnw->pdev) - pm_runtime_put(&lnw->pdev->dev); - - return 0; -} - -static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - return lnw->irq_base + offset; -} - -static int lnw_irq_type(struct irq_data *d, unsigned type) -{ - struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); - u32 gpio = d->irq - lnw->irq_base; - unsigned long flags; - u32 value; - void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); - void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); - - if (gpio >= lnw->chip.ngpio) - return -EINVAL; - - if (lnw->pdev) - pm_runtime_get(&lnw->pdev->dev); - - spin_lock_irqsave(&lnw->lock, flags); - if (type & IRQ_TYPE_EDGE_RISING) - value = readl(grer) | BIT(gpio % 32); - else - value = readl(grer) & (~BIT(gpio % 32)); - writel(value, grer); - - if (type & IRQ_TYPE_EDGE_FALLING) - value = readl(gfer) | BIT(gpio % 32); - else - value = readl(gfer) & (~BIT(gpio % 32)); - writel(value, gfer); - spin_unlock_irqrestore(&lnw->lock, flags); - - if (lnw->pdev) - pm_runtime_put(&lnw->pdev->dev); - - return 0; -} - -static void lnw_irq_unmask(struct irq_data *d) -{ -} - -static void lnw_irq_mask(struct irq_data *d) -{ -} - -static struct irq_chip lnw_irqchip = { - .name = "LNW-GPIO", - .irq_mask = lnw_irq_mask, - .irq_unmask = lnw_irq_unmask, - .irq_set_type = lnw_irq_type, -}; - -static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); - -static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct irq_data *data = irq_desc_get_irq_data(desc); - struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); - struct irq_chip *chip = irq_data_get_irq_chip(data); - u32 base, gpio, mask; - unsigned long pending; - void __iomem *gedr; - - /* check GPIO controller to check which pin triggered the interrupt */ - for (base = 0; base < lnw->chip.ngpio; base += 32) { - gedr = gpio_reg(&lnw->chip, base, GEDR); - pending = readl(gedr); - while (pending) { - gpio = __ffs(pending); - mask = BIT(gpio); - pending &= ~mask; - /* Clear before handling so we can't lose an edge */ - writel(mask, gedr); - generic_handle_irq(lnw->irq_base + base + gpio); - } - } - - chip->irq_eoi(data); -} - -#ifdef CONFIG_PM -static int lnw_gpio_runtime_resume(struct device *dev) -{ - return 0; -} - -static int lnw_gpio_runtime_suspend(struct device *dev) -{ - return 0; -} - -static int lnw_gpio_runtime_idle(struct device *dev) -{ - int err = pm_schedule_suspend(dev, 500); - - if (!err) - return 0; - - return -EBUSY; -} - -#else -#define lnw_gpio_runtime_suspend NULL -#define lnw_gpio_runtime_resume NULL -#define lnw_gpio_runtime_idle NULL -#endif - -static const struct dev_pm_ops lnw_gpio_pm_ops = { - .runtime_suspend = lnw_gpio_runtime_suspend, - .runtime_resume = lnw_gpio_runtime_resume, - .runtime_idle = lnw_gpio_runtime_idle, -}; - -static int __devinit lnw_gpio_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void *base; - int i; - resource_size_t start, len; - struct lnw_gpio *lnw; - u32 irq_base; - u32 gpio_base; - int retval = 0; - - retval = pci_enable_device(pdev); - if (retval) - goto done; - - retval = pci_request_regions(pdev, "langwell_gpio"); - if (retval) { - dev_err(&pdev->dev, "error requesting resources\n"); - goto err2; - } - /* get the irq_base from bar1 */ - start = pci_resource_start(pdev, 1); - len = pci_resource_len(pdev, 1); - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&pdev->dev, "error mapping bar1\n"); - goto err3; - } - irq_base = *(u32 *)base; - gpio_base = *((u32 *)base + 1); - /* release the IO mapping, since we already get the info from bar1 */ - iounmap(base); - /* get the register base from bar0 */ - start = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&pdev->dev, "error mapping bar0\n"); - retval = -EFAULT; - goto err3; - } - - lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); - if (!lnw) { - dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); - retval = -ENOMEM; - goto err4; - } - lnw->reg_base = base; - lnw->irq_base = irq_base; - lnw->chip.label = dev_name(&pdev->dev); - lnw->chip.request = lnw_gpio_request; - lnw->chip.direction_input = lnw_gpio_direction_input; - lnw->chip.direction_output = lnw_gpio_direction_output; - lnw->chip.get = lnw_gpio_get; - lnw->chip.set = lnw_gpio_set; - lnw->chip.to_irq = lnw_gpio_to_irq; - lnw->chip.base = gpio_base; - lnw->chip.ngpio = id->driver_data; - lnw->chip.can_sleep = 0; - lnw->pdev = pdev; - pci_set_drvdata(pdev, lnw); - retval = gpiochip_add(&lnw->chip); - if (retval) { - dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); - goto err5; - } - irq_set_handler_data(pdev->irq, lnw); - irq_set_chained_handler(pdev->irq, lnw_irq_handler); - for (i = 0; i < lnw->chip.ngpio; i++) { - irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, - handle_simple_irq, "demux"); - irq_set_chip_data(i + lnw->irq_base, lnw); - } - - spin_lock_init(&lnw->lock); - - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_allow(&pdev->dev); - - goto done; -err5: - kfree(lnw); -err4: - iounmap(base); -err3: - pci_release_regions(pdev); -err2: - pci_disable_device(pdev); -done: - return retval; -} - -static struct pci_driver lnw_gpio_driver = { - .name = "langwell_gpio", - .id_table = lnw_gpio_ids, - .probe = lnw_gpio_probe, - .driver = { - .pm = &lnw_gpio_pm_ops, - }, -}; - - -static int __devinit wp_gpio_probe(struct platform_device *pdev) -{ - struct lnw_gpio *lnw; - struct gpio_chip *gc; - struct resource *rc; - int retval = 0; - - rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!rc) - return -EINVAL; - - lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); - if (!lnw) { - dev_err(&pdev->dev, - "can't allocate whitneypoint_gpio chip data\n"); - return -ENOMEM; - } - lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc)); - if (lnw->reg_base == NULL) { - retval = -EINVAL; - goto err_kmalloc; - } - spin_lock_init(&lnw->lock); - gc = &lnw->chip; - gc->label = dev_name(&pdev->dev); - gc->owner = THIS_MODULE; - gc->direction_input = lnw_gpio_direction_input; - gc->direction_output = lnw_gpio_direction_output; - gc->get = lnw_gpio_get; - gc->set = lnw_gpio_set; - gc->to_irq = NULL; - gc->base = 0; - gc->ngpio = 64; - gc->can_sleep = 0; - retval = gpiochip_add(gc); - if (retval) { - dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n", - retval); - goto err_ioremap; - } - platform_set_drvdata(pdev, lnw); - return 0; -err_ioremap: - iounmap(lnw->reg_base); -err_kmalloc: - kfree(lnw); - return retval; -} - -static int __devexit wp_gpio_remove(struct platform_device *pdev) -{ - struct lnw_gpio *lnw = platform_get_drvdata(pdev); - int err; - err = gpiochip_remove(&lnw->chip); - if (err) - dev_err(&pdev->dev, "failed to remove gpio_chip.\n"); - iounmap(lnw->reg_base); - kfree(lnw); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver wp_gpio_driver = { - .probe = wp_gpio_probe, - .remove = __devexit_p(wp_gpio_remove), - .driver = { - .name = "wp_gpio", - .owner = THIS_MODULE, - }, -}; - -static int __init lnw_gpio_init(void) -{ - int ret; - ret = pci_register_driver(&lnw_gpio_driver); - if (ret < 0) - return ret; - ret = platform_driver_register(&wp_gpio_driver); - if (ret < 0) - pci_unregister_driver(&lnw_gpio_driver); - return ret; -} - -device_initcall(lnw_gpio_init); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-lpc32xx.c b/ANDROID_3.4.5/drivers/gpio/gpio-lpc32xx.c deleted file mode 100644 index 61c2d08d..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-lpc32xx.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * arch/arm/mach-lpc32xx/gpiolib.c - * - * Author: Kevin Wells <kevin.wells@nxp.com> - * - * Copyright (C) 2010 NXP Semiconductors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/errno.h> -#include <linux/gpio.h> - -#include <mach/hardware.h> -#include <mach/platform.h> -#include <mach/gpio-lpc32xx.h> - -#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) -#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) -#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) -#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) -#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) -#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) -#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) -#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) -#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) -#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) -#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) -#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) -#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) -#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) -#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) -#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) -#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) -#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) -#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) -#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) -#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) -#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) -#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) -#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) -#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) -#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) -#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) - -#define GPIO012_PIN_TO_BIT(x) (1 << (x)) -#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) -#define GPO3_PIN_TO_BIT(x) (1 << (x)) -#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) -#define GPIO3_PIN_IN_SHIFT(x) ((x) == 5 ? 24 : 10 + (x)) -#define GPIO3_PIN_IN_SEL(x, y) (((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1) -#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1) -#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) -#define GPO3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) - -struct gpio_regs { - void __iomem *inp_state; - void __iomem *outp_state; - void __iomem *outp_set; - void __iomem *outp_clr; - void __iomem *dir_set; - void __iomem *dir_clr; -}; - -/* - * GPIO names - */ -static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = { - "p0.0", "p0.1", "p0.2", "p0.3", - "p0.4", "p0.5", "p0.6", "p0.7" -}; - -static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = { - "p1.0", "p1.1", "p1.2", "p1.3", - "p1.4", "p1.5", "p1.6", "p1.7", - "p1.8", "p1.9", "p1.10", "p1.11", - "p1.12", "p1.13", "p1.14", "p1.15", - "p1.16", "p1.17", "p1.18", "p1.19", - "p1.20", "p1.21", "p1.22", "p1.23", -}; - -static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = { - "p2.0", "p2.1", "p2.2", "p2.3", - "p2.4", "p2.5", "p2.6", "p2.7", - "p2.8", "p2.9", "p2.10", "p2.11", - "p2.12" -}; - -static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { - "gpio00", "gpio01", "gpio02", "gpio03", - "gpio04", "gpio05" -}; - -static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = { - "gpi00", "gpi01", "gpi02", "gpi03", - "gpi04", "gpi05", "gpi06", "gpi07", - "gpi08", "gpi09", NULL, NULL, - NULL, NULL, NULL, "gpi15", - "gpi16", "gpi17", "gpi18", "gpi19", - "gpi20", "gpi21", "gpi22", "gpi23", - "gpi24", "gpi25", "gpi26", "gpi27" -}; - -static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = { - "gpo00", "gpo01", "gpo02", "gpo03", - "gpo04", "gpo05", "gpo06", "gpo07", - "gpo08", "gpo09", "gpo10", "gpo11", - "gpo12", "gpo13", "gpo14", "gpo15", - "gpo16", "gpo17", "gpo18", "gpo19", - "gpo20", "gpo21", "gpo22", "gpo23" -}; - -static struct gpio_regs gpio_grp_regs_p0 = { - .inp_state = LPC32XX_GPIO_P0_INP_STATE, - .outp_set = LPC32XX_GPIO_P0_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P0_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P0_DIR_SET, - .dir_clr = LPC32XX_GPIO_P0_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p1 = { - .inp_state = LPC32XX_GPIO_P1_INP_STATE, - .outp_set = LPC32XX_GPIO_P1_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P1_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P1_DIR_SET, - .dir_clr = LPC32XX_GPIO_P1_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p2 = { - .inp_state = LPC32XX_GPIO_P2_INP_STATE, - .outp_set = LPC32XX_GPIO_P2_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P2_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P2_DIR_SET, - .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, -}; - -static struct gpio_regs gpio_grp_regs_p3 = { - .inp_state = LPC32XX_GPIO_P3_INP_STATE, - .outp_state = LPC32XX_GPIO_P3_OUTP_STATE, - .outp_set = LPC32XX_GPIO_P3_OUTP_SET, - .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR, - .dir_set = LPC32XX_GPIO_P2_DIR_SET, - .dir_clr = LPC32XX_GPIO_P2_DIR_CLR, -}; - -struct lpc32xx_gpio_chip { - struct gpio_chip chip; - struct gpio_regs *gpio_grp; -}; - -static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio( - struct gpio_chip *gpc) -{ - return container_of(gpc, struct lpc32xx_gpio_chip, chip); -} - -static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, - unsigned pin, int input) -{ - if (input) - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->dir_clr); - else - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->dir_set); -} - -static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int input) -{ - u32 u = GPIO3_PIN_TO_BIT(pin); - - if (input) - __raw_writel(u, group->gpio_grp->dir_clr); - else - __raw_writel(u, group->gpio_grp->dir_set); -} - -static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - if (high) - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->outp_set); - else - __raw_writel(GPIO012_PIN_TO_BIT(pin), - group->gpio_grp->outp_clr); -} - -static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - u32 u = GPIO3_PIN_TO_BIT(pin); - - if (high) - __raw_writel(u, group->gpio_grp->outp_set); - else - __raw_writel(u, group->gpio_grp->outp_clr); -} - -static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, - unsigned pin, int high) -{ - if (high) - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); - else - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); -} - -static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), - pin); -} - -static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - int state = __raw_readl(group->gpio_grp->inp_state); - - /* - * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped - * to bits 10..14, while GPIOP3-5 is mapped to bit 24. - */ - return GPIO3_PIN_IN_SEL(state, pin); -} - -static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); -} - -static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group, - unsigned pin) -{ - return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin); -} - -/* - * GENERIC_GPIO primitives. - */ -static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip, - unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p012(group, pin, 1); - - return 0; -} - -static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip, - unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p3(group, pin, 1); - - return 0; -} - -static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip, - unsigned pin) -{ - return 0; -} - -static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpio_state_p012(group, pin); -} - -static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpio_state_p3(group, pin); -} - -static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpi_state_p3(group, pin); -} - -static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p012(group, pin, 0); - - return 0; -} - -static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_dir_p3(group, pin, 0); - - return 0; -} - -static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, - int value) -{ - return 0; -} - -static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_level_p012(group, pin, value); -} - -static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpio_level_p3(group, pin, value); -} - -static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin, - int value) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpo_level_p3(group, pin, value); -} - -static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin) -{ - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - return __get_gpo_state_p3(group, pin); -} - -static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) -{ - if (pin < chip->ngpio) - return 0; - - return -EINVAL; -} - -static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { - { - .chip = { - .label = "gpio_p0", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P0_GRP, - .ngpio = LPC32XX_GPIO_P0_MAX, - .names = gpio_p0_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p0, - }, - { - .chip = { - .label = "gpio_p1", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P1_GRP, - .ngpio = LPC32XX_GPIO_P1_MAX, - .names = gpio_p1_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p1, - }, - { - .chip = { - .label = "gpio_p2", - .direction_input = lpc32xx_gpio_dir_input_p012, - .get = lpc32xx_gpio_get_value_p012, - .direction_output = lpc32xx_gpio_dir_output_p012, - .set = lpc32xx_gpio_set_value_p012, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P2_GRP, - .ngpio = LPC32XX_GPIO_P2_MAX, - .names = gpio_p2_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p2, - }, - { - .chip = { - .label = "gpio_p3", - .direction_input = lpc32xx_gpio_dir_input_p3, - .get = lpc32xx_gpio_get_value_p3, - .direction_output = lpc32xx_gpio_dir_output_p3, - .set = lpc32xx_gpio_set_value_p3, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPIO_P3_GRP, - .ngpio = LPC32XX_GPIO_P3_MAX, - .names = gpio_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, - { - .chip = { - .label = "gpi_p3", - .direction_input = lpc32xx_gpio_dir_in_always, - .get = lpc32xx_gpi_get_value, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPI_P3_GRP, - .ngpio = LPC32XX_GPI_P3_MAX, - .names = gpi_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, - { - .chip = { - .label = "gpo_p3", - .direction_output = lpc32xx_gpio_dir_out_always, - .set = lpc32xx_gpo_set_value, - .get = lpc32xx_gpo_get_value, - .request = lpc32xx_gpio_request, - .base = LPC32XX_GPO_P3_GRP, - .ngpio = LPC32XX_GPO_P3_MAX, - .names = gpo_p3_names, - .can_sleep = 0, - }, - .gpio_grp = &gpio_grp_regs_p3, - }, -}; - -void __init lpc32xx_gpio_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) - gpiochip_add(&lpc32xx_gpiochip[i].chip); -} diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-max7300.c b/ANDROID_3.4.5/drivers/gpio/gpio-max7300.c deleted file mode 100644 index a5ca0ab1..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-max7300.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2009 Wolfram Sang, Pengutronix - * - * 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. - * - * Check max730x.c for further details. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/i2c.h> -#include <linux/spi/max7301.h> -#include <linux/slab.h> - -static int max7300_i2c_write(struct device *dev, unsigned int reg, - unsigned int val) -{ - struct i2c_client *client = to_i2c_client(dev); - - return i2c_smbus_write_byte_data(client, reg, val); -} - -static int max7300_i2c_read(struct device *dev, unsigned int reg) -{ - struct i2c_client *client = to_i2c_client(dev); - - return i2c_smbus_read_byte_data(client, reg); -} - -static int __devinit max7300_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max7301 *ts; - int ret; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - ts = kzalloc(sizeof(struct max7301), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->read = max7300_i2c_read; - ts->write = max7300_i2c_write; - ts->dev = &client->dev; - - ret = __max730x_probe(ts); - if (ret) - kfree(ts); - return ret; -} - -static int __devexit max7300_remove(struct i2c_client *client) -{ - return __max730x_remove(&client->dev); -} - -static const struct i2c_device_id max7300_id[] = { - { "max7300", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max7300_id); - -static struct i2c_driver max7300_driver = { - .driver = { - .name = "max7300", - .owner = THIS_MODULE, - }, - .probe = max7300_probe, - .remove = __devexit_p(max7300_remove), - .id_table = max7300_id, -}; - -static int __init max7300_init(void) -{ - return i2c_add_driver(&max7300_driver); -} -subsys_initcall(max7300_init); - -static void __exit max7300_exit(void) -{ - i2c_del_driver(&max7300_driver); -} -module_exit(max7300_exit); - -MODULE_AUTHOR("Wolfram Sang"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MAX7300 GPIO-Expander"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-max7301.c b/ANDROID_3.4.5/drivers/gpio/gpio-max7301.c deleted file mode 100644 index 741acfcb..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-max7301.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2006 Juergen Beisert, Pengutronix - * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix - * Copyright (C) 2009 Wolfram Sang, Pengutronix - * - * 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. - * - * Check max730x.c for further details. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> -#include <linux/spi/max7301.h> - -/* A write to the MAX7301 means one message with one transfer */ -static int max7301_spi_write(struct device *dev, unsigned int reg, - unsigned int val) -{ - struct spi_device *spi = to_spi_device(dev); - u16 word = ((reg & 0x7F) << 8) | (val & 0xFF); - - return spi_write(spi, (const u8 *)&word, sizeof(word)); -} - -/* A read from the MAX7301 means two transfers; here, one message each */ - -static int max7301_spi_read(struct device *dev, unsigned int reg) -{ - int ret; - u16 word; - struct spi_device *spi = to_spi_device(dev); - - word = 0x8000 | (reg << 8); - ret = spi_write(spi, (const u8 *)&word, sizeof(word)); - if (ret) - return ret; - /* - * This relies on the fact, that a transfer with NULL tx_buf shifts out - * zero bytes (=NOOP for MAX7301) - */ - ret = spi_read(spi, (u8 *)&word, sizeof(word)); - if (ret) - return ret; - return word & 0xff; -} - -static int __devinit max7301_probe(struct spi_device *spi) -{ - struct max7301 *ts; - int ret; - - /* bits_per_word cannot be configured in platform data */ - spi->bits_per_word = 16; - ret = spi_setup(spi); - if (ret < 0) - return ret; - - ts = kzalloc(sizeof(struct max7301), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->read = max7301_spi_read; - ts->write = max7301_spi_write; - ts->dev = &spi->dev; - - ret = __max730x_probe(ts); - if (ret) - kfree(ts); - return ret; -} - -static int __devexit max7301_remove(struct spi_device *spi) -{ - return __max730x_remove(&spi->dev); -} - -static const struct spi_device_id max7301_id[] = { - { "max7301", 0 }, - { } -}; -MODULE_DEVICE_TABLE(spi, max7301_id); - -static struct spi_driver max7301_driver = { - .driver = { - .name = "max7301", - .owner = THIS_MODULE, - }, - .probe = max7301_probe, - .remove = __devexit_p(max7301_remove), - .id_table = max7301_id, -}; - -static int __init max7301_init(void) -{ - return spi_register_driver(&max7301_driver); -} -/* register after spi postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(max7301_init); - -static void __exit max7301_exit(void) -{ - spi_unregister_driver(&max7301_driver); -} -module_exit(max7301_exit); - -MODULE_AUTHOR("Juergen Beisert, Wolfram Sang"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MAX7301 GPIO-Expander"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-max730x.c b/ANDROID_3.4.5/drivers/gpio/gpio-max730x.c deleted file mode 100644 index 05e2dac6..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-max730x.c +++ /dev/null @@ -1,255 +0,0 @@ -/** - * Copyright (C) 2006 Juergen Beisert, Pengutronix - * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix - * Copyright (C) 2009 Wolfram Sang, Pengutronix - * - * 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. - * - * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are - * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more - * details - * Note: - * - DIN must be stable at the rising edge of clock. - * - when writing: - * - always clock in 16 clocks at once - * - at DIN: D15 first, D0 last - * - D0..D7 = databyte, D8..D14 = commandbyte - * - D15 = low -> write command - * - when reading - * - always clock in 16 clocks at once - * - at DIN: D15 first, D0 last - * - D0..D7 = dummy, D8..D14 = register address - * - D15 = high -> read command - * - raise CS and assert it again - * - always clock in 16 clocks at once - * - at DOUT: D15 first, D0 last - * - D0..D7 contains the data from the first cycle - * - * The driver exports a standard gpiochip interface - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/spi/max7301.h> -#include <linux/gpio.h> -#include <linux/slab.h> - -/* - * Pin configurations, see MAX7301 datasheet page 6 - */ -#define PIN_CONFIG_MASK 0x03 -#define PIN_CONFIG_IN_PULLUP 0x03 -#define PIN_CONFIG_IN_WO_PULLUP 0x02 -#define PIN_CONFIG_OUT 0x01 - -#define PIN_NUMBER 28 - -static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct max7301 *ts = container_of(chip, struct max7301, chip); - u8 *config; - u8 offset_bits, pin_config; - int ret; - - /* First 4 pins are unused in the controller */ - offset += 4; - offset_bits = (offset & 3) << 1; - - config = &ts->port_config[offset >> 2]; - - if (ts->input_pullup_active & BIT(offset)) - pin_config = PIN_CONFIG_IN_PULLUP; - else - pin_config = PIN_CONFIG_IN_WO_PULLUP; - - mutex_lock(&ts->lock); - - *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) - | (pin_config << offset_bits); - - ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); - - mutex_unlock(&ts->lock); - - return ret; -} - -static int __max7301_set(struct max7301 *ts, unsigned offset, int value) -{ - if (value) { - ts->out_level |= 1 << offset; - return ts->write(ts->dev, 0x20 + offset, 0x01); - } else { - ts->out_level &= ~(1 << offset); - return ts->write(ts->dev, 0x20 + offset, 0x00); - } -} - -static int max7301_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct max7301 *ts = container_of(chip, struct max7301, chip); - u8 *config; - u8 offset_bits; - int ret; - - /* First 4 pins are unused in the controller */ - offset += 4; - offset_bits = (offset & 3) << 1; - - config = &ts->port_config[offset >> 2]; - - mutex_lock(&ts->lock); - - *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) - | (PIN_CONFIG_OUT << offset_bits); - - ret = __max7301_set(ts, offset, value); - - if (!ret) - ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); - - mutex_unlock(&ts->lock); - - return ret; -} - -static int max7301_get(struct gpio_chip *chip, unsigned offset) -{ - struct max7301 *ts = container_of(chip, struct max7301, chip); - int config, level = -EINVAL; - - /* First 4 pins are unused in the controller */ - offset += 4; - - mutex_lock(&ts->lock); - - config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1)) - & PIN_CONFIG_MASK; - - switch (config) { - case PIN_CONFIG_OUT: - /* Output: return cached level */ - level = !!(ts->out_level & (1 << offset)); - break; - case PIN_CONFIG_IN_WO_PULLUP: - case PIN_CONFIG_IN_PULLUP: - /* Input: read out */ - level = ts->read(ts->dev, 0x20 + offset) & 0x01; - } - mutex_unlock(&ts->lock); - - return level; -} - -static void max7301_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct max7301 *ts = container_of(chip, struct max7301, chip); - - /* First 4 pins are unused in the controller */ - offset += 4; - - mutex_lock(&ts->lock); - - __max7301_set(ts, offset, value); - - mutex_unlock(&ts->lock); -} - -int __devinit __max730x_probe(struct max7301 *ts) -{ - struct device *dev = ts->dev; - struct max7301_platform_data *pdata; - int i, ret; - - pdata = dev->platform_data; - if (!pdata || !pdata->base) { - dev_err(dev, "incorrect or missing platform data\n"); - return -EINVAL; - } - - mutex_init(&ts->lock); - dev_set_drvdata(dev, ts); - - /* Power up the chip and disable IRQ output */ - ts->write(dev, 0x04, 0x01); - - ts->input_pullup_active = pdata->input_pullup_active; - ts->chip.label = dev->driver->name; - - ts->chip.direction_input = max7301_direction_input; - ts->chip.get = max7301_get; - ts->chip.direction_output = max7301_direction_output; - ts->chip.set = max7301_set; - - ts->chip.base = pdata->base; - ts->chip.ngpio = PIN_NUMBER; - ts->chip.can_sleep = 1; - ts->chip.dev = dev; - ts->chip.owner = THIS_MODULE; - - /* - * initialize pullups according to platform data and cache the - * register values for later use. - */ - for (i = 1; i < 8; i++) { - int j; - /* - * initialize port_config with "0xAA", which means - * input with internal pullup disabled. This is needed - * to avoid writing zeros (in the inner for loop), - * which is not allowed according to the datasheet. - */ - ts->port_config[i] = 0xAA; - for (j = 0; j < 4; j++) { - int offset = (i - 1) * 4 + j; - ret = max7301_direction_input(&ts->chip, offset); - if (ret) - goto exit_destroy; - } - } - - ret = gpiochip_add(&ts->chip); - if (ret) - goto exit_destroy; - - return ret; - -exit_destroy: - dev_set_drvdata(dev, NULL); - mutex_destroy(&ts->lock); - return ret; -} -EXPORT_SYMBOL_GPL(__max730x_probe); - -int __devexit __max730x_remove(struct device *dev) -{ - struct max7301 *ts = dev_get_drvdata(dev); - int ret; - - if (ts == NULL) - return -ENODEV; - - dev_set_drvdata(dev, NULL); - - /* Power down the chip and disable IRQ output */ - ts->write(dev, 0x04, 0x00); - - ret = gpiochip_remove(&ts->chip); - if (!ret) { - mutex_destroy(&ts->lock); - kfree(ts); - } else - dev_err(dev, "Failed to remove GPIO controller: %d\n", ret); - - return ret; -} -EXPORT_SYMBOL_GPL(__max730x_remove); - -MODULE_AUTHOR("Juergen Beisert, Wolfram Sang"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-max732x.c b/ANDROID_3.4.5/drivers/gpio/gpio-max732x.c deleted file mode 100644 index 95041208..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-max732x.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * MAX732x I2C Port Expander with 8/16 I/O - * - * Copyright (C) 2007 Marvell International Ltd. - * Copyright (C) 2008 Jack Ren <jack.ren@marvell.com> - * Copyright (C) 2008 Eric Miao <eric.miao@marvell.com> - * - * Derived from drivers/gpio/pca953x.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/i2c.h> -#include <linux/i2c/max732x.h> - - -/* - * Each port of MAX732x (including MAX7319) falls into one of the - * following three types: - * - * - Push Pull Output - * - Input - * - Open Drain I/O - * - * designated by 'O', 'I' and 'P' individually according to MAXIM's - * datasheets. 'I' and 'P' ports are interrupt capables, some with - * a dedicated interrupt mask. - * - * There are two groups of I/O ports, each group usually includes - * up to 8 I/O ports, and is accessed by a specific I2C address: - * - * - Group A : by I2C address 0b'110xxxx - * - Group B : by I2C address 0b'101xxxx - * - * where 'xxxx' is decided by the connections of pin AD2/AD0. The - * address used also affects the initial state of output signals. - * - * Within each group of ports, there are five known combinations of - * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for - * the detailed organization of these ports. Only Goup A is interrupt - * capable. - * - * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16', - * and GPIOs from GROUP_A are numbered before those from GROUP_B - * (if there are two groups). - * - * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so - * they are not supported by this driver. - */ - -#define PORT_NONE 0x0 /* '/' No Port */ -#define PORT_OUTPUT 0x1 /* 'O' Push-Pull, Output Only */ -#define PORT_INPUT 0x2 /* 'I' Input Only */ -#define PORT_OPENDRAIN 0x3 /* 'P' Open-Drain, I/O */ - -#define IO_4I4O 0x5AA5 /* O7 O6 I5 I4 I3 I2 O1 O0 */ -#define IO_4P4O 0x5FF5 /* O7 O6 P5 P4 P3 P2 O1 O0 */ -#define IO_8I 0xAAAA /* I7 I6 I5 I4 I3 I2 I1 I0 */ -#define IO_8P 0xFFFF /* P7 P6 P5 P4 P3 P2 P1 P0 */ -#define IO_8O 0x5555 /* O7 O6 O5 O4 O3 O2 O1 O0 */ - -#define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */ -#define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */ - -#define INT_NONE 0x0 /* No interrupt capability */ -#define INT_NO_MASK 0x1 /* Has interrupts, no mask */ -#define INT_INDEP_MASK 0x2 /* Has interrupts, independent mask */ -#define INT_MERGED_MASK 0x3 /* Has interrupts, merged mask */ - -#define INT_CAPS(x) (((uint64_t)(x)) << 32) - -enum { - MAX7319, - MAX7320, - MAX7321, - MAX7322, - MAX7323, - MAX7324, - MAX7325, - MAX7326, - MAX7327, -}; - -static uint64_t max732x_features[] = { - [MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK), - [MAX7320] = GROUP_B(IO_8O), - [MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK), - [MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK), - [MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK), - [MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK), - [MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK), - [MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK), - [MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK), -}; - -static const struct i2c_device_id max732x_id[] = { - { "max7319", MAX7319 }, - { "max7320", MAX7320 }, - { "max7321", MAX7321 }, - { "max7322", MAX7322 }, - { "max7323", MAX7323 }, - { "max7324", MAX7324 }, - { "max7325", MAX7325 }, - { "max7326", MAX7326 }, - { "max7327", MAX7327 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, max732x_id); - -struct max732x_chip { - struct gpio_chip gpio_chip; - - struct i2c_client *client; /* "main" client */ - struct i2c_client *client_dummy; - struct i2c_client *client_group_a; - struct i2c_client *client_group_b; - - unsigned int mask_group_a; - unsigned int dir_input; - unsigned int dir_output; - - struct mutex lock; - uint8_t reg_out[2]; - -#ifdef CONFIG_GPIO_MAX732X_IRQ - struct mutex irq_lock; - int irq_base; - uint8_t irq_mask; - uint8_t irq_mask_cur; - uint8_t irq_trig_raise; - uint8_t irq_trig_fall; - uint8_t irq_features; -#endif -}; - -static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val) -{ - struct i2c_client *client; - int ret; - - client = group_a ? chip->client_group_a : chip->client_group_b; - ret = i2c_smbus_write_byte(client, val); - if (ret < 0) { - dev_err(&client->dev, "failed writing\n"); - return ret; - } - - return 0; -} - -static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val) -{ - struct i2c_client *client; - int ret; - - client = group_a ? chip->client_group_a : chip->client_group_b; - ret = i2c_smbus_read_byte(client); - if (ret < 0) { - dev_err(&client->dev, "failed reading\n"); - return ret; - } - - *val = (uint8_t)ret; - return 0; -} - -static inline int is_group_a(struct max732x_chip *chip, unsigned off) -{ - return (1u << off) & chip->mask_group_a; -} - -static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off) -{ - struct max732x_chip *chip; - uint8_t reg_val; - int ret; - - chip = container_of(gc, struct max732x_chip, gpio_chip); - - ret = max732x_readb(chip, is_group_a(chip, off), ®_val); - if (ret < 0) - return 0; - - return reg_val & (1u << (off & 0x7)); -} - -static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) -{ - struct max732x_chip *chip; - uint8_t reg_out, mask = 1u << (off & 0x7); - int ret; - - chip = container_of(gc, struct max732x_chip, gpio_chip); - - mutex_lock(&chip->lock); - - reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; - reg_out = (val) ? reg_out | mask : reg_out & ~mask; - - ret = max732x_writeb(chip, is_group_a(chip, off), reg_out); - if (ret < 0) - goto out; - - /* update the shadow register then */ - if (off > 7) - chip->reg_out[1] = reg_out; - else - chip->reg_out[0] = reg_out; -out: - mutex_unlock(&chip->lock); -} - -static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off) -{ - struct max732x_chip *chip; - unsigned int mask = 1u << off; - - chip = container_of(gc, struct max732x_chip, gpio_chip); - - if ((mask & chip->dir_input) == 0) { - dev_dbg(&chip->client->dev, "%s port %d is output only\n", - chip->client->name, off); - return -EACCES; - } - - /* - * Open-drain pins must be set to high impedance (which is - * equivalent to output-high) to be turned into an input. - */ - if ((mask & chip->dir_output)) - max732x_gpio_set_value(gc, off, 1); - - return 0; -} - -static int max732x_gpio_direction_output(struct gpio_chip *gc, - unsigned off, int val) -{ - struct max732x_chip *chip; - unsigned int mask = 1u << off; - - chip = container_of(gc, struct max732x_chip, gpio_chip); - - if ((mask & chip->dir_output) == 0) { - dev_dbg(&chip->client->dev, "%s port %d is input only\n", - chip->client->name, off); - return -EACCES; - } - - max732x_gpio_set_value(gc, off, val); - return 0; -} - -#ifdef CONFIG_GPIO_MAX732X_IRQ -static int max732x_writew(struct max732x_chip *chip, uint16_t val) -{ - int ret; - - val = cpu_to_le16(val); - - ret = i2c_master_send(chip->client_group_a, (char *)&val, 2); - if (ret < 0) { - dev_err(&chip->client_group_a->dev, "failed writing\n"); - return ret; - } - - return 0; -} - -static int max732x_readw(struct max732x_chip *chip, uint16_t *val) -{ - int ret; - - ret = i2c_master_recv(chip->client_group_a, (char *)val, 2); - if (ret < 0) { - dev_err(&chip->client_group_a->dev, "failed reading\n"); - return ret; - } - - *val = le16_to_cpu(*val); - return 0; -} - -static void max732x_irq_update_mask(struct max732x_chip *chip) -{ - uint16_t msg; - - if (chip->irq_mask == chip->irq_mask_cur) - return; - - chip->irq_mask = chip->irq_mask_cur; - - if (chip->irq_features == INT_NO_MASK) - return; - - mutex_lock(&chip->lock); - - switch (chip->irq_features) { - case INT_INDEP_MASK: - msg = (chip->irq_mask << 8) | chip->reg_out[0]; - max732x_writew(chip, msg); - break; - - case INT_MERGED_MASK: - msg = chip->irq_mask | chip->reg_out[0]; - max732x_writeb(chip, 1, (uint8_t)msg); - break; - } - - mutex_unlock(&chip->lock); -} - -static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) -{ - struct max732x_chip *chip; - - chip = container_of(gc, struct max732x_chip, gpio_chip); - return chip->irq_base + off; -} - -static void max732x_irq_mask(struct irq_data *d) -{ - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); - - chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base)); -} - -static void max732x_irq_unmask(struct irq_data *d) -{ - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); - - chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base); -} - -static void max732x_irq_bus_lock(struct irq_data *d) -{ - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); - - mutex_lock(&chip->irq_lock); - chip->irq_mask_cur = chip->irq_mask; -} - -static void max732x_irq_bus_sync_unlock(struct irq_data *d) -{ - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); - - max732x_irq_update_mask(chip); - mutex_unlock(&chip->irq_lock); -} - -static int max732x_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); - uint16_t off = d->irq - chip->irq_base; - uint16_t mask = 1 << off; - - if (!(mask & chip->dir_input)) { - dev_dbg(&chip->client->dev, "%s port %d is output only\n", - chip->client->name, off); - return -EACCES; - } - - if (!(type & IRQ_TYPE_EDGE_BOTH)) { - dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", - d->irq, type); - return -EINVAL; - } - - if (type & IRQ_TYPE_EDGE_FALLING) - chip->irq_trig_fall |= mask; - else - chip->irq_trig_fall &= ~mask; - - if (type & IRQ_TYPE_EDGE_RISING) - chip->irq_trig_raise |= mask; - else - chip->irq_trig_raise &= ~mask; - - return max732x_gpio_direction_input(&chip->gpio_chip, off); -} - -static struct irq_chip max732x_irq_chip = { - .name = "max732x", - .irq_mask = max732x_irq_mask, - .irq_unmask = max732x_irq_unmask, - .irq_bus_lock = max732x_irq_bus_lock, - .irq_bus_sync_unlock = max732x_irq_bus_sync_unlock, - .irq_set_type = max732x_irq_set_type, -}; - -static uint8_t max732x_irq_pending(struct max732x_chip *chip) -{ - uint8_t cur_stat; - uint8_t old_stat; - uint8_t trigger; - uint8_t pending; - uint16_t status; - int ret; - - ret = max732x_readw(chip, &status); - if (ret) - return 0; - - trigger = status >> 8; - trigger &= chip->irq_mask; - - if (!trigger) - return 0; - - cur_stat = status & 0xFF; - cur_stat &= chip->irq_mask; - - old_stat = cur_stat ^ trigger; - - pending = (old_stat & chip->irq_trig_fall) | - (cur_stat & chip->irq_trig_raise); - pending &= trigger; - - return pending; -} - -static irqreturn_t max732x_irq_handler(int irq, void *devid) -{ - struct max732x_chip *chip = devid; - uint8_t pending; - uint8_t level; - - pending = max732x_irq_pending(chip); - - if (!pending) - return IRQ_HANDLED; - - do { - level = __ffs(pending); - handle_nested_irq(level + chip->irq_base); - - pending &= ~(1 << level); - } while (pending); - - return IRQ_HANDLED; -} - -static int max732x_irq_setup(struct max732x_chip *chip, - const struct i2c_device_id *id) -{ - struct i2c_client *client = chip->client; - struct max732x_platform_data *pdata = client->dev.platform_data; - int has_irq = max732x_features[id->driver_data] >> 32; - int ret; - - if (pdata->irq_base && has_irq != INT_NONE) { - int lvl; - - chip->irq_base = pdata->irq_base; - chip->irq_features = has_irq; - mutex_init(&chip->irq_lock); - - for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { - int irq = lvl + chip->irq_base; - - if (!(chip->dir_input & (1 << lvl))) - continue; - - irq_set_chip_data(irq, chip); - irq_set_chip_and_handler(irq, &max732x_irq_chip, - handle_edge_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - ret = request_threaded_irq(client->irq, - NULL, - max732x_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(&client->dev), chip); - if (ret) { - dev_err(&client->dev, "failed to request irq %d\n", - client->irq); - goto out_failed; - } - - chip->gpio_chip.to_irq = max732x_gpio_to_irq; - } - - return 0; - -out_failed: - chip->irq_base = 0; - return ret; -} - -static void max732x_irq_teardown(struct max732x_chip *chip) -{ - if (chip->irq_base) - free_irq(chip->client->irq, chip); -} -#else /* CONFIG_GPIO_MAX732X_IRQ */ -static int max732x_irq_setup(struct max732x_chip *chip, - const struct i2c_device_id *id) -{ - struct i2c_client *client = chip->client; - struct max732x_platform_data *pdata = client->dev.platform_data; - int has_irq = max732x_features[id->driver_data] >> 32; - - if (pdata->irq_base && has_irq != INT_NONE) - dev_warn(&client->dev, "interrupt support not compiled in\n"); - - return 0; -} - -static void max732x_irq_teardown(struct max732x_chip *chip) -{ -} -#endif - -static int __devinit max732x_setup_gpio(struct max732x_chip *chip, - const struct i2c_device_id *id, - unsigned gpio_start) -{ - struct gpio_chip *gc = &chip->gpio_chip; - uint32_t id_data = (uint32_t)max732x_features[id->driver_data]; - int i, port = 0; - - for (i = 0; i < 16; i++, id_data >>= 2) { - unsigned int mask = 1 << port; - - switch (id_data & 0x3) { - case PORT_OUTPUT: - chip->dir_output |= mask; - break; - case PORT_INPUT: - chip->dir_input |= mask; - break; - case PORT_OPENDRAIN: - chip->dir_output |= mask; - chip->dir_input |= mask; - break; - default: - continue; - } - - if (i < 8) - chip->mask_group_a |= mask; - port++; - } - - if (chip->dir_input) - gc->direction_input = max732x_gpio_direction_input; - if (chip->dir_output) { - gc->direction_output = max732x_gpio_direction_output; - gc->set = max732x_gpio_set_value; - } - gc->get = max732x_gpio_get_value; - gc->can_sleep = 1; - - gc->base = gpio_start; - gc->ngpio = port; - gc->label = chip->client->name; - gc->owner = THIS_MODULE; - - return port; -} - -static int __devinit max732x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max732x_platform_data *pdata; - struct max732x_chip *chip; - struct i2c_client *c; - uint16_t addr_a, addr_b; - int ret, nr_port; - - pdata = client->dev.platform_data; - if (pdata == NULL) { - dev_dbg(&client->dev, "no platform data\n"); - return -EINVAL; - } - - chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->client = client; - - nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base); - - addr_a = (client->addr & 0x0f) | 0x60; - addr_b = (client->addr & 0x0f) | 0x50; - - switch (client->addr & 0x70) { - case 0x60: - chip->client_group_a = client; - if (nr_port > 8) { - c = i2c_new_dummy(client->adapter, addr_b); - chip->client_group_b = chip->client_dummy = c; - } - break; - case 0x50: - chip->client_group_b = client; - if (nr_port > 8) { - c = i2c_new_dummy(client->adapter, addr_a); - chip->client_group_a = chip->client_dummy = c; - } - break; - default: - dev_err(&client->dev, "invalid I2C address specified %02x\n", - client->addr); - ret = -EINVAL; - goto out_failed; - } - - mutex_init(&chip->lock); - - max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); - if (nr_port > 8) - max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); - - ret = max732x_irq_setup(chip, id); - if (ret) - goto out_failed; - - ret = gpiochip_add(&chip->gpio_chip); - if (ret) - goto out_failed; - - if (pdata->setup) { - ret = pdata->setup(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - i2c_set_clientdata(client, chip); - return 0; - -out_failed: - max732x_irq_teardown(chip); - kfree(chip); - return ret; -} - -static int __devexit max732x_remove(struct i2c_client *client) -{ - struct max732x_platform_data *pdata = client->dev.platform_data; - struct max732x_chip *chip = i2c_get_clientdata(client); - int ret; - - if (pdata->teardown) { - ret = pdata->teardown(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) { - dev_err(&client->dev, "%s failed, %d\n", - "teardown", ret); - return ret; - } - } - - ret = gpiochip_remove(&chip->gpio_chip); - if (ret) { - dev_err(&client->dev, "%s failed, %d\n", - "gpiochip_remove()", ret); - return ret; - } - - max732x_irq_teardown(chip); - - /* unregister any dummy i2c_client */ - if (chip->client_dummy) - i2c_unregister_device(chip->client_dummy); - - kfree(chip); - return 0; -} - -static struct i2c_driver max732x_driver = { - .driver = { - .name = "max732x", - .owner = THIS_MODULE, - }, - .probe = max732x_probe, - .remove = __devexit_p(max732x_remove), - .id_table = max732x_id, -}; - -static int __init max732x_init(void) -{ - return i2c_add_driver(&max732x_driver); -} -/* register after i2c postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(max732x_init); - -static void __exit max732x_exit(void) -{ - i2c_del_driver(&max732x_driver); -} -module_exit(max732x_exit); - -MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); -MODULE_DESCRIPTION("GPIO expander driver for MAX732X"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mc33880.c b/ANDROID_3.4.5/drivers/gpio/gpio-mc33880.c deleted file mode 100644 index 2de57ce5..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mc33880.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * MC33880 high-side/low-side switch GPIO driver - * Copyright (c) 2009 Intel Corporation - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Freescale MC33880 high-side/low-side switch - */ - -#include <linux/init.h> -#include <linux/mutex.h> -#include <linux/spi/spi.h> -#include <linux/spi/mc33880.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/module.h> - -#define DRIVER_NAME "mc33880" - -/* - * Pin configurations, see MAX7301 datasheet page 6 - */ -#define PIN_CONFIG_MASK 0x03 -#define PIN_CONFIG_IN_PULLUP 0x03 -#define PIN_CONFIG_IN_WO_PULLUP 0x02 -#define PIN_CONFIG_OUT 0x01 - -#define PIN_NUMBER 8 - - -/* - * Some registers must be read back to modify. - * To save time we cache them here in memory - */ -struct mc33880 { - struct mutex lock; /* protect from simultaneous accesses */ - u8 port_config; - struct gpio_chip chip; - struct spi_device *spi; -}; - -static int mc33880_write_config(struct mc33880 *mc) -{ - return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config)); -} - - -static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value) -{ - if (value) - mc->port_config |= 1 << offset; - else - mc->port_config &= ~(1 << offset); - - return mc33880_write_config(mc); -} - - -static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mc33880 *mc = container_of(chip, struct mc33880, chip); - - mutex_lock(&mc->lock); - - __mc33880_set(mc, offset, value); - - mutex_unlock(&mc->lock); -} - -static int __devinit mc33880_probe(struct spi_device *spi) -{ - struct mc33880 *mc; - struct mc33880_platform_data *pdata; - int ret; - - pdata = spi->dev.platform_data; - if (!pdata || !pdata->base) { - dev_dbg(&spi->dev, "incorrect or missing platform data\n"); - return -EINVAL; - } - - /* - * bits_per_word cannot be configured in platform data - */ - spi->bits_per_word = 8; - - ret = spi_setup(spi); - if (ret < 0) - return ret; - - mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL); - if (!mc) - return -ENOMEM; - - mutex_init(&mc->lock); - - dev_set_drvdata(&spi->dev, mc); - - mc->spi = spi; - - mc->chip.label = DRIVER_NAME, - mc->chip.set = mc33880_set; - mc->chip.base = pdata->base; - mc->chip.ngpio = PIN_NUMBER; - mc->chip.can_sleep = 1; - mc->chip.dev = &spi->dev; - mc->chip.owner = THIS_MODULE; - - mc->port_config = 0x00; - /* write twice, because during initialisation the first setting - * is just for testing SPI communication, and the second is the - * "real" configuration - */ - ret = mc33880_write_config(mc); - mc->port_config = 0x00; - if (!ret) - ret = mc33880_write_config(mc); - - if (ret) { - printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret); - goto exit_destroy; - } - - ret = gpiochip_add(&mc->chip); - if (ret) - goto exit_destroy; - - return ret; - -exit_destroy: - dev_set_drvdata(&spi->dev, NULL); - mutex_destroy(&mc->lock); - kfree(mc); - return ret; -} - -static int __devexit mc33880_remove(struct spi_device *spi) -{ - struct mc33880 *mc; - int ret; - - mc = dev_get_drvdata(&spi->dev); - if (mc == NULL) - return -ENODEV; - - dev_set_drvdata(&spi->dev, NULL); - - ret = gpiochip_remove(&mc->chip); - if (!ret) { - mutex_destroy(&mc->lock); - kfree(mc); - } else - dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", - ret); - - return ret; -} - -static struct spi_driver mc33880_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = mc33880_probe, - .remove = __devexit_p(mc33880_remove), -}; - -static int __init mc33880_init(void) -{ - return spi_register_driver(&mc33880_driver); -} -/* register after spi postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(mc33880_init); - -static void __exit mc33880_exit(void) -{ - spi_unregister_driver(&mc33880_driver); -} -module_exit(mc33880_exit); - -MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); -MODULE_LICENSE("GPL v2"); - diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mc9s08dz60.c b/ANDROID_3.4.5/drivers/gpio/gpio-mc9s08dz60.c deleted file mode 100644 index 2738cc44..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mc9s08dz60.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved. - * - * Author: Wu Guoxing <b39297@freescale.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/gpio.h> - -#define GPIO_GROUP_NUM 2 -#define GPIO_NUM_PER_GROUP 8 -#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP) - -struct mc9s08dz60 { - struct i2c_client *client; - struct gpio_chip chip; -}; - -static inline struct mc9s08dz60 *to_mc9s08dz60(struct gpio_chip *gc) -{ - return container_of(gc, struct mc9s08dz60, chip); -} - - -static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit) -{ - *reg = 0x20 + offset / GPIO_NUM_PER_GROUP; - *bit = offset % GPIO_NUM_PER_GROUP; -} - -static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset) -{ - u8 reg, bit; - s32 value; - struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); - - mc9s_gpio_to_reg_and_bit(offset, ®, &bit); - value = i2c_smbus_read_byte_data(mc9s->client, reg); - - return (value >= 0) ? (value >> bit) & 0x1 : 0; -} - -static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val) -{ - u8 reg, bit; - s32 value; - - mc9s_gpio_to_reg_and_bit(offset, ®, &bit); - value = i2c_smbus_read_byte_data(mc9s->client, reg); - if (value >= 0) { - if (val) - value |= 1 << bit; - else - value &= ~(1 << bit); - - return i2c_smbus_write_byte_data(mc9s->client, reg, value); - } else - return value; - -} - - -static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val) -{ - struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); - - mc9s08dz60_set(mc9s, offset, val); -} - -static int mc9s08dz60_direction_output(struct gpio_chip *gc, - unsigned offset, int val) -{ - struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); - - return mc9s08dz60_set(mc9s, offset, val); -} - -static int mc9s08dz60_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = 0; - struct mc9s08dz60 *mc9s; - - mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL); - if (!mc9s) - return -ENOMEM; - - mc9s->chip.label = client->name; - mc9s->chip.base = -1; - mc9s->chip.dev = &client->dev; - mc9s->chip.owner = THIS_MODULE; - mc9s->chip.ngpio = GPIO_NUM; - mc9s->chip.can_sleep = 1; - mc9s->chip.get = mc9s08dz60_get_value; - mc9s->chip.set = mc9s08dz60_set_value; - mc9s->chip.direction_output = mc9s08dz60_direction_output; - mc9s->client = client; - i2c_set_clientdata(client, mc9s); - - ret = gpiochip_add(&mc9s->chip); - if (ret) - goto error; - - return 0; - - error: - kfree(mc9s); - return ret; -} - -static int mc9s08dz60_remove(struct i2c_client *client) -{ - struct mc9s08dz60 *mc9s; - int ret; - - mc9s = i2c_get_clientdata(client); - - ret = gpiochip_remove(&mc9s->chip); - if (!ret) - kfree(mc9s); - - return ret; - -} - -static const struct i2c_device_id mc9s08dz60_id[] = { - {"mc9s08dz60", 0}, - {}, -}; - -MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id); - -static struct i2c_driver mc9s08dz60_i2c_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "mc9s08dz60", - }, - .probe = mc9s08dz60_probe, - .remove = mc9s08dz60_remove, - .id_table = mc9s08dz60_id, -}; - -module_i2c_driver(mc9s08dz60_i2c_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc. " - "Wu Guoxing <b39297@freescale.com>"); -MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mcp23s08.c b/ANDROID_3.4.5/drivers/gpio/gpio-mcp23s08.c deleted file mode 100644 index c5d83a8a..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mcp23s08.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - * MCP23S08 SPI/GPIO gpio expander driver - */ - -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/i2c.h> -#include <linux/spi/spi.h> -#include <linux/spi/mcp23s08.h> -#include <linux/slab.h> -#include <asm/byteorder.h> - -/** - * MCP types supported by driver - */ -#define MCP_TYPE_S08 0 -#define MCP_TYPE_S17 1 -#define MCP_TYPE_008 2 -#define MCP_TYPE_017 3 - -/* Registers are all 8 bits wide. - * - * The mcp23s17 has twice as many bits, and can be configured to work - * with either 16 bit registers or with two adjacent 8 bit banks. - */ -#define MCP_IODIR 0x00 /* init/reset: all ones */ -#define MCP_IPOL 0x01 -#define MCP_GPINTEN 0x02 -#define MCP_DEFVAL 0x03 -#define MCP_INTCON 0x04 -#define MCP_IOCON 0x05 -# define IOCON_SEQOP (1 << 5) -# define IOCON_HAEN (1 << 3) -# define IOCON_ODR (1 << 2) -# define IOCON_INTPOL (1 << 1) -#define MCP_GPPU 0x06 -#define MCP_INTF 0x07 -#define MCP_INTCAP 0x08 -#define MCP_GPIO 0x09 -#define MCP_OLAT 0x0a - -struct mcp23s08; - -struct mcp23s08_ops { - int (*read)(struct mcp23s08 *mcp, unsigned reg); - int (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val); - int (*read_regs)(struct mcp23s08 *mcp, unsigned reg, - u16 *vals, unsigned n); -}; - -struct mcp23s08 { - u8 addr; - - u16 cache[11]; - /* lock protects the cached values */ - struct mutex lock; - - struct gpio_chip chip; - - const struct mcp23s08_ops *ops; - void *data; /* ops specific data */ -}; - -/* A given spi_device can represent up to eight mcp23sxx chips - * sharing the same chipselect but using different addresses - * (e.g. chips #0 and #3 might be populated, but not #1 or $2). - * Driver data holds all the per-chip data. - */ -struct mcp23s08_driver_data { - unsigned ngpio; - struct mcp23s08 *mcp[8]; - struct mcp23s08 chip[]; -}; - -/*----------------------------------------------------------------------*/ - -#ifdef CONFIG_I2C - -static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) -{ - return i2c_smbus_read_byte_data(mcp->data, reg); -} - -static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) -{ - return i2c_smbus_write_byte_data(mcp->data, reg, val); -} - -static int -mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) -{ - while (n--) { - int ret = mcp23008_read(mcp, reg++); - if (ret < 0) - return ret; - *vals++ = ret; - } - - return 0; -} - -static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg) -{ - return i2c_smbus_read_word_data(mcp->data, reg << 1); -} - -static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) -{ - return i2c_smbus_write_word_data(mcp->data, reg << 1, val); -} - -static int -mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) -{ - while (n--) { - int ret = mcp23017_read(mcp, reg++); - if (ret < 0) - return ret; - *vals++ = ret; - } - - return 0; -} - -static const struct mcp23s08_ops mcp23008_ops = { - .read = mcp23008_read, - .write = mcp23008_write, - .read_regs = mcp23008_read_regs, -}; - -static const struct mcp23s08_ops mcp23017_ops = { - .read = mcp23017_read, - .write = mcp23017_write, - .read_regs = mcp23017_read_regs, -}; - -#endif /* CONFIG_I2C */ - -/*----------------------------------------------------------------------*/ - -#ifdef CONFIG_SPI_MASTER - -static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) -{ - u8 tx[2], rx[1]; - int status; - - tx[0] = mcp->addr | 0x01; - tx[1] = reg; - status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); - return (status < 0) ? status : rx[0]; -} - -static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) -{ - u8 tx[3]; - - tx[0] = mcp->addr; - tx[1] = reg; - tx[2] = val; - return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); -} - -static int -mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) -{ - u8 tx[2], *tmp; - int status; - - if ((n + reg) > sizeof mcp->cache) - return -EINVAL; - tx[0] = mcp->addr | 0x01; - tx[1] = reg; - - tmp = (u8 *)vals; - status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n); - if (status >= 0) { - while (n--) - vals[n] = tmp[n]; /* expand to 16bit */ - } - return status; -} - -static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) -{ - u8 tx[2], rx[2]; - int status; - - tx[0] = mcp->addr | 0x01; - tx[1] = reg << 1; - status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); - return (status < 0) ? status : (rx[0] | (rx[1] << 8)); -} - -static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) -{ - u8 tx[4]; - - tx[0] = mcp->addr; - tx[1] = reg << 1; - tx[2] = val; - tx[3] = val >> 8; - return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); -} - -static int -mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) -{ - u8 tx[2]; - int status; - - if ((n + reg) > sizeof mcp->cache) - return -EINVAL; - tx[0] = mcp->addr | 0x01; - tx[1] = reg << 1; - - status = spi_write_then_read(mcp->data, tx, sizeof tx, - (u8 *)vals, n * 2); - if (status >= 0) { - while (n--) - vals[n] = __le16_to_cpu((__le16)vals[n]); - } - - return status; -} - -static const struct mcp23s08_ops mcp23s08_ops = { - .read = mcp23s08_read, - .write = mcp23s08_write, - .read_regs = mcp23s08_read_regs, -}; - -static const struct mcp23s08_ops mcp23s17_ops = { - .read = mcp23s17_read, - .write = mcp23s17_write, - .read_regs = mcp23s17_read_regs, -}; - -#endif /* CONFIG_SPI_MASTER */ - -/*----------------------------------------------------------------------*/ - -static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); - int status; - - mutex_lock(&mcp->lock); - mcp->cache[MCP_IODIR] |= (1 << offset); - status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); - mutex_unlock(&mcp->lock); - return status; -} - -static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) -{ - struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); - int status; - - mutex_lock(&mcp->lock); - - /* REVISIT reading this clears any IRQ ... */ - status = mcp->ops->read(mcp, MCP_GPIO); - if (status < 0) - status = 0; - else { - mcp->cache[MCP_GPIO] = status; - status = !!(status & (1 << offset)); - } - mutex_unlock(&mcp->lock); - return status; -} - -static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value) -{ - unsigned olat = mcp->cache[MCP_OLAT]; - - if (value) - olat |= mask; - else - olat &= ~mask; - mcp->cache[MCP_OLAT] = olat; - return mcp->ops->write(mcp, MCP_OLAT, olat); -} - -static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); - unsigned mask = 1 << offset; - - mutex_lock(&mcp->lock); - __mcp23s08_set(mcp, mask, value); - mutex_unlock(&mcp->lock); -} - -static int -mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); - unsigned mask = 1 << offset; - int status; - - mutex_lock(&mcp->lock); - status = __mcp23s08_set(mcp, mask, value); - if (status == 0) { - mcp->cache[MCP_IODIR] &= ~mask; - status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); - } - mutex_unlock(&mcp->lock); - return status; -} - -/*----------------------------------------------------------------------*/ - -#ifdef CONFIG_DEBUG_FS - -#include <linux/seq_file.h> - -/* - * This shows more info than the generic gpio dump code: - * pullups, deglitching, open drain drive. - */ -static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct mcp23s08 *mcp; - char bank; - int t; - unsigned mask; - - mcp = container_of(chip, struct mcp23s08, chip); - - /* NOTE: we only handle one bank for now ... */ - bank = '0' + ((mcp->addr >> 1) & 0x7); - - mutex_lock(&mcp->lock); - t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); - if (t < 0) { - seq_printf(s, " I/O ERROR %d\n", t); - goto done; - } - - for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) { - const char *label; - - label = gpiochip_is_requested(chip, t); - if (!label) - continue; - - seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s", - chip->base + t, bank, t, label, - (mcp->cache[MCP_IODIR] & mask) ? "in " : "out", - (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo", - (mcp->cache[MCP_GPPU] & mask) ? " " : "up"); - /* NOTE: ignoring the irq-related registers */ - seq_printf(s, "\n"); - } -done: - mutex_unlock(&mcp->lock); -} - -#else -#define mcp23s08_dbg_show NULL -#endif - -/*----------------------------------------------------------------------*/ - -static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, - void *data, unsigned addr, - unsigned type, unsigned base, unsigned pullups) -{ - int status; - - mutex_init(&mcp->lock); - - mcp->data = data; - mcp->addr = addr; - - mcp->chip.direction_input = mcp23s08_direction_input; - mcp->chip.get = mcp23s08_get; - mcp->chip.direction_output = mcp23s08_direction_output; - mcp->chip.set = mcp23s08_set; - mcp->chip.dbg_show = mcp23s08_dbg_show; - - switch (type) { -#ifdef CONFIG_SPI_MASTER - case MCP_TYPE_S08: - mcp->ops = &mcp23s08_ops; - mcp->chip.ngpio = 8; - mcp->chip.label = "mcp23s08"; - break; - - case MCP_TYPE_S17: - mcp->ops = &mcp23s17_ops; - mcp->chip.ngpio = 16; - mcp->chip.label = "mcp23s17"; - break; -#endif /* CONFIG_SPI_MASTER */ - -#ifdef CONFIG_I2C - case MCP_TYPE_008: - mcp->ops = &mcp23008_ops; - mcp->chip.ngpio = 8; - mcp->chip.label = "mcp23008"; - break; - - case MCP_TYPE_017: - mcp->ops = &mcp23017_ops; - mcp->chip.ngpio = 16; - mcp->chip.label = "mcp23017"; - break; -#endif /* CONFIG_I2C */ - - default: - dev_err(dev, "invalid device type (%d)\n", type); - return -EINVAL; - } - - mcp->chip.base = base; - mcp->chip.can_sleep = 1; - mcp->chip.dev = dev; - mcp->chip.owner = THIS_MODULE; - - /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, - * and MCP_IOCON.HAEN = 1, so we work with all chips. - */ - status = mcp->ops->read(mcp, MCP_IOCON); - if (status < 0) - goto fail; - if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { - /* mcp23s17 has IOCON twice, make sure they are in sync */ - status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); - status |= IOCON_HAEN | (IOCON_HAEN << 8); - status = mcp->ops->write(mcp, MCP_IOCON, status); - if (status < 0) - goto fail; - } - - /* configure ~100K pullups */ - status = mcp->ops->write(mcp, MCP_GPPU, pullups); - if (status < 0) - goto fail; - - status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); - if (status < 0) - goto fail; - - /* disable inverter on input */ - if (mcp->cache[MCP_IPOL] != 0) { - mcp->cache[MCP_IPOL] = 0; - status = mcp->ops->write(mcp, MCP_IPOL, 0); - if (status < 0) - goto fail; - } - - /* disable irqs */ - if (mcp->cache[MCP_GPINTEN] != 0) { - mcp->cache[MCP_GPINTEN] = 0; - status = mcp->ops->write(mcp, MCP_GPINTEN, 0); - if (status < 0) - goto fail; - } - - status = gpiochip_add(&mcp->chip); -fail: - if (status < 0) - dev_dbg(dev, "can't setup chip %d, --> %d\n", - addr, status); - return status; -} - -/*----------------------------------------------------------------------*/ - -#ifdef CONFIG_I2C - -static int __devinit mcp230xx_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct mcp23s08_platform_data *pdata; - struct mcp23s08 *mcp; - int status; - - pdata = client->dev.platform_data; - if (!pdata || !gpio_is_valid(pdata->base)) { - dev_dbg(&client->dev, "invalid or missing platform data\n"); - return -EINVAL; - } - - mcp = kzalloc(sizeof *mcp, GFP_KERNEL); - if (!mcp) - return -ENOMEM; - - status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, - id->driver_data, pdata->base, - pdata->chip[0].pullups); - if (status) - goto fail; - - i2c_set_clientdata(client, mcp); - - return 0; - -fail: - kfree(mcp); - - return status; -} - -static int __devexit mcp230xx_remove(struct i2c_client *client) -{ - struct mcp23s08 *mcp = i2c_get_clientdata(client); - int status; - - status = gpiochip_remove(&mcp->chip); - if (status == 0) - kfree(mcp); - - return status; -} - -static const struct i2c_device_id mcp230xx_id[] = { - { "mcp23008", MCP_TYPE_008 }, - { "mcp23017", MCP_TYPE_017 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, mcp230xx_id); - -static struct i2c_driver mcp230xx_driver = { - .driver = { - .name = "mcp230xx", - .owner = THIS_MODULE, - }, - .probe = mcp230xx_probe, - .remove = __devexit_p(mcp230xx_remove), - .id_table = mcp230xx_id, -}; - -static int __init mcp23s08_i2c_init(void) -{ - return i2c_add_driver(&mcp230xx_driver); -} - -static void mcp23s08_i2c_exit(void) -{ - i2c_del_driver(&mcp230xx_driver); -} - -#else - -static int __init mcp23s08_i2c_init(void) { return 0; } -static void mcp23s08_i2c_exit(void) { } - -#endif /* CONFIG_I2C */ - -/*----------------------------------------------------------------------*/ - -#ifdef CONFIG_SPI_MASTER - -static int mcp23s08_probe(struct spi_device *spi) -{ - struct mcp23s08_platform_data *pdata; - unsigned addr; - unsigned chips = 0; - struct mcp23s08_driver_data *data; - int status, type; - unsigned base; - - type = spi_get_device_id(spi)->driver_data; - - pdata = spi->dev.platform_data; - if (!pdata || !gpio_is_valid(pdata->base)) { - dev_dbg(&spi->dev, "invalid or missing platform data\n"); - return -EINVAL; - } - - for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { - if (!pdata->chip[addr].is_present) - continue; - chips++; - if ((type == MCP_TYPE_S08) && (addr > 3)) { - dev_err(&spi->dev, - "mcp23s08 only supports address 0..3\n"); - return -EINVAL; - } - } - if (!chips) - return -ENODEV; - - data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08), - GFP_KERNEL); - if (!data) - return -ENOMEM; - spi_set_drvdata(spi, data); - - base = pdata->base; - for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { - if (!pdata->chip[addr].is_present) - continue; - chips--; - data->mcp[addr] = &data->chip[chips]; - status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, - 0x40 | (addr << 1), type, base, - pdata->chip[addr].pullups); - if (status < 0) - goto fail; - - base += (type == MCP_TYPE_S17) ? 16 : 8; - } - data->ngpio = base - pdata->base; - - /* NOTE: these chips have a relatively sane IRQ framework, with - * per-signal masking and level/edge triggering. It's not yet - * handled here... - */ - - return 0; - -fail: - for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { - int tmp; - - if (!data->mcp[addr]) - continue; - tmp = gpiochip_remove(&data->mcp[addr]->chip); - if (tmp < 0) - dev_err(&spi->dev, "%s --> %d\n", "remove", tmp); - } - kfree(data); - return status; -} - -static int mcp23s08_remove(struct spi_device *spi) -{ - struct mcp23s08_driver_data *data = spi_get_drvdata(spi); - unsigned addr; - int status = 0; - - for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { - int tmp; - - if (!data->mcp[addr]) - continue; - - tmp = gpiochip_remove(&data->mcp[addr]->chip); - if (tmp < 0) { - dev_err(&spi->dev, "%s --> %d\n", "remove", tmp); - status = tmp; - } - } - if (status == 0) - kfree(data); - return status; -} - -static const struct spi_device_id mcp23s08_ids[] = { - { "mcp23s08", MCP_TYPE_S08 }, - { "mcp23s17", MCP_TYPE_S17 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, mcp23s08_ids); - -static struct spi_driver mcp23s08_driver = { - .probe = mcp23s08_probe, - .remove = mcp23s08_remove, - .id_table = mcp23s08_ids, - .driver = { - .name = "mcp23s08", - .owner = THIS_MODULE, - }, -}; - -static int __init mcp23s08_spi_init(void) -{ - return spi_register_driver(&mcp23s08_driver); -} - -static void mcp23s08_spi_exit(void) -{ - spi_unregister_driver(&mcp23s08_driver); -} - -#else - -static int __init mcp23s08_spi_init(void) { return 0; } -static void mcp23s08_spi_exit(void) { } - -#endif /* CONFIG_SPI_MASTER */ - -/*----------------------------------------------------------------------*/ - -static int __init mcp23s08_init(void) -{ - int ret; - - ret = mcp23s08_spi_init(); - if (ret) - goto spi_fail; - - ret = mcp23s08_i2c_init(); - if (ret) - goto i2c_fail; - - return 0; - - i2c_fail: - mcp23s08_spi_exit(); - spi_fail: - return ret; -} -/* register after spi/i2c postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(mcp23s08_init); - -static void __exit mcp23s08_exit(void) -{ - mcp23s08_spi_exit(); - mcp23s08_i2c_exit(); -} -module_exit(mcp23s08_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ml-ioh.c b/ANDROID_3.4.5/drivers/gpio/gpio-ml-ioh.c deleted file mode 100644 index f0febe5b..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ml-ioh.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/irq.h> - -#define IOH_EDGE_FALLING 0 -#define IOH_EDGE_RISING BIT(0) -#define IOH_LEVEL_L BIT(1) -#define IOH_LEVEL_H (BIT(0) | BIT(1)) -#define IOH_EDGE_BOTH BIT(2) -#define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) - -#define IOH_IRQ_BASE 0 - -#define PCI_VENDOR_ID_ROHM 0x10DB - -struct ioh_reg_comn { - u32 ien; - u32 istatus; - u32 idisp; - u32 iclr; - u32 imask; - u32 imaskclr; - u32 po; - u32 pi; - u32 pm; - u32 im_0; - u32 im_1; - u32 reserved; -}; - -struct ioh_regs { - struct ioh_reg_comn regs[8]; - u32 reserve1[16]; - u32 ioh_sel_reg[4]; - u32 reserve2[11]; - u32 srst; -}; - -/** - * struct ioh_gpio_reg_data - The register store data. - * @ien_reg To store contents of interrupt enable register. - * @imask_reg: To store contents of interrupt mask regist - * @po_reg: To store contents of PO register. - * @pm_reg: To store contents of PM register. - * @im0_reg: To store contents of interrupt mode regist0 - * @im1_reg: To store contents of interrupt mode regist1 - * @use_sel_reg: To store contents of GPIO_USE_SEL0~3 - */ -struct ioh_gpio_reg_data { - u32 ien_reg; - u32 imask_reg; - u32 po_reg; - u32 pm_reg; - u32 im0_reg; - u32 im1_reg; - u32 use_sel_reg; -}; - -/** - * struct ioh_gpio - GPIO private data structure. - * @base: PCI base address of Memory mapped I/O register. - * @reg: Memory mapped IOH GPIO register list. - * @dev: Pointer to device structure. - * @gpio: Data for GPIO infrastructure. - * @ioh_gpio_reg: Memory mapped Register data is saved here - * when suspend. - * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM - * @ch: Indicate GPIO channel - * @irq_base: Save base of IRQ number for interrupt - * @spinlock: Used for register access protection in - * interrupt context ioh_irq_type and PM; - */ -struct ioh_gpio { - void __iomem *base; - struct ioh_regs __iomem *reg; - struct device *dev; - struct gpio_chip gpio; - struct ioh_gpio_reg_data ioh_gpio_reg; - u32 gpio_use_sel; - struct mutex lock; - int ch; - int irq_base; - spinlock_t spinlock; -}; - -static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; - -static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) -{ - u32 reg_val; - struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); - - mutex_lock(&chip->lock); - reg_val = ioread32(&chip->reg->regs[chip->ch].po); - if (val) - reg_val |= (1 << nr); - else - reg_val &= ~(1 << nr); - - iowrite32(reg_val, &chip->reg->regs[chip->ch].po); - mutex_unlock(&chip->lock); -} - -static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr) -{ - struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); - - return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr); -} - -static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, - int val) -{ - struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); - u32 pm; - u32 reg_val; - - mutex_lock(&chip->lock); - pm = ioread32(&chip->reg->regs[chip->ch].pm) & - ((1 << num_ports[chip->ch]) - 1); - pm |= (1 << nr); - iowrite32(pm, &chip->reg->regs[chip->ch].pm); - - reg_val = ioread32(&chip->reg->regs[chip->ch].po); - if (val) - reg_val |= (1 << nr); - else - reg_val &= ~(1 << nr); - iowrite32(reg_val, &chip->reg->regs[chip->ch].po); - - mutex_unlock(&chip->lock); - - return 0; -} - -static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) -{ - struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); - u32 pm; - - mutex_lock(&chip->lock); - pm = ioread32(&chip->reg->regs[chip->ch].pm) & - ((1 << num_ports[chip->ch]) - 1); - pm &= ~(1 << nr); - iowrite32(pm, &chip->reg->regs[chip->ch].pm); - mutex_unlock(&chip->lock); - - return 0; -} - -#ifdef CONFIG_PM -/* - * Save register configuration and disable interrupts. - */ -static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) -{ - int i; - - for (i = 0; i < 8; i ++, chip++) { - chip->ioh_gpio_reg.po_reg = - ioread32(&chip->reg->regs[chip->ch].po); - chip->ioh_gpio_reg.pm_reg = - ioread32(&chip->reg->regs[chip->ch].pm); - chip->ioh_gpio_reg.ien_reg = - ioread32(&chip->reg->regs[chip->ch].ien); - chip->ioh_gpio_reg.imask_reg = - ioread32(&chip->reg->regs[chip->ch].imask); - chip->ioh_gpio_reg.im0_reg = - ioread32(&chip->reg->regs[chip->ch].im_0); - chip->ioh_gpio_reg.im1_reg = - ioread32(&chip->reg->regs[chip->ch].im_1); - if (i < 4) - chip->ioh_gpio_reg.use_sel_reg = - ioread32(&chip->reg->ioh_sel_reg[i]); - } -} - -/* - * This function restores the register configuration of the GPIO device. - */ -static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) -{ - int i; - - for (i = 0; i < 8; i ++, chip++) { - iowrite32(chip->ioh_gpio_reg.po_reg, - &chip->reg->regs[chip->ch].po); - iowrite32(chip->ioh_gpio_reg.pm_reg, - &chip->reg->regs[chip->ch].pm); - iowrite32(chip->ioh_gpio_reg.ien_reg, - &chip->reg->regs[chip->ch].ien); - iowrite32(chip->ioh_gpio_reg.imask_reg, - &chip->reg->regs[chip->ch].imask); - iowrite32(chip->ioh_gpio_reg.im0_reg, - &chip->reg->regs[chip->ch].im_0); - iowrite32(chip->ioh_gpio_reg.im1_reg, - &chip->reg->regs[chip->ch].im_1); - if (i < 4) - iowrite32(chip->ioh_gpio_reg.use_sel_reg, - &chip->reg->ioh_sel_reg[i]); - } -} -#endif - -static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) -{ - struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); - return chip->irq_base + offset; -} - -static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) -{ - struct gpio_chip *gpio = &chip->gpio; - - gpio->label = dev_name(chip->dev); - gpio->owner = THIS_MODULE; - gpio->direction_input = ioh_gpio_direction_input; - gpio->get = ioh_gpio_get; - gpio->direction_output = ioh_gpio_direction_output; - gpio->set = ioh_gpio_set; - gpio->dbg_show = NULL; - gpio->base = -1; - gpio->ngpio = num_port; - gpio->can_sleep = 0; - gpio->to_irq = ioh_gpio_to_irq; -} - -static int ioh_irq_type(struct irq_data *d, unsigned int type) -{ - u32 im; - void __iomem *im_reg; - u32 ien; - u32 im_pos; - int ch; - unsigned long flags; - u32 val; - int irq = d->irq; - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct ioh_gpio *chip = gc->private; - - ch = irq - chip->irq_base; - if (irq <= chip->irq_base + 7) { - im_reg = &chip->reg->regs[chip->ch].im_0; - im_pos = ch; - } else { - im_reg = &chip->reg->regs[chip->ch].im_1; - im_pos = ch - 8; - } - dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n", - __func__, irq, type, ch, im_pos, type); - - spin_lock_irqsave(&chip->spinlock, flags); - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - val = IOH_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - val = IOH_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - val = IOH_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - val = IOH_LEVEL_H; - break; - case IRQ_TYPE_LEVEL_LOW: - val = IOH_LEVEL_L; - break; - case IRQ_TYPE_PROBE: - goto end; - default: - dev_warn(chip->dev, "%s: unknown type(%dd)", - __func__, type); - goto end; - } - - /* Set interrupt mode */ - im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4)); - iowrite32(im | (val << (im_pos * 4)), im_reg); - - /* iclr */ - iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr); - - /* IMASKCLR */ - iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr); - - /* Enable interrupt */ - ien = ioread32(&chip->reg->regs[chip->ch].ien); - iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien); -end: - spin_unlock_irqrestore(&chip->spinlock, flags); - - return 0; -} - -static void ioh_irq_unmask(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct ioh_gpio *chip = gc->private; - - iowrite32(1 << (d->irq - chip->irq_base), - &chip->reg->regs[chip->ch].imaskclr); -} - -static void ioh_irq_mask(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct ioh_gpio *chip = gc->private; - - iowrite32(1 << (d->irq - chip->irq_base), - &chip->reg->regs[chip->ch].imask); -} - -static void ioh_irq_disable(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct ioh_gpio *chip = gc->private; - unsigned long flags; - u32 ien; - - spin_lock_irqsave(&chip->spinlock, flags); - ien = ioread32(&chip->reg->regs[chip->ch].ien); - ien &= ~(1 << (d->irq - chip->irq_base)); - iowrite32(ien, &chip->reg->regs[chip->ch].ien); - spin_unlock_irqrestore(&chip->spinlock, flags); -} - -static void ioh_irq_enable(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct ioh_gpio *chip = gc->private; - unsigned long flags; - u32 ien; - - spin_lock_irqsave(&chip->spinlock, flags); - ien = ioread32(&chip->reg->regs[chip->ch].ien); - ien |= 1 << (d->irq - chip->irq_base); - iowrite32(ien, &chip->reg->regs[chip->ch].ien); - spin_unlock_irqrestore(&chip->spinlock, flags); -} - -static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) -{ - struct ioh_gpio *chip = dev_id; - u32 reg_val; - int i, j; - int ret = IRQ_NONE; - - for (i = 0; i < 8; i++, chip++) { - reg_val = ioread32(&chip->reg->regs[i].istatus); - for (j = 0; j < num_ports[i]; j++) { - if (reg_val & BIT(j)) { - dev_dbg(chip->dev, - "%s:[%d]:irq=%d status=0x%x\n", - __func__, j, irq, reg_val); - iowrite32(BIT(j), - &chip->reg->regs[chip->ch].iclr); - generic_handle_irq(chip->irq_base + j); - ret = IRQ_HANDLED; - } - } - } - return ret; -} - -static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, - unsigned int irq_start, unsigned int num) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base, - handle_simple_irq); - gc->private = chip; - ct = gc->chip_types; - - ct->chip.irq_mask = ioh_irq_mask; - ct->chip.irq_unmask = ioh_irq_unmask; - ct->chip.irq_set_type = ioh_irq_type; - ct->chip.irq_disable = ioh_irq_disable; - ct->chip.irq_enable = ioh_irq_enable; - - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); -} - -static int __devinit ioh_gpio_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int ret; - int i, j; - struct ioh_gpio *chip; - void __iomem *base; - void *chip_save; - int irq_base; - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__); - goto err_pci_enable; - } - - ret = pci_request_regions(pdev, KBUILD_MODNAME); - if (ret) { - dev_err(&pdev->dev, "pci_request_regions failed-%d", ret); - goto err_request_regions; - } - - base = pci_iomap(pdev, 1, 0); - if (!base) { - dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); - ret = -ENOMEM; - goto err_iomap; - } - - chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); - if (chip_save == NULL) { - dev_err(&pdev->dev, "%s : kzalloc failed", __func__); - ret = -ENOMEM; - goto err_kzalloc; - } - - chip = chip_save; - for (i = 0; i < 8; i++, chip++) { - chip->dev = &pdev->dev; - chip->base = base; - chip->reg = chip->base; - chip->ch = i; - mutex_init(&chip->lock); - spin_lock_init(&chip->spinlock); - ioh_gpio_setup(chip, num_ports[i]); - ret = gpiochip_add(&chip->gpio); - if (ret) { - dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n"); - goto err_gpiochip_add; - } - } - - chip = chip_save; - for (j = 0; j < 8; j++, chip++) { - irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j], - NUMA_NO_NODE); - if (irq_base < 0) { - dev_warn(&pdev->dev, - "ml_ioh_gpio: Failed to get IRQ base num\n"); - chip->irq_base = -1; - goto err_irq_alloc_descs; - } - chip->irq_base = irq_base; - ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]); - } - - chip = chip_save; - ret = request_irq(pdev->irq, ioh_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); - if (ret != 0) { - dev_err(&pdev->dev, - "%s request_irq failed\n", __func__); - goto err_request_irq; - } - - pci_set_drvdata(pdev, chip); - - return 0; - -err_request_irq: - chip = chip_save; -err_irq_alloc_descs: - while (--j >= 0) { - chip--; - irq_free_descs(chip->irq_base, num_ports[j]); - } - - chip = chip_save; -err_gpiochip_add: - while (--i >= 0) { - chip--; - ret = gpiochip_remove(&chip->gpio); - if (ret) - dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); - } - kfree(chip_save); - -err_kzalloc: - pci_iounmap(pdev, base); - -err_iomap: - pci_release_regions(pdev); - -err_request_regions: - pci_disable_device(pdev); - -err_pci_enable: - - dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); - return ret; -} - -static void __devexit ioh_gpio_remove(struct pci_dev *pdev) -{ - int err; - int i; - struct ioh_gpio *chip = pci_get_drvdata(pdev); - void *chip_save; - - chip_save = chip; - - free_irq(pdev->irq, chip); - - for (i = 0; i < 8; i++, chip++) { - irq_free_descs(chip->irq_base, num_ports[i]); - err = gpiochip_remove(&chip->gpio); - if (err) - dev_err(&pdev->dev, "Failed gpiochip_remove\n"); - } - - chip = chip_save; - pci_iounmap(pdev, chip->base); - pci_release_regions(pdev); - pci_disable_device(pdev); - kfree(chip); -} - -#ifdef CONFIG_PM -static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state) -{ - s32 ret; - struct ioh_gpio *chip = pci_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&chip->spinlock, flags); - ioh_gpio_save_reg_conf(chip); - spin_unlock_irqrestore(&chip->spinlock, flags); - - ret = pci_save_state(pdev); - if (ret) { - dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); - return ret; - } - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_wake(pdev, PCI_D0, 1); - if (ret) - dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); - - return 0; -} - -static int ioh_gpio_resume(struct pci_dev *pdev) -{ - s32 ret; - struct ioh_gpio *chip = pci_get_drvdata(pdev); - unsigned long flags; - - ret = pci_enable_wake(pdev, PCI_D0, 0); - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); - return ret; - } - pci_restore_state(pdev); - - spin_lock_irqsave(&chip->spinlock, flags); - iowrite32(0x01, &chip->reg->srst); - iowrite32(0x00, &chip->reg->srst); - ioh_gpio_restore_reg_conf(chip); - spin_unlock_irqrestore(&chip->spinlock, flags); - - return 0; -} -#else -#define ioh_gpio_suspend NULL -#define ioh_gpio_resume NULL -#endif - -static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { - { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); - -static struct pci_driver ioh_gpio_driver = { - .name = "ml_ioh_gpio", - .id_table = ioh_gpio_pcidev_id, - .probe = ioh_gpio_probe, - .remove = __devexit_p(ioh_gpio_remove), - .suspend = ioh_gpio_suspend, - .resume = ioh_gpio_resume -}; - -static int __init ioh_gpio_pci_init(void) -{ - return pci_register_driver(&ioh_gpio_driver); -} -module_init(ioh_gpio_pci_init); - -static void __exit ioh_gpio_pci_exit(void) -{ - pci_unregister_driver(&ioh_gpio_driver); -} -module_exit(ioh_gpio_pci_exit); - -MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mpc5200.c b/ANDROID_3.4.5/drivers/gpio/gpio-mpc5200.c deleted file mode 100644 index 2c7cef36..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mpc5200.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * MPC52xx gpio driver - * - * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix - * - * 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. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/of.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/of_gpio.h> -#include <linux/io.h> -#include <linux/of_platform.h> -#include <linux/module.h> - -#include <asm/gpio.h> -#include <asm/mpc52xx.h> -#include <sysdev/fsl_soc.h> - -static DEFINE_SPINLOCK(gpio_lock); - -struct mpc52xx_gpiochip { - struct of_mm_gpio_chip mmchip; - unsigned int shadow_dvo; - unsigned int shadow_gpioe; - unsigned int shadow_ddr; -}; - -/* - * GPIO LIB API implementation for wakeup GPIOs. - * - * There's a maximum of 8 wakeup GPIOs. Which of these are available - * for use depends on your board setup. - * - * 0 -> GPIO_WKUP_7 - * 1 -> GPIO_WKUP_6 - * 2 -> PSC6_1 - * 3 -> PSC6_0 - * 4 -> ETH_17 - * 5 -> PSC3_9 - * 6 -> PSC2_4 - * 7 -> PSC1_4 - * - */ -static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; - unsigned int ret; - - ret = (in_8(®s->wkup_ival) >> (7 - gpio)) & 1; - - pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret); - - return ret; -} - -static inline void -__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; - - if (val) - chip->shadow_dvo |= 1 << (7 - gpio); - else - chip->shadow_dvo &= ~(1 << (7 - gpio)); - - out_8(®s->wkup_dvo, chip->shadow_dvo); -} - -static void -mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - __mpc52xx_wkup_gpio_set(gc, gpio, val); - - spin_unlock_irqrestore(&gpio_lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); -} - -static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - /* set the direction */ - chip->shadow_ddr &= ~(1 << (7 - gpio)); - out_8(®s->wkup_ddr, chip->shadow_ddr); - - /* and enable the pin */ - chip->shadow_gpioe |= 1 << (7 - gpio); - out_8(®s->wkup_gpioe, chip->shadow_gpioe); - - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -} - -static int -mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - __mpc52xx_wkup_gpio_set(gc, gpio, val); - - /* Then set direction */ - chip->shadow_ddr |= 1 << (7 - gpio); - out_8(®s->wkup_ddr, chip->shadow_ddr); - - /* Finally enable the pin */ - chip->shadow_gpioe |= 1 << (7 - gpio); - out_8(®s->wkup_gpioe, chip->shadow_gpioe); - - spin_unlock_irqrestore(&gpio_lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); - - return 0; -} - -static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) -{ - struct mpc52xx_gpiochip *chip; - struct mpc52xx_gpio_wkup __iomem *regs; - struct gpio_chip *gc; - int ret; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - gc = &chip->mmchip.gc; - - gc->ngpio = 8; - gc->direction_input = mpc52xx_wkup_gpio_dir_in; - gc->direction_output = mpc52xx_wkup_gpio_dir_out; - gc->get = mpc52xx_wkup_gpio_get; - gc->set = mpc52xx_wkup_gpio_set; - - ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip); - if (ret) - return ret; - - regs = chip->mmchip.regs; - chip->shadow_gpioe = in_8(®s->wkup_gpioe); - chip->shadow_ddr = in_8(®s->wkup_ddr); - chip->shadow_dvo = in_8(®s->wkup_dvo); - - return 0; -} - -static int mpc52xx_gpiochip_remove(struct platform_device *ofdev) -{ - return -EBUSY; -} - -static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { - { .compatible = "fsl,mpc5200-gpio-wkup", }, - {} -}; - -static struct platform_driver mpc52xx_wkup_gpiochip_driver = { - .driver = { - .name = "mpc5200-gpio-wkup", - .owner = THIS_MODULE, - .of_match_table = mpc52xx_wkup_gpiochip_match, - }, - .probe = mpc52xx_wkup_gpiochip_probe, - .remove = mpc52xx_gpiochip_remove, -}; - -/* - * GPIO LIB API implementation for simple GPIOs - * - * There's a maximum of 32 simple GPIOs. Which of these are available - * for use depends on your board setup. - * The numbering reflects the bit numbering in the port registers: - * - * 0..1 > reserved - * 2..3 > IRDA - * 4..7 > ETHR - * 8..11 > reserved - * 12..15 > USB - * 16..17 > reserved - * 18..23 > PSC3 - * 24..27 > PSC2 - * 28..31 > PSC1 - */ -static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpio __iomem *regs = mm_gc->regs; - unsigned int ret; - - ret = (in_be32(®s->simple_ival) >> (31 - gpio)) & 1; - - return ret; -} - -static inline void -__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - struct mpc52xx_gpio __iomem *regs = mm_gc->regs; - - if (val) - chip->shadow_dvo |= 1 << (31 - gpio); - else - chip->shadow_dvo &= ~(1 << (31 - gpio)); - out_be32(®s->simple_dvo, chip->shadow_dvo); -} - -static void -mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - __mpc52xx_simple_gpio_set(gc, gpio, val); - - spin_unlock_irqrestore(&gpio_lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); -} - -static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - struct mpc52xx_gpio __iomem *regs = mm_gc->regs; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - /* set the direction */ - chip->shadow_ddr &= ~(1 << (31 - gpio)); - out_be32(®s->simple_ddr, chip->shadow_ddr); - - /* and enable the pin */ - chip->shadow_gpioe |= 1 << (31 - gpio); - out_be32(®s->simple_gpioe, chip->shadow_gpioe); - - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -} - -static int -mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct mpc52xx_gpiochip *chip = container_of(mm_gc, - struct mpc52xx_gpiochip, mmchip); - struct mpc52xx_gpio __iomem *regs = mm_gc->regs; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - /* First set initial value */ - __mpc52xx_simple_gpio_set(gc, gpio, val); - - /* Then set direction */ - chip->shadow_ddr |= 1 << (31 - gpio); - out_be32(®s->simple_ddr, chip->shadow_ddr); - - /* Finally enable the pin */ - chip->shadow_gpioe |= 1 << (31 - gpio); - out_be32(®s->simple_gpioe, chip->shadow_gpioe); - - spin_unlock_irqrestore(&gpio_lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); - - return 0; -} - -static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev) -{ - struct mpc52xx_gpiochip *chip; - struct gpio_chip *gc; - struct mpc52xx_gpio __iomem *regs; - int ret; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - gc = &chip->mmchip.gc; - - gc->ngpio = 32; - gc->direction_input = mpc52xx_simple_gpio_dir_in; - gc->direction_output = mpc52xx_simple_gpio_dir_out; - gc->get = mpc52xx_simple_gpio_get; - gc->set = mpc52xx_simple_gpio_set; - - ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip); - if (ret) - return ret; - - regs = chip->mmchip.regs; - chip->shadow_gpioe = in_be32(®s->simple_gpioe); - chip->shadow_ddr = in_be32(®s->simple_ddr); - chip->shadow_dvo = in_be32(®s->simple_dvo); - - return 0; -} - -static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { - { .compatible = "fsl,mpc5200-gpio", }, - {} -}; - -static struct platform_driver mpc52xx_simple_gpiochip_driver = { - .driver = { - .name = "mpc5200-gpio", - .owner = THIS_MODULE, - .of_match_table = mpc52xx_simple_gpiochip_match, - }, - .probe = mpc52xx_simple_gpiochip_probe, - .remove = mpc52xx_gpiochip_remove, -}; - -static int __init mpc52xx_gpio_init(void) -{ - if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver)) - printk(KERN_ERR "Unable to register wakeup GPIO driver\n"); - - if (platform_driver_register(&mpc52xx_simple_gpiochip_driver)) - printk(KERN_ERR "Unable to register simple GPIO driver\n"); - - return 0; -} - - -/* Make sure we get initialised before anyone else tries to use us */ -subsys_initcall(mpc52xx_gpio_init); - -/* No exit call at the moment as we cannot unregister of gpio chips */ - -MODULE_DESCRIPTION("Freescale MPC52xx gpio driver"); -MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); -MODULE_LICENSE("GPL v2"); - diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mpc8xxx.c b/ANDROID_3.4.5/drivers/gpio/gpio-mpc8xxx.c deleted file mode 100644 index 5a1817ee..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mpc8xxx.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * GPIOs on MPC512x/8349/8572/8610 and compatible - * - * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_gpio.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/irq.h> - -#define MPC8XXX_GPIO_PINS 32 - -#define GPIO_DIR 0x00 -#define GPIO_ODR 0x04 -#define GPIO_DAT 0x08 -#define GPIO_IER 0x0c -#define GPIO_IMR 0x10 -#define GPIO_ICR 0x14 -#define GPIO_ICR2 0x18 - -struct mpc8xxx_gpio_chip { - struct of_mm_gpio_chip mm_gc; - spinlock_t lock; - - /* - * shadowed data register to be able to clear/set output pins in - * open drain mode safely - */ - u32 data; - struct irq_domain *irq; - void *of_dev_id_data; -}; - -static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) -{ - return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); -} - -static inline struct mpc8xxx_gpio_chip * -to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm) -{ - return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc); -} - -static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - - mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); -} - -/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs - * defined as output cannot be determined by reading GPDAT register, - * so we use shadow data register instead. The status of input pins - * is determined by reading GPDAT register. - */ -static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - u32 val; - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - - val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); - - return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); -} - -static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - - return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); -} - -static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - unsigned long flags; - - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - - if (val) - mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); - else - mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); - - out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); - - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); -} - -static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - unsigned long flags; - - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - - clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); - - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - - return 0; -} - -static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - unsigned long flags; - - mpc8xxx_gpio_set(gc, gpio, val); - - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - - setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); - - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - - return 0; -} - -static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - /* GPIO 28..31 are input only on MPC5121 */ - if (gpio >= 28) - return -EINVAL; - - return mpc8xxx_gpio_dir_out(gc, gpio, val); -} - -static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); - struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); - - if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS) - return irq_create_mapping(mpc8xxx_gc->irq, offset); - else - return -ENXIO; -} - -static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - unsigned int mask; - - mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR); - if (mask) - generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, - 32 - ffs(mask))); - if (chip->irq_eoi) - chip->irq_eoi(&desc->irq_data); -} - -static void mpc8xxx_irq_unmask(struct irq_data *d) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - unsigned long flags; - - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - - setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); -} - -static void mpc8xxx_irq_mask(struct irq_data *d) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - unsigned long flags; - - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - - clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); -} - -static void mpc8xxx_irq_ack(struct irq_data *d) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - - out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); -} - -static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - unsigned long flags; - - switch (flow_type) { - case IRQ_TYPE_EDGE_FALLING: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - setbits32(mm->regs + GPIO_ICR, - mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - break; - - case IRQ_TYPE_EDGE_BOTH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - clrbits32(mm->regs + GPIO_ICR, - mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); - struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; - unsigned long gpio = irqd_to_hwirq(d); - void __iomem *reg; - unsigned int shift; - unsigned long flags; - - if (gpio < 16) { - reg = mm->regs + GPIO_ICR; - shift = (15 - gpio) * 2; - } else { - reg = mm->regs + GPIO_ICR2; - shift = (15 - (gpio % 16)) * 2; - } - - switch (flow_type) { - case IRQ_TYPE_EDGE_FALLING: - case IRQ_TYPE_LEVEL_LOW: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - clrsetbits_be32(reg, 3 << shift, 2 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - break; - - case IRQ_TYPE_EDGE_RISING: - case IRQ_TYPE_LEVEL_HIGH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - clrsetbits_be32(reg, 3 << shift, 1 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - break; - - case IRQ_TYPE_EDGE_BOTH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); - clrbits32(reg, 3 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static struct irq_chip mpc8xxx_irq_chip = { - .name = "mpc8xxx-gpio", - .irq_unmask = mpc8xxx_irq_unmask, - .irq_mask = mpc8xxx_irq_mask, - .irq_ack = mpc8xxx_irq_ack, - .irq_set_type = mpc8xxx_irq_set_type, -}; - -static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data; - - if (mpc8xxx_gc->of_dev_id_data) - mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data; - - irq_set_chip_data(virq, h->host_data); - irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); - irq_set_irq_type(virq, IRQ_TYPE_NONE); - - return 0; -} - -static struct irq_domain_ops mpc8xxx_gpio_irq_ops = { - .map = mpc8xxx_gpio_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { - { .compatible = "fsl,mpc8349-gpio", }, - { .compatible = "fsl,mpc8572-gpio", }, - { .compatible = "fsl,mpc8610-gpio", }, - { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, }, - { .compatible = "fsl,pq3-gpio", }, - { .compatible = "fsl,qoriq-gpio", }, - {} -}; - -static void __init mpc8xxx_add_controller(struct device_node *np) -{ - struct mpc8xxx_gpio_chip *mpc8xxx_gc; - struct of_mm_gpio_chip *mm_gc; - struct gpio_chip *gc; - const struct of_device_id *id; - unsigned hwirq; - int ret; - - mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); - if (!mpc8xxx_gc) { - ret = -ENOMEM; - goto err; - } - - spin_lock_init(&mpc8xxx_gc->lock); - - mm_gc = &mpc8xxx_gc->mm_gc; - gc = &mm_gc->gc; - - mm_gc->save_regs = mpc8xxx_gpio_save_regs; - gc->ngpio = MPC8XXX_GPIO_PINS; - gc->direction_input = mpc8xxx_gpio_dir_in; - gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ? - mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out; - gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? - mpc8572_gpio_get : mpc8xxx_gpio_get; - gc->set = mpc8xxx_gpio_set; - gc->to_irq = mpc8xxx_gpio_to_irq; - - ret = of_mm_gpiochip_add(np, mm_gc); - if (ret) - goto err; - - hwirq = irq_of_parse_and_map(np, 0); - if (hwirq == NO_IRQ) - goto skip_irq; - - mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS, - &mpc8xxx_gpio_irq_ops, mpc8xxx_gc); - if (!mpc8xxx_gc->irq) - goto skip_irq; - - id = of_match_node(mpc8xxx_gpio_ids, np); - if (id) - mpc8xxx_gc->of_dev_id_data = id->data; - - /* ack and mask all irqs */ - out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); - out_be32(mm_gc->regs + GPIO_IMR, 0); - - irq_set_handler_data(hwirq, mpc8xxx_gc); - irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade); - -skip_irq: - return; - -err: - pr_err("%s: registration failed with status %d\n", - np->full_name, ret); - kfree(mpc8xxx_gc); - - return; -} - -static int __init mpc8xxx_add_gpiochips(void) -{ - struct device_node *np; - - for_each_matching_node(np, mpc8xxx_gpio_ids) - mpc8xxx_add_controller(np); - - return 0; -} -arch_initcall(mpc8xxx_add_gpiochips); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-msm-v1.c b/ANDROID_3.4.5/drivers/gpio/gpio-msm-v1.c deleted file mode 100644 index 52a4d428..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-msm-v1.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#include <linux/bitops.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/module.h> -#include <mach/cpu.h> -#include <mach/msm_gpiomux.h> -#include <mach/msm_iomap.h> - -/* see 80-VA736-2 Rev C pp 695-751 -** -** These are actually the *shadow* gpio registers, since the -** real ones (which allow full access) are only available to the -** ARM9 side of the world. -** -** Since the _BASE need to be page-aligned when we're mapping them -** to virtual addresses, adjust for the additional offset in these -** macros. -*/ - -#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off)) -#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off)) -#define MSM_GPIO1_SHADOW_REG(off) (MSM_GPIO1_BASE + 0x800 + (off)) -#define MSM_GPIO2_SHADOW_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off)) - -/* - * MSM7X00 registers - */ -/* output value */ -#define MSM7X00_GPIO_OUT_0 MSM_GPIO1_SHADOW_REG(0x00) /* gpio 15-0 */ -#define MSM7X00_GPIO_OUT_1 MSM_GPIO2_SHADOW_REG(0x00) /* gpio 42-16 */ -#define MSM7X00_GPIO_OUT_2 MSM_GPIO1_SHADOW_REG(0x04) /* gpio 67-43 */ -#define MSM7X00_GPIO_OUT_3 MSM_GPIO1_SHADOW_REG(0x08) /* gpio 94-68 */ -#define MSM7X00_GPIO_OUT_4 MSM_GPIO1_SHADOW_REG(0x0C) /* gpio 106-95 */ -#define MSM7X00_GPIO_OUT_5 MSM_GPIO1_SHADOW_REG(0x50) /* gpio 107-121 */ - -/* same pin map as above, output enable */ -#define MSM7X00_GPIO_OE_0 MSM_GPIO1_SHADOW_REG(0x10) -#define MSM7X00_GPIO_OE_1 MSM_GPIO2_SHADOW_REG(0x08) -#define MSM7X00_GPIO_OE_2 MSM_GPIO1_SHADOW_REG(0x14) -#define MSM7X00_GPIO_OE_3 MSM_GPIO1_SHADOW_REG(0x18) -#define MSM7X00_GPIO_OE_4 MSM_GPIO1_SHADOW_REG(0x1C) -#define MSM7X00_GPIO_OE_5 MSM_GPIO1_SHADOW_REG(0x54) - -/* same pin map as above, input read */ -#define MSM7X00_GPIO_IN_0 MSM_GPIO1_SHADOW_REG(0x34) -#define MSM7X00_GPIO_IN_1 MSM_GPIO2_SHADOW_REG(0x20) -#define MSM7X00_GPIO_IN_2 MSM_GPIO1_SHADOW_REG(0x38) -#define MSM7X00_GPIO_IN_3 MSM_GPIO1_SHADOW_REG(0x3C) -#define MSM7X00_GPIO_IN_4 MSM_GPIO1_SHADOW_REG(0x40) -#define MSM7X00_GPIO_IN_5 MSM_GPIO1_SHADOW_REG(0x44) - -/* same pin map as above, 1=edge 0=level interrup */ -#define MSM7X00_GPIO_INT_EDGE_0 MSM_GPIO1_SHADOW_REG(0x60) -#define MSM7X00_GPIO_INT_EDGE_1 MSM_GPIO2_SHADOW_REG(0x50) -#define MSM7X00_GPIO_INT_EDGE_2 MSM_GPIO1_SHADOW_REG(0x64) -#define MSM7X00_GPIO_INT_EDGE_3 MSM_GPIO1_SHADOW_REG(0x68) -#define MSM7X00_GPIO_INT_EDGE_4 MSM_GPIO1_SHADOW_REG(0x6C) -#define MSM7X00_GPIO_INT_EDGE_5 MSM_GPIO1_SHADOW_REG(0xC0) - -/* same pin map as above, 1=positive 0=negative */ -#define MSM7X00_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x70) -#define MSM7X00_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58) -#define MSM7X00_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x74) -#define MSM7X00_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x78) -#define MSM7X00_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x7C) -#define MSM7X00_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xBC) - -/* same pin map as above, interrupt enable */ -#define MSM7X00_GPIO_INT_EN_0 MSM_GPIO1_SHADOW_REG(0x80) -#define MSM7X00_GPIO_INT_EN_1 MSM_GPIO2_SHADOW_REG(0x60) -#define MSM7X00_GPIO_INT_EN_2 MSM_GPIO1_SHADOW_REG(0x84) -#define MSM7X00_GPIO_INT_EN_3 MSM_GPIO1_SHADOW_REG(0x88) -#define MSM7X00_GPIO_INT_EN_4 MSM_GPIO1_SHADOW_REG(0x8C) -#define MSM7X00_GPIO_INT_EN_5 MSM_GPIO1_SHADOW_REG(0xB8) - -/* same pin map as above, write 1 to clear interrupt */ -#define MSM7X00_GPIO_INT_CLEAR_0 MSM_GPIO1_SHADOW_REG(0x90) -#define MSM7X00_GPIO_INT_CLEAR_1 MSM_GPIO2_SHADOW_REG(0x68) -#define MSM7X00_GPIO_INT_CLEAR_2 MSM_GPIO1_SHADOW_REG(0x94) -#define MSM7X00_GPIO_INT_CLEAR_3 MSM_GPIO1_SHADOW_REG(0x98) -#define MSM7X00_GPIO_INT_CLEAR_4 MSM_GPIO1_SHADOW_REG(0x9C) -#define MSM7X00_GPIO_INT_CLEAR_5 MSM_GPIO1_SHADOW_REG(0xB4) - -/* same pin map as above, 1=interrupt pending */ -#define MSM7X00_GPIO_INT_STATUS_0 MSM_GPIO1_SHADOW_REG(0xA0) -#define MSM7X00_GPIO_INT_STATUS_1 MSM_GPIO2_SHADOW_REG(0x70) -#define MSM7X00_GPIO_INT_STATUS_2 MSM_GPIO1_SHADOW_REG(0xA4) -#define MSM7X00_GPIO_INT_STATUS_3 MSM_GPIO1_SHADOW_REG(0xA8) -#define MSM7X00_GPIO_INT_STATUS_4 MSM_GPIO1_SHADOW_REG(0xAC) -#define MSM7X00_GPIO_INT_STATUS_5 MSM_GPIO1_SHADOW_REG(0xB0) - -/* - * QSD8X50 registers - */ -/* output value */ -#define QSD8X50_GPIO_OUT_0 MSM_GPIO1_SHADOW_REG(0x00) /* gpio 15-0 */ -#define QSD8X50_GPIO_OUT_1 MSM_GPIO2_SHADOW_REG(0x00) /* gpio 42-16 */ -#define QSD8X50_GPIO_OUT_2 MSM_GPIO1_SHADOW_REG(0x04) /* gpio 67-43 */ -#define QSD8X50_GPIO_OUT_3 MSM_GPIO1_SHADOW_REG(0x08) /* gpio 94-68 */ -#define QSD8X50_GPIO_OUT_4 MSM_GPIO1_SHADOW_REG(0x0C) /* gpio 103-95 */ -#define QSD8X50_GPIO_OUT_5 MSM_GPIO1_SHADOW_REG(0x10) /* gpio 121-104 */ -#define QSD8X50_GPIO_OUT_6 MSM_GPIO1_SHADOW_REG(0x14) /* gpio 152-122 */ -#define QSD8X50_GPIO_OUT_7 MSM_GPIO1_SHADOW_REG(0x18) /* gpio 164-153 */ - -/* same pin map as above, output enable */ -#define QSD8X50_GPIO_OE_0 MSM_GPIO1_SHADOW_REG(0x20) -#define QSD8X50_GPIO_OE_1 MSM_GPIO2_SHADOW_REG(0x08) -#define QSD8X50_GPIO_OE_2 MSM_GPIO1_SHADOW_REG(0x24) -#define QSD8X50_GPIO_OE_3 MSM_GPIO1_SHADOW_REG(0x28) -#define QSD8X50_GPIO_OE_4 MSM_GPIO1_SHADOW_REG(0x2C) -#define QSD8X50_GPIO_OE_5 MSM_GPIO1_SHADOW_REG(0x30) -#define QSD8X50_GPIO_OE_6 MSM_GPIO1_SHADOW_REG(0x34) -#define QSD8X50_GPIO_OE_7 MSM_GPIO1_SHADOW_REG(0x38) - -/* same pin map as above, input read */ -#define QSD8X50_GPIO_IN_0 MSM_GPIO1_SHADOW_REG(0x50) -#define QSD8X50_GPIO_IN_1 MSM_GPIO2_SHADOW_REG(0x20) -#define QSD8X50_GPIO_IN_2 MSM_GPIO1_SHADOW_REG(0x54) -#define QSD8X50_GPIO_IN_3 MSM_GPIO1_SHADOW_REG(0x58) -#define QSD8X50_GPIO_IN_4 MSM_GPIO1_SHADOW_REG(0x5C) -#define QSD8X50_GPIO_IN_5 MSM_GPIO1_SHADOW_REG(0x60) -#define QSD8X50_GPIO_IN_6 MSM_GPIO1_SHADOW_REG(0x64) -#define QSD8X50_GPIO_IN_7 MSM_GPIO1_SHADOW_REG(0x68) - -/* same pin map as above, 1=edge 0=level interrup */ -#define QSD8X50_GPIO_INT_EDGE_0 MSM_GPIO1_SHADOW_REG(0x70) -#define QSD8X50_GPIO_INT_EDGE_1 MSM_GPIO2_SHADOW_REG(0x50) -#define QSD8X50_GPIO_INT_EDGE_2 MSM_GPIO1_SHADOW_REG(0x74) -#define QSD8X50_GPIO_INT_EDGE_3 MSM_GPIO1_SHADOW_REG(0x78) -#define QSD8X50_GPIO_INT_EDGE_4 MSM_GPIO1_SHADOW_REG(0x7C) -#define QSD8X50_GPIO_INT_EDGE_5 MSM_GPIO1_SHADOW_REG(0x80) -#define QSD8X50_GPIO_INT_EDGE_6 MSM_GPIO1_SHADOW_REG(0x84) -#define QSD8X50_GPIO_INT_EDGE_7 MSM_GPIO1_SHADOW_REG(0x88) - -/* same pin map as above, 1=positive 0=negative */ -#define QSD8X50_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x90) -#define QSD8X50_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58) -#define QSD8X50_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x94) -#define QSD8X50_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x98) -#define QSD8X50_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x9C) -#define QSD8X50_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xA0) -#define QSD8X50_GPIO_INT_POS_6 MSM_GPIO1_SHADOW_REG(0xA4) -#define QSD8X50_GPIO_INT_POS_7 MSM_GPIO1_SHADOW_REG(0xA8) - -/* same pin map as above, interrupt enable */ -#define QSD8X50_GPIO_INT_EN_0 MSM_GPIO1_SHADOW_REG(0xB0) -#define QSD8X50_GPIO_INT_EN_1 MSM_GPIO2_SHADOW_REG(0x60) -#define QSD8X50_GPIO_INT_EN_2 MSM_GPIO1_SHADOW_REG(0xB4) -#define QSD8X50_GPIO_INT_EN_3 MSM_GPIO1_SHADOW_REG(0xB8) -#define QSD8X50_GPIO_INT_EN_4 MSM_GPIO1_SHADOW_REG(0xBC) -#define QSD8X50_GPIO_INT_EN_5 MSM_GPIO1_SHADOW_REG(0xC0) -#define QSD8X50_GPIO_INT_EN_6 MSM_GPIO1_SHADOW_REG(0xC4) -#define QSD8X50_GPIO_INT_EN_7 MSM_GPIO1_SHADOW_REG(0xC8) - -/* same pin map as above, write 1 to clear interrupt */ -#define QSD8X50_GPIO_INT_CLEAR_0 MSM_GPIO1_SHADOW_REG(0xD0) -#define QSD8X50_GPIO_INT_CLEAR_1 MSM_GPIO2_SHADOW_REG(0x68) -#define QSD8X50_GPIO_INT_CLEAR_2 MSM_GPIO1_SHADOW_REG(0xD4) -#define QSD8X50_GPIO_INT_CLEAR_3 MSM_GPIO1_SHADOW_REG(0xD8) -#define QSD8X50_GPIO_INT_CLEAR_4 MSM_GPIO1_SHADOW_REG(0xDC) -#define QSD8X50_GPIO_INT_CLEAR_5 MSM_GPIO1_SHADOW_REG(0xE0) -#define QSD8X50_GPIO_INT_CLEAR_6 MSM_GPIO1_SHADOW_REG(0xE4) -#define QSD8X50_GPIO_INT_CLEAR_7 MSM_GPIO1_SHADOW_REG(0xE8) - -/* same pin map as above, 1=interrupt pending */ -#define QSD8X50_GPIO_INT_STATUS_0 MSM_GPIO1_SHADOW_REG(0xF0) -#define QSD8X50_GPIO_INT_STATUS_1 MSM_GPIO2_SHADOW_REG(0x70) -#define QSD8X50_GPIO_INT_STATUS_2 MSM_GPIO1_SHADOW_REG(0xF4) -#define QSD8X50_GPIO_INT_STATUS_3 MSM_GPIO1_SHADOW_REG(0xF8) -#define QSD8X50_GPIO_INT_STATUS_4 MSM_GPIO1_SHADOW_REG(0xFC) -#define QSD8X50_GPIO_INT_STATUS_5 MSM_GPIO1_SHADOW_REG(0x100) -#define QSD8X50_GPIO_INT_STATUS_6 MSM_GPIO1_SHADOW_REG(0x104) -#define QSD8X50_GPIO_INT_STATUS_7 MSM_GPIO1_SHADOW_REG(0x108) - -/* - * MSM7X30 registers - */ -/* output value */ -#define MSM7X30_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */ -#define MSM7X30_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 43-16 */ -#define MSM7X30_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-44 */ -#define MSM7X30_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */ -#define MSM7X30_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */ -#define MSM7X30_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 133-107 */ -#define MSM7X30_GPIO_OUT_6 MSM_GPIO1_REG(0xC4) /* gpio 150-134 */ -#define MSM7X30_GPIO_OUT_7 MSM_GPIO1_REG(0x214) /* gpio 181-151 */ - -/* same pin map as above, output enable */ -#define MSM7X30_GPIO_OE_0 MSM_GPIO1_REG(0x10) -#define MSM7X30_GPIO_OE_1 MSM_GPIO2_REG(0x08) -#define MSM7X30_GPIO_OE_2 MSM_GPIO1_REG(0x14) -#define MSM7X30_GPIO_OE_3 MSM_GPIO1_REG(0x18) -#define MSM7X30_GPIO_OE_4 MSM_GPIO1_REG(0x1C) -#define MSM7X30_GPIO_OE_5 MSM_GPIO1_REG(0x54) -#define MSM7X30_GPIO_OE_6 MSM_GPIO1_REG(0xC8) -#define MSM7X30_GPIO_OE_7 MSM_GPIO1_REG(0x218) - -/* same pin map as above, input read */ -#define MSM7X30_GPIO_IN_0 MSM_GPIO1_REG(0x34) -#define MSM7X30_GPIO_IN_1 MSM_GPIO2_REG(0x20) -#define MSM7X30_GPIO_IN_2 MSM_GPIO1_REG(0x38) -#define MSM7X30_GPIO_IN_3 MSM_GPIO1_REG(0x3C) -#define MSM7X30_GPIO_IN_4 MSM_GPIO1_REG(0x40) -#define MSM7X30_GPIO_IN_5 MSM_GPIO1_REG(0x44) -#define MSM7X30_GPIO_IN_6 MSM_GPIO1_REG(0xCC) -#define MSM7X30_GPIO_IN_7 MSM_GPIO1_REG(0x21C) - -/* same pin map as above, 1=edge 0=level interrup */ -#define MSM7X30_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60) -#define MSM7X30_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50) -#define MSM7X30_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64) -#define MSM7X30_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68) -#define MSM7X30_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C) -#define MSM7X30_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0) -#define MSM7X30_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0xD0) -#define MSM7X30_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x240) - -/* same pin map as above, 1=positive 0=negative */ -#define MSM7X30_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70) -#define MSM7X30_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58) -#define MSM7X30_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74) -#define MSM7X30_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78) -#define MSM7X30_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C) -#define MSM7X30_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC) -#define MSM7X30_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4) -#define MSM7X30_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228) - -/* same pin map as above, interrupt enable */ -#define MSM7X30_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80) -#define MSM7X30_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60) -#define MSM7X30_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84) -#define MSM7X30_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88) -#define MSM7X30_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C) -#define MSM7X30_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8) -#define MSM7X30_GPIO_INT_EN_6 MSM_GPIO1_REG(0xD8) -#define MSM7X30_GPIO_INT_EN_7 MSM_GPIO1_REG(0x22C) - -/* same pin map as above, write 1 to clear interrupt */ -#define MSM7X30_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90) -#define MSM7X30_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68) -#define MSM7X30_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94) -#define MSM7X30_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98) -#define MSM7X30_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C) -#define MSM7X30_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4) -#define MSM7X30_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xDC) -#define MSM7X30_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0x230) - -/* same pin map as above, 1=interrupt pending */ -#define MSM7X30_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0) -#define MSM7X30_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70) -#define MSM7X30_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4) -#define MSM7X30_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8) -#define MSM7X30_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC) -#define MSM7X30_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0) -#define MSM7X30_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0xE0) -#define MSM7X30_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x234) - -#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0) - -#define MSM_GPIO_BANK(soc, bank, first, last) \ - { \ - .regs = { \ - .out = soc##_GPIO_OUT_##bank, \ - .in = soc##_GPIO_IN_##bank, \ - .int_status = soc##_GPIO_INT_STATUS_##bank, \ - .int_clear = soc##_GPIO_INT_CLEAR_##bank, \ - .int_en = soc##_GPIO_INT_EN_##bank, \ - .int_edge = soc##_GPIO_INT_EDGE_##bank, \ - .int_pos = soc##_GPIO_INT_POS_##bank, \ - .oe = soc##_GPIO_OE_##bank, \ - }, \ - .chip = { \ - .base = (first), \ - .ngpio = (last) - (first) + 1, \ - .get = msm_gpio_get, \ - .set = msm_gpio_set, \ - .direction_input = msm_gpio_direction_input, \ - .direction_output = msm_gpio_direction_output, \ - .to_irq = msm_gpio_to_irq, \ - .request = msm_gpio_request, \ - .free = msm_gpio_free, \ - } \ - } - -#define MSM_GPIO_BROKEN_INT_CLEAR 1 - -struct msm_gpio_regs { - void __iomem *out; - void __iomem *in; - void __iomem *int_status; - void __iomem *int_clear; - void __iomem *int_en; - void __iomem *int_edge; - void __iomem *int_pos; - void __iomem *oe; -}; - -struct msm_gpio_chip { - spinlock_t lock; - struct gpio_chip chip; - struct msm_gpio_regs regs; -#if MSM_GPIO_BROKEN_INT_CLEAR - unsigned int_status_copy; -#endif - unsigned int both_edge_detect; - unsigned int int_enable[2]; /* 0: awake, 1: sleep */ -}; - -static int msm_gpio_write(struct msm_gpio_chip *msm_chip, - unsigned offset, unsigned on) -{ - unsigned mask = BIT(offset); - unsigned val; - - val = readl(msm_chip->regs.out); - if (on) - writel(val | mask, msm_chip->regs.out); - else - writel(val & ~mask, msm_chip->regs.out); - return 0; -} - -static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip) -{ - int loop_limit = 100; - unsigned pol, val, val2, intstat; - do { - val = readl(msm_chip->regs.in); - pol = readl(msm_chip->regs.int_pos); - pol = (pol & ~msm_chip->both_edge_detect) | - (~val & msm_chip->both_edge_detect); - writel(pol, msm_chip->regs.int_pos); - intstat = readl(msm_chip->regs.int_status); - val2 = readl(msm_chip->regs.in); - if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0) - return; - } while (loop_limit-- > 0); - printk(KERN_ERR "msm_gpio_update_both_edge_detect, " - "failed to reach stable state %x != %x\n", val, val2); -} - -static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip, - unsigned offset) -{ - unsigned bit = BIT(offset); - -#if MSM_GPIO_BROKEN_INT_CLEAR - /* Save interrupts that already triggered before we loose them. */ - /* Any interrupt that triggers between the read of int_status */ - /* and the write to int_clear will still be lost though. */ - msm_chip->int_status_copy |= readl(msm_chip->regs.int_status); - msm_chip->int_status_copy &= ~bit; -#endif - writel(bit, msm_chip->regs.int_clear); - msm_gpio_update_both_edge_detect(msm_chip); - return 0; -} - -static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct msm_gpio_chip *msm_chip; - unsigned long irq_flags; - - msm_chip = container_of(chip, struct msm_gpio_chip, chip); - spin_lock_irqsave(&msm_chip->lock, irq_flags); - writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); - return 0; -} - -static int -msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) -{ - struct msm_gpio_chip *msm_chip; - unsigned long irq_flags; - - msm_chip = container_of(chip, struct msm_gpio_chip, chip); - spin_lock_irqsave(&msm_chip->lock, irq_flags); - msm_gpio_write(msm_chip, offset, value); - writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); - return 0; -} - -static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct msm_gpio_chip *msm_chip; - - msm_chip = container_of(chip, struct msm_gpio_chip, chip); - return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0; -} - -static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct msm_gpio_chip *msm_chip; - unsigned long irq_flags; - - msm_chip = container_of(chip, struct msm_gpio_chip, chip); - spin_lock_irqsave(&msm_chip->lock, irq_flags); - msm_gpio_write(msm_chip, offset, value); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); -} - -static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return MSM_GPIO_TO_INT(chip->base + offset); -} - -#ifdef CONFIG_MSM_GPIOMUX -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); -} -#else -#define msm_gpio_request NULL -#define msm_gpio_free NULL -#endif - -static struct msm_gpio_chip *msm_gpio_chips; -static int msm_gpio_count; - -static struct msm_gpio_chip msm_gpio_chips_msm7x01[] = { - MSM_GPIO_BANK(MSM7X00, 0, 0, 15), - MSM_GPIO_BANK(MSM7X00, 1, 16, 42), - MSM_GPIO_BANK(MSM7X00, 2, 43, 67), - MSM_GPIO_BANK(MSM7X00, 3, 68, 94), - MSM_GPIO_BANK(MSM7X00, 4, 95, 106), - MSM_GPIO_BANK(MSM7X00, 5, 107, 121), -}; - -static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = { - MSM_GPIO_BANK(MSM7X30, 0, 0, 15), - MSM_GPIO_BANK(MSM7X30, 1, 16, 43), - MSM_GPIO_BANK(MSM7X30, 2, 44, 67), - MSM_GPIO_BANK(MSM7X30, 3, 68, 94), - MSM_GPIO_BANK(MSM7X30, 4, 95, 106), - MSM_GPIO_BANK(MSM7X30, 5, 107, 133), - MSM_GPIO_BANK(MSM7X30, 6, 134, 150), - MSM_GPIO_BANK(MSM7X30, 7, 151, 181), -}; - -static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = { - MSM_GPIO_BANK(QSD8X50, 0, 0, 15), - MSM_GPIO_BANK(QSD8X50, 1, 16, 42), - MSM_GPIO_BANK(QSD8X50, 2, 43, 67), - MSM_GPIO_BANK(QSD8X50, 3, 68, 94), - MSM_GPIO_BANK(QSD8X50, 4, 95, 103), - MSM_GPIO_BANK(QSD8X50, 5, 104, 121), - MSM_GPIO_BANK(QSD8X50, 6, 122, 152), - MSM_GPIO_BANK(QSD8X50, 7, 153, 164), -}; - -static void msm_gpio_irq_ack(struct irq_data *d) -{ - unsigned long irq_flags; - struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d); - spin_lock_irqsave(&msm_chip->lock, irq_flags); - msm_gpio_clear_detect_status(msm_chip, - d->irq - gpio_to_irq(msm_chip->chip.base)); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); -} - -static void msm_gpio_irq_mask(struct irq_data *d) -{ - unsigned long irq_flags; - struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d); - unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base); - - spin_lock_irqsave(&msm_chip->lock, irq_flags); - /* level triggered interrupts are also latched */ - if (!(readl(msm_chip->regs.int_edge) & BIT(offset))) - msm_gpio_clear_detect_status(msm_chip, offset); - msm_chip->int_enable[0] &= ~BIT(offset); - writel(msm_chip->int_enable[0], msm_chip->regs.int_en); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); -} - -static void msm_gpio_irq_unmask(struct irq_data *d) -{ - unsigned long irq_flags; - struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d); - unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base); - - spin_lock_irqsave(&msm_chip->lock, irq_flags); - /* level triggered interrupts are also latched */ - if (!(readl(msm_chip->regs.int_edge) & BIT(offset))) - msm_gpio_clear_detect_status(msm_chip, offset); - msm_chip->int_enable[0] |= BIT(offset); - writel(msm_chip->int_enable[0], msm_chip->regs.int_en); - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); -} - -static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) -{ - unsigned long irq_flags; - struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d); - unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base); - - spin_lock_irqsave(&msm_chip->lock, irq_flags); - - if (on) - msm_chip->int_enable[1] |= BIT(offset); - else - msm_chip->int_enable[1] &= ~BIT(offset); - - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); - return 0; -} - -static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - unsigned long irq_flags; - struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d); - unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base); - unsigned val, mask = BIT(offset); - - spin_lock_irqsave(&msm_chip->lock, irq_flags); - val = readl(msm_chip->regs.int_edge); - if (flow_type & IRQ_TYPE_EDGE_BOTH) { - writel(val | mask, msm_chip->regs.int_edge); - __irq_set_handler_locked(d->irq, handle_edge_irq); - } else { - writel(val & ~mask, msm_chip->regs.int_edge); - __irq_set_handler_locked(d->irq, handle_level_irq); - } - if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { - msm_chip->both_edge_detect |= mask; - msm_gpio_update_both_edge_detect(msm_chip); - } else { - msm_chip->both_edge_detect &= ~mask; - val = readl(msm_chip->regs.int_pos); - if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) - writel(val | mask, msm_chip->regs.int_pos); - else - writel(val & ~mask, msm_chip->regs.int_pos); - } - spin_unlock_irqrestore(&msm_chip->lock, irq_flags); - return 0; -} - -static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - int i, j, mask; - unsigned val; - - for (i = 0; i < msm_gpio_count; i++) { - struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i]; - val = readl(msm_chip->regs.int_status); - val &= msm_chip->int_enable[0]; - while (val) { - mask = val & -val; - j = fls(mask) - 1; - /* printk("%s %08x %08x bit %d gpio %d irq %d\n", - __func__, v, m, j, msm_chip->chip.start + j, - FIRST_GPIO_IRQ + msm_chip->chip.start + j); */ - val &= ~mask; - generic_handle_irq(FIRST_GPIO_IRQ + - msm_chip->chip.base + j); - } - } - desc->irq_data.chip->irq_ack(&desc->irq_data); -} - -static struct irq_chip msm_gpio_irq_chip = { - .name = "msmgpio", - .irq_ack = msm_gpio_irq_ack, - .irq_mask = msm_gpio_irq_mask, - .irq_unmask = msm_gpio_irq_unmask, - .irq_set_wake = msm_gpio_irq_set_wake, - .irq_set_type = msm_gpio_irq_set_type, -}; - -static int __init msm_init_gpio(void) -{ - int i, j = 0; - - if (cpu_is_msm7x01()) { - msm_gpio_chips = msm_gpio_chips_msm7x01; - msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x01); - } else if (cpu_is_msm7x30()) { - msm_gpio_chips = msm_gpio_chips_msm7x30; - msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x30); - } else if (cpu_is_qsd8x50()) { - msm_gpio_chips = msm_gpio_chips_qsd8x50; - msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_qsd8x50); - } else { - return 0; - } - - for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) { - if (i - FIRST_GPIO_IRQ >= - msm_gpio_chips[j].chip.base + - msm_gpio_chips[j].chip.ngpio) - j++; - irq_set_chip_data(i, &msm_gpio_chips[j]); - irq_set_chip_and_handler(i, &msm_gpio_irq_chip, - handle_edge_irq); - set_irq_flags(i, IRQF_VALID); - } - - for (i = 0; i < msm_gpio_count; i++) { - spin_lock_init(&msm_gpio_chips[i].lock); - writel(0, msm_gpio_chips[i].regs.int_en); - gpiochip_add(&msm_gpio_chips[i].chip); - } - - irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler); - irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler); - irq_set_irq_wake(INT_GPIO_GROUP1, 1); - irq_set_irq_wake(INT_GPIO_GROUP2, 2); - return 0; -} - -postcore_initcall(msm_init_gpio); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-msm-v2.c b/ANDROID_3.4.5/drivers/gpio/gpio-msm-v2.c deleted file mode 100644 index 5cb1227d..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-msm-v2.c +++ /dev/null @@ -1,433 +0,0 @@ -/* Copyright (c) 2010-2011, 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. - * - */ -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include <linux/bitmap.h> -#include <linux/bitops.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> - -#include <asm/mach/irq.h> - -#include <mach/msm_gpiomux.h> -#include <mach/msm_iomap.h> - -/* Bits of interest in the GPIO_IN_OUT register. - */ -enum { - GPIO_IN = 0, - GPIO_OUT = 1 -}; - -/* Bits of interest in the GPIO_INTR_STATUS register. - */ -enum { - INTR_STATUS = 0, -}; - -/* Bits of interest in the GPIO_CFG register. - */ -enum { - GPIO_OE = 9, -}; - -/* Bits of interest in the GPIO_INTR_CFG register. - * When a GPIO triggers, two separate decisions are made, controlled - * by two separate flags. - * - * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS - * register for that GPIO will be updated to reflect the triggering of that - * gpio. If this bit is 0, this register will not be updated. - * - Second, INTR_ENABLE controls whether an interrupt is triggered. - * - * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt - * can be triggered but the status register will not reflect it. - */ -enum { - INTR_ENABLE = 0, - INTR_POL_CTL = 1, - INTR_DECT_CTL = 2, - INTR_RAW_STATUS_EN = 3, -}; - -/* Codes of interest in GPIO_INTR_CFG_SU. - */ -enum { - TARGET_PROC_SCORPION = 4, - TARGET_PROC_NONE = 7, -}; - - -#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio))) -#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio))) -#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio))) -#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio))) -#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio))) - -/** - * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure - * - * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By - * keeping track of which gpios are unmasked as irq sources, we avoid - * having to do readl calls on hundreds of iomapped registers each time - * the summary interrupt fires in order to locate the active interrupts. - * - * @wake_irqs: a bitmap for tracking which interrupt lines are enabled - * as wakeup sources. When the device is suspended, interrupts which are - * not wakeup sources are disabled. - * - * @dual_edge_irqs: a bitmap used to track which irqs are configured - * as dual-edge, as this is not supported by the hardware and requires - * some special handling in the driver. - */ -struct msm_gpio_dev { - struct gpio_chip gpio_chip; - DECLARE_BITMAP(enabled_irqs, NR_GPIO_IRQS); - DECLARE_BITMAP(wake_irqs, NR_GPIO_IRQS); - DECLARE_BITMAP(dual_edge_irqs, NR_GPIO_IRQS); -}; - -static DEFINE_SPINLOCK(tlmm_lock); - -static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip) -{ - return container_of(chip, struct msm_gpio_dev, gpio_chip); -} - -static inline void set_gpio_bits(unsigned n, void __iomem *reg) -{ - writel(readl(reg) | n, reg); -} - -static inline void clear_gpio_bits(unsigned n, void __iomem *reg) -{ - writel(readl(reg) & ~n, reg); -} - -static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN); -} - -static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - writel(val ? BIT(GPIO_OUT) : 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); - clear_gpio_bits(BIT(GPIO_OE), 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); - set_gpio_bits(BIT(GPIO_OE), 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 int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return MSM_GPIO_TO_INT(chip->base + offset); -} - -static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq) -{ - return irq - MSM_GPIO_TO_INT(chip->base); -} - -static struct msm_gpio_dev msm_gpio = { - .gpio_chip = { - .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, - .to_irq = msm_gpio_to_irq, - .request = msm_gpio_request, - .free = msm_gpio_free, - }, -}; - -/* For dual-edge interrupts in software, since the hardware has no - * such support: - * - * At appropriate moments, this function may be called to flip the polarity - * settings of both-edge irq lines to try and catch the next edge. - * - * The attempt is considered successful if: - * - the status bit goes high, indicating that an edge was caught, or - * - the input value of the gpio doesn't change during the attempt. - * If the value changes twice during the process, that would cause the first - * test to fail but would force the second, as two opposite - * transitions would cause a detection no matter the polarity setting. - * - * The do-loop tries to sledge-hammer closed the timing hole between - * the initial value-read and the polarity-write - if the line value changes - * during that window, an interrupt is lost, the new polarity setting is - * incorrect, and the first success test will fail, causing a retry. - * - * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c. - */ -static void msm_gpio_update_dual_edge_pos(unsigned gpio) -{ - int loop_limit = 100; - unsigned val, val2, intstat; - - do { - val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); - if (val) - clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); - else - set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); - val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); - intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS); - if (intstat || val == val2) - return; - } while (loop_limit-- > 0); - pr_err("dual-edge irq failed to stabilize, " - "interrupts dropped. %#08x != %#08x\n", - val, val2); -} - -static void msm_gpio_irq_ack(struct irq_data *d) -{ - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); - - writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio)); - if (test_bit(gpio, msm_gpio.dual_edge_irqs)) - msm_gpio_update_dual_edge_pos(gpio); -} - -static void msm_gpio_irq_mask(struct irq_data *d) -{ - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); - unsigned long irq_flags; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); - clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); - __clear_bit(gpio, msm_gpio.enabled_irqs); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); -} - -static void msm_gpio_irq_unmask(struct irq_data *d) -{ - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); - unsigned long irq_flags; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - __set_bit(gpio, msm_gpio.enabled_irqs); - set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); - writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio)); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); -} - -static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); - unsigned long irq_flags; - uint32_t bits; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - - bits = readl(GPIO_INTR_CFG(gpio)); - - if (flow_type & IRQ_TYPE_EDGE_BOTH) { - bits |= BIT(INTR_DECT_CTL); - __irq_set_handler_locked(d->irq, handle_edge_irq); - if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - __set_bit(gpio, msm_gpio.dual_edge_irqs); - else - __clear_bit(gpio, msm_gpio.dual_edge_irqs); - } else { - bits &= ~BIT(INTR_DECT_CTL); - __irq_set_handler_locked(d->irq, handle_level_irq); - __clear_bit(gpio, msm_gpio.dual_edge_irqs); - } - - if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) - bits |= BIT(INTR_POL_CTL); - else - bits &= ~BIT(INTR_POL_CTL); - - writel(bits, GPIO_INTR_CFG(gpio)); - - if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - msm_gpio_update_dual_edge_pos(gpio); - - spin_unlock_irqrestore(&tlmm_lock, irq_flags); - - return 0; -} - -/* - * When the summary IRQ is raised, any number of GPIO lines may be high. - * It is the job of the summary handler to find all those GPIO lines - * which have been set as summary IRQ lines and which are triggered, - * and to call their interrupt handlers. - */ -static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - unsigned long i; - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS); - i < NR_GPIO_IRQS; - i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) { - if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS)) - generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip, - i)); - } - - chained_irq_exit(chip, desc); -} - -static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) -{ - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); - - if (on) { - if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) - irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1); - set_bit(gpio, msm_gpio.wake_irqs); - } else { - clear_bit(gpio, msm_gpio.wake_irqs); - if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) - irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0); - } - - return 0; -} - -static struct irq_chip msm_gpio_irq_chip = { - .name = "msmgpio", - .irq_mask = msm_gpio_irq_mask, - .irq_unmask = msm_gpio_irq_unmask, - .irq_ack = msm_gpio_irq_ack, - .irq_set_type = msm_gpio_irq_set_type, - .irq_set_wake = msm_gpio_irq_set_wake, -}; - -static int __devinit msm_gpio_probe(struct platform_device *dev) -{ - int i, irq, ret; - - bitmap_zero(msm_gpio.enabled_irqs, NR_GPIO_IRQS); - bitmap_zero(msm_gpio.wake_irqs, NR_GPIO_IRQS); - bitmap_zero(msm_gpio.dual_edge_irqs, NR_GPIO_IRQS); - msm_gpio.gpio_chip.label = dev->name; - ret = gpiochip_add(&msm_gpio.gpio_chip); - if (ret < 0) - return ret; - - for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) { - irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i); - irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, - handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } - - irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ, - msm_summary_irq_handler); - return 0; -} - -static int __devexit msm_gpio_remove(struct platform_device *dev) -{ - int ret = gpiochip_remove(&msm_gpio.gpio_chip); - - if (ret < 0) - return ret; - - irq_set_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"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mxc.c b/ANDROID_3.4.5/drivers/gpio/gpio-mxc.c deleted file mode 100644 index e7914763..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mxc.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * Based on code from Freescale, - * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * 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/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/basic_mmio_gpio.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/module.h> -#include <asm-generic/bug.h> -#include <asm/mach/irq.h> - -#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START) - -enum mxc_gpio_hwtype { - IMX1_GPIO, /* runs on i.mx1 */ - IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ - IMX31_GPIO, /* runs on all other i.mx */ -}; - -/* device type dependent stuff */ -struct mxc_gpio_hwdata { - unsigned dr_reg; - unsigned gdir_reg; - unsigned psr_reg; - unsigned icr1_reg; - unsigned icr2_reg; - unsigned imr_reg; - unsigned isr_reg; - unsigned low_level; - unsigned high_level; - unsigned rise_edge; - unsigned fall_edge; -}; - -struct mxc_gpio_port { - struct list_head node; - void __iomem *base; - int irq; - int irq_high; - int virtual_irq_start; - struct bgpio_chip bgc; - u32 both_edges; -}; - -static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { - .dr_reg = 0x1c, - .gdir_reg = 0x00, - .psr_reg = 0x24, - .icr1_reg = 0x28, - .icr2_reg = 0x2c, - .imr_reg = 0x30, - .isr_reg = 0x34, - .low_level = 0x03, - .high_level = 0x02, - .rise_edge = 0x00, - .fall_edge = 0x01, -}; - -static struct mxc_gpio_hwdata imx31_gpio_hwdata = { - .dr_reg = 0x00, - .gdir_reg = 0x04, - .psr_reg = 0x08, - .icr1_reg = 0x0c, - .icr2_reg = 0x10, - .imr_reg = 0x14, - .isr_reg = 0x18, - .low_level = 0x00, - .high_level = 0x01, - .rise_edge = 0x02, - .fall_edge = 0x03, -}; - -static enum mxc_gpio_hwtype mxc_gpio_hwtype; -static struct mxc_gpio_hwdata *mxc_gpio_hwdata; - -#define GPIO_DR (mxc_gpio_hwdata->dr_reg) -#define GPIO_GDIR (mxc_gpio_hwdata->gdir_reg) -#define GPIO_PSR (mxc_gpio_hwdata->psr_reg) -#define GPIO_ICR1 (mxc_gpio_hwdata->icr1_reg) -#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg) -#define GPIO_IMR (mxc_gpio_hwdata->imr_reg) -#define GPIO_ISR (mxc_gpio_hwdata->isr_reg) - -#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level) -#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level) -#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge) -#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge) -#define GPIO_INT_NONE 0x4 - -static struct platform_device_id mxc_gpio_devtype[] = { - { - .name = "imx1-gpio", - .driver_data = IMX1_GPIO, - }, { - .name = "imx21-gpio", - .driver_data = IMX21_GPIO, - }, { - .name = "imx31-gpio", - .driver_data = IMX31_GPIO, - }, { - /* sentinel */ - } -}; - -static const struct of_device_id mxc_gpio_dt_ids[] = { - { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], }, - { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], }, - { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], }, - { /* sentinel */ } -}; - -/* - * MX2 has one interrupt *for all* gpio ports. The list is used - * to save the references to all ports, so that mx2_gpio_irq_handler - * can walk through all interrupt status registers. - */ -static LIST_HEAD(mxc_gpio_ports); - -/* Note: This driver assumes 32 GPIOs are handled in one register */ - -static int gpio_set_irq_type(struct irq_data *d, u32 type) -{ - u32 gpio = irq_to_gpio(d->irq); - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mxc_gpio_port *port = gc->private; - u32 bit, val; - int edge; - void __iomem *reg = port->base; - - port->both_edges &= ~(1 << (gpio & 31)); - switch (type) { - case IRQ_TYPE_EDGE_RISING: - edge = GPIO_INT_RISE_EDGE; - break; - case IRQ_TYPE_EDGE_FALLING: - edge = GPIO_INT_FALL_EDGE; - break; - case IRQ_TYPE_EDGE_BOTH: - val = gpio_get_value(gpio); - if (val) { - edge = GPIO_INT_LOW_LEV; - pr_debug("mxc: set GPIO %d to low trigger\n", gpio); - } else { - edge = GPIO_INT_HIGH_LEV; - pr_debug("mxc: set GPIO %d to high trigger\n", gpio); - } - port->both_edges |= 1 << (gpio & 31); - break; - case IRQ_TYPE_LEVEL_LOW: - edge = GPIO_INT_LOW_LEV; - break; - case IRQ_TYPE_LEVEL_HIGH: - edge = GPIO_INT_HIGH_LEV; - break; - default: - return -EINVAL; - } - - reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ - bit = gpio & 0xf; - val = readl(reg) & ~(0x3 << (bit << 1)); - writel(val | (edge << (bit << 1)), reg); - writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); - - return 0; -} - -static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) -{ - void __iomem *reg = port->base; - u32 bit, val; - int edge; - - reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ - bit = gpio & 0xf; - val = readl(reg); - edge = (val >> (bit << 1)) & 3; - val &= ~(0x3 << (bit << 1)); - if (edge == GPIO_INT_HIGH_LEV) { - edge = GPIO_INT_LOW_LEV; - pr_debug("mxc: switch GPIO %d to low trigger\n", gpio); - } else if (edge == GPIO_INT_LOW_LEV) { - edge = GPIO_INT_HIGH_LEV; - pr_debug("mxc: switch GPIO %d to high trigger\n", gpio); - } else { - pr_err("mxc: invalid configuration for GPIO %d: %x\n", - gpio, edge); - return; - } - writel(val | (edge << (bit << 1)), reg); -} - -/* handle 32 interrupts in one status register */ -static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) -{ - u32 gpio_irq_no_base = port->virtual_irq_start; - - while (irq_stat != 0) { - int irqoffset = fls(irq_stat) - 1; - - if (port->both_edges & (1 << irqoffset)) - mxc_flip_edge(port, irqoffset); - - generic_handle_irq(gpio_irq_no_base + irqoffset); - - irq_stat &= ~(1 << irqoffset); - } -} - -/* MX1 and MX3 has one interrupt *per* gpio port */ -static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) -{ - u32 irq_stat; - struct mxc_gpio_port *port = irq_get_handler_data(irq); - struct irq_chip *chip = irq_get_chip(irq); - - chained_irq_enter(chip, desc); - - irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR); - - mxc_gpio_irq_handler(port, irq_stat); - - chained_irq_exit(chip, desc); -} - -/* MX2 has one interrupt *for all* gpio ports */ -static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) -{ - u32 irq_msk, irq_stat; - struct mxc_gpio_port *port; - - /* walk through all interrupt status registers */ - list_for_each_entry(port, &mxc_gpio_ports, node) { - irq_msk = readl(port->base + GPIO_IMR); - if (!irq_msk) - continue; - - irq_stat = readl(port->base + GPIO_ISR) & irq_msk; - if (irq_stat) - mxc_gpio_irq_handler(port, irq_stat); - } -} - -/* - * Set interrupt number "irq" in the GPIO as a wake-up source. - * While system is running, all registered GPIO interrupts need to have - * wake-up enabled. When system is suspended, only selected GPIO interrupts - * need to have wake-up enabled. - * @param irq interrupt source number - * @param enable enable as wake-up if equal to non-zero - * @return This function returns 0 on success. - */ -static int gpio_set_wake_irq(struct irq_data *d, u32 enable) -{ - u32 gpio = irq_to_gpio(d->irq); - u32 gpio_idx = gpio & 0x1F; - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mxc_gpio_port *port = gc->private; - - if (enable) { - if (port->irq_high && (gpio_idx >= 16)) - enable_irq_wake(port->irq_high); - else - enable_irq_wake(port->irq); - } else { - if (port->irq_high && (gpio_idx >= 16)) - disable_irq_wake(port->irq_high); - else - disable_irq_wake(port->irq); - } - - return 0; -} - -static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start, - port->base, handle_level_irq); - gc->private = port; - - ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; - ct->chip.irq_set_type = gpio_set_irq_type; - ct->chip.irq_set_wake = gpio_set_wake_irq; - ct->regs.ack = GPIO_ISR; - ct->regs.mask = GPIO_IMR; - - irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, - IRQ_NOREQUEST, 0); -} - -static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) -{ - const struct of_device_id *of_id = - of_match_device(mxc_gpio_dt_ids, &pdev->dev); - enum mxc_gpio_hwtype hwtype; - - if (of_id) - pdev->id_entry = of_id->data; - hwtype = pdev->id_entry->driver_data; - - if (mxc_gpio_hwtype) { - /* - * The driver works with a reasonable presupposition, - * that is all gpio ports must be the same type when - * running on one soc. - */ - BUG_ON(mxc_gpio_hwtype != hwtype); - return; - } - - if (hwtype == IMX31_GPIO) - mxc_gpio_hwdata = &imx31_gpio_hwdata; - else - mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata; - - mxc_gpio_hwtype = hwtype; -} - -static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - struct mxc_gpio_port *port = - container_of(bgc, struct mxc_gpio_port, bgc); - - return port->virtual_irq_start + offset; -} - -static int __devinit mxc_gpio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct mxc_gpio_port *port; - struct resource *iores; - int err; - - mxc_gpio_get_hw(pdev); - - port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); - if (!port) - return -ENOMEM; - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) { - err = -ENODEV; - goto out_kfree; - } - - if (!request_mem_region(iores->start, resource_size(iores), - pdev->name)) { - err = -EBUSY; - goto out_kfree; - } - - port->base = ioremap(iores->start, resource_size(iores)); - if (!port->base) { - err = -ENOMEM; - goto out_release_mem; - } - - port->irq_high = platform_get_irq(pdev, 1); - port->irq = platform_get_irq(pdev, 0); - if (port->irq < 0) { - err = -EINVAL; - goto out_iounmap; - } - - /* disable the interrupt and clear the status */ - writel(0, port->base + GPIO_IMR); - writel(~0, port->base + GPIO_ISR); - - if (mxc_gpio_hwtype == IMX21_GPIO) { - /* setup one handler for all GPIO interrupts */ - if (pdev->id == 0) - irq_set_chained_handler(port->irq, - mx2_gpio_irq_handler); - } else { - /* setup one handler for each entry */ - irq_set_chained_handler(port->irq, mx3_gpio_irq_handler); - irq_set_handler_data(port->irq, port); - if (port->irq_high > 0) { - /* setup handler for GPIO 16 to 31 */ - irq_set_chained_handler(port->irq_high, - mx3_gpio_irq_handler); - irq_set_handler_data(port->irq_high, port); - } - } - - err = bgpio_init(&port->bgc, &pdev->dev, 4, - port->base + GPIO_PSR, - port->base + GPIO_DR, NULL, - port->base + GPIO_GDIR, NULL, false); - if (err) - goto out_iounmap; - - port->bgc.gc.to_irq = mxc_gpio_to_irq; - port->bgc.gc.base = pdev->id * 32; - port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir); - port->bgc.data = port->bgc.read_reg(port->bgc.reg_set); - - err = gpiochip_add(&port->bgc.gc); - if (err) - goto out_bgpio_remove; - - /* - * In dt case, we use gpio number range dynamically - * allocated by gpio core. - */ - port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base : - pdev->id * 32); - - /* gpio-mxc can be a generic irq chip */ - mxc_gpio_init_gc(port); - - list_add_tail(&port->node, &mxc_gpio_ports); - - return 0; - -out_bgpio_remove: - bgpio_remove(&port->bgc); -out_iounmap: - iounmap(port->base); -out_release_mem: - release_mem_region(iores->start, resource_size(iores)); -out_kfree: - kfree(port); - dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); - return err; -} - -static struct platform_driver mxc_gpio_driver = { - .driver = { - .name = "gpio-mxc", - .owner = THIS_MODULE, - .of_match_table = mxc_gpio_dt_ids, - }, - .probe = mxc_gpio_probe, - .id_table = mxc_gpio_devtype, -}; - -static int __init gpio_mxc_init(void) -{ - return platform_driver_register(&mxc_gpio_driver); -} -postcore_initcall(gpio_mxc_init); - -MODULE_AUTHOR("Freescale Semiconductor, " - "Daniel Mack <danielncaiaq.de>, " - "Juergen Beisert <kernel@pengutronix.de>"); -MODULE_DESCRIPTION("Freescale MXC GPIO"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-mxs.c b/ANDROID_3.4.5/drivers/gpio/gpio-mxs.c deleted file mode 100644 index 385c58e8..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-mxs.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * Based on code from Freescale, - * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * 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/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/basic_mmio_gpio.h> -#include <linux/module.h> -#include <mach/mxs.h> - -#define MXS_SET 0x4 -#define MXS_CLR 0x8 - -#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) -#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) -#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10) -#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10) -#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10) -#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10) -#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10) -#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10) - -#define GPIO_INT_FALL_EDGE 0x0 -#define GPIO_INT_LOW_LEV 0x1 -#define GPIO_INT_RISE_EDGE 0x2 -#define GPIO_INT_HIGH_LEV 0x3 -#define GPIO_INT_LEV_MASK (1 << 0) -#define GPIO_INT_POL_MASK (1 << 1) - -#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) - -struct mxs_gpio_port { - void __iomem *base; - int id; - int irq; - int virtual_irq_start; - struct bgpio_chip bgc; -}; - -/* Note: This driver assumes 32 GPIOs are handled in one register */ - -static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) -{ - u32 gpio = irq_to_gpio(d->irq); - u32 pin_mask = 1 << (gpio & 31); - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mxs_gpio_port *port = gc->private; - void __iomem *pin_addr; - int edge; - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - edge = GPIO_INT_RISE_EDGE; - break; - case IRQ_TYPE_EDGE_FALLING: - edge = GPIO_INT_FALL_EDGE; - break; - case IRQ_TYPE_LEVEL_LOW: - edge = GPIO_INT_LOW_LEV; - break; - case IRQ_TYPE_LEVEL_HIGH: - edge = GPIO_INT_HIGH_LEV; - break; - default: - return -EINVAL; - } - - /* set level or edge */ - pin_addr = port->base + PINCTRL_IRQLEV(port->id); - if (edge & GPIO_INT_LEV_MASK) - writel(pin_mask, pin_addr + MXS_SET); - else - writel(pin_mask, pin_addr + MXS_CLR); - - /* set polarity */ - pin_addr = port->base + PINCTRL_IRQPOL(port->id); - if (edge & GPIO_INT_POL_MASK) - writel(pin_mask, pin_addr + MXS_SET); - else - writel(pin_mask, pin_addr + MXS_CLR); - - writel(1 << (gpio & 0x1f), - port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); - - return 0; -} - -/* MXS has one interrupt *per* gpio port */ -static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) -{ - u32 irq_stat; - struct mxs_gpio_port *port = irq_get_handler_data(irq); - u32 gpio_irq_no_base = port->virtual_irq_start; - - desc->irq_data.chip->irq_ack(&desc->irq_data); - - irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & - readl(port->base + PINCTRL_IRQEN(port->id)); - - while (irq_stat != 0) { - int irqoffset = fls(irq_stat) - 1; - generic_handle_irq(gpio_irq_no_base + irqoffset); - irq_stat &= ~(1 << irqoffset); - } -} - -/* - * Set interrupt number "irq" in the GPIO as a wake-up source. - * While system is running, all registered GPIO interrupts need to have - * wake-up enabled. When system is suspended, only selected GPIO interrupts - * need to have wake-up enabled. - * @param irq interrupt source number - * @param enable enable as wake-up if equal to non-zero - * @return This function returns 0 on success. - */ -static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mxs_gpio_port *port = gc->private; - - if (enable) - enable_irq_wake(port->irq); - else - disable_irq_wake(port->irq); - - return 0; -} - -static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start, - port->base, handle_level_irq); - gc->private = port; - - ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; - ct->chip.irq_set_type = mxs_gpio_set_irq_type; - ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; - ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; - ct->regs.mask = PINCTRL_IRQEN(port->id); - - irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); -} - -static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - struct mxs_gpio_port *port = - container_of(bgc, struct mxs_gpio_port, bgc); - - return port->virtual_irq_start + offset; -} - -static int __devinit mxs_gpio_probe(struct platform_device *pdev) -{ - static void __iomem *base; - struct mxs_gpio_port *port; - struct resource *iores = NULL; - int err; - - port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); - if (!port) - return -ENOMEM; - - port->id = pdev->id; - port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; - - /* - * map memory region only once, as all the gpio ports - * share the same one - */ - if (!base) { - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) { - err = -ENODEV; - goto out_kfree; - } - - if (!request_mem_region(iores->start, resource_size(iores), - pdev->name)) { - err = -EBUSY; - goto out_kfree; - } - - base = ioremap(iores->start, resource_size(iores)); - if (!base) { - err = -ENOMEM; - goto out_release_mem; - } - } - port->base = base; - - port->irq = platform_get_irq(pdev, 0); - if (port->irq < 0) { - err = -EINVAL; - goto out_iounmap; - } - - /* - * select the pin interrupt functionality but initially - * disable the interrupts - */ - writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id)); - writel(0, port->base + PINCTRL_IRQEN(port->id)); - - /* clear address has to be used to clear IRQSTAT bits */ - writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); - - /* gpio-mxs can be a generic irq chip */ - mxs_gpio_init_gc(port); - - /* setup one handler for each entry */ - irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); - irq_set_handler_data(port->irq, port); - - err = bgpio_init(&port->bgc, &pdev->dev, 4, - port->base + PINCTRL_DIN(port->id), - port->base + PINCTRL_DOUT(port->id), NULL, - port->base + PINCTRL_DOE(port->id), NULL, false); - if (err) - goto out_iounmap; - - port->bgc.gc.to_irq = mxs_gpio_to_irq; - port->bgc.gc.base = port->id * 32; - - err = gpiochip_add(&port->bgc.gc); - if (err) - goto out_bgpio_remove; - - return 0; - -out_bgpio_remove: - bgpio_remove(&port->bgc); -out_iounmap: - if (iores) - iounmap(port->base); -out_release_mem: - if (iores) - release_mem_region(iores->start, resource_size(iores)); -out_kfree: - kfree(port); - dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); - return err; -} - -static struct platform_driver mxs_gpio_driver = { - .driver = { - .name = "gpio-mxs", - .owner = THIS_MODULE, - }, - .probe = mxs_gpio_probe, -}; - -static int __init mxs_gpio_init(void) -{ - return platform_driver_register(&mxs_gpio_driver); -} -postcore_initcall(mxs_gpio_init); - -MODULE_AUTHOR("Freescale Semiconductor, " - "Daniel Mack <danielncaiaq.de>, " - "Juergen Beisert <kernel@pengutronix.de>"); -MODULE_DESCRIPTION("Freescale MXS GPIO"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-nomadik.c b/ANDROID_3.4.5/drivers/gpio/gpio-nomadik.c deleted file mode 100644 index 839624f9..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-nomadik.c +++ /dev/null @@ -1,1187 +0,0 @@ -/* - * Generic GPIO driver for logic cells found in the Nomadik SoC - * - * Copyright (C) 2008,2009 STMicroelectronics - * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> - * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> - * Copyright (C) 2011 Linus Walleij <linus.walleij@linaro.org> - * - * 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/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/gpio.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/slab.h> - -#include <asm/mach/irq.h> - -#include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> -#include <mach/hardware.h> -#include <asm/gpio.h> - -/* - * The GPIO module in the Nomadik family of Systems-on-Chip is an - * AMBA device, managing 32 pins and alternate functions. The logic block - * is currently used in the Nomadik and ux500. - * - * Symbols in this file are called "nmk_gpio" for "nomadik gpio" - */ - -#define NMK_GPIO_PER_CHIP 32 - -struct nmk_gpio_chip { - struct gpio_chip chip; - void __iomem *addr; - struct clk *clk; - unsigned int bank; - unsigned int parent_irq; - int secondary_parent_irq; - u32 (*get_secondary_status)(unsigned int bank); - void (*set_ioforce)(bool enable); - spinlock_t lock; - bool sleepmode; - /* Keep track of configured edges */ - u32 edge_rising; - u32 edge_falling; - u32 real_wake; - u32 rwimsc; - u32 fwimsc; - u32 slpm; - u32 pull_up; -}; - -static struct nmk_gpio_chip * -nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; - -static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); - -#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips) - -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; - nmk_chip->pull_up &= ~bit; - } else { - pdis &= ~bit; - } - - writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); - - if (pull == NMK_GPIO_PULL_UP) { - nmk_chip->pull_up |= bit; - writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - } else if (pull == NMK_GPIO_PULL_DOWN) { - nmk_chip->pull_up &= ~bit; - 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_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_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, - unsigned offset, int gpio_mode, - bool glitch) -{ - u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); - u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); - - if (glitch && nmk_chip->set_ioforce) { - u32 bit = BIT(offset); - - /* Prevent spurious wakeups */ - writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC); - writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC); - - nmk_chip->set_ioforce(true); - } - - __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode); - - if (glitch && nmk_chip->set_ioforce) { - nmk_chip->set_ioforce(false); - - writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC); - writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC); - } -} - -static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, - pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) -{ - 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/wakeup", - [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", - }; - - int pin = PIN_NUM(cfg); - 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); - bool glitch = af == NMK_GPIO_ALT_C; - - dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", - pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], - output ? "output " : "input", - output ? (val ? "high" : "low") : ""); - - if (sleep) { - int slpm_pull = PIN_SLPM_PULL(cfg); - int slpm_output = PIN_SLPM_DIR(cfg); - int slpm_val = PIN_SLPM_VAL(cfg); - - af = NMK_GPIO_ALT_GPIO; - - /* - * The SLPM_* values are normal values + 1 to allow zero to - * mean "same as normal". - */ - if (slpm_pull) - pull = slpm_pull - 1; - if (slpm_output) - output = slpm_output - 1; - if (slpm_val) - val = slpm_val - 1; - - dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", - pin, - slpm_pull ? pullnames[pull] : "same", - slpm_output ? (output ? "output" : "input") : "same", - slpm_val ? (val ? "high" : "low") : "same"); - } - - 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); - } - - /* - * If we've backed up the SLPM registers (glitch workaround), modify - * the backups since they will be restored. - */ - if (slpmregs) { - if (slpm == NMK_GPIO_SLPM_NOCHANGE) - slpmregs[nmk_chip->bank] |= BIT(offset); - else - slpmregs[nmk_chip->bank] &= ~BIT(offset); - } else - __nmk_gpio_set_slpm(nmk_chip, offset, slpm); - - __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch); -} - -/* - * Safe sequence used to switch IOs between GPIO and Alternate-C mode: - * - Save SLPM registers - * - Set SLPM=0 for the IOs you want to switch and others to 1 - * - Configure the GPIO registers for the IOs that are being switched - * - Set IOFORCE=1 - * - Modify the AFLSA/B registers for the IOs that are being switched - * - Set IOFORCE=0 - * - Restore SLPM registers - * - Any spurious wake up event during switch sequence to be ignored and - * cleared - */ -static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - unsigned int temp = slpm[i]; - - if (!chip) - break; - - clk_enable(chip->clk); - - slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); - writel(temp, chip->addr + NMK_GPIO_SLPC); - } -} - -static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - - if (!chip) - break; - - writel(slpm[i], chip->addr + NMK_GPIO_SLPC); - - clk_disable(chip->clk); - } -} - -static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) -{ - static unsigned int slpm[NUM_BANKS]; - unsigned long flags; - bool glitch = false; - int ret = 0; - int i; - - for (i = 0; i < num; i++) { - if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) { - glitch = true; - break; - } - } - - spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); - - if (glitch) { - memset(slpm, 0xff, sizeof(slpm)); - - for (i = 0; i < num; i++) { - int pin = PIN_NUM(cfgs[i]); - int offset = pin % NMK_GPIO_PER_CHIP; - - if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) - slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset); - } - - nmk_gpio_glitch_slpm_init(slpm); - } - - for (i = 0; i < num; i++) { - struct nmk_gpio_chip *nmk_chip; - int pin = PIN_NUM(cfgs[i]); - - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin)); - if (!nmk_chip) { - ret = -EINVAL; - break; - } - - clk_enable(nmk_chip->clk); - spin_lock(&nmk_chip->lock); - __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, - cfgs[i], sleep, glitch ? slpm : NULL); - spin_unlock(&nmk_chip->lock); - clk_disable(nmk_chip->clk); - } - - if (glitch) - nmk_gpio_glitch_slpm_restore(slpm); - - spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); - - return ret; -} - -/** - * 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, bool sleep) -{ - return __nmk_config_pins(&cfg, 1, sleep); -} -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) -{ - return __nmk_config_pins(cfgs, num, false); -} -EXPORT_SYMBOL(nmk_config_pins); - -int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num) -{ - return __nmk_config_pins(cfgs, num, true); -} -EXPORT_SYMBOL(nmk_config_pins_sleep); - -/** - * nmk_gpio_set_slpm() - configure the sleep mode of a pin - * @gpio: pin number - * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE, - * - * This register is actually in the pinmux layer, not the GPIO block itself. - * The GPIO1B_SLPM register defines the GPIO mode when SLEEP/DEEP-SLEEP - * mode is entered (i.e. when signal IOFORCE is HIGH by the platform code). - * Each GPIO can be configured to be forced into GPIO mode when IOFORCE is - * HIGH, overriding the normal setting defined by GPIO_AFSELx registers. - * When IOFORCE returns LOW (by software, after SLEEP/DEEP-SLEEP exit), - * the GPIOs return to the normal setting defined by GPIO_AFSELx registers. - * - * If @mode is NMK_GPIO_SLPM_INPUT, the corresponding GPIO is switched to GPIO - * mode when signal IOFORCE is HIGH (i.e. when SLEEP/DEEP-SLEEP mode is - * entered) regardless of the altfunction selected. Also wake-up detection is - * ENABLED. - * - * If @mode is NMK_GPIO_SLPM_NOCHANGE, the corresponding GPIO remains - * controlled by NMK_GPIO_DATC, NMK_GPIO_DATS, NMK_GPIO_DIR, NMK_GPIO_PDIS - * (for altfunction GPIO) or respective on-chip peripherals (for other - * altfuncs) when IOFORCE is HIGH. Also wake-up detection DISABLED. - * - * Note that enable_irq_wake() will automatically enable wakeup detection. - */ -int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) -{ - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - clk_enable(nmk_chip->clk); - spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); - spin_lock(&nmk_chip->lock); - - __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); - - spin_unlock(&nmk_chip->lock); - spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); - clk_disable(nmk_chip->clk); - - 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 = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - clk_enable(nmk_chip->clk); - 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); - clk_disable(nmk_chip->clk); - - return 0; -} - -/* Mode functions */ -/** - * nmk_gpio_set_mode() - set the mux mode of a gpio pin - * @gpio: pin number - * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A, - * NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C - * - * Sets the mode of the specified pin to one of the alternate functions or - * plain GPIO. - */ -int nmk_gpio_set_mode(int gpio, int gpio_mode) -{ - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - clk_enable(nmk_chip->clk); - spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); - spin_unlock_irqrestore(&nmk_chip->lock, flags); - clk_disable(nmk_chip->clk); - - return 0; -} -EXPORT_SYMBOL(nmk_gpio_set_mode); - -int nmk_gpio_get_mode(int gpio) -{ - struct nmk_gpio_chip *nmk_chip; - u32 afunc, bfunc, bit; - - nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - bit = 1 << (gpio - nmk_chip->chip.base); - - clk_enable(nmk_chip->clk); - - afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; - bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; - - clk_disable(nmk_chip->clk); - - return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); -} -EXPORT_SYMBOL(nmk_gpio_get_mode); - - -/* IRQ functions */ -static inline int nmk_gpio_get_bitmask(int gpio) -{ - return 1 << (gpio % 32); -} - -static void nmk_gpio_irq_ack(struct irq_data *d) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); - nmk_chip = irq_data_get_irq_chip_data(d); - if (!nmk_chip) - return; - - clk_enable(nmk_chip->clk); - writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); - clk_disable(nmk_chip->clk); -} - -enum nmk_gpio_irq_type { - NORMAL, - WAKE, -}; - -static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, - 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 + rimsc); - if (enable) - reg |= bitmask; - else - reg &= ~bitmask; - writel(reg, nmk_chip->addr + rimsc); - } - if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + fimsc); - if (enable) - reg |= bitmask; - else - reg &= ~bitmask; - writel(reg, nmk_chip->addr + fimsc); - } -} - -static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, - int gpio, bool on) -{ - if (nmk_chip->sleepmode) { - __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, - on ? NMK_GPIO_SLPM_WAKEUP_ENABLE - : NMK_GPIO_SLPM_WAKEUP_DISABLE); - } - - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); -} - -static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask; - - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); - nmk_chip = irq_data_get_irq_chip_data(d); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return -EINVAL; - - clk_enable(nmk_chip->clk); - spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); - spin_lock(&nmk_chip->lock); - - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable); - - if (!(nmk_chip->real_wake & bitmask)) - __nmk_gpio_set_wake(nmk_chip, gpio, enable); - - spin_unlock(&nmk_chip->lock); - spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); - clk_disable(nmk_chip->clk); - - return 0; -} - -static void nmk_gpio_irq_mask(struct irq_data *d) -{ - nmk_gpio_irq_maskunmask(d, false); -} - -static void nmk_gpio_irq_unmask(struct irq_data *d) -{ - nmk_gpio_irq_maskunmask(d, true); -} - -static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) -{ - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask; - int gpio; - - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); - nmk_chip = irq_data_get_irq_chip_data(d); - if (!nmk_chip) - return -EINVAL; - bitmask = nmk_gpio_get_bitmask(gpio); - - clk_enable(nmk_chip->clk); - spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); - spin_lock(&nmk_chip->lock); - - if (irqd_irq_disabled(d)) - __nmk_gpio_set_wake(nmk_chip, gpio, on); - - if (on) - nmk_chip->real_wake |= bitmask; - else - nmk_chip->real_wake &= ~bitmask; - - spin_unlock(&nmk_chip->lock); - spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); - clk_disable(nmk_chip->clk); - - return 0; -} - -static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) -{ - bool enabled = !irqd_irq_disabled(d); - bool wake = irqd_is_wakeup_set(d); - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask; - - gpio = NOMADIK_IRQ_TO_GPIO(d->irq); - nmk_chip = irq_data_get_irq_chip_data(d); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return -EINVAL; - - if (type & IRQ_TYPE_LEVEL_HIGH) - return -EINVAL; - if (type & IRQ_TYPE_LEVEL_LOW) - return -EINVAL; - - clk_enable(nmk_chip->clk); - spin_lock_irqsave(&nmk_chip->lock, flags); - - if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); - - if (enabled || wake) - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); - - nmk_chip->edge_rising &= ~bitmask; - if (type & IRQ_TYPE_EDGE_RISING) - nmk_chip->edge_rising |= bitmask; - - nmk_chip->edge_falling &= ~bitmask; - if (type & IRQ_TYPE_EDGE_FALLING) - nmk_chip->edge_falling |= bitmask; - - if (enabled) - __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); - - if (enabled || wake) - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); - - spin_unlock_irqrestore(&nmk_chip->lock, flags); - clk_disable(nmk_chip->clk); - - return 0; -} - -static unsigned int nmk_gpio_irq_startup(struct irq_data *d) -{ - struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); - - clk_enable(nmk_chip->clk); - nmk_gpio_irq_unmask(d); - return 0; -} - -static void nmk_gpio_irq_shutdown(struct irq_data *d) -{ - struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); - - nmk_gpio_irq_mask(d); - clk_disable(nmk_chip->clk); -} - -static struct irq_chip nmk_gpio_irq_chip = { - .name = "Nomadik-GPIO", - .irq_ack = nmk_gpio_irq_ack, - .irq_mask = nmk_gpio_irq_mask, - .irq_unmask = nmk_gpio_irq_unmask, - .irq_set_type = nmk_gpio_irq_set_type, - .irq_set_wake = nmk_gpio_irq_set_wake, - .irq_startup = nmk_gpio_irq_startup, - .irq_shutdown = nmk_gpio_irq_shutdown, -}; - -static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, - u32 status) -{ - struct nmk_gpio_chip *nmk_chip; - struct irq_chip *host_chip = irq_get_chip(irq); - unsigned int first_irq; - - chained_irq_enter(host_chip, desc); - - nmk_chip = irq_get_handler_data(irq); - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - while (status) { - int bit = __ffs(status); - - generic_handle_irq(first_irq + bit); - status &= ~BIT(bit); - } - - chained_irq_exit(host_chip, desc); -} - -static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); - u32 status; - - clk_enable(nmk_chip->clk); - status = readl(nmk_chip->addr + NMK_GPIO_IS); - clk_disable(nmk_chip->clk); - - __nmk_gpio_irq_handler(irq, desc, status); -} - -static void nmk_gpio_secondary_irq_handler(unsigned int irq, - struct irq_desc *desc) -{ - struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); - u32 status = nmk_chip->get_secondary_status(nmk_chip->bank); - - __nmk_gpio_irq_handler(irq, desc, status); -} - -static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) -{ - unsigned int first_irq; - int i; - - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) { - irq_set_chip_and_handler(i, &nmk_gpio_irq_chip, - handle_edge_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, nmk_chip); - irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING); - } - - irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); - irq_set_handler_data(nmk_chip->parent_irq, nmk_chip); - - if (nmk_chip->secondary_parent_irq >= 0) { - irq_set_chained_handler(nmk_chip->secondary_parent_irq, - nmk_gpio_secondary_irq_handler); - irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip); - } - - return 0; -} - -/* I/O Functions */ -static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - clk_enable(nmk_chip->clk); - - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); - - clk_disable(nmk_chip->clk); - - return 0; -} - -static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - u32 bit = 1 << offset; - int value; - - clk_enable(nmk_chip->clk); - - value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; - - clk_disable(nmk_chip->clk); - - return value; -} - -static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - clk_enable(nmk_chip->clk); - - __nmk_gpio_set_output(nmk_chip, offset, val); - - clk_disable(nmk_chip->clk); -} - -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); - - clk_enable(nmk_chip->clk); - - __nmk_gpio_make_output(nmk_chip, offset, val); - - clk_disable(nmk_chip->clk); - - 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; -} - -#ifdef CONFIG_DEBUG_FS - -#include <linux/seq_file.h> - -static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - int mode; - unsigned i; - unsigned gpio = chip->base; - int is_out; - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - const char *modes[] = { - [NMK_GPIO_ALT_GPIO] = "gpio", - [NMK_GPIO_ALT_A] = "altA", - [NMK_GPIO_ALT_B] = "altB", - [NMK_GPIO_ALT_C] = "altC", - }; - - clk_enable(nmk_chip->clk); - - for (i = 0; i < chip->ngpio; i++, gpio++) { - const char *label = gpiochip_is_requested(chip, i); - bool pull; - u32 bit = 1 << i; - - is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit; - pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); - mode = nmk_gpio_get_mode(gpio); - seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", - gpio, label ?: "(none)", - is_out ? "out" : "in ", - chip->get - ? (chip->get(chip, i) ? "hi" : "lo") - : "? ", - (mode < 0) ? "unknown" : modes[mode], - pull ? "pull" : "none"); - - if (label && !is_out) { - int irq = gpio_to_irq(gpio); - struct irq_desc *desc = irq_to_desc(irq); - - /* This races with request_irq(), set_irq_type(), - * and set_irq_wake() ... but those are "rare". - */ - if (irq >= 0 && desc->action) { - char *trigger; - u32 bitmask = nmk_gpio_get_bitmask(gpio); - - if (nmk_chip->edge_rising & bitmask) - trigger = "edge-rising"; - else if (nmk_chip->edge_falling & bitmask) - trigger = "edge-falling"; - else - trigger = "edge-undefined"; - - seq_printf(s, " irq-%d %s%s", - irq, trigger, - irqd_is_wakeup_set(&desc->irq_data) - ? " wakeup" : ""); - } - } - - seq_printf(s, "\n"); - } - - clk_disable(nmk_chip->clk); -} - -#else -#define nmk_gpio_dbg_show NULL -#endif - -/* 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, - .dbg_show = nmk_gpio_dbg_show, - .can_sleep = 0, -}; - -void nmk_gpio_clocks_enable(void) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - - if (!chip) - continue; - - clk_enable(chip->clk); - } -} - -void nmk_gpio_clocks_disable(void) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - - if (!chip) - continue; - - clk_disable(chip->clk); - } -} - -/* - * Called from the suspend/resume path to only keep the real wakeup interrupts - * (those that have had set_irq_wake() called on them) as wakeup interrupts, - * and not the rest of the interrupts which we needed to have as wakeups for - * cpuidle. - * - * PM ops are not used since this needs to be done at the end, after all the - * other drivers are done with their suspend callbacks. - */ -void nmk_gpio_wakeups_suspend(void) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - - if (!chip) - break; - - clk_enable(chip->clk); - - chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); - chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); - - writel(chip->rwimsc & chip->real_wake, - chip->addr + NMK_GPIO_RWIMSC); - writel(chip->fwimsc & chip->real_wake, - chip->addr + NMK_GPIO_FWIMSC); - - if (chip->sleepmode) { - chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); - - /* 0 -> wakeup enable */ - writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); - } - - clk_disable(chip->clk); - } -} - -void nmk_gpio_wakeups_resume(void) -{ - int i; - - for (i = 0; i < NUM_BANKS; i++) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; - - if (!chip) - break; - - clk_enable(chip->clk); - - writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); - writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); - - if (chip->sleepmode) - writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); - - clk_disable(chip->clk); - } -} - -/* - * Read the pull up/pull down status. - * A bit set in 'pull_up' means that pull up - * is selected if pull is enabled in PDIS register. - * Note: only pull up/down set via this driver can - * be detected due to HW limitations. - */ -void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) -{ - if (gpio_bank < NUM_BANKS) { - struct nmk_gpio_chip *chip = nmk_gpio_chips[gpio_bank]; - - if (!chip) - return; - - *pull_up = chip->pull_up; - } -} - -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; - struct gpio_chip *chip; - struct resource *res; - struct clk *clk; - int secondary_irq; - int irq; - int ret; - - if (!pdata) - return -ENODEV; - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto out; - } - - irq = platform_get_irq(dev, 0); - if (irq < 0) { - ret = irq; - goto out; - } - - secondary_irq = platform_get_irq(dev, 1); - if (secondary_irq >= 0 && !pdata->get_secondary_status) { - ret = -EINVAL; - goto out; - } - - if (request_mem_region(res->start, resource_size(res), - dev_name(&dev->dev)) == NULL) { - ret = -EBUSY; - goto out; - } - - clk = clk_get(&dev->dev, NULL); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto out_release; - } - - nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); - if (!nmk_chip) { - ret = -ENOMEM; - goto out_clk; - } - /* - * The virt address in nmk_chip->addr is in the nomadik register space, - * so we can simply convert the resource address, without remapping - */ - nmk_chip->bank = dev->id; - nmk_chip->clk = clk; - nmk_chip->addr = io_p2v(res->start); - nmk_chip->chip = nmk_gpio_template; - nmk_chip->parent_irq = irq; - nmk_chip->secondary_parent_irq = secondary_irq; - nmk_chip->get_secondary_status = pdata->get_secondary_status; - nmk_chip->set_ioforce = pdata->set_ioforce; - nmk_chip->sleepmode = pdata->supports_sleepmode; - spin_lock_init(&nmk_chip->lock); - - chip = &nmk_chip->chip; - chip->base = pdata->first_gpio; - chip->ngpio = pdata->num_gpio; - chip->label = pdata->name ?: dev_name(&dev->dev); - chip->dev = &dev->dev; - chip->owner = THIS_MODULE; - - ret = gpiochip_add(&nmk_chip->chip); - if (ret) - goto out_free; - - BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); - - nmk_gpio_chips[nmk_chip->bank] = nmk_chip; - platform_set_drvdata(dev, nmk_chip); - - nmk_gpio_init_irq(nmk_chip); - - dev_info(&dev->dev, "at address %p\n", - nmk_chip->addr); - return 0; - -out_free: - kfree(nmk_chip); -out_clk: - clk_disable(clk); - clk_put(clk); -out_release: - release_mem_region(res->start, resource_size(res)); -out: - dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, - pdata->first_gpio, pdata->first_gpio+31); - return ret; -} - -static struct platform_driver nmk_gpio_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "gpio", - }, - .probe = nmk_gpio_probe, -}; - -static int __init nmk_gpio_init(void) -{ - return platform_driver_register(&nmk_gpio_driver); -} - -core_initcall(nmk_gpio_init); - -MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); -MODULE_DESCRIPTION("Nomadik GPIO Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-omap.c b/ANDROID_3.4.5/drivers/gpio/gpio-omap.c deleted file mode 100644 index 44615406..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-omap.c +++ /dev/null @@ -1,1545 +0,0 @@ -/* - * Support functions for OMAP GPIO - * - * Copyright (C) 2003-2005 Nokia Corporation - * Written by Juha Yrjölä <juha.yrjola@nokia.com> - * - * Copyright (C) 2009 Texas Instruments - * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> - * - * 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/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/syscore_ops.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/device.h> -#include <linux/pm_runtime.h> -#include <linux/pm.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/irqdomain.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <asm/gpio.h> -#include <asm/mach/irq.h> - -#define OFF_MODE 1 - -static LIST_HEAD(omap_gpio_list); - -struct gpio_regs { - u32 irqenable1; - u32 irqenable2; - u32 wake_en; - u32 ctrl; - u32 oe; - u32 leveldetect0; - u32 leveldetect1; - u32 risingdetect; - u32 fallingdetect; - u32 dataout; - u32 debounce; - u32 debounce_en; -}; - -struct gpio_bank { - struct list_head node; - void __iomem *base; - u16 irq; - int irq_base; - struct irq_domain *domain; - u32 suspend_wakeup; - u32 saved_wakeup; - u32 non_wakeup_gpios; - u32 enabled_non_wakeup_gpios; - struct gpio_regs context; - u32 saved_datain; - u32 saved_fallingdetect; - u32 saved_risingdetect; - u32 level_mask; - u32 toggle_mask; - spinlock_t lock; - struct gpio_chip chip; - struct clk *dbck; - u32 mod_usage; - u32 dbck_enable_mask; - bool dbck_enabled; - struct device *dev; - bool is_mpuio; - bool dbck_flag; - bool loses_context; - int stride; - u32 width; - int context_loss_count; - int power_mode; - bool workaround_enabled; - - void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); - int (*get_context_loss_count)(struct device *dev); - - struct omap_gpio_reg_offs *regs; -}; - -#define GPIO_INDEX(bank, gpio) (gpio % bank->width) -#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) -#define GPIO_MOD_CTRL_BIT BIT(0) - -static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) -{ - return gpio_irq - bank->irq_base + bank->chip.base; -} - -static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) -{ - void __iomem *reg = bank->base; - u32 l; - - reg += bank->regs->direction; - l = __raw_readl(reg); - if (is_input) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); - bank->context.oe = l; -} - - -/* set data out value using dedicate set/clear register */ -static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable) -{ - void __iomem *reg = bank->base; - u32 l = GPIO_BIT(bank, gpio); - - if (enable) { - reg += bank->regs->set_dataout; - bank->context.dataout |= l; - } else { - reg += bank->regs->clr_dataout; - bank->context.dataout &= ~l; - } - - __raw_writel(l, reg); -} - -/* set data out value using mask register */ -static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable) -{ - void __iomem *reg = bank->base + bank->regs->dataout; - u32 gpio_bit = GPIO_BIT(bank, gpio); - u32 l; - - l = __raw_readl(reg); - if (enable) - l |= gpio_bit; - else - l &= ~gpio_bit; - __raw_writel(l, reg); - bank->context.dataout = l; -} - -static int _get_gpio_datain(struct gpio_bank *bank, int offset) -{ - void __iomem *reg = bank->base + bank->regs->datain; - - return (__raw_readl(reg) & (1 << offset)) != 0; -} - -static int _get_gpio_dataout(struct gpio_bank *bank, int offset) -{ - void __iomem *reg = bank->base + bank->regs->dataout; - - return (__raw_readl(reg) & (1 << offset)) != 0; -} - -static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) -{ - int l = __raw_readl(base + reg); - - if (set) - l |= mask; - else - l &= ~mask; - - __raw_writel(l, base + reg); -} - -static inline void _gpio_dbck_enable(struct gpio_bank *bank) -{ - if (bank->dbck_enable_mask && !bank->dbck_enabled) { - clk_enable(bank->dbck); - bank->dbck_enabled = true; - } -} - -static inline void _gpio_dbck_disable(struct gpio_bank *bank) -{ - if (bank->dbck_enable_mask && bank->dbck_enabled) { - clk_disable(bank->dbck); - bank->dbck_enabled = false; - } -} - -/** - * _set_gpio_debounce - low level gpio debounce time - * @bank: the gpio bank we're acting upon - * @gpio: the gpio number on this @gpio - * @debounce: debounce time to use - * - * OMAP's debounce time is in 31us steps so we need - * to convert and round up to the closest unit. - */ -static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, - unsigned debounce) -{ - void __iomem *reg; - u32 val; - u32 l; - - if (!bank->dbck_flag) - return; - - if (debounce < 32) - debounce = 0x01; - else if (debounce > 7936) - debounce = 0xff; - else - debounce = (debounce / 0x1f) - 1; - - l = GPIO_BIT(bank, gpio); - - clk_enable(bank->dbck); - reg = bank->base + bank->regs->debounce; - __raw_writel(debounce, reg); - - reg = bank->base + bank->regs->debounce_en; - val = __raw_readl(reg); - - if (debounce) - val |= l; - else - val &= ~l; - bank->dbck_enable_mask = val; - - __raw_writel(val, reg); - clk_disable(bank->dbck); - /* - * Enable debounce clock per module. - * This call is mandatory because in omap_gpio_request() when - * *_runtime_get_sync() is called, _gpio_dbck_enable() within - * runtime callbck fails to turn on dbck because dbck_enable_mask - * used within _gpio_dbck_enable() is still not initialized at - * that point. Therefore we have to enable dbck here. - */ - _gpio_dbck_enable(bank); - if (bank->dbck_enable_mask) { - bank->context.debounce = debounce; - bank->context.debounce_en = val; - } -} - -static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, - unsigned trigger) -{ - void __iomem *base = bank->base; - u32 gpio_bit = 1 << gpio; - - _gpio_rmw(base, bank->regs->leveldetect0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - _gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - _gpio_rmw(base, bank->regs->risingdetect, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - _gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); - - bank->context.leveldetect0 = - __raw_readl(bank->base + bank->regs->leveldetect0); - bank->context.leveldetect1 = - __raw_readl(bank->base + bank->regs->leveldetect1); - bank->context.risingdetect = - __raw_readl(bank->base + bank->regs->risingdetect); - bank->context.fallingdetect = - __raw_readl(bank->base + bank->regs->fallingdetect); - - if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { - _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); - bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - } - - /* This part needs to be executed always for OMAP{34xx, 44xx} */ - if (!bank->regs->irqctrl) { - /* On omap24xx proceed only when valid GPIO bit is set */ - if (bank->non_wakeup_gpios) { - if (!(bank->non_wakeup_gpios & gpio_bit)) - goto exit; - } - - /* - * Log the edge gpio and manually trigger the IRQ - * after resume if the input level changes - * to avoid irq lost during PER RET/OFF mode - * Applies for omap2 non-wakeup gpio and all omap3 gpios - */ - if (trigger & IRQ_TYPE_EDGE_BOTH) - bank->enabled_non_wakeup_gpios |= gpio_bit; - else - bank->enabled_non_wakeup_gpios &= ~gpio_bit; - } - -exit: - bank->level_mask = - __raw_readl(bank->base + bank->regs->leveldetect0) | - __raw_readl(bank->base + bank->regs->leveldetect1); -} - -#ifdef CONFIG_ARCH_OMAP1 -/* - * This only applies to chips that can't do both rising and falling edge - * detection at once. For all other chips, this function is a noop. - */ -static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) -{ - void __iomem *reg = bank->base; - u32 l = 0; - - if (!bank->regs->irqctrl) - return; - - reg += bank->regs->irqctrl; - - l = __raw_readl(reg); - if ((l >> gpio) & 1) - l &= ~(1 << gpio); - else - l |= 1 << gpio; - - __raw_writel(l, reg); -} -#else -static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} -#endif - -static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, - unsigned trigger) -{ - void __iomem *reg = bank->base; - void __iomem *base = bank->base; - u32 l = 0; - - if (bank->regs->leveldetect0 && bank->regs->wkup_en) { - set_gpio_trigger(bank, gpio, trigger); - } else if (bank->regs->irqctrl) { - reg += bank->regs->irqctrl; - - l = __raw_readl(reg); - if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) - bank->toggle_mask |= 1 << gpio; - if (trigger & IRQ_TYPE_EDGE_RISING) - l |= 1 << gpio; - else if (trigger & IRQ_TYPE_EDGE_FALLING) - l &= ~(1 << gpio); - else - return -EINVAL; - - __raw_writel(l, reg); - } else if (bank->regs->edgectrl1) { - if (gpio & 0x08) - reg += bank->regs->edgectrl2; - else - reg += bank->regs->edgectrl1; - - gpio &= 0x07; - l = __raw_readl(reg); - l &= ~(3 << (gpio << 1)); - if (trigger & IRQ_TYPE_EDGE_RISING) - l |= 2 << (gpio << 1); - if (trigger & IRQ_TYPE_EDGE_FALLING) - l |= 1 << (gpio << 1); - - /* Enable wake-up during idle for dynamic tick */ - _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); - bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - __raw_writel(l, reg); - } - return 0; -} - -static int gpio_irq_type(struct irq_data *d, unsigned type) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned gpio; - int retval; - unsigned long flags; - - if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE) - gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE); - else - gpio = irq_to_gpio(bank, d->irq); - - if (type & ~IRQ_TYPE_SENSE_MASK) - return -EINVAL; - - if (!bank->regs->leveldetect0 && - (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) - return -EINVAL; - - spin_lock_irqsave(&bank->lock, flags); - retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type); - spin_unlock_irqrestore(&bank->lock, flags); - - if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __irq_set_handler_locked(d->irq, handle_level_irq); - else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - __irq_set_handler_locked(d->irq, handle_edge_irq); - - return retval; -} - -static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) -{ - void __iomem *reg = bank->base; - - reg += bank->regs->irqstatus; - __raw_writel(gpio_mask, reg); - - /* Workaround for clearing DSP GPIO interrupts to allow retention */ - if (bank->regs->irqstatus2) { - reg = bank->base + bank->regs->irqstatus2; - __raw_writel(gpio_mask, reg); - } - - /* Flush posted write for the irq status to avoid spurious interrupts */ - __raw_readl(reg); -} - -static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) -{ - _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); -} - -static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) -{ - void __iomem *reg = bank->base; - u32 l; - u32 mask = (1 << bank->width) - 1; - - reg += bank->regs->irqenable; - l = __raw_readl(reg); - if (bank->regs->irqenable_inv) - l = ~l; - l &= mask; - return l; -} - -static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) -{ - void __iomem *reg = bank->base; - u32 l; - - if (bank->regs->set_irqenable) { - reg += bank->regs->set_irqenable; - l = gpio_mask; - bank->context.irqenable1 |= gpio_mask; - } else { - reg += bank->regs->irqenable; - l = __raw_readl(reg); - if (bank->regs->irqenable_inv) - l &= ~gpio_mask; - else - l |= gpio_mask; - bank->context.irqenable1 = l; - } - - __raw_writel(l, reg); -} - -static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) -{ - void __iomem *reg = bank->base; - u32 l; - - if (bank->regs->clr_irqenable) { - reg += bank->regs->clr_irqenable; - l = gpio_mask; - bank->context.irqenable1 &= ~gpio_mask; - } else { - reg += bank->regs->irqenable; - l = __raw_readl(reg); - if (bank->regs->irqenable_inv) - l |= gpio_mask; - else - l &= ~gpio_mask; - bank->context.irqenable1 = l; - } - - __raw_writel(l, reg); -} - -static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) -{ - if (enable) - _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); - else - _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); -} - -/* - * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register. - * 1510 does not seem to have a wake-up register. If JTAG is connected - * to the target, system will wake up always on GPIO events. While - * system is running all registered GPIO interrupts need to have wake-up - * enabled. When system is suspended, only selected GPIO interrupts need - * to have wake-up enabled. - */ -static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) -{ - u32 gpio_bit = GPIO_BIT(bank, gpio); - unsigned long flags; - - if (bank->non_wakeup_gpios & gpio_bit) { - dev_err(bank->dev, - "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio); - return -EINVAL; - } - - spin_lock_irqsave(&bank->lock, flags); - if (enable) - bank->suspend_wakeup |= gpio_bit; - else - bank->suspend_wakeup &= ~gpio_bit; - - __raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static void _reset_gpio(struct gpio_bank *bank, int gpio) -{ - _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1); - _set_gpio_irqenable(bank, gpio, 0); - _clear_gpio_irqstatus(bank, gpio); - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); -} - -/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ -static int gpio_wake_enable(struct irq_data *d, unsigned int enable) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); - - return _set_gpio_wakeup(bank, gpio, enable); -} - -static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); - unsigned long flags; - - /* - * If this is the first gpio_request for the bank, - * enable the bank module. - */ - if (!bank->mod_usage) - pm_runtime_get_sync(bank->dev); - - spin_lock_irqsave(&bank->lock, flags); - /* Set trigger to none. You need to enable the desired trigger with - * request_irq() or set_irq_type(). - */ - _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); - - if (bank->regs->pinctrl) { - void __iomem *reg = bank->base + bank->regs->pinctrl; - - /* Claim the pin for MPU */ - __raw_writel(__raw_readl(reg) | (1 << offset), reg); - } - - if (bank->regs->ctrl && !bank->mod_usage) { - void __iomem *reg = bank->base + bank->regs->ctrl; - u32 ctrl; - - ctrl = __raw_readl(reg); - /* Module is enabled, clocks are not gated */ - ctrl &= ~GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); - bank->context.ctrl = ctrl; - } - - bank->mod_usage |= 1 << offset; - - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); - void __iomem *base = bank->base; - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - - if (bank->regs->wkup_en) { - /* Disable wake-up during idle for dynamic tick */ - _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); - bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - } - - bank->mod_usage &= ~(1 << offset); - - if (bank->regs->ctrl && !bank->mod_usage) { - void __iomem *reg = bank->base + bank->regs->ctrl; - u32 ctrl; - - ctrl = __raw_readl(reg); - /* Module is disabled, clocks are gated */ - ctrl |= GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); - bank->context.ctrl = ctrl; - } - - _reset_gpio(bank, bank->chip.base + offset); - spin_unlock_irqrestore(&bank->lock, flags); - - /* - * If this is the last gpio to be freed in the bank, - * disable the bank module. - */ - if (!bank->mod_usage) - pm_runtime_put(bank->dev); -} - -/* - * We need to unmask the GPIO bank interrupt as soon as possible to - * avoid missing GPIO interrupts for other lines in the bank. - * Then we need to mask-read-clear-unmask the triggered GPIO lines - * in the bank to avoid missing nested interrupts for a GPIO line. - * If we wait to unmask individual GPIO lines in the bank after the - * line's interrupt handler has been run, we may miss some nested - * interrupts. - */ -static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - void __iomem *isr_reg = NULL; - u32 isr; - unsigned int gpio_irq, gpio_index; - struct gpio_bank *bank; - u32 retrigger = 0; - int unmasked = 0; - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - bank = irq_get_handler_data(irq); - isr_reg = bank->base + bank->regs->irqstatus; - pm_runtime_get_sync(bank->dev); - - if (WARN_ON(!isr_reg)) - goto exit; - - while(1) { - u32 isr_saved, level_mask = 0; - u32 enabled; - - enabled = _get_gpio_irqbank_mask(bank); - isr_saved = isr = __raw_readl(isr_reg) & enabled; - - if (bank->level_mask) - level_mask = bank->level_mask & enabled; - - /* clear edge sensitive interrupts before handler(s) are - called so that we don't miss any interrupt occurred while - executing them */ - _disable_gpio_irqbank(bank, isr_saved & ~level_mask); - _clear_gpio_irqbank(bank, isr_saved & ~level_mask); - _enable_gpio_irqbank(bank, isr_saved & ~level_mask); - - /* if there is only edge sensitive GPIO pin interrupts - configured, we could unmask GPIO bank interrupt immediately */ - if (!level_mask && !unmasked) { - unmasked = 1; - chained_irq_exit(chip, desc); - } - - isr |= retrigger; - retrigger = 0; - if (!isr) - break; - - gpio_irq = bank->irq_base; - for (; isr != 0; isr >>= 1, gpio_irq++) { - int gpio = irq_to_gpio(bank, gpio_irq); - - if (!(isr & 1)) - continue; - - gpio_index = GPIO_INDEX(bank, gpio); - - /* - * Some chips can't respond to both rising and falling - * at the same time. If this irq was requested with - * both flags, we need to flip the ICR data for the IRQ - * to respond to the IRQ for the opposite direction. - * This will be indicated in the bank toggle_mask. - */ - if (bank->toggle_mask & (1 << gpio_index)) - _toggle_gpio_edge_triggering(bank, gpio_index); - - generic_handle_irq(gpio_irq); - } - } - /* if bank has any level sensitive GPIO pin interrupt - configured, we must unmask the bank interrupt only after - handler(s) are executed in order to avoid spurious bank - interrupt */ -exit: - if (!unmasked) - chained_irq_exit(chip, desc); - pm_runtime_put(bank->dev); -} - -static void gpio_irq_shutdown(struct irq_data *d) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - _reset_gpio(bank, gpio); - spin_unlock_irqrestore(&bank->lock, flags); -} - -static void gpio_ack_irq(struct irq_data *d) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); - - _clear_gpio_irqstatus(bank, gpio); -} - -static void gpio_mask_irq(struct irq_data *d) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_irqenable(bank, gpio, 0); - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); - spin_unlock_irqrestore(&bank->lock, flags); -} - -static void gpio_unmask_irq(struct irq_data *d) -{ - struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); - unsigned int irq_mask = GPIO_BIT(bank, gpio); - u32 trigger = irqd_get_trigger_type(d); - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - if (trigger) - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); - - /* For level-triggered GPIOs, the clearing must be done after - * the HW source is cleared, thus after the handler has run */ - if (bank->level_mask & irq_mask) { - _set_gpio_irqenable(bank, gpio, 0); - _clear_gpio_irqstatus(bank, gpio); - } - - _set_gpio_irqenable(bank, gpio, 1); - spin_unlock_irqrestore(&bank->lock, flags); -} - -static struct irq_chip gpio_irq_chip = { - .name = "GPIO", - .irq_shutdown = gpio_irq_shutdown, - .irq_ack = gpio_ack_irq, - .irq_mask = gpio_mask_irq, - .irq_unmask = gpio_unmask_irq, - .irq_set_type = gpio_irq_type, - .irq_set_wake = gpio_wake_enable, -}; - -/*---------------------------------------------------------------------*/ - -static int omap_mpuio_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *mask_reg = bank->base + - OMAP_MPUIO_GPIO_MASKIT / bank->stride; - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - bank->saved_wakeup = __raw_readl(mask_reg); - __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static int omap_mpuio_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *mask_reg = bank->base + - OMAP_MPUIO_GPIO_MASKIT / bank->stride; - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - __raw_writel(bank->saved_wakeup, mask_reg); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static const struct dev_pm_ops omap_mpuio_dev_pm_ops = { - .suspend_noirq = omap_mpuio_suspend_noirq, - .resume_noirq = omap_mpuio_resume_noirq, -}; - -/* use platform_driver for this. */ -static struct platform_driver omap_mpuio_driver = { - .driver = { - .name = "mpuio", - .pm = &omap_mpuio_dev_pm_ops, - }, -}; - -static struct platform_device omap_mpuio_device = { - .name = "mpuio", - .id = -1, - .dev = { - .driver = &omap_mpuio_driver.driver, - } - /* could list the /proc/iomem resources */ -}; - -static inline void mpuio_init(struct gpio_bank *bank) -{ - platform_set_drvdata(&omap_mpuio_device, bank); - - if (platform_driver_register(&omap_mpuio_driver) == 0) - (void) platform_device_register(&omap_mpuio_device); -} - -/*---------------------------------------------------------------------*/ - -static int gpio_input(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank; - unsigned long flags; - - bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_direction(bank, offset, 1); - spin_unlock_irqrestore(&bank->lock, flags); - return 0; -} - -static int gpio_is_input(struct gpio_bank *bank, int mask) -{ - void __iomem *reg = bank->base + bank->regs->direction; - - return __raw_readl(reg) & mask; -} - -static int gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank; - u32 mask; - - bank = container_of(chip, struct gpio_bank, chip); - mask = (1 << offset); - - if (gpio_is_input(bank, mask)) - return _get_gpio_datain(bank, offset); - else - return _get_gpio_dataout(bank, offset); -} - -static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) -{ - struct gpio_bank *bank; - unsigned long flags; - - bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); - bank->set_dataout(bank, offset, value); - _set_gpio_direction(bank, offset, 0); - spin_unlock_irqrestore(&bank->lock, flags); - return 0; -} - -static int gpio_debounce(struct gpio_chip *chip, unsigned offset, - unsigned debounce) -{ - struct gpio_bank *bank; - unsigned long flags; - - bank = container_of(chip, struct gpio_bank, chip); - - if (!bank->dbck) { - bank->dbck = clk_get(bank->dev, "dbclk"); - if (IS_ERR(bank->dbck)) - dev_err(bank->dev, "Could not get gpio dbck\n"); - } - - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_debounce(bank, offset, debounce); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct gpio_bank *bank; - unsigned long flags; - - bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); - bank->set_dataout(bank, offset, value); - spin_unlock_irqrestore(&bank->lock, flags); -} - -static int gpio_2irq(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank; - - bank = container_of(chip, struct gpio_bank, chip); - return bank->irq_base + offset; -} - -/*---------------------------------------------------------------------*/ - -static void __init omap_gpio_show_rev(struct gpio_bank *bank) -{ - static bool called; - u32 rev; - - if (called || bank->regs->revision == USHRT_MAX) - return; - - rev = __raw_readw(bank->base + bank->regs->revision); - pr_info("OMAP GPIO hardware version %d.%d\n", - (rev >> 4) & 0x0f, rev & 0x0f); - - called = true; -} - -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - -static void omap_gpio_mod_init(struct gpio_bank *bank) -{ - void __iomem *base = bank->base; - u32 l = 0xffffffff; - - if (bank->width == 16) - l = 0xffff; - - if (bank->is_mpuio) { - __raw_writel(l, bank->base + bank->regs->irqenable); - return; - } - - _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); - _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv); - if (bank->regs->debounce_en) - __raw_writel(0, base + bank->regs->debounce_en); - - /* Save OE default value (0xffffffff) in the context */ - bank->context.oe = __raw_readl(bank->base + bank->regs->direction); - /* Initialize interface clk ungated, module enabled */ - if (bank->regs->ctrl) - __raw_writel(0, base + bank->regs->ctrl); -} - -static __devinit void -omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, - unsigned int num) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base, - handle_simple_irq); - if (!gc) { - dev_err(bank->dev, "Memory alloc failed for gc\n"); - return; - } - - ct = gc->chip_types; - - /* NOTE: No ack required, reading IRQ status clears it. */ - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->chip.irq_set_type = gpio_irq_type; - - if (bank->regs->wkup_en) - ct->chip.irq_set_wake = gpio_wake_enable, - - ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride; - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); -} - -static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) -{ - int j; - static int gpio; - - /* - * REVISIT eventually switch from OMAP-specific gpio structs - * over to the generic ones - */ - bank->chip.request = omap_gpio_request; - bank->chip.free = omap_gpio_free; - bank->chip.direction_input = gpio_input; - bank->chip.get = gpio_get; - bank->chip.direction_output = gpio_output; - bank->chip.set_debounce = gpio_debounce; - bank->chip.set = gpio_set; - bank->chip.to_irq = gpio_2irq; - if (bank->is_mpuio) { - bank->chip.label = "mpuio"; - if (bank->regs->wkup_en) - bank->chip.dev = &omap_mpuio_device.dev; - bank->chip.base = OMAP_MPUIO(0); - } else { - bank->chip.label = "gpio"; - bank->chip.base = gpio; - gpio += bank->width; - } - bank->chip.ngpio = bank->width; - - gpiochip_add(&bank->chip); - - for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) { - irq_set_lockdep_class(j, &gpio_lock_class); - irq_set_chip_data(j, bank); - if (bank->is_mpuio) { - omap_mpuio_alloc_gc(bank, j, bank->width); - } else { - irq_set_chip(j, &gpio_irq_chip); - irq_set_handler(j, handle_simple_irq); - set_irq_flags(j, IRQF_VALID); - } - } - irq_set_chained_handler(bank->irq, gpio_irq_handler); - irq_set_handler_data(bank->irq, bank); -} - -static const struct of_device_id omap_gpio_match[]; - -static int __devinit omap_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - const struct of_device_id *match; - struct omap_gpio_platform_data *pdata; - struct resource *res; - struct gpio_bank *bank; - int ret = 0; - - match = of_match_device(of_match_ptr(omap_gpio_match), dev); - - pdata = match ? match->data : dev->platform_data; - if (!pdata) - return -EINVAL; - - bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); - if (!bank) { - dev_err(dev, "Memory alloc failed\n"); - return -ENOMEM; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(dev, "Invalid IRQ resource\n"); - return -ENODEV; - } - - bank->irq = res->start; - bank->dev = dev; - bank->dbck_flag = pdata->dbck_flag; - bank->stride = pdata->bank_stride; - bank->width = pdata->bank_width; - bank->is_mpuio = pdata->is_mpuio; - bank->non_wakeup_gpios = pdata->non_wakeup_gpios; - bank->loses_context = pdata->loses_context; - bank->get_context_loss_count = pdata->get_context_loss_count; - bank->regs = pdata->regs; -#ifdef CONFIG_OF_GPIO - bank->chip.of_node = of_node_get(node); -#endif - - bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0); - if (bank->irq_base < 0) { - dev_err(dev, "Couldn't allocate IRQ numbers\n"); - return -ENODEV; - } - - bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base, - 0, &irq_domain_simple_ops, NULL); - - if (bank->regs->set_dataout && bank->regs->clr_dataout) - bank->set_dataout = _set_gpio_dataout_reg; - else - bank->set_dataout = _set_gpio_dataout_mask; - - spin_lock_init(&bank->lock); - - /* Static mapping, never released */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(dev, "Invalid mem resource\n"); - return -ENODEV; - } - - if (!devm_request_mem_region(dev, res->start, resource_size(res), - pdev->name)) { - dev_err(dev, "Region already claimed\n"); - return -EBUSY; - } - - bank->base = devm_ioremap(dev, res->start, resource_size(res)); - if (!bank->base) { - dev_err(dev, "Could not ioremap\n"); - return -ENOMEM; - } - - platform_set_drvdata(pdev, bank); - - pm_runtime_enable(bank->dev); - pm_runtime_irq_safe(bank->dev); - pm_runtime_get_sync(bank->dev); - - if (bank->is_mpuio) - mpuio_init(bank); - - omap_gpio_mod_init(bank); - omap_gpio_chip_init(bank); - omap_gpio_show_rev(bank); - - pm_runtime_put(bank->dev); - - list_add_tail(&bank->node, &omap_gpio_list); - - return ret; -} - -#ifdef CONFIG_ARCH_OMAP2PLUS - -#if defined(CONFIG_PM_SLEEP) -static int omap_gpio_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *base = bank->base; - void __iomem *wakeup_enable; - unsigned long flags; - - if (!bank->mod_usage || !bank->loses_context) - return 0; - - if (!bank->regs->wkup_en || !bank->suspend_wakeup) - return 0; - - wakeup_enable = bank->base + bank->regs->wkup_en; - - spin_lock_irqsave(&bank->lock, flags); - bank->saved_wakeup = __raw_readl(wakeup_enable); - _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); - _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static int omap_gpio_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *base = bank->base; - unsigned long flags; - - if (!bank->mod_usage || !bank->loses_context) - return 0; - - if (!bank->regs->wkup_en || !bank->saved_wakeup) - return 0; - - spin_lock_irqsave(&bank->lock, flags); - _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); - _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - -#if defined(CONFIG_PM_RUNTIME) -static void omap_gpio_restore_context(struct gpio_bank *bank); - -static int omap_gpio_runtime_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - u32 l1 = 0, l2 = 0; - unsigned long flags; - u32 wake_low, wake_hi; - - spin_lock_irqsave(&bank->lock, flags); - - /* - * Only edges can generate a wakeup event to the PRCM. - * - * Therefore, ensure any wake-up capable GPIOs have - * edge-detection enabled before going idle to ensure a wakeup - * to the PRCM is generated on a GPIO transition. (c.f. 34xx - * NDA TRM 25.5.3.1) - * - * The normal values will be restored upon ->runtime_resume() - * by writing back the values saved in bank->context. - */ - wake_low = bank->context.leveldetect0 & bank->context.wake_en; - if (wake_low) - __raw_writel(wake_low | bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - wake_hi = bank->context.leveldetect1 & bank->context.wake_en; - if (wake_hi) - __raw_writel(wake_hi | bank->context.risingdetect, - bank->base + bank->regs->risingdetect); - - if (bank->power_mode != OFF_MODE) { - bank->power_mode = 0; - goto update_gpio_context_count; - } - /* - * If going to OFF, remove triggering for all - * non-wakeup GPIOs. Otherwise spurious IRQs will be - * generated. See OMAP2420 Errata item 1.101. - */ - bank->saved_datain = __raw_readl(bank->base + - bank->regs->datain); - l1 = __raw_readl(bank->base + bank->regs->fallingdetect); - l2 = __raw_readl(bank->base + bank->regs->risingdetect); - - bank->saved_fallingdetect = l1; - bank->saved_risingdetect = l2; - l1 &= ~bank->enabled_non_wakeup_gpios; - l2 &= ~bank->enabled_non_wakeup_gpios; - - __raw_writel(l1, bank->base + bank->regs->fallingdetect); - __raw_writel(l2, bank->base + bank->regs->risingdetect); - - bank->workaround_enabled = true; - -update_gpio_context_count: - if (bank->get_context_loss_count) - bank->context_loss_count = - bank->get_context_loss_count(bank->dev); - - _gpio_dbck_disable(bank); - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static int omap_gpio_runtime_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); - int context_lost_cnt_after; - u32 l = 0, gen, gen0, gen1; - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); - _gpio_dbck_enable(bank); - - /* - * In ->runtime_suspend(), level-triggered, wakeup-enabled - * GPIOs were set to edge trigger also in order to be able to - * generate a PRCM wakeup. Here we restore the - * pre-runtime_suspend() values for edge triggering. - */ - __raw_writel(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - __raw_writel(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); - - if (!bank->workaround_enabled) { - spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } - - if (bank->get_context_loss_count) { - context_lost_cnt_after = - bank->get_context_loss_count(bank->dev); - if (context_lost_cnt_after != bank->context_loss_count || - !context_lost_cnt_after) { - omap_gpio_restore_context(bank); - } else { - spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } - } - - __raw_writel(bank->saved_fallingdetect, - bank->base + bank->regs->fallingdetect); - __raw_writel(bank->saved_risingdetect, - bank->base + bank->regs->risingdetect); - l = __raw_readl(bank->base + bank->regs->datain); - - /* - * Check if any of the non-wakeup interrupt GPIOs have changed - * state. If so, generate an IRQ by software. This is - * horribly racy, but it's the best we can do to work around - * this silicon bug. - */ - l ^= bank->saved_datain; - l &= bank->enabled_non_wakeup_gpios; - - /* - * No need to generate IRQs for the rising edge for gpio IRQs - * configured with falling edge only; and vice versa. - */ - gen0 = l & bank->saved_fallingdetect; - gen0 &= bank->saved_datain; - - gen1 = l & bank->saved_risingdetect; - gen1 &= ~(bank->saved_datain); - - /* FIXME: Consider GPIO IRQs with level detections properly! */ - gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect)); - /* Consider all GPIO IRQs needed to be updated */ - gen |= gen0 | gen1; - - if (gen) { - u32 old0, old1; - - old0 = __raw_readl(bank->base + bank->regs->leveldetect0); - old1 = __raw_readl(bank->base + bank->regs->leveldetect1); - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - __raw_writel(old0 | gen, bank->base + - bank->regs->leveldetect0); - __raw_writel(old1 | gen, bank->base + - bank->regs->leveldetect1); - } - - if (cpu_is_omap44xx()) { - __raw_writel(old0 | l, bank->base + - bank->regs->leveldetect0); - __raw_writel(old1 | l, bank->base + - bank->regs->leveldetect1); - } - __raw_writel(old0, bank->base + bank->regs->leveldetect0); - __raw_writel(old1, bank->base + bank->regs->leveldetect1); - } - - bank->workaround_enabled = false; - spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} -#endif /* CONFIG_PM_RUNTIME */ - -void omap2_gpio_prepare_for_idle(int pwr_mode) -{ - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) - continue; - - bank->power_mode = pwr_mode; - - pm_runtime_put_sync_suspend(bank->dev); - } -} - -void omap2_gpio_resume_after_idle(void) -{ - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) - continue; - - pm_runtime_get_sync(bank->dev); - } -} - -#if defined(CONFIG_PM_RUNTIME) -static void omap_gpio_restore_context(struct gpio_bank *bank) -{ - __raw_writel(bank->context.wake_en, - bank->base + bank->regs->wkup_en); - __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); - __raw_writel(bank->context.leveldetect0, - bank->base + bank->regs->leveldetect0); - __raw_writel(bank->context.leveldetect1, - bank->base + bank->regs->leveldetect1); - __raw_writel(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); - __raw_writel(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - if (bank->regs->set_dataout && bank->regs->clr_dataout) - __raw_writel(bank->context.dataout, - bank->base + bank->regs->set_dataout); - else - __raw_writel(bank->context.dataout, - bank->base + bank->regs->dataout); - __raw_writel(bank->context.oe, bank->base + bank->regs->direction); - - if (bank->dbck_enable_mask) { - __raw_writel(bank->context.debounce, bank->base + - bank->regs->debounce); - __raw_writel(bank->context.debounce_en, - bank->base + bank->regs->debounce_en); - } - - __raw_writel(bank->context.irqenable1, - bank->base + bank->regs->irqenable); - __raw_writel(bank->context.irqenable2, - bank->base + bank->regs->irqenable2); -} -#endif /* CONFIG_PM_RUNTIME */ -#else -#define omap_gpio_suspend NULL -#define omap_gpio_resume NULL -#define omap_gpio_runtime_suspend NULL -#define omap_gpio_runtime_resume NULL -#endif - -static const struct dev_pm_ops gpio_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) - SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, - NULL) -}; - -#if defined(CONFIG_OF) -static struct omap_gpio_reg_offs omap2_gpio_regs = { - .revision = OMAP24XX_GPIO_REVISION, - .direction = OMAP24XX_GPIO_OE, - .datain = OMAP24XX_GPIO_DATAIN, - .dataout = OMAP24XX_GPIO_DATAOUT, - .set_dataout = OMAP24XX_GPIO_SETDATAOUT, - .clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT, - .irqstatus = OMAP24XX_GPIO_IRQSTATUS1, - .irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2, - .irqenable = OMAP24XX_GPIO_IRQENABLE1, - .irqenable2 = OMAP24XX_GPIO_IRQENABLE2, - .set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1, - .clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1, - .debounce = OMAP24XX_GPIO_DEBOUNCE_VAL, - .debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN, - .ctrl = OMAP24XX_GPIO_CTRL, - .wkup_en = OMAP24XX_GPIO_WAKE_EN, - .leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0, - .leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1, - .risingdetect = OMAP24XX_GPIO_RISINGDETECT, - .fallingdetect = OMAP24XX_GPIO_FALLINGDETECT, -}; - -static struct omap_gpio_reg_offs omap4_gpio_regs = { - .revision = OMAP4_GPIO_REVISION, - .direction = OMAP4_GPIO_OE, - .datain = OMAP4_GPIO_DATAIN, - .dataout = OMAP4_GPIO_DATAOUT, - .set_dataout = OMAP4_GPIO_SETDATAOUT, - .clr_dataout = OMAP4_GPIO_CLEARDATAOUT, - .irqstatus = OMAP4_GPIO_IRQSTATUS0, - .irqstatus2 = OMAP4_GPIO_IRQSTATUS1, - .irqenable = OMAP4_GPIO_IRQSTATUSSET0, - .irqenable2 = OMAP4_GPIO_IRQSTATUSSET1, - .set_irqenable = OMAP4_GPIO_IRQSTATUSSET0, - .clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0, - .debounce = OMAP4_GPIO_DEBOUNCINGTIME, - .debounce_en = OMAP4_GPIO_DEBOUNCENABLE, - .ctrl = OMAP4_GPIO_CTRL, - .wkup_en = OMAP4_GPIO_IRQWAKEN0, - .leveldetect0 = OMAP4_GPIO_LEVELDETECT0, - .leveldetect1 = OMAP4_GPIO_LEVELDETECT1, - .risingdetect = OMAP4_GPIO_RISINGDETECT, - .fallingdetect = OMAP4_GPIO_FALLINGDETECT, -}; - -static struct omap_gpio_platform_data omap2_pdata = { - .regs = &omap2_gpio_regs, - .bank_width = 32, - .dbck_flag = false, -}; - -static struct omap_gpio_platform_data omap3_pdata = { - .regs = &omap2_gpio_regs, - .bank_width = 32, - .dbck_flag = true, -}; - -static struct omap_gpio_platform_data omap4_pdata = { - .regs = &omap4_gpio_regs, - .bank_width = 32, - .dbck_flag = true, -}; - -static const struct of_device_id omap_gpio_match[] = { - { - .compatible = "ti,omap4-gpio", - .data = &omap4_pdata, - }, - { - .compatible = "ti,omap3-gpio", - .data = &omap3_pdata, - }, - { - .compatible = "ti,omap2-gpio", - .data = &omap2_pdata, - }, - { }, -}; -MODULE_DEVICE_TABLE(of, omap_gpio_match); -#endif - -static struct platform_driver omap_gpio_driver = { - .probe = omap_gpio_probe, - .driver = { - .name = "omap_gpio", - .pm = &gpio_pm_ops, - .of_match_table = of_match_ptr(omap_gpio_match), - }, -}; - -/* - * gpio driver register needs to be done before - * machine_init functions access gpio APIs. - * Hence omap_gpio_drv_reg() is a postcore_initcall. - */ -static int __init omap_gpio_drv_reg(void) -{ - return platform_driver_register(&omap_gpio_driver); -} -postcore_initcall(omap_gpio_drv_reg); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-pca953x.c b/ANDROID_3.4.5/drivers/gpio/gpio-pca953x.c deleted file mode 100644 index d3f3e8f5..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-pca953x.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * PCA953x 4/8/16 bit I/O ports - * - * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> - * Copyright (C) 2007 Marvell International Ltd. - * - * Derived from drivers/i2c/chips/pca9539.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/i2c.h> -#include <linux/i2c/pca953x.h> -#include <linux/slab.h> -#ifdef CONFIG_OF_GPIO -#include <linux/of_platform.h> -#endif - -#define PCA953X_INPUT 0 -#define PCA953X_OUTPUT 1 -#define PCA953X_INVERT 2 -#define PCA953X_DIRECTION 3 - -#define PCA957X_IN 0 -#define PCA957X_INVRT 1 -#define PCA957X_BKEN 2 -#define PCA957X_PUPD 3 -#define PCA957X_CFG 4 -#define PCA957X_OUT 5 -#define PCA957X_MSK 6 -#define PCA957X_INTS 7 - -#define PCA_GPIO_MASK 0x00FF -#define PCA_INT 0x0100 -#define PCA953X_TYPE 0x1000 -#define PCA957X_TYPE 0x2000 - -static const struct i2c_device_id pca953x_id[] = { - { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, - { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, - { "pca9536", 4 | PCA953X_TYPE, }, - { "pca9537", 4 | PCA953X_TYPE | PCA_INT, }, - { "pca9538", 8 | PCA953X_TYPE | PCA_INT, }, - { "pca9539", 16 | PCA953X_TYPE | PCA_INT, }, - { "pca9554", 8 | PCA953X_TYPE | PCA_INT, }, - { "pca9555", 16 | PCA953X_TYPE | PCA_INT, }, - { "pca9556", 8 | PCA953X_TYPE, }, - { "pca9557", 8 | PCA953X_TYPE, }, - { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, - { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, - - { "max7310", 8 | PCA953X_TYPE, }, - { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, - { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, - { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, - { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, - { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, - { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, - /* NYET: { "tca6424", 24, }, */ - { } -}; -MODULE_DEVICE_TABLE(i2c, pca953x_id); - -struct pca953x_chip { - unsigned gpio_start; - uint16_t reg_output; - uint16_t reg_direction; - struct mutex i2c_lock; - -#ifdef CONFIG_GPIO_PCA953X_IRQ - struct mutex irq_lock; - uint16_t irq_mask; - uint16_t irq_stat; - uint16_t irq_trig_raise; - uint16_t irq_trig_fall; - int irq_base; -#endif - - struct i2c_client *client; - struct gpio_chip gpio_chip; - const char *const *names; - int chip_type; -}; - -static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) -{ - int ret = 0; - - if (chip->gpio_chip.ngpio <= 8) - ret = i2c_smbus_write_byte_data(chip->client, reg, val); - else { - switch (chip->chip_type) { - case PCA953X_TYPE: - ret = i2c_smbus_write_word_data(chip->client, - reg << 1, val); - break; - case PCA957X_TYPE: - ret = i2c_smbus_write_byte_data(chip->client, reg << 1, - val & 0xff); - if (ret < 0) - break; - ret = i2c_smbus_write_byte_data(chip->client, - (reg << 1) + 1, - (val & 0xff00) >> 8); - break; - } - } - - if (ret < 0) { - dev_err(&chip->client->dev, "failed writing register\n"); - return ret; - } - - return 0; -} - -static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) -{ - int ret; - - if (chip->gpio_chip.ngpio <= 8) - ret = i2c_smbus_read_byte_data(chip->client, reg); - else - ret = i2c_smbus_read_word_data(chip->client, reg << 1); - - if (ret < 0) { - dev_err(&chip->client->dev, "failed reading register\n"); - return ret; - } - - *val = (uint16_t)ret; - return 0; -} - -static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) -{ - struct pca953x_chip *chip; - uint16_t reg_val; - int ret, offset = 0; - - chip = container_of(gc, struct pca953x_chip, gpio_chip); - - mutex_lock(&chip->i2c_lock); - reg_val = chip->reg_direction | (1u << off); - - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_DIRECTION; - break; - case PCA957X_TYPE: - offset = PCA957X_CFG; - break; - } - ret = pca953x_write_reg(chip, offset, reg_val); - if (ret) - goto exit; - - chip->reg_direction = reg_val; - ret = 0; -exit: - mutex_unlock(&chip->i2c_lock); - return ret; -} - -static int pca953x_gpio_direction_output(struct gpio_chip *gc, - unsigned off, int val) -{ - struct pca953x_chip *chip; - uint16_t reg_val; - int ret, offset = 0; - - chip = container_of(gc, struct pca953x_chip, gpio_chip); - - mutex_lock(&chip->i2c_lock); - /* set output level */ - if (val) - reg_val = chip->reg_output | (1u << off); - else - reg_val = chip->reg_output & ~(1u << off); - - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_OUTPUT; - break; - case PCA957X_TYPE: - offset = PCA957X_OUT; - break; - } - ret = pca953x_write_reg(chip, offset, reg_val); - if (ret) - goto exit; - - chip->reg_output = reg_val; - - /* then direction */ - reg_val = chip->reg_direction & ~(1u << off); - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_DIRECTION; - break; - case PCA957X_TYPE: - offset = PCA957X_CFG; - break; - } - ret = pca953x_write_reg(chip, offset, reg_val); - if (ret) - goto exit; - - chip->reg_direction = reg_val; - ret = 0; -exit: - mutex_unlock(&chip->i2c_lock); - return ret; -} - -static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) -{ - struct pca953x_chip *chip; - uint16_t reg_val; - int ret, offset = 0; - - chip = container_of(gc, struct pca953x_chip, gpio_chip); - - mutex_lock(&chip->i2c_lock); - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_INPUT; - break; - case PCA957X_TYPE: - offset = PCA957X_IN; - break; - } - ret = pca953x_read_reg(chip, offset, ®_val); - mutex_unlock(&chip->i2c_lock); - if (ret < 0) { - /* NOTE: diagnostic already emitted; that's all we should - * do unless gpio_*_value_cansleep() calls become different - * from their nonsleeping siblings (and report faults). - */ - return 0; - } - - return (reg_val & (1u << off)) ? 1 : 0; -} - -static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) -{ - struct pca953x_chip *chip; - uint16_t reg_val; - int ret, offset = 0; - - chip = container_of(gc, struct pca953x_chip, gpio_chip); - - mutex_lock(&chip->i2c_lock); - if (val) - reg_val = chip->reg_output | (1u << off); - else - reg_val = chip->reg_output & ~(1u << off); - - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_OUTPUT; - break; - case PCA957X_TYPE: - offset = PCA957X_OUT; - break; - } - ret = pca953x_write_reg(chip, offset, reg_val); - if (ret) - goto exit; - - chip->reg_output = reg_val; -exit: - mutex_unlock(&chip->i2c_lock); -} - -static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) -{ - struct gpio_chip *gc; - - gc = &chip->gpio_chip; - - gc->direction_input = pca953x_gpio_direction_input; - gc->direction_output = pca953x_gpio_direction_output; - gc->get = pca953x_gpio_get_value; - gc->set = pca953x_gpio_set_value; - gc->can_sleep = 1; - - gc->base = chip->gpio_start; - gc->ngpio = gpios; - gc->label = chip->client->name; - gc->dev = &chip->client->dev; - gc->owner = THIS_MODULE; - gc->names = chip->names; -} - -#ifdef CONFIG_GPIO_PCA953X_IRQ -static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) -{ - struct pca953x_chip *chip; - - chip = container_of(gc, struct pca953x_chip, gpio_chip); - return chip->irq_base + off; -} - -static void pca953x_irq_mask(struct irq_data *d) -{ - struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - - chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); -} - -static void pca953x_irq_unmask(struct irq_data *d) -{ - struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - - chip->irq_mask |= 1 << (d->irq - chip->irq_base); -} - -static void pca953x_irq_bus_lock(struct irq_data *d) -{ - struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - - mutex_lock(&chip->irq_lock); -} - -static void pca953x_irq_bus_sync_unlock(struct irq_data *d) -{ - struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - uint16_t new_irqs; - uint16_t level; - - /* Look for any newly setup interrupt */ - new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; - new_irqs &= ~chip->reg_direction; - - while (new_irqs) { - level = __ffs(new_irqs); - pca953x_gpio_direction_input(&chip->gpio_chip, level); - new_irqs &= ~(1 << level); - } - - mutex_unlock(&chip->irq_lock); -} - -static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); - uint16_t level = d->irq - chip->irq_base; - uint16_t mask = 1 << level; - - if (!(type & IRQ_TYPE_EDGE_BOTH)) { - dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", - d->irq, type); - return -EINVAL; - } - - if (type & IRQ_TYPE_EDGE_FALLING) - chip->irq_trig_fall |= mask; - else - chip->irq_trig_fall &= ~mask; - - if (type & IRQ_TYPE_EDGE_RISING) - chip->irq_trig_raise |= mask; - else - chip->irq_trig_raise &= ~mask; - - return 0; -} - -static struct irq_chip pca953x_irq_chip = { - .name = "pca953x", - .irq_mask = pca953x_irq_mask, - .irq_unmask = pca953x_irq_unmask, - .irq_bus_lock = pca953x_irq_bus_lock, - .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, - .irq_set_type = pca953x_irq_set_type, -}; - -static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) -{ - uint16_t cur_stat; - uint16_t old_stat; - uint16_t pending; - uint16_t trigger; - int ret, offset = 0; - - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_INPUT; - break; - case PCA957X_TYPE: - offset = PCA957X_IN; - break; - } - ret = pca953x_read_reg(chip, offset, &cur_stat); - if (ret) - return 0; - - /* Remove output pins from the equation */ - cur_stat &= chip->reg_direction; - - old_stat = chip->irq_stat; - trigger = (cur_stat ^ old_stat) & chip->irq_mask; - - if (!trigger) - return 0; - - chip->irq_stat = cur_stat; - - pending = (old_stat & chip->irq_trig_fall) | - (cur_stat & chip->irq_trig_raise); - pending &= trigger; - - return pending; -} - -static irqreturn_t pca953x_irq_handler(int irq, void *devid) -{ - struct pca953x_chip *chip = devid; - uint16_t pending; - uint16_t level; - - pending = pca953x_irq_pending(chip); - - if (!pending) - return IRQ_HANDLED; - - do { - level = __ffs(pending); - handle_nested_irq(level + chip->irq_base); - - pending &= ~(1 << level); - } while (pending); - - return IRQ_HANDLED; -} - -static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id, - int irq_base) -{ - struct i2c_client *client = chip->client; - int ret, offset = 0; - - if (irq_base != -1 - && (id->driver_data & PCA_INT)) { - int lvl; - - switch (chip->chip_type) { - case PCA953X_TYPE: - offset = PCA953X_INPUT; - break; - case PCA957X_TYPE: - offset = PCA957X_IN; - break; - } - ret = pca953x_read_reg(chip, offset, &chip->irq_stat); - if (ret) - goto out_failed; - - /* - * There is no way to know which GPIO line generated the - * interrupt. We have to rely on the previous read for - * this purpose. - */ - chip->irq_stat &= chip->reg_direction; - mutex_init(&chip->irq_lock); - - chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); - if (chip->irq_base < 0) - goto out_failed; - - for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { - int irq = lvl + chip->irq_base; - - irq_clear_status_flags(irq, IRQ_NOREQUEST); - irq_set_chip_data(irq, chip); - irq_set_chip(irq, &pca953x_irq_chip); - irq_set_nested_thread(irq, true); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - ret = request_threaded_irq(client->irq, - NULL, - pca953x_irq_handler, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - dev_name(&client->dev), chip); - if (ret) { - dev_err(&client->dev, "failed to request irq %d\n", - client->irq); - goto out_failed; - } - - chip->gpio_chip.to_irq = pca953x_gpio_to_irq; - } - - return 0; - -out_failed: - chip->irq_base = -1; - return ret; -} - -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ - if (chip->irq_base != -1) { - irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); - free_irq(chip->client->irq, chip); - } -} -#else /* CONFIG_GPIO_PCA953X_IRQ */ -static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id, - int irq_base) -{ - struct i2c_client *client = chip->client; - - if (irq_base != -1 && (id->driver_data & PCA_INT)) - dev_warn(&client->dev, "interrupt support not compiled in\n"); - - return 0; -} - -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ -} -#endif - -/* - * Handlers for alternative sources of platform_data - */ -#ifdef CONFIG_OF_GPIO -/* - * Translate OpenFirmware node properties into platform_data - * WARNING: This is DEPRECATED and will be removed eventually! - */ -static void -pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) -{ - struct device_node *node; - const __be32 *val; - int size; - - node = client->dev.of_node; - if (node == NULL) - return; - - *gpio_base = -1; - val = of_get_property(node, "linux,gpio-base", &size); - WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__); - if (val) { - if (size != sizeof(*val)) - dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", - node->full_name); - else - *gpio_base = be32_to_cpup(val); - } - - val = of_get_property(node, "polarity", NULL); - WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__); - if (val) - *invert = *val; -} -#else -static void -pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) -{ - *gpio_base = -1; -} -#endif - -static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) -{ - int ret; - - ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); - if (ret) - goto out; - - ret = pca953x_read_reg(chip, PCA953X_DIRECTION, - &chip->reg_direction); - if (ret) - goto out; - - /* set platform specific polarity inversion */ - ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); -out: - return ret; -} - -static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) -{ - int ret; - uint16_t val = 0; - - /* Let every port in proper state, that could save power */ - pca953x_write_reg(chip, PCA957X_PUPD, 0x0); - pca953x_write_reg(chip, PCA957X_CFG, 0xffff); - pca953x_write_reg(chip, PCA957X_OUT, 0x0); - - ret = pca953x_read_reg(chip, PCA957X_IN, &val); - if (ret) - goto out; - ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); - if (ret) - goto out; - ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); - if (ret) - goto out; - - /* set platform specific polarity inversion */ - pca953x_write_reg(chip, PCA957X_INVRT, invert); - - /* To enable register 6, 7 to controll pull up and pull down */ - pca953x_write_reg(chip, PCA957X_BKEN, 0x202); - - return 0; -out: - return ret; -} - -static int __devinit pca953x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct pca953x_platform_data *pdata; - struct pca953x_chip *chip; - int irq_base=0, invert=0; - int ret; - - chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - pdata = client->dev.platform_data; - if (pdata) { - irq_base = pdata->irq_base; - chip->gpio_start = pdata->gpio_base; - invert = pdata->invert; - chip->names = pdata->names; - } else { - pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); -#ifdef CONFIG_OF_GPIO - /* If I2C node has no interrupts property, disable GPIO interrupts */ - if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL) - irq_base = -1; -#endif - } - - chip->client = client; - - chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE); - - mutex_init(&chip->i2c_lock); - - /* initialize cached registers from their original values. - * we can't share this chip with another i2c master. - */ - pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK); - - if (chip->chip_type == PCA953X_TYPE) - ret = device_pca953x_init(chip, invert); - else - ret = device_pca957x_init(chip, invert); - if (ret) - goto out_failed; - - ret = pca953x_irq_setup(chip, id, irq_base); - if (ret) - goto out_failed; - - ret = gpiochip_add(&chip->gpio_chip); - if (ret) - goto out_failed_irq; - - if (pdata && pdata->setup) { - ret = pdata->setup(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - i2c_set_clientdata(client, chip); - return 0; - -out_failed_irq: - pca953x_irq_teardown(chip); -out_failed: - kfree(chip); - return ret; -} - -static int pca953x_remove(struct i2c_client *client) -{ - struct pca953x_platform_data *pdata = client->dev.platform_data; - struct pca953x_chip *chip = i2c_get_clientdata(client); - int ret = 0; - - if (pdata && pdata->teardown) { - ret = pdata->teardown(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) { - dev_err(&client->dev, "%s failed, %d\n", - "teardown", ret); - return ret; - } - } - - ret = gpiochip_remove(&chip->gpio_chip); - if (ret) { - dev_err(&client->dev, "%s failed, %d\n", - "gpiochip_remove()", ret); - return ret; - } - - pca953x_irq_teardown(chip); - kfree(chip); - return 0; -} - -static struct i2c_driver pca953x_driver = { - .driver = { - .name = "pca953x", - }, - .probe = pca953x_probe, - .remove = pca953x_remove, - .id_table = pca953x_id, -}; - -static int __init pca953x_init(void) -{ - return i2c_add_driver(&pca953x_driver); -} -/* register after i2c postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(pca953x_init); - -static void __exit pca953x_exit(void) -{ - i2c_del_driver(&pca953x_driver); -} -module_exit(pca953x_exit); - -MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); -MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-pcf857x.c b/ANDROID_3.4.5/drivers/gpio/gpio-pcf857x.c deleted file mode 100644 index 2d1de9e7..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-pcf857x.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders - * - * Copyright (C) 2007 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/i2c.h> -#include <linux/i2c/pcf857x.h> -#include <linux/module.h> - - -static const struct i2c_device_id pcf857x_id[] = { - { "pcf8574", 8 }, - { "pcf8574a", 8 }, - { "pca8574", 8 }, - { "pca9670", 8 }, - { "pca9672", 8 }, - { "pca9674", 8 }, - { "pcf8575", 16 }, - { "pca8575", 16 }, - { "pca9671", 16 }, - { "pca9673", 16 }, - { "pca9675", 16 }, - { "max7328", 8 }, - { "max7329", 8 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pcf857x_id); - -/* - * The pcf857x, pca857x, and pca967x chips only expose one read and one - * write register. Writing a "one" bit (to match the reset state) lets - * that pin be used as an input; it's not an open-drain model, but acts - * a bit like one. This is described as "quasi-bidirectional"; read the - * chip documentation for details. - * - * Many other I2C GPIO expander chips (like the pca953x models) have - * more complex register models and more conventional circuitry using - * push/pull drivers. They often use the same 0x20..0x27 addresses as - * pcf857x parts, making the "legacy" I2C driver model problematic. - */ -struct pcf857x { - struct gpio_chip chip; - struct i2c_client *client; - struct mutex lock; /* protect 'out' */ - unsigned out; /* software latch */ -}; - -/*-------------------------------------------------------------------------*/ - -/* Talk to 8-bit I/O expander */ - -static int pcf857x_input8(struct gpio_chip *chip, unsigned offset) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - int status; - - mutex_lock(&gpio->lock); - gpio->out |= (1 << offset); - status = i2c_smbus_write_byte(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; -} - -static int pcf857x_get8(struct gpio_chip *chip, unsigned offset) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - s32 value; - - value = i2c_smbus_read_byte(gpio->client); - return (value < 0) ? 0 : (value & (1 << offset)); -} - -static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - unsigned bit = 1 << offset; - int status; - - mutex_lock(&gpio->lock); - if (value) - gpio->out |= bit; - else - gpio->out &= ~bit; - status = i2c_smbus_write_byte(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; -} - -static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value) -{ - pcf857x_output8(chip, offset, value); -} - -/*-------------------------------------------------------------------------*/ - -/* Talk to 16-bit I/O expander */ - -static int i2c_write_le16(struct i2c_client *client, u16 word) -{ - u8 buf[2] = { word & 0xff, word >> 8, }; - int status; - - status = i2c_master_send(client, buf, 2); - return (status < 0) ? status : 0; -} - -static int i2c_read_le16(struct i2c_client *client) -{ - u8 buf[2]; - int status; - - status = i2c_master_recv(client, buf, 2); - if (status < 0) - return status; - return (buf[1] << 8) | buf[0]; -} - -static int pcf857x_input16(struct gpio_chip *chip, unsigned offset) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - int status; - - mutex_lock(&gpio->lock); - gpio->out |= (1 << offset); - status = i2c_write_le16(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; -} - -static int pcf857x_get16(struct gpio_chip *chip, unsigned offset) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - int value; - - value = i2c_read_le16(gpio->client); - return (value < 0) ? 0 : (value & (1 << offset)); -} - -static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value) -{ - struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); - unsigned bit = 1 << offset; - int status; - - mutex_lock(&gpio->lock); - if (value) - gpio->out |= bit; - else - gpio->out &= ~bit; - status = i2c_write_le16(gpio->client, gpio->out); - mutex_unlock(&gpio->lock); - - return status; -} - -static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value) -{ - pcf857x_output16(chip, offset, value); -} - -/*-------------------------------------------------------------------------*/ - -static int pcf857x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct pcf857x_platform_data *pdata; - struct pcf857x *gpio; - int status; - - pdata = client->dev.platform_data; - if (!pdata) { - dev_dbg(&client->dev, "no platform data\n"); - } - - /* Allocate, initialize, and register this gpio_chip. */ - gpio = kzalloc(sizeof *gpio, GFP_KERNEL); - if (!gpio) - return -ENOMEM; - - mutex_init(&gpio->lock); - - gpio->chip.base = pdata ? pdata->gpio_base : -1; - gpio->chip.can_sleep = 1; - gpio->chip.dev = &client->dev; - gpio->chip.owner = THIS_MODULE; - - /* NOTE: the OnSemi jlc1562b is also largely compatible with - * these parts, notably for output. It has a low-resolution - * DAC instead of pin change IRQs; and its inputs can be the - * result of comparators. - */ - - /* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f; - * 9670, 9672, 9764, and 9764a use quite a variety. - * - * NOTE: we don't distinguish here between *4 and *4a parts. - */ - gpio->chip.ngpio = id->driver_data; - if (gpio->chip.ngpio == 8) { - gpio->chip.direction_input = pcf857x_input8; - gpio->chip.get = pcf857x_get8; - gpio->chip.direction_output = pcf857x_output8; - gpio->chip.set = pcf857x_set8; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE)) - status = -EIO; - - /* fail if there's no chip present */ - else - status = i2c_smbus_read_byte(client); - - /* '75/'75c addresses are 0x20..0x27, just like the '74; - * the '75c doesn't have a current source pulling high. - * 9671, 9673, and 9765 use quite a variety of addresses. - * - * NOTE: we don't distinguish here between '75 and '75c parts. - */ - } else if (gpio->chip.ngpio == 16) { - gpio->chip.direction_input = pcf857x_input16; - gpio->chip.get = pcf857x_get16; - gpio->chip.direction_output = pcf857x_output16; - gpio->chip.set = pcf857x_set16; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - status = -EIO; - - /* fail if there's no chip present */ - else - status = i2c_read_le16(client); - - } else { - dev_dbg(&client->dev, "unsupported number of gpios\n"); - status = -EINVAL; - } - - if (status < 0) - goto fail; - - gpio->chip.label = client->name; - - gpio->client = client; - i2c_set_clientdata(client, gpio); - - /* NOTE: these chips have strange "quasi-bidirectional" I/O pins. - * We can't actually know whether a pin is configured (a) as output - * and driving the signal low, or (b) as input and reporting a low - * value ... without knowing the last value written since the chip - * came out of reset (if any). We can't read the latched output. - * - * In short, the only reliable solution for setting up pin direction - * is to do it explicitly. The setup() method can do that, but it - * may cause transient glitching since it can't know the last value - * written (some pins may need to be driven low). - * - * Using pdata->n_latch avoids that trouble. When left initialized - * to zero, our software copy of the "latch" then matches the chip's - * all-ones reset state. Otherwise it flags pins to be driven low. - */ - gpio->out = pdata ? ~pdata->n_latch : ~0; - - status = gpiochip_add(&gpio->chip); - if (status < 0) - goto fail; - - /* NOTE: these chips can issue "some pin-changed" IRQs, which we - * don't yet even try to use. Among other issues, the relevant - * genirq state isn't available to modular drivers; and most irq - * methods can't be called from sleeping contexts. - */ - - dev_info(&client->dev, "%s\n", - client->irq ? " (irq ignored)" : ""); - - /* Let platform code set up the GPIOs and their users. - * Now is the first time anyone could use them. - */ - if (pdata && pdata->setup) { - status = pdata->setup(client, - gpio->chip.base, gpio->chip.ngpio, - pdata->context); - if (status < 0) - dev_warn(&client->dev, "setup --> %d\n", status); - } - - return 0; - -fail: - dev_dbg(&client->dev, "probe error %d for '%s'\n", - status, client->name); - kfree(gpio); - return status; -} - -static int pcf857x_remove(struct i2c_client *client) -{ - struct pcf857x_platform_data *pdata = client->dev.platform_data; - struct pcf857x *gpio = i2c_get_clientdata(client); - int status = 0; - - if (pdata && pdata->teardown) { - status = pdata->teardown(client, - gpio->chip.base, gpio->chip.ngpio, - pdata->context); - if (status < 0) { - dev_err(&client->dev, "%s --> %d\n", - "teardown", status); - return status; - } - } - - status = gpiochip_remove(&gpio->chip); - if (status == 0) - kfree(gpio); - else - dev_err(&client->dev, "%s --> %d\n", "remove", status); - return status; -} - -static struct i2c_driver pcf857x_driver = { - .driver = { - .name = "pcf857x", - .owner = THIS_MODULE, - }, - .probe = pcf857x_probe, - .remove = pcf857x_remove, - .id_table = pcf857x_id, -}; - -static int __init pcf857x_init(void) -{ - return i2c_add_driver(&pcf857x_driver); -} -/* register after i2c postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(pcf857x_init); - -static void __exit pcf857x_exit(void) -{ - i2c_del_driver(&pcf857x_driver); -} -module_exit(pcf857x_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Brownell"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-pch.c b/ANDROID_3.4.5/drivers/gpio/gpio-pch.c deleted file mode 100644 index 2cd958e0..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-pch.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/irq.h> - -#define PCH_EDGE_FALLING 0 -#define PCH_EDGE_RISING BIT(0) -#define PCH_LEVEL_L BIT(1) -#define PCH_LEVEL_H (BIT(0) | BIT(1)) -#define PCH_EDGE_BOTH BIT(2) -#define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) - -#define PCH_IRQ_BASE 24 - -struct pch_regs { - u32 ien; - u32 istatus; - u32 idisp; - u32 iclr; - u32 imask; - u32 imaskclr; - u32 po; - u32 pi; - u32 pm; - u32 im0; - u32 im1; - u32 reserved[3]; - u32 gpio_use_sel; - u32 reset; -}; - -enum pch_type_t { - INTEL_EG20T_PCH, - OKISEMI_ML7223m_IOH, /* LAPIS Semiconductor ML7223 IOH PCIe Bus-m */ - OKISEMI_ML7223n_IOH /* LAPIS Semiconductor ML7223 IOH PCIe Bus-n */ -}; - -/* Specifies number of GPIO PINS */ -static int gpio_pins[] = { - [INTEL_EG20T_PCH] = 12, - [OKISEMI_ML7223m_IOH] = 8, - [OKISEMI_ML7223n_IOH] = 8, -}; - -/** - * struct pch_gpio_reg_data - The register store data. - * @ien_reg: To store contents of IEN register. - * @imask_reg: To store contents of IMASK register. - * @po_reg: To store contents of PO register. - * @pm_reg: To store contents of PM register. - * @im0_reg: To store contents of IM0 register. - * @im1_reg: To store contents of IM1 register. - * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register. - * (Only ML7223 Bus-n) - */ -struct pch_gpio_reg_data { - u32 ien_reg; - u32 imask_reg; - u32 po_reg; - u32 pm_reg; - u32 im0_reg; - u32 im1_reg; - u32 gpio_use_sel_reg; -}; - -/** - * struct pch_gpio - GPIO private data structure. - * @base: PCI base address of Memory mapped I/O register. - * @reg: Memory mapped PCH GPIO register list. - * @dev: Pointer to device structure. - * @gpio: Data for GPIO infrastructure. - * @pch_gpio_reg: Memory mapped Register data is saved here - * when suspend. - * @lock: Used for register access protection - * @irq_base: Save base of IRQ number for interrupt - * @ioh: IOH ID - * @spinlock: Used for register access protection in - * interrupt context pch_irq_mask, - * pch_irq_unmask and pch_irq_type; - */ -struct pch_gpio { - void __iomem *base; - struct pch_regs __iomem *reg; - struct device *dev; - struct gpio_chip gpio; - struct pch_gpio_reg_data pch_gpio_reg; - struct mutex lock; - int irq_base; - enum pch_type_t ioh; - spinlock_t spinlock; -}; - -static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) -{ - u32 reg_val; - struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); - - mutex_lock(&chip->lock); - reg_val = ioread32(&chip->reg->po); - if (val) - reg_val |= (1 << nr); - else - reg_val &= ~(1 << nr); - - iowrite32(reg_val, &chip->reg->po); - mutex_unlock(&chip->lock); -} - -static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr) -{ - struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); - - return ioread32(&chip->reg->pi) & (1 << nr); -} - -static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, - int val) -{ - struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); - u32 pm; - u32 reg_val; - - mutex_lock(&chip->lock); - pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); - pm |= (1 << nr); - iowrite32(pm, &chip->reg->pm); - - reg_val = ioread32(&chip->reg->po); - if (val) - reg_val |= (1 << nr); - else - reg_val &= ~(1 << nr); - iowrite32(reg_val, &chip->reg->po); - - mutex_unlock(&chip->lock); - - return 0; -} - -static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) -{ - struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); - u32 pm; - - mutex_lock(&chip->lock); - pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); - pm &= ~(1 << nr); - iowrite32(pm, &chip->reg->pm); - mutex_unlock(&chip->lock); - - return 0; -} - -/* - * Save register configuration and disable interrupts. - */ -static void pch_gpio_save_reg_conf(struct pch_gpio *chip) -{ - chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien); - chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask); - chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po); - chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm); - chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0); - if (chip->ioh == INTEL_EG20T_PCH) - chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1); - if (chip->ioh == OKISEMI_ML7223n_IOH) - chip->pch_gpio_reg.gpio_use_sel_reg =\ - ioread32(&chip->reg->gpio_use_sel); -} - -/* - * This function restores the register configuration of the GPIO device. - */ -static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) -{ - iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien); - iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask); - /* to store contents of PO register */ - iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po); - /* to store contents of PM register */ - iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm); - iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0); - if (chip->ioh == INTEL_EG20T_PCH) - iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1); - if (chip->ioh == OKISEMI_ML7223n_IOH) - iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, - &chip->reg->gpio_use_sel); -} - -static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) -{ - struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); - return chip->irq_base + offset; -} - -static void pch_gpio_setup(struct pch_gpio *chip) -{ - struct gpio_chip *gpio = &chip->gpio; - - gpio->label = dev_name(chip->dev); - gpio->owner = THIS_MODULE; - gpio->direction_input = pch_gpio_direction_input; - gpio->get = pch_gpio_get; - gpio->direction_output = pch_gpio_direction_output; - gpio->set = pch_gpio_set; - gpio->dbg_show = NULL; - gpio->base = -1; - gpio->ngpio = gpio_pins[chip->ioh]; - gpio->can_sleep = 0; - gpio->to_irq = pch_gpio_to_irq; -} - -static int pch_irq_type(struct irq_data *d, unsigned int type) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct pch_gpio *chip = gc->private; - u32 im, im_pos, val; - u32 __iomem *im_reg; - unsigned long flags; - int ch, irq = d->irq; - - ch = irq - chip->irq_base; - if (irq <= chip->irq_base + 7) { - im_reg = &chip->reg->im0; - im_pos = ch; - } else { - im_reg = &chip->reg->im1; - im_pos = ch - 8; - } - dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n", - __func__, irq, type, ch, im_pos); - - spin_lock_irqsave(&chip->spinlock, flags); - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - val = PCH_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - val = PCH_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - val = PCH_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - val = PCH_LEVEL_H; - break; - case IRQ_TYPE_LEVEL_LOW: - val = PCH_LEVEL_L; - break; - default: - goto unlock; - } - - /* Set interrupt mode */ - im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4)); - iowrite32(im | (val << (im_pos * 4)), im_reg); - - /* And the handler */ - if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __irq_set_handler_locked(d->irq, handle_level_irq); - else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - __irq_set_handler_locked(d->irq, handle_edge_irq); - -unlock: - spin_unlock_irqrestore(&chip->spinlock, flags); - return 0; -} - -static void pch_irq_unmask(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct pch_gpio *chip = gc->private; - - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr); -} - -static void pch_irq_mask(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct pch_gpio *chip = gc->private; - - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask); -} - -static void pch_irq_ack(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct pch_gpio *chip = gc->private; - - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->iclr); -} - -static irqreturn_t pch_gpio_handler(int irq, void *dev_id) -{ - struct pch_gpio *chip = dev_id; - u32 reg_val = ioread32(&chip->reg->istatus); - int i, ret = IRQ_NONE; - - for (i = 0; i < gpio_pins[chip->ioh]; i++) { - if (reg_val & BIT(i)) { - dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n", - __func__, i, irq, reg_val); - generic_handle_irq(chip->irq_base + i); - ret = IRQ_HANDLED; - } - } - return ret; -} - -static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip, - unsigned int irq_start, unsigned int num) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base, - handle_simple_irq); - gc->private = chip; - ct = gc->chip_types; - - ct->chip.irq_ack = pch_irq_ack; - ct->chip.irq_mask = pch_irq_mask; - ct->chip.irq_unmask = pch_irq_unmask; - ct->chip.irq_set_type = pch_irq_type; - - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); -} - -static int __devinit pch_gpio_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - s32 ret; - struct pch_gpio *chip; - int irq_base; - u32 msk; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->dev = &pdev->dev; - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__); - goto err_pci_enable; - } - - ret = pci_request_regions(pdev, KBUILD_MODNAME); - if (ret) { - dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret); - goto err_request_regions; - } - - chip->base = pci_iomap(pdev, 1, 0); - if (!chip->base) { - dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); - ret = -ENOMEM; - goto err_iomap; - } - - if (pdev->device == 0x8803) - chip->ioh = INTEL_EG20T_PCH; - else if (pdev->device == 0x8014) - chip->ioh = OKISEMI_ML7223m_IOH; - else if (pdev->device == 0x8043) - chip->ioh = OKISEMI_ML7223n_IOH; - - chip->reg = chip->base; - pci_set_drvdata(pdev, chip); - mutex_init(&chip->lock); - spin_lock_init(&chip->spinlock); - pch_gpio_setup(chip); - ret = gpiochip_add(&chip->gpio); - if (ret) { - dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n"); - goto err_gpiochip_add; - } - - irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE); - if (irq_base < 0) { - dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n"); - chip->irq_base = -1; - goto end; - } - chip->irq_base = irq_base; - - /* Mask all interrupts, but enable them */ - msk = (1 << gpio_pins[chip->ioh]) - 1; - iowrite32(msk, &chip->reg->imask); - iowrite32(msk, &chip->reg->ien); - - ret = request_irq(pdev->irq, pch_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); - if (ret != 0) { - dev_err(&pdev->dev, - "%s request_irq failed\n", __func__); - goto err_request_irq; - } - - pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]); - -end: - return 0; - -err_request_irq: - irq_free_descs(irq_base, gpio_pins[chip->ioh]); - - ret = gpiochip_remove(&chip->gpio); - if (ret) - dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); - -err_gpiochip_add: - pci_iounmap(pdev, chip->base); - -err_iomap: - pci_release_regions(pdev); - -err_request_regions: - pci_disable_device(pdev); - -err_pci_enable: - kfree(chip); - dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); - return ret; -} - -static void __devexit pch_gpio_remove(struct pci_dev *pdev) -{ - int err; - struct pch_gpio *chip = pci_get_drvdata(pdev); - - if (chip->irq_base != -1) { - free_irq(pdev->irq, chip); - - irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]); - } - - err = gpiochip_remove(&chip->gpio); - if (err) - dev_err(&pdev->dev, "Failed gpiochip_remove\n"); - - pci_iounmap(pdev, chip->base); - pci_release_regions(pdev); - pci_disable_device(pdev); - kfree(chip); -} - -#ifdef CONFIG_PM -static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state) -{ - s32 ret; - struct pch_gpio *chip = pci_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&chip->spinlock, flags); - pch_gpio_save_reg_conf(chip); - spin_unlock_irqrestore(&chip->spinlock, flags); - - ret = pci_save_state(pdev); - if (ret) { - dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); - return ret; - } - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_wake(pdev, PCI_D0, 1); - if (ret) - dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); - - return 0; -} - -static int pch_gpio_resume(struct pci_dev *pdev) -{ - s32 ret; - struct pch_gpio *chip = pci_get_drvdata(pdev); - unsigned long flags; - - ret = pci_enable_wake(pdev, PCI_D0, 0); - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); - return ret; - } - pci_restore_state(pdev); - - spin_lock_irqsave(&chip->spinlock, flags); - iowrite32(0x01, &chip->reg->reset); - iowrite32(0x00, &chip->reg->reset); - pch_gpio_restore_reg_conf(chip); - spin_unlock_irqrestore(&chip->spinlock, flags); - - return 0; -} -#else -#define pch_gpio_suspend NULL -#define pch_gpio_resume NULL -#endif - -#define PCI_VENDOR_ID_ROHM 0x10DB -static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, - { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, - { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, - { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); - -static struct pci_driver pch_gpio_driver = { - .name = "pch_gpio", - .id_table = pch_gpio_pcidev_id, - .probe = pch_gpio_probe, - .remove = __devexit_p(pch_gpio_remove), - .suspend = pch_gpio_suspend, - .resume = pch_gpio_resume -}; - -static int __init pch_gpio_pci_init(void) -{ - return pci_register_driver(&pch_gpio_driver); -} -module_init(pch_gpio_pci_init); - -static void __exit pch_gpio_pci_exit(void) -{ - pci_unregister_driver(&pch_gpio_driver); -} -module_exit(pch_gpio_pci_exit); - -MODULE_DESCRIPTION("PCH GPIO PCI Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-pl061.c b/ANDROID_3.4.5/drivers/gpio/gpio-pl061.c deleted file mode 100644 index b4b5da4f..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-pl061.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Provigent Ltd. - * - * 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. - * - * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061) - * - * Data sheet: ARM DDI 0190B, September 2000 - */ -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/irq.h> -#include <linux/bitops.h> -#include <linux/workqueue.h> -#include <linux/gpio.h> -#include <linux/device.h> -#include <linux/amba/bus.h> -#include <linux/amba/pl061.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <asm/mach/irq.h> - -#define GPIODIR 0x400 -#define GPIOIS 0x404 -#define GPIOIBE 0x408 -#define GPIOIEV 0x40C -#define GPIOIE 0x410 -#define GPIORIS 0x414 -#define GPIOMIS 0x418 -#define GPIOIC 0x41C - -#define PL061_GPIO_NR 8 - -#ifdef CONFIG_PM -struct pl061_context_save_regs { - u8 gpio_data; - u8 gpio_dir; - u8 gpio_is; - u8 gpio_ibe; - u8 gpio_iev; - u8 gpio_ie; -}; -#endif - -struct pl061_gpio { - /* Each of the two spinlocks protects a different set of hardware - * regiters and data structurs. This decouples the code of the IRQ from - * the GPIO code. This also makes the case of a GPIO routine call from - * the IRQ code simpler. - */ - spinlock_t lock; /* GPIO registers */ - - void __iomem *base; - int irq_base; - struct irq_chip_generic *irq_gc; - struct gpio_chip gc; - -#ifdef CONFIG_PM - struct pl061_context_save_regs csave_regs; -#endif -}; - -static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - unsigned long flags; - unsigned char gpiodir; - - if (offset >= gc->ngpio) - return -EINVAL; - - spin_lock_irqsave(&chip->lock, flags); - gpiodir = readb(chip->base + GPIODIR); - gpiodir &= ~(1 << offset); - writeb(gpiodir, chip->base + GPIODIR); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static int pl061_direction_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - unsigned long flags; - unsigned char gpiodir; - - if (offset >= gc->ngpio) - return -EINVAL; - - spin_lock_irqsave(&chip->lock, flags); - writeb(!!value << offset, chip->base + (1 << (offset + 2))); - gpiodir = readb(chip->base + GPIODIR); - gpiodir |= 1 << offset; - writeb(gpiodir, chip->base + GPIODIR); - - /* - * gpio value is set again, because pl061 doesn't allow to set value of - * a gpio pin before configuring it in OUT mode. - */ - writeb(!!value << offset, chip->base + (1 << (offset + 2))); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static int pl061_get_value(struct gpio_chip *gc, unsigned offset) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - - return !!readb(chip->base + (1 << (offset + 2))); -} - -static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - - writeb(!!value << offset, chip->base + (1 << (offset + 2))); -} - -static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - - if (chip->irq_base <= 0) - return -EINVAL; - - return chip->irq_base + offset; -} - -static int pl061_irq_type(struct irq_data *d, unsigned trigger) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct pl061_gpio *chip = gc->private; - int offset = d->irq - chip->irq_base; - unsigned long flags; - u8 gpiois, gpioibe, gpioiev; - - if (offset < 0 || offset >= PL061_GPIO_NR) - return -EINVAL; - - raw_spin_lock_irqsave(&gc->lock, flags); - - gpioiev = readb(chip->base + GPIOIEV); - - gpiois = readb(chip->base + GPIOIS); - if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - gpiois |= 1 << offset; - if (trigger & IRQ_TYPE_LEVEL_HIGH) - gpioiev |= 1 << offset; - else - gpioiev &= ~(1 << offset); - } else - gpiois &= ~(1 << offset); - writeb(gpiois, chip->base + GPIOIS); - - gpioibe = readb(chip->base + GPIOIBE); - if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - gpioibe |= 1 << offset; - else { - gpioibe &= ~(1 << offset); - if (trigger & IRQ_TYPE_EDGE_RISING) - gpioiev |= 1 << offset; - else if (trigger & IRQ_TYPE_EDGE_FALLING) - gpioiev &= ~(1 << offset); - } - writeb(gpioibe, chip->base + GPIOIBE); - - writeb(gpioiev, chip->base + GPIOIEV); - - raw_spin_unlock_irqrestore(&gc->lock, flags); - - return 0; -} - -static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) -{ - unsigned long pending; - int offset; - struct pl061_gpio *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irqchip = irq_desc_get_chip(desc); - - chained_irq_enter(irqchip, desc); - - pending = readb(chip->base + GPIOMIS); - writeb(pending, chip->base + GPIOIC); - if (pending) { - for_each_set_bit(offset, &pending, PL061_GPIO_NR) - generic_handle_irq(pl061_to_irq(&chip->gc, offset)); - } - - chained_irq_exit(irqchip, desc); -} - -static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) -{ - struct irq_chip_type *ct; - - chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, - chip->base, handle_simple_irq); - chip->irq_gc->private = chip; - - ct = chip->irq_gc->chip_types; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; - ct->chip.irq_set_type = pl061_irq_type; - ct->chip.irq_set_wake = irq_gc_set_wake; - ct->regs.mask = GPIOIE; - - irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), - IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); -} - -static int pl061_probe(struct amba_device *dev, const struct amba_id *id) -{ - struct pl061_platform_data *pdata; - struct pl061_gpio *chip; - int ret, irq, i; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - pdata = dev->dev.platform_data; - if (pdata) { - chip->gc.base = pdata->gpio_base; - chip->irq_base = pdata->irq_base; - } else if (dev->dev.of_node) { - chip->gc.base = -1; - chip->irq_base = 0; - } else { - ret = -ENODEV; - goto free_mem; - } - - if (!request_mem_region(dev->res.start, - resource_size(&dev->res), "pl061")) { - ret = -EBUSY; - goto free_mem; - } - - chip->base = ioremap(dev->res.start, resource_size(&dev->res)); - if (chip->base == NULL) { - ret = -ENOMEM; - goto release_region; - } - - spin_lock_init(&chip->lock); - - chip->gc.direction_input = pl061_direction_input; - chip->gc.direction_output = pl061_direction_output; - chip->gc.get = pl061_get_value; - chip->gc.set = pl061_set_value; - chip->gc.to_irq = pl061_to_irq; - chip->gc.ngpio = PL061_GPIO_NR; - chip->gc.label = dev_name(&dev->dev); - chip->gc.dev = &dev->dev; - chip->gc.owner = THIS_MODULE; - - ret = gpiochip_add(&chip->gc); - if (ret) - goto iounmap; - - /* - * irq_chip support - */ - - if (chip->irq_base <= 0) - return 0; - - pl061_init_gc(chip, chip->irq_base); - - writeb(0, chip->base + GPIOIE); /* disable irqs */ - irq = dev->irq[0]; - if (irq < 0) { - ret = -ENODEV; - goto iounmap; - } - irq_set_chained_handler(irq, pl061_irq_handler); - irq_set_handler_data(irq, chip); - - for (i = 0; i < PL061_GPIO_NR; i++) { - if (pdata) { - if (pdata->directions & (1 << i)) - pl061_direction_output(&chip->gc, i, - pdata->values & (1 << i)); - else - pl061_direction_input(&chip->gc, i); - } - } - - amba_set_drvdata(dev, chip); - - return 0; - -iounmap: - iounmap(chip->base); -release_region: - release_mem_region(dev->res.start, resource_size(&dev->res)); -free_mem: - kfree(chip); - - return ret; -} - -#ifdef CONFIG_PM -static int pl061_suspend(struct device *dev) -{ - struct pl061_gpio *chip = dev_get_drvdata(dev); - int offset; - - chip->csave_regs.gpio_data = 0; - chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR); - chip->csave_regs.gpio_is = readb(chip->base + GPIOIS); - chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE); - chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV); - chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE); - - for (offset = 0; offset < PL061_GPIO_NR; offset++) { - if (chip->csave_regs.gpio_dir & (1 << offset)) - chip->csave_regs.gpio_data |= - pl061_get_value(&chip->gc, offset) << offset; - } - - return 0; -} - -static int pl061_resume(struct device *dev) -{ - struct pl061_gpio *chip = dev_get_drvdata(dev); - int offset; - - for (offset = 0; offset < PL061_GPIO_NR; offset++) { - if (chip->csave_regs.gpio_dir & (1 << offset)) - pl061_direction_output(&chip->gc, offset, - chip->csave_regs.gpio_data & - (1 << offset)); - else - pl061_direction_input(&chip->gc, offset); - } - - writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS); - writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE); - writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV); - writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE); - - return 0; -} - -static const struct dev_pm_ops pl061_dev_pm_ops = { - .suspend = pl061_suspend, - .resume = pl061_resume, - .freeze = pl061_suspend, - .restore = pl061_resume, -}; -#endif - -static struct amba_id pl061_ids[] = { - { - .id = 0x00041061, - .mask = 0x000fffff, - }, - { 0, 0 }, -}; - -MODULE_DEVICE_TABLE(amba, pl061_ids); - -static struct amba_driver pl061_gpio_driver = { - .drv = { - .name = "pl061_gpio", -#ifdef CONFIG_PM - .pm = &pl061_dev_pm_ops, -#endif - }, - .id_table = pl061_ids, - .probe = pl061_probe, -}; - -static int __init pl061_gpio_init(void) -{ - return amba_driver_register(&pl061_gpio_driver); -} -subsys_initcall(pl061_gpio_init); - -MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); -MODULE_DESCRIPTION("PL061 GPIO driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-pxa.c b/ANDROID_3.4.5/drivers/gpio/gpio-pxa.c deleted file mode 100644 index fc3ace3f..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-pxa.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * linux/arch/arm/plat-pxa/gpio.c - * - * Generic PXA GPIO handling - * - * Author: Nicolas Pitre - * Created: Jun 15, 2001 - * Copyright: MontaVista Software Inc. - * - * 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/clk.h> -#include <linux/err.h> -#include <linux/gpio.h> -#include <linux/gpio-pxa.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/syscore_ops.h> -#include <linux/slab.h> - -#include <mach/irqs.h> - -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 -#define GAFR_OFFSET 0x54 -#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */ - -#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) - -int pxa_last_gpio; - -struct pxa_gpio_chip { - struct gpio_chip chip; - void __iomem *regbase; - char label[10]; - - unsigned long irq_mask; - unsigned long irq_edge_rise; - unsigned long irq_edge_fall; - int (*set_wake)(unsigned int gpio, unsigned int on); - -#ifdef CONFIG_PM - unsigned long saved_gplr; - unsigned long saved_gpdr; - unsigned long saved_grer; - unsigned long saved_gfer; -#endif -}; - -enum { - PXA25X_GPIO = 0, - PXA26X_GPIO, - PXA27X_GPIO, - PXA3XX_GPIO, - PXA93X_GPIO, - MMP_GPIO = 0x10, - MMP2_GPIO, -}; - -static DEFINE_SPINLOCK(gpio_lock); -static struct pxa_gpio_chip *pxa_gpio_chips; -static int gpio_type; -static void __iomem *gpio_reg_base; - -#define for_each_gpio_chip(i, c) \ - for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) - -static inline void __iomem *gpio_chip_base(struct gpio_chip *c) -{ - return container_of(c, struct pxa_gpio_chip, chip)->regbase; -} - -static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) -{ - return &pxa_gpio_chips[gpio_to_bank(gpio)]; -} - -static inline int gpio_is_pxa_type(int type) -{ - return (type & MMP_GPIO) == 0; -} - -static inline int gpio_is_mmp_type(int type) -{ - return (type & MMP_GPIO) != 0; -} - -/* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted, - * as well as their Alternate Function value being '1' for GPIO in GAFRx. - */ -static inline int __gpio_is_inverted(int gpio) -{ - if ((gpio_type == PXA26X_GPIO) && (gpio > 85)) - return 1; - return 0; -} - -/* - * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate - * function of a GPIO, and GPDRx cannot be altered once configured. It - * is attributed as "occupied" here (I know this terminology isn't - * accurate, you are welcome to propose a better one :-) - */ -static inline int __gpio_is_occupied(unsigned gpio) -{ - struct pxa_gpio_chip *pxachip; - void __iomem *base; - unsigned long gafr = 0, gpdr = 0; - int ret, af = 0, dir = 0; - - pxachip = gpio_to_pxachip(gpio); - base = gpio_chip_base(&pxachip->chip); - gpdr = readl_relaxed(base + GPDR_OFFSET); - - switch (gpio_type) { - case PXA25X_GPIO: - case PXA26X_GPIO: - case PXA27X_GPIO: - gafr = readl_relaxed(base + GAFR_OFFSET); - af = (gafr >> ((gpio & 0xf) * 2)) & 0x3; - dir = gpdr & GPIO_bit(gpio); - - if (__gpio_is_inverted(gpio)) - ret = (af != 1) || (dir == 0); - else - ret = (af != 0) || (dir != 0); - break; - default: - ret = gpdr & GPIO_bit(gpio); - break; - } - return ret; -} - -#ifdef CONFIG_ARCH_PXA -static inline int __pxa_gpio_to_irq(int gpio) -{ - if (gpio_is_pxa_type(gpio_type)) - return PXA_GPIO_TO_IRQ(gpio); - return -1; -} - -static inline int __pxa_irq_to_gpio(int irq) -{ - if (gpio_is_pxa_type(gpio_type)) - return irq - PXA_GPIO_TO_IRQ(0); - return -1; -} -#else -static inline int __pxa_gpio_to_irq(int gpio) { return -1; } -static inline int __pxa_irq_to_gpio(int irq) { return -1; } -#endif - -#ifdef CONFIG_ARCH_MMP -static inline int __mmp_gpio_to_irq(int gpio) -{ - if (gpio_is_mmp_type(gpio_type)) - return MMP_GPIO_TO_IRQ(gpio); - return -1; -} - -static inline int __mmp_irq_to_gpio(int irq) -{ - if (gpio_is_mmp_type(gpio_type)) - return irq - MMP_GPIO_TO_IRQ(0); - return -1; -} -#else -static inline int __mmp_gpio_to_irq(int gpio) { return -1; } -static inline int __mmp_irq_to_gpio(int irq) { return -1; } -#endif - -static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - int gpio, ret; - - gpio = chip->base + offset; - ret = __pxa_gpio_to_irq(gpio); - if (ret >= 0) - return ret; - return __mmp_gpio_to_irq(gpio); -} - -int pxa_irq_to_gpio(int irq) -{ - int ret; - - ret = __pxa_irq_to_gpio(irq); - if (ret >= 0) - return ret; - return __mmp_irq_to_gpio(irq); -} - -static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t value, mask = 1 << offset; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - value = readl_relaxed(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - value |= mask; - else - value &= ~mask; - writel_relaxed(value, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t tmp, mask = 1 << offset; - unsigned long flags; - - writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); - - spin_lock_irqsave(&gpio_lock, flags); - - tmp = readl_relaxed(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - tmp &= ~mask; - else - tmp |= mask; - writel_relaxed(tmp, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); -} - -static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - writel_relaxed(1 << offset, gpio_chip_base(chip) + - (value ? GPSR_OFFSET : GPCR_OFFSET)); -} - -static int __devinit pxa_init_gpio_chip(int gpio_end, - int (*set_wake)(unsigned int, unsigned int)) -{ - int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; - struct pxa_gpio_chip *chips; - - chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); - if (chips == NULL) { - pr_err("%s: failed to allocate GPIO chips\n", __func__); - return -ENOMEM; - } - - for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { - struct gpio_chip *c = &chips[i].chip; - - sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = gpio_reg_base + BANK_OFF(i); - chips[i].set_wake = set_wake; - - c->base = gpio; - c->label = chips[i].label; - - c->direction_input = pxa_gpio_direction_input; - c->direction_output = pxa_gpio_direction_output; - c->get = pxa_gpio_get; - c->set = pxa_gpio_set; - c->to_irq = pxa_gpio_to_irq; - - /* number of GPIOs on last bank may be less than 32 */ - c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; - gpiochip_add(c); - } - pxa_gpio_chips = chips; - return 0; -} - -/* Update only those GRERx and GFERx edge detection register bits if those - * bits are set in c->irq_mask - */ -static inline void update_edge_detect(struct pxa_gpio_chip *c) -{ - uint32_t grer, gfer; - - grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask; - gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask; - grer |= c->irq_edge_rise & c->irq_mask; - gfer |= c->irq_edge_fall & c->irq_mask; - writel_relaxed(grer, c->regbase + GRER_OFFSET); - writel_relaxed(gfer, c->regbase + GFER_OFFSET); -} - -static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - struct pxa_gpio_chip *c; - int gpio = pxa_irq_to_gpio(d->irq); - unsigned long gpdr, mask = GPIO_bit(gpio); - - c = gpio_to_pxachip(gpio); - - if (type == IRQ_TYPE_PROBE) { - /* Don't mess with enabled GPIOs using preconfigured edges or - * GPIOs set to alternate function or to output during probe - */ - if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) - return 0; - - if (__gpio_is_occupied(gpio)) - return 0; - - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - } - - gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); - - if (__gpio_is_inverted(gpio)) - writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET); - else - writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET); - - if (type & IRQ_TYPE_EDGE_RISING) - c->irq_edge_rise |= mask; - else - c->irq_edge_rise &= ~mask; - - if (type & IRQ_TYPE_EDGE_FALLING) - c->irq_edge_fall |= mask; - else - c->irq_edge_fall &= ~mask; - - update_edge_detect(c); - - pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio, - ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), - ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); - return 0; -} - -static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) -{ - struct pxa_gpio_chip *c; - int loop, gpio, gpio_base, n; - unsigned long gedr; - - do { - loop = 0; - for_each_gpio_chip(gpio, c) { - gpio_base = c->chip.base; - - gedr = readl_relaxed(c->regbase + GEDR_OFFSET); - gedr = gedr & c->irq_mask; - writel_relaxed(gedr, c->regbase + GEDR_OFFSET); - - n = find_first_bit(&gedr, BITS_PER_LONG); - while (n < BITS_PER_LONG) { - loop = 1; - - generic_handle_irq(gpio_to_irq(gpio_base + n)); - n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); - } - } - } while (loop); -} - -static void pxa_ack_muxed_gpio(struct irq_data *d) -{ - int gpio = pxa_irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - - writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); -} - -static void pxa_mask_muxed_gpio(struct irq_data *d) -{ - int gpio = pxa_irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - uint32_t grer, gfer; - - c->irq_mask &= ~GPIO_bit(gpio); - - grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - writel_relaxed(grer, c->regbase + GRER_OFFSET); - writel_relaxed(gfer, c->regbase + GFER_OFFSET); -} - -static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on) -{ - int gpio = pxa_irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - - if (c->set_wake) - return c->set_wake(gpio, on); - else - return 0; -} - -static void pxa_unmask_muxed_gpio(struct irq_data *d) -{ - int gpio = pxa_irq_to_gpio(d->irq); - struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - - c->irq_mask |= GPIO_bit(gpio); - update_edge_detect(c); -} - -static struct irq_chip pxa_muxed_gpio_chip = { - .name = "GPIO", - .irq_ack = pxa_ack_muxed_gpio, - .irq_mask = pxa_mask_muxed_gpio, - .irq_unmask = pxa_unmask_muxed_gpio, - .irq_set_type = pxa_gpio_irq_type, - .irq_set_wake = pxa_gpio_set_wake, -}; - -static int pxa_gpio_nums(void) -{ - int count = 0; - -#ifdef CONFIG_ARCH_PXA - if (cpu_is_pxa25x()) { -#ifdef CONFIG_CPU_PXA26x - count = 89; - gpio_type = PXA26X_GPIO; -#elif defined(CONFIG_PXA25x) - count = 84; - gpio_type = PXA26X_GPIO; -#endif /* CONFIG_CPU_PXA26x */ - } else if (cpu_is_pxa27x()) { - count = 120; - gpio_type = PXA27X_GPIO; - } else if (cpu_is_pxa93x() || cpu_is_pxa95x()) { - count = 191; - gpio_type = PXA93X_GPIO; - } else if (cpu_is_pxa3xx()) { - count = 127; - gpio_type = PXA3XX_GPIO; - } -#endif /* CONFIG_ARCH_PXA */ - -#ifdef CONFIG_ARCH_MMP - if (cpu_is_pxa168() || cpu_is_pxa910()) { - count = 127; - gpio_type = MMP_GPIO; - } else if (cpu_is_mmp2()) { - count = 191; - gpio_type = MMP2_GPIO; - } -#endif /* CONFIG_ARCH_MMP */ - return count; -} - -static int __devinit pxa_gpio_probe(struct platform_device *pdev) -{ - struct pxa_gpio_chip *c; - struct resource *res; - struct clk *clk; - struct pxa_gpio_platform_data *info; - int gpio, irq, ret; - int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; - - pxa_last_gpio = pxa_gpio_nums(); - if (!pxa_last_gpio) - return -EINVAL; - - irq0 = platform_get_irq_byname(pdev, "gpio0"); - irq1 = platform_get_irq_byname(pdev, "gpio1"); - irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); - if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) - || (irq_mux <= 0)) - return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - gpio_reg_base = ioremap(res->start, resource_size(res)); - if (!gpio_reg_base) - return -EINVAL; - - if (irq0 > 0) - gpio_offset = 2; - - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "Error %ld to get gpio clock\n", - PTR_ERR(clk)); - iounmap(gpio_reg_base); - return PTR_ERR(clk); - } - ret = clk_prepare(clk); - if (ret) { - clk_put(clk); - iounmap(gpio_reg_base); - return ret; - } - ret = clk_enable(clk); - if (ret) { - clk_unprepare(clk); - clk_put(clk); - iounmap(gpio_reg_base); - return ret; - } - - /* Initialize GPIO chips */ - info = dev_get_platdata(&pdev->dev); - pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL); - - /* clear all GPIO edge detects */ - for_each_gpio_chip(gpio, c) { - writel_relaxed(0, c->regbase + GFER_OFFSET); - writel_relaxed(0, c->regbase + GRER_OFFSET); - writel_relaxed(~0,c->regbase + GEDR_OFFSET); - /* unmask GPIO edge detect for AP side */ - if (gpio_is_mmp_type(gpio_type)) - writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); - } - -#ifdef CONFIG_ARCH_PXA - irq = gpio_to_irq(0); - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); - - irq = gpio_to_irq(1); - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); -#endif - - for (irq = gpio_to_irq(gpio_offset); - irq <= gpio_to_irq(pxa_last_gpio); irq++) { - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - - irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); - return 0; -} - -static struct platform_driver pxa_gpio_driver = { - .probe = pxa_gpio_probe, - .driver = { - .name = "pxa-gpio", - }, -}; - -static int __init pxa_gpio_init(void) -{ - return platform_driver_register(&pxa_gpio_driver); -} -postcore_initcall(pxa_gpio_init); - -#ifdef CONFIG_PM -static int pxa_gpio_suspend(void) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET); - c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); - c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET); - c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET); - - /* Clear GPIO transition detect bits */ - writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET); - } - return 0; -} - -static void pxa_gpio_resume(void) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - /* restore level with set/clear */ - writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET); - writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET); - - writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET); - writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET); - writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET); - } -} -#else -#define pxa_gpio_suspend NULL -#define pxa_gpio_resume NULL -#endif - -struct syscore_ops pxa_gpio_syscore_ops = { - .suspend = pxa_gpio_suspend, - .resume = pxa_gpio_resume, -}; - -static int __init pxa_gpio_sysinit(void) -{ - register_syscore_ops(&pxa_gpio_syscore_ops); - return 0; -} -postcore_initcall(pxa_gpio_sysinit); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-rdc321x.c b/ANDROID_3.4.5/drivers/gpio/gpio-rdc321x.c deleted file mode 100644 index e97016af..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-rdc321x.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * RDC321x GPIO driver - * - * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> - * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/pci.h> -#include <linux/gpio.h> -#include <linux/mfd/rdc321x.h> -#include <linux/slab.h> - -struct rdc321x_gpio { - spinlock_t lock; - struct pci_dev *sb_pdev; - u32 data_reg[2]; - int reg1_ctrl_base; - int reg1_data_base; - int reg2_ctrl_base; - int reg2_data_base; - struct gpio_chip chip; -}; - -/* read GPIO pin */ -static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio) -{ - struct rdc321x_gpio *gpch; - u32 value = 0; - int reg; - - gpch = container_of(chip, struct rdc321x_gpio, chip); - reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base; - - spin_lock(&gpch->lock); - pci_write_config_dword(gpch->sb_pdev, reg, - gpch->data_reg[gpio < 32 ? 0 : 1]); - pci_read_config_dword(gpch->sb_pdev, reg, &value); - spin_unlock(&gpch->lock); - - return (1 << (gpio & 0x1f)) & value ? 1 : 0; -} - -static void rdc_gpio_set_value_impl(struct gpio_chip *chip, - unsigned gpio, int value) -{ - struct rdc321x_gpio *gpch; - int reg = (gpio < 32) ? 0 : 1; - - gpch = container_of(chip, struct rdc321x_gpio, chip); - - if (value) - gpch->data_reg[reg] |= 1 << (gpio & 0x1f); - else - gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f)); - - pci_write_config_dword(gpch->sb_pdev, - reg ? gpch->reg2_data_base : gpch->reg1_data_base, - gpch->data_reg[reg]); -} - -/* set GPIO pin to value */ -static void rdc_gpio_set_value(struct gpio_chip *chip, - unsigned gpio, int value) -{ - struct rdc321x_gpio *gpch; - - gpch = container_of(chip, struct rdc321x_gpio, chip); - spin_lock(&gpch->lock); - rdc_gpio_set_value_impl(chip, gpio, value); - spin_unlock(&gpch->lock); -} - -static int rdc_gpio_config(struct gpio_chip *chip, - unsigned gpio, int value) -{ - struct rdc321x_gpio *gpch; - int err; - u32 reg; - - gpch = container_of(chip, struct rdc321x_gpio, chip); - - spin_lock(&gpch->lock); - err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ? - gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, ®); - if (err) - goto unlock; - - reg |= 1 << (gpio & 0x1f); - - err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ? - gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg); - if (err) - goto unlock; - - rdc_gpio_set_value_impl(chip, gpio, value); - -unlock: - spin_unlock(&gpch->lock); - - return err; -} - -/* configure GPIO pin as input */ -static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) -{ - return rdc_gpio_config(chip, gpio, 1); -} - -/* - * Cache the initial value of both GPIO data registers - */ -static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) -{ - int err; - struct resource *r; - struct rdc321x_gpio *rdc321x_gpio_dev; - struct rdc321x_gpio_pdata *pdata; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data supplied\n"); - return -ENODEV; - } - - rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL); - if (!rdc321x_gpio_dev) { - dev_err(&pdev->dev, "failed to allocate private data\n"); - return -ENOMEM; - } - - r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1"); - if (!r) { - dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n"); - err = -ENODEV; - goto out_free; - } - - spin_lock_init(&rdc321x_gpio_dev->lock); - rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev; - rdc321x_gpio_dev->reg1_ctrl_base = r->start; - rdc321x_gpio_dev->reg1_data_base = r->start + 0x4; - - r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2"); - if (!r) { - dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n"); - err = -ENODEV; - goto out_free; - } - - rdc321x_gpio_dev->reg2_ctrl_base = r->start; - rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; - - rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; - rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; - rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; - rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; - rdc321x_gpio_dev->chip.set = rdc_gpio_set_value; - rdc321x_gpio_dev->chip.base = 0; - rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios; - - platform_set_drvdata(pdev, rdc321x_gpio_dev); - - /* This might not be, what others (BIOS, bootloader, etc.) - wrote to these registers before, but it's a good guess. Still - better than just using 0xffffffff. */ - err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, - rdc321x_gpio_dev->reg1_data_base, - &rdc321x_gpio_dev->data_reg[0]); - if (err) - goto out_drvdata; - - err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, - rdc321x_gpio_dev->reg2_data_base, - &rdc321x_gpio_dev->data_reg[1]); - if (err) - goto out_drvdata; - - dev_info(&pdev->dev, "registering %d GPIOs\n", - rdc321x_gpio_dev->chip.ngpio); - return gpiochip_add(&rdc321x_gpio_dev->chip); - -out_drvdata: - platform_set_drvdata(pdev, NULL); -out_free: - kfree(rdc321x_gpio_dev); - return err; -} - -static int __devexit rdc321x_gpio_remove(struct platform_device *pdev) -{ - int ret; - struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev); - - ret = gpiochip_remove(&rdc321x_gpio_dev->chip); - if (ret) - dev_err(&pdev->dev, "failed to unregister chip\n"); - - kfree(rdc321x_gpio_dev); - platform_set_drvdata(pdev, NULL); - - return ret; -} - -static struct platform_driver rdc321x_gpio_driver = { - .driver.name = "rdc321x-gpio", - .driver.owner = THIS_MODULE, - .probe = rdc321x_gpio_probe, - .remove = __devexit_p(rdc321x_gpio_remove), -}; - -module_platform_driver(rdc321x_gpio_driver); - -MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); -MODULE_DESCRIPTION("RDC321x GPIO driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:rdc321x-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-sa1100.c b/ANDROID_3.4.5/drivers/gpio/gpio-sa1100.c deleted file mode 100644 index 8ea3b33d..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-sa1100.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/gpio.c - * - * Generic SA-1100 GPIO handling - * - * 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/gpio.h> -#include <linux/init.h> -#include <linux/module.h> - -#include <mach/hardware.h> -#include <mach/irqs.h> - -static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return GPLR & GPIO_GPIO(offset); -} - -static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (value) - GPSR = GPIO_GPIO(offset); - else - GPCR = GPIO_GPIO(offset); -} - -static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) -{ - unsigned long flags; - - local_irq_save(flags); - GPDR &= ~GPIO_GPIO(offset); - local_irq_restore(flags); - return 0; -} - -static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) -{ - unsigned long flags; - - local_irq_save(flags); - sa1100_gpio_set(chip, offset, value); - GPDR |= GPIO_GPIO(offset); - local_irq_restore(flags); - return 0; -} - -static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return offset < 11 ? (IRQ_GPIO0 + offset) : (IRQ_GPIO11 - 11 + offset); -} - -static struct gpio_chip sa1100_gpio_chip = { - .label = "gpio", - .direction_input = sa1100_direction_input, - .direction_output = sa1100_direction_output, - .set = sa1100_gpio_set, - .get = sa1100_gpio_get, - .to_irq = sa1100_to_irq, - .base = 0, - .ngpio = GPIO_MAX + 1, -}; - -void __init sa1100_init_gpio(void) -{ - gpiochip_add(&sa1100_gpio_chip); -} diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-samsung.c b/ANDROID_3.4.5/drivers/gpio/gpio-samsung.c deleted file mode 100644 index e991d917..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-samsung.c +++ /dev/null @@ -1,3205 +0,0 @@ -/* - * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * SAMSUNG - GPIOlib support - * - * 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/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/ioport.h> -#include <linux/of.h> -#include <linux/slab.h> -#include <linux/of_address.h> - -#include <asm/irq.h> - -#include <mach/hardware.h> -#include <mach/map.h> -#include <mach/regs-clock.h> -#include <mach/regs-gpio.h> - -#include <plat/cpu.h> -#include <plat/gpio-core.h> -#include <plat/gpio-cfg.h> -#include <plat/gpio-cfg-helpers.h> -#include <plat/gpio-fns.h> -#include <plat/pm.h> - -#ifndef DEBUG_GPIO -#define gpio_dbg(x...) do { } while (0) -#else -#define gpio_dbg(x...) printk(KERN_DEBUG x) -#endif - -int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull) -{ - void __iomem *reg = chip->base + 0x08; - int shift = off * 2; - u32 pup; - - pup = __raw_readl(reg); - pup &= ~(3 << shift); - pup |= pull << shift; - __raw_writel(pup, reg); - - return 0; -} - -samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip, - unsigned int off) -{ - void __iomem *reg = chip->base + 0x08; - int shift = off * 2; - u32 pup = __raw_readl(reg); - - pup >>= shift; - pup &= 0x3; - - return (__force samsung_gpio_pull_t)pup; -} - -int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull) -{ - switch (pull) { - case S3C_GPIO_PULL_NONE: - pull = 0x01; - break; - case S3C_GPIO_PULL_UP: - pull = 0x00; - break; - case S3C_GPIO_PULL_DOWN: - pull = 0x02; - break; - } - return samsung_gpio_setpull_updown(chip, off, pull); -} - -samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip, - unsigned int off) -{ - samsung_gpio_pull_t pull; - - pull = samsung_gpio_getpull_updown(chip, off); - - switch (pull) { - case 0x00: - pull = S3C_GPIO_PULL_UP; - break; - case 0x01: - case 0x03: - pull = S3C_GPIO_PULL_NONE; - break; - case 0x02: - pull = S3C_GPIO_PULL_DOWN; - break; - } - - return pull; -} - -static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull, - samsung_gpio_pull_t updown) -{ - void __iomem *reg = chip->base + 0x08; - u32 pup = __raw_readl(reg); - - if (pull == updown) - pup &= ~(1 << off); - else if (pull == S3C_GPIO_PULL_NONE) - pup |= (1 << off); - else - return -EINVAL; - - __raw_writel(pup, reg); - return 0; -} - -static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip, - unsigned int off, - samsung_gpio_pull_t updown) -{ - void __iomem *reg = chip->base + 0x08; - u32 pup = __raw_readl(reg); - - pup &= (1 << off); - return pup ? S3C_GPIO_PULL_NONE : updown; -} - -samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip, - unsigned int off) -{ - return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP); -} - -int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull) -{ - return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP); -} - -samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip, - unsigned int off) -{ - return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN); -} - -int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull) -{ - return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN); -} - -static int exynos_gpio_setpull(struct samsung_gpio_chip *chip, - unsigned int off, samsung_gpio_pull_t pull) -{ - if (pull == S3C_GPIO_PULL_UP) - pull = 3; - - return samsung_gpio_setpull_updown(chip, off, pull); -} - -static samsung_gpio_pull_t exynos_gpio_getpull(struct samsung_gpio_chip *chip, - unsigned int off) -{ - samsung_gpio_pull_t pull; - - pull = samsung_gpio_getpull_updown(chip, off); - - if (pull == 3) - pull = S3C_GPIO_PULL_UP; - - return pull; -} - -/* - * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration. - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * @cfg: The configuration value to set. - * - * This helper deal with the GPIO cases where the control register - * has two bits of configuration per gpio, which have the following - * functions: - * 00 = input - * 01 = output - * 1x = special function - */ - -static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip, - unsigned int off, unsigned int cfg) -{ - void __iomem *reg = chip->base; - unsigned int shift = off * 2; - u32 con; - - if (samsung_gpio_is_cfg_special(cfg)) { - cfg &= 0xf; - if (cfg > 3) - return -EINVAL; - - cfg <<= shift; - } - - con = __raw_readl(reg); - con &= ~(0x3 << shift); - con |= cfg; - __raw_writel(con, reg); - - return 0; -} - -/* - * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read. - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * - * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which - * could be directly passed back to samsung_gpio_setcfg_2bit(), from the - * S3C_GPIO_SPECIAL() macro. - */ - -static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip, - unsigned int off) -{ - u32 con; - - con = __raw_readl(chip->base); - con >>= off * 2; - con &= 3; - - /* this conversion works for IN and OUT as well as special mode */ - return S3C_GPIO_SPECIAL(con); -} - -/* - * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config. - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * @cfg: The configuration value to set. - * - * This helper deal with the GPIO cases where the control register has 4 bits - * of control per GPIO, generally in the form of: - * 0000 = Input - * 0001 = Output - * others = Special functions (dependent on bank) - * - * Note, since the code to deal with the case where there are two control - * registers instead of one, we do not have a separate set of functions for - * each case. - */ - -static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip, - unsigned int off, unsigned int cfg) -{ - void __iomem *reg = chip->base; - unsigned int shift = (off & 7) * 4; - u32 con; - - if (off < 8 && chip->chip.ngpio > 8) - reg -= 4; - - if (samsung_gpio_is_cfg_special(cfg)) { - cfg &= 0xf; - cfg <<= shift; - } - - con = __raw_readl(reg); - con &= ~(0xf << shift); - con |= cfg; - __raw_writel(con, reg); - - return 0; -} - -/* - * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read. - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * - * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration - * register setting into a value the software can use, such as could be passed - * to samsung_gpio_setcfg_4bit(). - * - * @sa samsung_gpio_getcfg_2bit - */ - -static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip, - unsigned int off) -{ - void __iomem *reg = chip->base; - unsigned int shift = (off & 7) * 4; - u32 con; - - if (off < 8 && chip->chip.ngpio > 8) - reg -= 4; - - con = __raw_readl(reg); - con >>= shift; - con &= 0xf; - - /* this conversion works for IN and OUT as well as special mode */ - return S3C_GPIO_SPECIAL(con); -} - -#ifdef CONFIG_PLAT_S3C24XX -/* - * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A) - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * @cfg: The configuration value to set. - * - * This helper deal with the GPIO cases where the control register - * has one bit of configuration for the gpio, where setting the bit - * means the pin is in special function mode and unset means output. - */ - -static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip, - unsigned int off, unsigned int cfg) -{ - void __iomem *reg = chip->base; - unsigned int shift = off; - u32 con; - - if (samsung_gpio_is_cfg_special(cfg)) { - cfg &= 0xf; - - /* Map output to 0, and SFN2 to 1 */ - cfg -= 1; - if (cfg > 1) - return -EINVAL; - - cfg <<= shift; - } - - con = __raw_readl(reg); - con &= ~(0x1 << shift); - con |= cfg; - __raw_writel(con, reg); - - return 0; -} - -/* - * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A) - * @chip: The gpio chip that is being configured. - * @off: The offset for the GPIO being configured. - * - * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable - * GPIO configuration value. - * - * @sa samsung_gpio_getcfg_2bit - * @sa samsung_gpio_getcfg_4bit - */ - -static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip, - unsigned int off) -{ - u32 con; - - con = __raw_readl(chip->base); - con >>= off; - con &= 1; - con++; - - return S3C_GPIO_SFN(con); -} -#endif - -#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) -static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip, - unsigned int off, unsigned int cfg) -{ - void __iomem *reg = chip->base; - unsigned int shift; - u32 con; - - switch (off) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - shift = (off & 7) * 4; - reg -= 4; - break; - case 6: - shift = ((off + 1) & 7) * 4; - reg -= 4; - default: - shift = ((off + 1) & 7) * 4; - break; - } - - if (samsung_gpio_is_cfg_special(cfg)) { - cfg &= 0xf; - cfg <<= shift; - } - - con = __raw_readl(reg); - con &= ~(0xf << shift); - con |= cfg; - __raw_writel(con, reg); - - return 0; -} -#endif - -static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg, - int nr_chips) -{ - for (; nr_chips > 0; nr_chips--, chipcfg++) { - if (!chipcfg->set_config) - chipcfg->set_config = samsung_gpio_setcfg_4bit; - if (!chipcfg->get_config) - chipcfg->get_config = samsung_gpio_getcfg_4bit; - if (!chipcfg->set_pull) - chipcfg->set_pull = samsung_gpio_setpull_updown; - if (!chipcfg->get_pull) - chipcfg->get_pull = samsung_gpio_getpull_updown; - } -} - -struct samsung_gpio_cfg s3c24xx_gpiocfg_default = { - .set_config = samsung_gpio_setcfg_2bit, - .get_config = samsung_gpio_getcfg_2bit, -}; - -#ifdef CONFIG_PLAT_S3C24XX -static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { - .set_config = s3c24xx_gpio_setcfg_abank, - .get_config = s3c24xx_gpio_getcfg_abank, -}; -#endif - -#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) -static struct samsung_gpio_cfg exynos_gpio_cfg = { - .set_pull = exynos_gpio_setpull, - .get_pull = exynos_gpio_getpull, - .set_config = samsung_gpio_setcfg_4bit, - .get_config = samsung_gpio_getcfg_4bit, -}; -#endif - -#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) -static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = { - .cfg_eint = 0x3, - .set_config = s5p64x0_gpio_setcfg_rbank, - .get_config = samsung_gpio_getcfg_4bit, - .set_pull = samsung_gpio_setpull_updown, - .get_pull = samsung_gpio_getpull_updown, -}; -#endif - -static struct samsung_gpio_cfg samsung_gpio_cfgs[] = { - [0] = { - .cfg_eint = 0x0, - }, - [1] = { - .cfg_eint = 0x3, - }, - [2] = { - .cfg_eint = 0x7, - }, - [3] = { - .cfg_eint = 0xF, - }, - [4] = { - .cfg_eint = 0x0, - .set_config = samsung_gpio_setcfg_2bit, - .get_config = samsung_gpio_getcfg_2bit, - }, - [5] = { - .cfg_eint = 0x2, - .set_config = samsung_gpio_setcfg_2bit, - .get_config = samsung_gpio_getcfg_2bit, - }, - [6] = { - .cfg_eint = 0x3, - .set_config = samsung_gpio_setcfg_2bit, - .get_config = samsung_gpio_getcfg_2bit, - }, - [7] = { - .set_config = samsung_gpio_setcfg_2bit, - .get_config = samsung_gpio_getcfg_2bit, - }, - [8] = { - .set_pull = exynos_gpio_setpull, - .get_pull = exynos_gpio_getpull, - }, - [9] = { - .cfg_eint = 0x3, - .set_pull = exynos_gpio_setpull, - .get_pull = exynos_gpio_getpull, - } -}; - -/* - * 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 samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long con; - - samsung_gpio_lock(ourchip, flags); - - con = __raw_readl(base + 0x00); - con &= ~(3 << (offset * 2)); - - __raw_writel(con, base + 0x00); - - samsung_gpio_unlock(ourchip, flags); - return 0; -} - -static int samsung_gpiolib_2bit_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long dat; - unsigned long con; - - samsung_gpio_lock(ourchip, 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); - - samsung_gpio_unlock(ourchip, flags); - return 0; -} - -/* - * The samsung_gpiolib_4bit routines are to control the gpio banks where - * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the - * following example: - * - * base + 0x00: Control register, 4 bits per gpio - * gpio n: 4 bits starting at (4*n) - * 0000 = input, 0001 = output, others mean special-function - * base + 0x04: Data register, 1 bit per gpio - * bit n: data bit n - * - * Note, since the data register is one bit per gpio and is at base + 0x4 - * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the - * state of the output. - */ - -static int samsung_gpiolib_4bit_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long con; - - con = __raw_readl(base + GPIOCON_OFF); - con &= ~(0xf << con_4bit_shift(offset)); - __raw_writel(con, base + GPIOCON_OFF); - - gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); - - return 0; -} - -static int samsung_gpiolib_4bit_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long con; - unsigned long dat; - - con = __raw_readl(base + GPIOCON_OFF); - con &= ~(0xf << con_4bit_shift(offset)); - con |= 0x1 << con_4bit_shift(offset); - - dat = __raw_readl(base + GPIODAT_OFF); - - if (value) - dat |= 1 << offset; - else - dat &= ~(1 << offset); - - __raw_writel(dat, base + GPIODAT_OFF); - __raw_writel(con, base + GPIOCON_OFF); - __raw_writel(dat, base + GPIODAT_OFF); - - gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); - - return 0; -} - -/* - * The next set of routines are for the case where the GPIO configuration - * registers are 4 bits per GPIO but there is more than one register (the - * bank has more than 8 GPIOs. - * - * This case is the similar to the 4 bit case, but the registers are as - * follows: - * - * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs) - * gpio n: 4 bits starting at (4*n) - * 0000 = input, 0001 = output, others mean special-function - * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs) - * gpio n: 4 bits starting at (4*n) - * 0000 = input, 0001 = output, others mean special-function - * base + 0x08: Data register, 1 bit per gpio - * bit n: data bit n - * - * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set - * routines we store the 'base + 0x4' address so that these routines see - * the data register at ourchip->base + 0x04. - */ - -static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - - if (offset > 7) - offset -= 8; - else - regcon -= 4; - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(offset)); - __raw_writel(con, regcon); - - gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con); - - return 0; -} - -static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - unsigned long dat; - unsigned con_offset = offset; - - if (con_offset > 7) - con_offset -= 8; - else - regcon -= 4; - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(con_offset)); - con |= 0x1 << con_4bit_shift(con_offset); - - dat = __raw_readl(base + GPIODAT_OFF); - - if (value) - dat |= 1 << offset; - else - dat &= ~(1 << offset); - - __raw_writel(dat, base + GPIODAT_OFF); - __raw_writel(con, regcon); - __raw_writel(dat, base + GPIODAT_OFF); - - gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); - - return 0; -} - -#ifdef CONFIG_PLAT_S3C24XX -/* The next set of routines are for the case of s3c24xx bank a */ - -static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset) -{ - return -EINVAL; -} - -static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long dat; - unsigned long con; - - local_irq_save(flags); - - con = __raw_readl(base + 0x00); - dat = __raw_readl(base + 0x04); - - dat &= ~(1 << offset); - if (value) - dat |= 1 << offset; - - __raw_writel(dat, base + 0x04); - - con &= ~(1 << offset); - - __raw_writel(con, base + 0x00); - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); - return 0; -} -#endif - -/* The next set of routines are for the case of s5p64x0 bank r */ - -static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - unsigned long flags; - - switch (offset) { - case 6: - offset += 1; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - regcon -= 4; - break; - default: - offset -= 7; - break; - } - - samsung_gpio_lock(ourchip, flags); - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(offset)); - __raw_writel(con, regcon); - - samsung_gpio_unlock(ourchip, flags); - - return 0; -} - -static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - void __iomem *regcon = base; - unsigned long con; - unsigned long dat; - unsigned long flags; - unsigned con_offset = offset; - - switch (con_offset) { - case 6: - con_offset += 1; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - regcon -= 4; - break; - default: - con_offset -= 7; - break; - } - - samsung_gpio_lock(ourchip, flags); - - con = __raw_readl(regcon); - con &= ~(0xf << con_4bit_shift(con_offset)); - con |= 0x1 << con_4bit_shift(con_offset); - - dat = __raw_readl(base + GPIODAT_OFF); - if (value) - dat |= 1 << offset; - else - dat &= ~(1 << offset); - - __raw_writel(con, regcon); - __raw_writel(dat, base + GPIODAT_OFF); - - samsung_gpio_unlock(ourchip, flags); - - return 0; -} - -static void samsung_gpiolib_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long dat; - - samsung_gpio_lock(ourchip, flags); - - dat = __raw_readl(base + 0x04); - dat &= ~(1 << offset); - if (value) - dat |= 1 << offset; - __raw_writel(dat, base + 0x04); - - samsung_gpio_unlock(ourchip, flags); -} - -static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset) -{ - struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip); - unsigned long val; - - val = __raw_readl(ourchip->base + 0x04); - val >>= offset; - val &= 1; - - return val; -} - -/* - * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios - * for use with the configuration calls, and other parts of the s3c gpiolib - * support code. - * - * Not all s3c support code will need this, as some configurations of cpu - * may only support one or two different configuration options and have an - * easy gpio to samsung_gpio_chip mapping function. If this is the case, then - * the machine support file should provide its own samsung_gpiolib_getchip() - * and any other necessary functions. - */ - -#ifdef CONFIG_S3C_GPIO_TRACK -struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END]; - -static __init void s3c_gpiolib_track(struct samsung_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 */ - -/* - * samsung_gpiolib_add() - add the Samsung gpio_chip. - * @chip: The chip to register - * - * This is a wrapper to gpiochip_add() that takes our specific gpio chip - * information and makes the necessary alterations for the platform and - * notes the information for use with the configuration systems and any - * other parts of the system. - */ - -static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip) -{ - struct gpio_chip *gc = &chip->chip; - int ret; - - BUG_ON(!chip->base); - BUG_ON(!gc->label); - BUG_ON(!gc->ngpio); - - spin_lock_init(&chip->lock); - - if (!gc->direction_input) - gc->direction_input = samsung_gpiolib_2bit_input; - if (!gc->direction_output) - gc->direction_output = samsung_gpiolib_2bit_output; - if (!gc->set) - gc->set = samsung_gpiolib_set; - if (!gc->get) - gc->get = samsung_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); -} - -static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, - int nr_chips, void __iomem *base) -{ - int i; - struct gpio_chip *gc = &chip->chip; - - for (i = 0 ; i < nr_chips; i++, chip++) { - /* skip banks not present on SoC */ - if (chip->chip.base >= S3C_GPIO_END) - continue; - - if (!chip->config) - chip->config = &s3c24xx_gpiocfg_default; - if (!chip->pm) - chip->pm = __gpio_pm(&samsung_gpio_pm_2bit); - if ((base != NULL) && (chip->base == NULL)) - chip->base = base + ((i) * 0x10); - - if (!gc->direction_input) - gc->direction_input = samsung_gpiolib_2bit_input; - if (!gc->direction_output) - gc->direction_output = samsung_gpiolib_2bit_output; - - samsung_gpiolib_add(chip); - } -} - -static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip, - int nr_chips, void __iomem *base, - unsigned int offset) -{ - int i; - - for (i = 0 ; i < nr_chips; i++, chip++) { - chip->chip.direction_input = samsung_gpiolib_2bit_input; - chip->chip.direction_output = samsung_gpiolib_2bit_output; - - if (!chip->config) - chip->config = &samsung_gpio_cfgs[7]; - if (!chip->pm) - chip->pm = __gpio_pm(&samsung_gpio_pm_2bit); - if ((base != NULL) && (chip->base == NULL)) - chip->base = base + ((i) * offset); - - samsung_gpiolib_add(chip); - } -} - -/* - * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config. - * @chip: The gpio chip that is being configured. - * @nr_chips: The no of chips (gpio ports) for the GPIO being configured. - * - * This helper deal with the GPIO cases where the control register has 4 bits - * of control per GPIO, generally in the form of: - * 0000 = Input - * 0001 = Output - * others = Special functions (dependent on bank) - * - * Note, since the code to deal with the case where there are two control - * registers instead of one, we do not have a separate set of function - * (samsung_gpiolib_add_4bit2_chips)for each case. - */ - -static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip, - int nr_chips, void __iomem *base) -{ - int i; - - for (i = 0 ; i < nr_chips; i++, chip++) { - chip->chip.direction_input = samsung_gpiolib_4bit_input; - chip->chip.direction_output = samsung_gpiolib_4bit_output; - - if (!chip->config) - chip->config = &samsung_gpio_cfgs[2]; - if (!chip->pm) - chip->pm = __gpio_pm(&samsung_gpio_pm_4bit); - if ((base != NULL) && (chip->base == NULL)) - chip->base = base + ((i) * 0x20); - - samsung_gpiolib_add(chip); - } -} - -static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip, - int nr_chips) -{ - for (; nr_chips > 0; nr_chips--, chip++) { - chip->chip.direction_input = samsung_gpiolib_4bit2_input; - chip->chip.direction_output = samsung_gpiolib_4bit2_output; - - if (!chip->config) - chip->config = &samsung_gpio_cfgs[2]; - if (!chip->pm) - chip->pm = __gpio_pm(&samsung_gpio_pm_4bit); - - samsung_gpiolib_add(chip); - } -} - -static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip, - int nr_chips) -{ - for (; nr_chips > 0; nr_chips--, chip++) { - chip->chip.direction_input = s5p64x0_gpiolib_rbank_input; - chip->chip.direction_output = s5p64x0_gpiolib_rbank_output; - - if (!chip->pm) - chip->pm = __gpio_pm(&samsung_gpio_pm_4bit); - - samsung_gpiolib_add(chip); - } -} - -int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip); - - return samsung_chip->irq_base + offset; -} - -#ifdef CONFIG_PLAT_S3C24XX -static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset) -{ - if (offset < 4) - return IRQ_EINT0 + offset; - - if (offset < 8) - return IRQ_EINT4 + offset - 4; - - return -EINVAL; -} -#endif - -#ifdef CONFIG_PLAT_S3C64XX -static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin) -{ - return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO; -} - -static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin) -{ - return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO; -} -#endif - -struct samsung_gpio_chip s3c24xx_gpios[] = { -#ifdef CONFIG_PLAT_S3C24XX - { - .config = &s3c24xx_gpiocfg_banka, - .chip = { - .base = S3C2410_GPA(0), - .owner = THIS_MODULE, - .label = "GPIOA", - .ngpio = 24, - .direction_input = s3c24xx_gpiolib_banka_input, - .direction_output = s3c24xx_gpiolib_banka_output, - }, - }, { - .chip = { - .base = S3C2410_GPB(0), - .owner = THIS_MODULE, - .label = "GPIOB", - .ngpio = 16, - }, - }, { - .chip = { - .base = S3C2410_GPC(0), - .owner = THIS_MODULE, - .label = "GPIOC", - .ngpio = 16, - }, - }, { - .chip = { - .base = S3C2410_GPD(0), - .owner = THIS_MODULE, - .label = "GPIOD", - .ngpio = 16, - }, - }, { - .chip = { - .base = S3C2410_GPE(0), - .label = "GPIOE", - .owner = THIS_MODULE, - .ngpio = 16, - }, - }, { - .chip = { - .base = S3C2410_GPF(0), - .owner = THIS_MODULE, - .label = "GPIOF", - .ngpio = 8, - .to_irq = s3c24xx_gpiolib_fbank_to_irq, - }, - }, { - .irq_base = IRQ_EINT8, - .chip = { - .base = S3C2410_GPG(0), - .owner = THIS_MODULE, - .label = "GPIOG", - .ngpio = 16, - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .chip = { - .base = S3C2410_GPH(0), - .owner = THIS_MODULE, - .label = "GPIOH", - .ngpio = 11, - }, - }, - /* GPIOS for the S3C2443 and later devices. */ - { - .base = S3C2440_GPJCON, - .chip = { - .base = S3C2410_GPJ(0), - .owner = THIS_MODULE, - .label = "GPIOJ", - .ngpio = 16, - }, - }, { - .base = S3C2443_GPKCON, - .chip = { - .base = S3C2410_GPK(0), - .owner = THIS_MODULE, - .label = "GPIOK", - .ngpio = 16, - }, - }, { - .base = S3C2443_GPLCON, - .chip = { - .base = S3C2410_GPL(0), - .owner = THIS_MODULE, - .label = "GPIOL", - .ngpio = 15, - }, - }, { - .base = S3C2443_GPMCON, - .chip = { - .base = S3C2410_GPM(0), - .owner = THIS_MODULE, - .label = "GPIOM", - .ngpio = 2, - }, - }, -#endif -}; - -/* - * GPIO bank summary: - * - * Bank GPIOs Style SlpCon ExtInt Group - * A 8 4Bit Yes 1 - * B 7 4Bit Yes 1 - * C 8 4Bit Yes 2 - * D 5 4Bit Yes 3 - * E 5 4Bit Yes None - * F 16 2Bit Yes 4 [1] - * G 7 4Bit Yes 5 - * H 10 4Bit[2] Yes 6 - * I 16 2Bit Yes None - * J 12 2Bit Yes None - * K 16 4Bit[2] No None - * L 15 4Bit[2] No None - * M 6 4Bit No IRQ_EINT - * N 16 2Bit No IRQ_EINT - * O 16 2Bit Yes 7 - * P 15 2Bit Yes 8 - * Q 9 2Bit Yes 9 - * - * [1] BANKF pins 14,15 do not form part of the external interrupt sources - * [2] BANK has two control registers, GPxCON0 and GPxCON1 - */ - -static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = { -#ifdef CONFIG_PLAT_S3C64XX - { - .chip = { - .base = S3C64XX_GPA(0), - .ngpio = S3C64XX_GPIO_A_NR, - .label = "GPA", - }, - }, { - .chip = { - .base = S3C64XX_GPB(0), - .ngpio = S3C64XX_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = S3C64XX_GPC(0), - .ngpio = S3C64XX_GPIO_C_NR, - .label = "GPC", - }, - }, { - .chip = { - .base = S3C64XX_GPD(0), - .ngpio = S3C64XX_GPIO_D_NR, - .label = "GPD", - }, - }, { - .config = &samsung_gpio_cfgs[0], - .chip = { - .base = S3C64XX_GPE(0), - .ngpio = S3C64XX_GPIO_E_NR, - .label = "GPE", - }, - }, { - .base = S3C64XX_GPG_BASE, - .chip = { - .base = S3C64XX_GPG(0), - .ngpio = S3C64XX_GPIO_G_NR, - .label = "GPG", - }, - }, { - .base = S3C64XX_GPM_BASE, - .config = &samsung_gpio_cfgs[1], - .chip = { - .base = S3C64XX_GPM(0), - .ngpio = S3C64XX_GPIO_M_NR, - .label = "GPM", - .to_irq = s3c64xx_gpiolib_mbank_to_irq, - }, - }, -#endif -}; - -static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = { -#ifdef CONFIG_PLAT_S3C64XX - { - .base = S3C64XX_GPH_BASE + 0x4, - .chip = { - .base = S3C64XX_GPH(0), - .ngpio = S3C64XX_GPIO_H_NR, - .label = "GPH", - }, - }, { - .base = S3C64XX_GPK_BASE + 0x4, - .config = &samsung_gpio_cfgs[0], - .chip = { - .base = S3C64XX_GPK(0), - .ngpio = S3C64XX_GPIO_K_NR, - .label = "GPK", - }, - }, { - .base = S3C64XX_GPL_BASE + 0x4, - .config = &samsung_gpio_cfgs[1], - .chip = { - .base = S3C64XX_GPL(0), - .ngpio = S3C64XX_GPIO_L_NR, - .label = "GPL", - .to_irq = s3c64xx_gpiolib_lbank_to_irq, - }, - }, -#endif -}; - -static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = { -#ifdef CONFIG_PLAT_S3C64XX - { - .base = S3C64XX_GPF_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S3C64XX_GPF(0), - .ngpio = S3C64XX_GPIO_F_NR, - .label = "GPF", - }, - }, { - .config = &samsung_gpio_cfgs[7], - .chip = { - .base = S3C64XX_GPI(0), - .ngpio = S3C64XX_GPIO_I_NR, - .label = "GPI", - }, - }, { - .config = &samsung_gpio_cfgs[7], - .chip = { - .base = S3C64XX_GPJ(0), - .ngpio = S3C64XX_GPIO_J_NR, - .label = "GPJ", - }, - }, { - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S3C64XX_GPO(0), - .ngpio = S3C64XX_GPIO_O_NR, - .label = "GPO", - }, - }, { - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S3C64XX_GPP(0), - .ngpio = S3C64XX_GPIO_P_NR, - .label = "GPP", - }, - }, { - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S3C64XX_GPQ(0), - .ngpio = S3C64XX_GPIO_Q_NR, - .label = "GPQ", - }, - }, { - .base = S3C64XX_GPN_BASE, - .irq_base = IRQ_EINT(0), - .config = &samsung_gpio_cfgs[5], - .chip = { - .base = S3C64XX_GPN(0), - .ngpio = S3C64XX_GPIO_N_NR, - .label = "GPN", - .to_irq = samsung_gpiolib_to_irq, - }, - }, -#endif -}; - -/* - * S5P6440 GPIO bank summary: - * - * Bank GPIOs Style SlpCon ExtInt Group - * A 6 4Bit Yes 1 - * B 7 4Bit Yes 1 - * C 8 4Bit Yes 2 - * F 2 2Bit Yes 4 [1] - * G 7 4Bit Yes 5 - * H 10 4Bit[2] Yes 6 - * I 16 2Bit Yes None - * J 12 2Bit Yes None - * N 16 2Bit No IRQ_EINT - * P 8 2Bit Yes 8 - * R 15 4Bit[2] Yes 8 - */ - -static struct samsung_gpio_chip s5p6440_gpios_4bit[] = { -#ifdef CONFIG_CPU_S5P6440 - { - .chip = { - .base = S5P6440_GPA(0), - .ngpio = S5P6440_GPIO_A_NR, - .label = "GPA", - }, - }, { - .chip = { - .base = S5P6440_GPB(0), - .ngpio = S5P6440_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = S5P6440_GPC(0), - .ngpio = S5P6440_GPIO_C_NR, - .label = "GPC", - }, - }, { - .base = S5P64X0_GPG_BASE, - .chip = { - .base = S5P6440_GPG(0), - .ngpio = S5P6440_GPIO_G_NR, - .label = "GPG", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = { -#ifdef CONFIG_CPU_S5P6440 - { - .base = S5P64X0_GPH_BASE + 0x4, - .chip = { - .base = S5P6440_GPH(0), - .ngpio = S5P6440_GPIO_H_NR, - .label = "GPH", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6440_gpios_rbank[] = { -#ifdef CONFIG_CPU_S5P6440 - { - .base = S5P64X0_GPR_BASE + 0x4, - .config = &s5p64x0_gpio_cfg_rbank, - .chip = { - .base = S5P6440_GPR(0), - .ngpio = S5P6440_GPIO_R_NR, - .label = "GPR", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6440_gpios_2bit[] = { -#ifdef CONFIG_CPU_S5P6440 - { - .base = S5P64X0_GPF_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S5P6440_GPF(0), - .ngpio = S5P6440_GPIO_F_NR, - .label = "GPF", - }, - }, { - .base = S5P64X0_GPI_BASE, - .config = &samsung_gpio_cfgs[4], - .chip = { - .base = S5P6440_GPI(0), - .ngpio = S5P6440_GPIO_I_NR, - .label = "GPI", - }, - }, { - .base = S5P64X0_GPJ_BASE, - .config = &samsung_gpio_cfgs[4], - .chip = { - .base = S5P6440_GPJ(0), - .ngpio = S5P6440_GPIO_J_NR, - .label = "GPJ", - }, - }, { - .base = S5P64X0_GPN_BASE, - .config = &samsung_gpio_cfgs[5], - .chip = { - .base = S5P6440_GPN(0), - .ngpio = S5P6440_GPIO_N_NR, - .label = "GPN", - }, - }, { - .base = S5P64X0_GPP_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S5P6440_GPP(0), - .ngpio = S5P6440_GPIO_P_NR, - .label = "GPP", - }, - }, -#endif -}; - -/* - * S5P6450 GPIO bank summary: - * - * Bank GPIOs Style SlpCon ExtInt Group - * A 6 4Bit Yes 1 - * B 7 4Bit Yes 1 - * C 8 4Bit Yes 2 - * D 8 4Bit Yes None - * F 2 2Bit Yes None - * G 14 4Bit[2] Yes 5 - * H 10 4Bit[2] Yes 6 - * I 16 2Bit Yes None - * J 12 2Bit Yes None - * K 5 4Bit Yes None - * N 16 2Bit No IRQ_EINT - * P 11 2Bit Yes 8 - * Q 14 2Bit Yes None - * R 15 4Bit[2] Yes None - * S 8 2Bit Yes None - * - * [1] BANKF pins 14,15 do not form part of the external interrupt sources - * [2] BANK has two control registers, GPxCON0 and GPxCON1 - */ - -static struct samsung_gpio_chip s5p6450_gpios_4bit[] = { -#ifdef CONFIG_CPU_S5P6450 - { - .chip = { - .base = S5P6450_GPA(0), - .ngpio = S5P6450_GPIO_A_NR, - .label = "GPA", - }, - }, { - .chip = { - .base = S5P6450_GPB(0), - .ngpio = S5P6450_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = S5P6450_GPC(0), - .ngpio = S5P6450_GPIO_C_NR, - .label = "GPC", - }, - }, { - .chip = { - .base = S5P6450_GPD(0), - .ngpio = S5P6450_GPIO_D_NR, - .label = "GPD", - }, - }, { - .base = S5P6450_GPK_BASE, - .chip = { - .base = S5P6450_GPK(0), - .ngpio = S5P6450_GPIO_K_NR, - .label = "GPK", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = { -#ifdef CONFIG_CPU_S5P6450 - { - .base = S5P64X0_GPG_BASE + 0x4, - .chip = { - .base = S5P6450_GPG(0), - .ngpio = S5P6450_GPIO_G_NR, - .label = "GPG", - }, - }, { - .base = S5P64X0_GPH_BASE + 0x4, - .chip = { - .base = S5P6450_GPH(0), - .ngpio = S5P6450_GPIO_H_NR, - .label = "GPH", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6450_gpios_rbank[] = { -#ifdef CONFIG_CPU_S5P6450 - { - .base = S5P64X0_GPR_BASE + 0x4, - .config = &s5p64x0_gpio_cfg_rbank, - .chip = { - .base = S5P6450_GPR(0), - .ngpio = S5P6450_GPIO_R_NR, - .label = "GPR", - }, - }, -#endif -}; - -static struct samsung_gpio_chip s5p6450_gpios_2bit[] = { -#ifdef CONFIG_CPU_S5P6450 - { - .base = S5P64X0_GPF_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S5P6450_GPF(0), - .ngpio = S5P6450_GPIO_F_NR, - .label = "GPF", - }, - }, { - .base = S5P64X0_GPI_BASE, - .config = &samsung_gpio_cfgs[4], - .chip = { - .base = S5P6450_GPI(0), - .ngpio = S5P6450_GPIO_I_NR, - .label = "GPI", - }, - }, { - .base = S5P64X0_GPJ_BASE, - .config = &samsung_gpio_cfgs[4], - .chip = { - .base = S5P6450_GPJ(0), - .ngpio = S5P6450_GPIO_J_NR, - .label = "GPJ", - }, - }, { - .base = S5P64X0_GPN_BASE, - .config = &samsung_gpio_cfgs[5], - .chip = { - .base = S5P6450_GPN(0), - .ngpio = S5P6450_GPIO_N_NR, - .label = "GPN", - }, - }, { - .base = S5P64X0_GPP_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S5P6450_GPP(0), - .ngpio = S5P6450_GPIO_P_NR, - .label = "GPP", - }, - }, { - .base = S5P6450_GPQ_BASE, - .config = &samsung_gpio_cfgs[5], - .chip = { - .base = S5P6450_GPQ(0), - .ngpio = S5P6450_GPIO_Q_NR, - .label = "GPQ", - }, - }, { - .base = S5P6450_GPS_BASE, - .config = &samsung_gpio_cfgs[6], - .chip = { - .base = S5P6450_GPS(0), - .ngpio = S5P6450_GPIO_S_NR, - .label = "GPS", - }, - }, -#endif -}; - -/* - * S5PC100 GPIO bank summary: - * - * Bank GPIOs Style INT Type - * A0 8 4Bit GPIO_INT0 - * A1 5 4Bit GPIO_INT1 - * B 8 4Bit GPIO_INT2 - * C 5 4Bit GPIO_INT3 - * D 7 4Bit GPIO_INT4 - * E0 8 4Bit GPIO_INT5 - * E1 6 4Bit GPIO_INT6 - * F0 8 4Bit GPIO_INT7 - * F1 8 4Bit GPIO_INT8 - * F2 8 4Bit GPIO_INT9 - * F3 4 4Bit GPIO_INT10 - * G0 8 4Bit GPIO_INT11 - * G1 3 4Bit GPIO_INT12 - * G2 7 4Bit GPIO_INT13 - * G3 7 4Bit GPIO_INT14 - * H0 8 4Bit WKUP_INT - * H1 8 4Bit WKUP_INT - * H2 8 4Bit WKUP_INT - * H3 8 4Bit WKUP_INT - * I 8 4Bit GPIO_INT15 - * J0 8 4Bit GPIO_INT16 - * J1 5 4Bit GPIO_INT17 - * J2 8 4Bit GPIO_INT18 - * J3 8 4Bit GPIO_INT19 - * J4 4 4Bit GPIO_INT20 - * K0 8 4Bit None - * K1 6 4Bit None - * K2 8 4Bit None - * K3 8 4Bit None - * L0 8 4Bit None - * L1 8 4Bit None - * L2 8 4Bit None - * L3 8 4Bit None - */ - -static struct samsung_gpio_chip s5pc100_gpios_4bit[] = { -#ifdef CONFIG_CPU_S5PC100 - { - .chip = { - .base = S5PC100_GPA0(0), - .ngpio = S5PC100_GPIO_A0_NR, - .label = "GPA0", - }, - }, { - .chip = { - .base = S5PC100_GPA1(0), - .ngpio = S5PC100_GPIO_A1_NR, - .label = "GPA1", - }, - }, { - .chip = { - .base = S5PC100_GPB(0), - .ngpio = S5PC100_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = S5PC100_GPC(0), - .ngpio = S5PC100_GPIO_C_NR, - .label = "GPC", - }, - }, { - .chip = { - .base = S5PC100_GPD(0), - .ngpio = S5PC100_GPIO_D_NR, - .label = "GPD", - }, - }, { - .chip = { - .base = S5PC100_GPE0(0), - .ngpio = S5PC100_GPIO_E0_NR, - .label = "GPE0", - }, - }, { - .chip = { - .base = S5PC100_GPE1(0), - .ngpio = S5PC100_GPIO_E1_NR, - .label = "GPE1", - }, - }, { - .chip = { - .base = S5PC100_GPF0(0), - .ngpio = S5PC100_GPIO_F0_NR, - .label = "GPF0", - }, - }, { - .chip = { - .base = S5PC100_GPF1(0), - .ngpio = S5PC100_GPIO_F1_NR, - .label = "GPF1", - }, - }, { - .chip = { - .base = S5PC100_GPF2(0), - .ngpio = S5PC100_GPIO_F2_NR, - .label = "GPF2", - }, - }, { - .chip = { - .base = S5PC100_GPF3(0), - .ngpio = S5PC100_GPIO_F3_NR, - .label = "GPF3", - }, - }, { - .chip = { - .base = S5PC100_GPG0(0), - .ngpio = S5PC100_GPIO_G0_NR, - .label = "GPG0", - }, - }, { - .chip = { - .base = S5PC100_GPG1(0), - .ngpio = S5PC100_GPIO_G1_NR, - .label = "GPG1", - }, - }, { - .chip = { - .base = S5PC100_GPG2(0), - .ngpio = S5PC100_GPIO_G2_NR, - .label = "GPG2", - }, - }, { - .chip = { - .base = S5PC100_GPG3(0), - .ngpio = S5PC100_GPIO_G3_NR, - .label = "GPG3", - }, - }, { - .chip = { - .base = S5PC100_GPI(0), - .ngpio = S5PC100_GPIO_I_NR, - .label = "GPI", - }, - }, { - .chip = { - .base = S5PC100_GPJ0(0), - .ngpio = S5PC100_GPIO_J0_NR, - .label = "GPJ0", - }, - }, { - .chip = { - .base = S5PC100_GPJ1(0), - .ngpio = S5PC100_GPIO_J1_NR, - .label = "GPJ1", - }, - }, { - .chip = { - .base = S5PC100_GPJ2(0), - .ngpio = S5PC100_GPIO_J2_NR, - .label = "GPJ2", - }, - }, { - .chip = { - .base = S5PC100_GPJ3(0), - .ngpio = S5PC100_GPIO_J3_NR, - .label = "GPJ3", - }, - }, { - .chip = { - .base = S5PC100_GPJ4(0), - .ngpio = S5PC100_GPIO_J4_NR, - .label = "GPJ4", - }, - }, { - .chip = { - .base = S5PC100_GPK0(0), - .ngpio = S5PC100_GPIO_K0_NR, - .label = "GPK0", - }, - }, { - .chip = { - .base = S5PC100_GPK1(0), - .ngpio = S5PC100_GPIO_K1_NR, - .label = "GPK1", - }, - }, { - .chip = { - .base = S5PC100_GPK2(0), - .ngpio = S5PC100_GPIO_K2_NR, - .label = "GPK2", - }, - }, { - .chip = { - .base = S5PC100_GPK3(0), - .ngpio = S5PC100_GPIO_K3_NR, - .label = "GPK3", - }, - }, { - .chip = { - .base = S5PC100_GPL0(0), - .ngpio = S5PC100_GPIO_L0_NR, - .label = "GPL0", - }, - }, { - .chip = { - .base = S5PC100_GPL1(0), - .ngpio = S5PC100_GPIO_L1_NR, - .label = "GPL1", - }, - }, { - .chip = { - .base = S5PC100_GPL2(0), - .ngpio = S5PC100_GPIO_L2_NR, - .label = "GPL2", - }, - }, { - .chip = { - .base = S5PC100_GPL3(0), - .ngpio = S5PC100_GPIO_L3_NR, - .label = "GPL3", - }, - }, { - .chip = { - .base = S5PC100_GPL4(0), - .ngpio = S5PC100_GPIO_L4_NR, - .label = "GPL4", - }, - }, { - .base = (S5P_VA_GPIO + 0xC00), - .irq_base = IRQ_EINT(0), - .chip = { - .base = S5PC100_GPH0(0), - .ngpio = S5PC100_GPIO_H0_NR, - .label = "GPH0", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC20), - .irq_base = IRQ_EINT(8), - .chip = { - .base = S5PC100_GPH1(0), - .ngpio = S5PC100_GPIO_H1_NR, - .label = "GPH1", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC40), - .irq_base = IRQ_EINT(16), - .chip = { - .base = S5PC100_GPH2(0), - .ngpio = S5PC100_GPIO_H2_NR, - .label = "GPH2", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC60), - .irq_base = IRQ_EINT(24), - .chip = { - .base = S5PC100_GPH3(0), - .ngpio = S5PC100_GPIO_H3_NR, - .label = "GPH3", - .to_irq = samsung_gpiolib_to_irq, - }, - }, -#endif -}; - -/* - * Followings are the gpio banks in S5PV210/S5PC110 - * - * The 'config' member when left to NULL, is initialized to the default - * structure samsung_gpio_cfgs[3] in the init function below. - * - * The 'base' member is also initialized in the init function below. - * Note: The initialization of 'base' member of samsung_gpio_chip structure - * uses the above macro and depends on the banks being listed in order here. - */ - -static struct samsung_gpio_chip s5pv210_gpios_4bit[] = { -#ifdef CONFIG_CPU_S5PV210 - { - .chip = { - .base = S5PV210_GPA0(0), - .ngpio = S5PV210_GPIO_A0_NR, - .label = "GPA0", - }, - }, { - .chip = { - .base = S5PV210_GPA1(0), - .ngpio = S5PV210_GPIO_A1_NR, - .label = "GPA1", - }, - }, { - .chip = { - .base = S5PV210_GPB(0), - .ngpio = S5PV210_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = S5PV210_GPC0(0), - .ngpio = S5PV210_GPIO_C0_NR, - .label = "GPC0", - }, - }, { - .chip = { - .base = S5PV210_GPC1(0), - .ngpio = S5PV210_GPIO_C1_NR, - .label = "GPC1", - }, - }, { - .chip = { - .base = S5PV210_GPD0(0), - .ngpio = S5PV210_GPIO_D0_NR, - .label = "GPD0", - }, - }, { - .chip = { - .base = S5PV210_GPD1(0), - .ngpio = S5PV210_GPIO_D1_NR, - .label = "GPD1", - }, - }, { - .chip = { - .base = S5PV210_GPE0(0), - .ngpio = S5PV210_GPIO_E0_NR, - .label = "GPE0", - }, - }, { - .chip = { - .base = S5PV210_GPE1(0), - .ngpio = S5PV210_GPIO_E1_NR, - .label = "GPE1", - }, - }, { - .chip = { - .base = S5PV210_GPF0(0), - .ngpio = S5PV210_GPIO_F0_NR, - .label = "GPF0", - }, - }, { - .chip = { - .base = S5PV210_GPF1(0), - .ngpio = S5PV210_GPIO_F1_NR, - .label = "GPF1", - }, - }, { - .chip = { - .base = S5PV210_GPF2(0), - .ngpio = S5PV210_GPIO_F2_NR, - .label = "GPF2", - }, - }, { - .chip = { - .base = S5PV210_GPF3(0), - .ngpio = S5PV210_GPIO_F3_NR, - .label = "GPF3", - }, - }, { - .chip = { - .base = S5PV210_GPG0(0), - .ngpio = S5PV210_GPIO_G0_NR, - .label = "GPG0", - }, - }, { - .chip = { - .base = S5PV210_GPG1(0), - .ngpio = S5PV210_GPIO_G1_NR, - .label = "GPG1", - }, - }, { - .chip = { - .base = S5PV210_GPG2(0), - .ngpio = S5PV210_GPIO_G2_NR, - .label = "GPG2", - }, - }, { - .chip = { - .base = S5PV210_GPG3(0), - .ngpio = S5PV210_GPIO_G3_NR, - .label = "GPG3", - }, - }, { - .chip = { - .base = S5PV210_GPI(0), - .ngpio = S5PV210_GPIO_I_NR, - .label = "GPI", - }, - }, { - .chip = { - .base = S5PV210_GPJ0(0), - .ngpio = S5PV210_GPIO_J0_NR, - .label = "GPJ0", - }, - }, { - .chip = { - .base = S5PV210_GPJ1(0), - .ngpio = S5PV210_GPIO_J1_NR, - .label = "GPJ1", - }, - }, { - .chip = { - .base = S5PV210_GPJ2(0), - .ngpio = S5PV210_GPIO_J2_NR, - .label = "GPJ2", - }, - }, { - .chip = { - .base = S5PV210_GPJ3(0), - .ngpio = S5PV210_GPIO_J3_NR, - .label = "GPJ3", - }, - }, { - .chip = { - .base = S5PV210_GPJ4(0), - .ngpio = S5PV210_GPIO_J4_NR, - .label = "GPJ4", - }, - }, { - .chip = { - .base = S5PV210_MP01(0), - .ngpio = S5PV210_GPIO_MP01_NR, - .label = "MP01", - }, - }, { - .chip = { - .base = S5PV210_MP02(0), - .ngpio = S5PV210_GPIO_MP02_NR, - .label = "MP02", - }, - }, { - .chip = { - .base = S5PV210_MP03(0), - .ngpio = S5PV210_GPIO_MP03_NR, - .label = "MP03", - }, - }, { - .chip = { - .base = S5PV210_MP04(0), - .ngpio = S5PV210_GPIO_MP04_NR, - .label = "MP04", - }, - }, { - .chip = { - .base = S5PV210_MP05(0), - .ngpio = S5PV210_GPIO_MP05_NR, - .label = "MP05", - }, - }, { - .base = (S5P_VA_GPIO + 0xC00), - .irq_base = IRQ_EINT(0), - .chip = { - .base = S5PV210_GPH0(0), - .ngpio = S5PV210_GPIO_H0_NR, - .label = "GPH0", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC20), - .irq_base = IRQ_EINT(8), - .chip = { - .base = S5PV210_GPH1(0), - .ngpio = S5PV210_GPIO_H1_NR, - .label = "GPH1", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC40), - .irq_base = IRQ_EINT(16), - .chip = { - .base = S5PV210_GPH2(0), - .ngpio = S5PV210_GPIO_H2_NR, - .label = "GPH2", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .base = (S5P_VA_GPIO + 0xC60), - .irq_base = IRQ_EINT(24), - .chip = { - .base = S5PV210_GPH3(0), - .ngpio = S5PV210_GPIO_H3_NR, - .label = "GPH3", - .to_irq = samsung_gpiolib_to_irq, - }, - }, -#endif -}; - -/* - * Followings are the gpio banks in EXYNOS SoCs - * - * The 'config' member when left to NULL, is initialized to the default - * structure exynos_gpio_cfg in the init function below. - * - * The 'base' member is also initialized in the init function below. - * Note: The initialization of 'base' member of samsung_gpio_chip structure - * uses the above macro and depends on the banks being listed in order here. - */ - -#ifdef CONFIG_ARCH_EXYNOS4 -static struct samsung_gpio_chip exynos4_gpios_1[] = { - { - .chip = { - .base = EXYNOS4_GPA0(0), - .ngpio = EXYNOS4_GPIO_A0_NR, - .label = "GPA0", - }, - }, { - .chip = { - .base = EXYNOS4_GPA1(0), - .ngpio = EXYNOS4_GPIO_A1_NR, - .label = "GPA1", - }, - }, { - .chip = { - .base = EXYNOS4_GPB(0), - .ngpio = EXYNOS4_GPIO_B_NR, - .label = "GPB", - }, - }, { - .chip = { - .base = EXYNOS4_GPC0(0), - .ngpio = EXYNOS4_GPIO_C0_NR, - .label = "GPC0", - }, - }, { - .chip = { - .base = EXYNOS4_GPC1(0), - .ngpio = EXYNOS4_GPIO_C1_NR, - .label = "GPC1", - }, - }, { - .chip = { - .base = EXYNOS4_GPD0(0), - .ngpio = EXYNOS4_GPIO_D0_NR, - .label = "GPD0", - }, - }, { - .chip = { - .base = EXYNOS4_GPD1(0), - .ngpio = EXYNOS4_GPIO_D1_NR, - .label = "GPD1", - }, - }, { - .chip = { - .base = EXYNOS4_GPE0(0), - .ngpio = EXYNOS4_GPIO_E0_NR, - .label = "GPE0", - }, - }, { - .chip = { - .base = EXYNOS4_GPE1(0), - .ngpio = EXYNOS4_GPIO_E1_NR, - .label = "GPE1", - }, - }, { - .chip = { - .base = EXYNOS4_GPE2(0), - .ngpio = EXYNOS4_GPIO_E2_NR, - .label = "GPE2", - }, - }, { - .chip = { - .base = EXYNOS4_GPE3(0), - .ngpio = EXYNOS4_GPIO_E3_NR, - .label = "GPE3", - }, - }, { - .chip = { - .base = EXYNOS4_GPE4(0), - .ngpio = EXYNOS4_GPIO_E4_NR, - .label = "GPE4", - }, - }, { - .chip = { - .base = EXYNOS4_GPF0(0), - .ngpio = EXYNOS4_GPIO_F0_NR, - .label = "GPF0", - }, - }, { - .chip = { - .base = EXYNOS4_GPF1(0), - .ngpio = EXYNOS4_GPIO_F1_NR, - .label = "GPF1", - }, - }, { - .chip = { - .base = EXYNOS4_GPF2(0), - .ngpio = EXYNOS4_GPIO_F2_NR, - .label = "GPF2", - }, - }, { - .chip = { - .base = EXYNOS4_GPF3(0), - .ngpio = EXYNOS4_GPIO_F3_NR, - .label = "GPF3", - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS4 -static struct samsung_gpio_chip exynos4_gpios_2[] = { - { - .chip = { - .base = EXYNOS4_GPJ0(0), - .ngpio = EXYNOS4_GPIO_J0_NR, - .label = "GPJ0", - }, - }, { - .chip = { - .base = EXYNOS4_GPJ1(0), - .ngpio = EXYNOS4_GPIO_J1_NR, - .label = "GPJ1", - }, - }, { - .chip = { - .base = EXYNOS4_GPK0(0), - .ngpio = EXYNOS4_GPIO_K0_NR, - .label = "GPK0", - }, - }, { - .chip = { - .base = EXYNOS4_GPK1(0), - .ngpio = EXYNOS4_GPIO_K1_NR, - .label = "GPK1", - }, - }, { - .chip = { - .base = EXYNOS4_GPK2(0), - .ngpio = EXYNOS4_GPIO_K2_NR, - .label = "GPK2", - }, - }, { - .chip = { - .base = EXYNOS4_GPK3(0), - .ngpio = EXYNOS4_GPIO_K3_NR, - .label = "GPK3", - }, - }, { - .chip = { - .base = EXYNOS4_GPL0(0), - .ngpio = EXYNOS4_GPIO_L0_NR, - .label = "GPL0", - }, - }, { - .chip = { - .base = EXYNOS4_GPL1(0), - .ngpio = EXYNOS4_GPIO_L1_NR, - .label = "GPL1", - }, - }, { - .chip = { - .base = EXYNOS4_GPL2(0), - .ngpio = EXYNOS4_GPIO_L2_NR, - .label = "GPL2", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY0(0), - .ngpio = EXYNOS4_GPIO_Y0_NR, - .label = "GPY0", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY1(0), - .ngpio = EXYNOS4_GPIO_Y1_NR, - .label = "GPY1", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY2(0), - .ngpio = EXYNOS4_GPIO_Y2_NR, - .label = "GPY2", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY3(0), - .ngpio = EXYNOS4_GPIO_Y3_NR, - .label = "GPY3", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY4(0), - .ngpio = EXYNOS4_GPIO_Y4_NR, - .label = "GPY4", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY5(0), - .ngpio = EXYNOS4_GPIO_Y5_NR, - .label = "GPY5", - }, - }, { - .config = &samsung_gpio_cfgs[8], - .chip = { - .base = EXYNOS4_GPY6(0), - .ngpio = EXYNOS4_GPIO_Y6_NR, - .label = "GPY6", - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(0), - .chip = { - .base = EXYNOS4_GPX0(0), - .ngpio = EXYNOS4_GPIO_X0_NR, - .label = "GPX0", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(8), - .chip = { - .base = EXYNOS4_GPX1(0), - .ngpio = EXYNOS4_GPIO_X1_NR, - .label = "GPX1", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(16), - .chip = { - .base = EXYNOS4_GPX2(0), - .ngpio = EXYNOS4_GPIO_X2_NR, - .label = "GPX2", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(24), - .chip = { - .base = EXYNOS4_GPX3(0), - .ngpio = EXYNOS4_GPIO_X3_NR, - .label = "GPX3", - .to_irq = samsung_gpiolib_to_irq, - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS4 -static struct samsung_gpio_chip exynos4_gpios_3[] = { - { - .chip = { - .base = EXYNOS4_GPZ(0), - .ngpio = EXYNOS4_GPIO_Z_NR, - .label = "GPZ", - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS5 -static struct samsung_gpio_chip exynos5_gpios_1[] = { - { - .chip = { - .base = EXYNOS5_GPA0(0), - .ngpio = EXYNOS5_GPIO_A0_NR, - .label = "GPA0", - }, - }, { - .chip = { - .base = EXYNOS5_GPA1(0), - .ngpio = EXYNOS5_GPIO_A1_NR, - .label = "GPA1", - }, - }, { - .chip = { - .base = EXYNOS5_GPA2(0), - .ngpio = EXYNOS5_GPIO_A2_NR, - .label = "GPA2", - }, - }, { - .chip = { - .base = EXYNOS5_GPB0(0), - .ngpio = EXYNOS5_GPIO_B0_NR, - .label = "GPB0", - }, - }, { - .chip = { - .base = EXYNOS5_GPB1(0), - .ngpio = EXYNOS5_GPIO_B1_NR, - .label = "GPB1", - }, - }, { - .chip = { - .base = EXYNOS5_GPB2(0), - .ngpio = EXYNOS5_GPIO_B2_NR, - .label = "GPB2", - }, - }, { - .chip = { - .base = EXYNOS5_GPB3(0), - .ngpio = EXYNOS5_GPIO_B3_NR, - .label = "GPB3", - }, - }, { - .chip = { - .base = EXYNOS5_GPC0(0), - .ngpio = EXYNOS5_GPIO_C0_NR, - .label = "GPC0", - }, - }, { - .chip = { - .base = EXYNOS5_GPC1(0), - .ngpio = EXYNOS5_GPIO_C1_NR, - .label = "GPC1", - }, - }, { - .chip = { - .base = EXYNOS5_GPC2(0), - .ngpio = EXYNOS5_GPIO_C2_NR, - .label = "GPC2", - }, - }, { - .chip = { - .base = EXYNOS5_GPC3(0), - .ngpio = EXYNOS5_GPIO_C3_NR, - .label = "GPC3", - }, - }, { - .chip = { - .base = EXYNOS5_GPD0(0), - .ngpio = EXYNOS5_GPIO_D0_NR, - .label = "GPD0", - }, - }, { - .chip = { - .base = EXYNOS5_GPD1(0), - .ngpio = EXYNOS5_GPIO_D1_NR, - .label = "GPD1", - }, - }, { - .chip = { - .base = EXYNOS5_GPY0(0), - .ngpio = EXYNOS5_GPIO_Y0_NR, - .label = "GPY0", - }, - }, { - .chip = { - .base = EXYNOS5_GPY1(0), - .ngpio = EXYNOS5_GPIO_Y1_NR, - .label = "GPY1", - }, - }, { - .chip = { - .base = EXYNOS5_GPY2(0), - .ngpio = EXYNOS5_GPIO_Y2_NR, - .label = "GPY2", - }, - }, { - .chip = { - .base = EXYNOS5_GPY3(0), - .ngpio = EXYNOS5_GPIO_Y3_NR, - .label = "GPY3", - }, - }, { - .chip = { - .base = EXYNOS5_GPY4(0), - .ngpio = EXYNOS5_GPIO_Y4_NR, - .label = "GPY4", - }, - }, { - .chip = { - .base = EXYNOS5_GPY5(0), - .ngpio = EXYNOS5_GPIO_Y5_NR, - .label = "GPY5", - }, - }, { - .chip = { - .base = EXYNOS5_GPY6(0), - .ngpio = EXYNOS5_GPIO_Y6_NR, - .label = "GPY6", - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(0), - .chip = { - .base = EXYNOS5_GPX0(0), - .ngpio = EXYNOS5_GPIO_X0_NR, - .label = "GPX0", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(8), - .chip = { - .base = EXYNOS5_GPX1(0), - .ngpio = EXYNOS5_GPIO_X1_NR, - .label = "GPX1", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(16), - .chip = { - .base = EXYNOS5_GPX2(0), - .ngpio = EXYNOS5_GPIO_X2_NR, - .label = "GPX2", - .to_irq = samsung_gpiolib_to_irq, - }, - }, { - .config = &samsung_gpio_cfgs[9], - .irq_base = IRQ_EINT(24), - .chip = { - .base = EXYNOS5_GPX3(0), - .ngpio = EXYNOS5_GPIO_X3_NR, - .label = "GPX3", - .to_irq = samsung_gpiolib_to_irq, - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS5 -static struct samsung_gpio_chip exynos5_gpios_2[] = { - { - .chip = { - .base = EXYNOS5_GPE0(0), - .ngpio = EXYNOS5_GPIO_E0_NR, - .label = "GPE0", - }, - }, { - .chip = { - .base = EXYNOS5_GPE1(0), - .ngpio = EXYNOS5_GPIO_E1_NR, - .label = "GPE1", - }, - }, { - .chip = { - .base = EXYNOS5_GPF0(0), - .ngpio = EXYNOS5_GPIO_F0_NR, - .label = "GPF0", - }, - }, { - .chip = { - .base = EXYNOS5_GPF1(0), - .ngpio = EXYNOS5_GPIO_F1_NR, - .label = "GPF1", - }, - }, { - .chip = { - .base = EXYNOS5_GPG0(0), - .ngpio = EXYNOS5_GPIO_G0_NR, - .label = "GPG0", - }, - }, { - .chip = { - .base = EXYNOS5_GPG1(0), - .ngpio = EXYNOS5_GPIO_G1_NR, - .label = "GPG1", - }, - }, { - .chip = { - .base = EXYNOS5_GPG2(0), - .ngpio = EXYNOS5_GPIO_G2_NR, - .label = "GPG2", - }, - }, { - .chip = { - .base = EXYNOS5_GPH0(0), - .ngpio = EXYNOS5_GPIO_H0_NR, - .label = "GPH0", - }, - }, { - .chip = { - .base = EXYNOS5_GPH1(0), - .ngpio = EXYNOS5_GPIO_H1_NR, - .label = "GPH1", - - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS5 -static struct samsung_gpio_chip exynos5_gpios_3[] = { - { - .chip = { - .base = EXYNOS5_GPV0(0), - .ngpio = EXYNOS5_GPIO_V0_NR, - .label = "GPV0", - }, - }, { - .chip = { - .base = EXYNOS5_GPV1(0), - .ngpio = EXYNOS5_GPIO_V1_NR, - .label = "GPV1", - }, - }, { - .chip = { - .base = EXYNOS5_GPV2(0), - .ngpio = EXYNOS5_GPIO_V2_NR, - .label = "GPV2", - }, - }, { - .chip = { - .base = EXYNOS5_GPV3(0), - .ngpio = EXYNOS5_GPIO_V3_NR, - .label = "GPV3", - }, - }, { - .chip = { - .base = EXYNOS5_GPV4(0), - .ngpio = EXYNOS5_GPIO_V4_NR, - .label = "GPV4", - }, - }, -}; -#endif - -#ifdef CONFIG_ARCH_EXYNOS5 -static struct samsung_gpio_chip exynos5_gpios_4[] = { - { - .chip = { - .base = EXYNOS5_GPZ(0), - .ngpio = EXYNOS5_GPIO_Z_NR, - .label = "GPZ", - }, - }, -}; -#endif - - -#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) -static int exynos_gpio_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, u32 *flags) -{ - unsigned int pin; - - if (WARN_ON(gc->of_gpio_n_cells < 4)) - return -EINVAL; - - if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) - return -EINVAL; - - if (gpiospec->args[0] > gc->ngpio) - return -EINVAL; - - pin = gc->base + gpiospec->args[0]; - - if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) - pr_warn("gpio_xlate: failed to set pin function\n"); - if (s3c_gpio_setpull(pin, gpiospec->args[2])) - pr_warn("gpio_xlate: failed to set pin pull up/down\n"); - if (s5p_gpio_set_drvstr(pin, gpiospec->args[3])) - pr_warn("gpio_xlate: failed to set pin drive strength\n"); - - return gpiospec->args[0]; -} - -static const struct of_device_id exynos_gpio_dt_match[] __initdata = { - { .compatible = "samsung,exynos4-gpio", }, - {} -}; - -static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, - u64 base, u64 offset) -{ - struct gpio_chip *gc = &chip->chip; - u64 address; - - if (!of_have_populated_dt()) - return; - - address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; - gc->of_node = of_find_matching_node_by_address(NULL, - exynos_gpio_dt_match, address); - if (!gc->of_node) { - pr_info("gpio: device tree node not found for gpio controller" - " with base address %08llx\n", address); - return; - } - gc->of_gpio_n_cells = 4; - gc->of_xlate = exynos_gpio_xlate; -} -#elif defined(CONFIG_ARCH_EXYNOS) -static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, - u64 base, u64 offset) -{ - return; -} -#endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */ - -/* TODO: cleanup soc_is_* */ -static __init int samsung_gpiolib_init(void) -{ - struct samsung_gpio_chip *chip; - int i, nr_chips; -#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250) - void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4; -#endif - int group = 0; - - samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs)); - - if (soc_is_s3c24xx()) { - s3c24xx_gpiolib_add_chips(s3c24xx_gpios, - ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO); - } else if (soc_is_s3c64xx()) { - samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit, - ARRAY_SIZE(s3c64xx_gpios_2bit), - S3C64XX_VA_GPIO + 0xE0, 0x20); - samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit, - ARRAY_SIZE(s3c64xx_gpios_4bit), - S3C64XX_VA_GPIO); - samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2, - ARRAY_SIZE(s3c64xx_gpios_4bit2)); - } else if (soc_is_s5p6440()) { - samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit, - ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0); - samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit, - ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO); - samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2, - ARRAY_SIZE(s5p6440_gpios_4bit2)); - s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank, - ARRAY_SIZE(s5p6440_gpios_rbank)); - } else if (soc_is_s5p6450()) { - samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit, - ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0); - samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit, - ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO); - samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2, - ARRAY_SIZE(s5p6450_gpios_4bit2)); - s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank, - ARRAY_SIZE(s5p6450_gpios_rbank)); - } else if (soc_is_s5pc100()) { - group = 0; - chip = s5pc100_gpios_4bit; - nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &samsung_gpio_cfgs[3]; - chip->group = group++; - } - } - samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO); -#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT) - s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR); -#endif - } else if (soc_is_s5pv210()) { - group = 0; - chip = s5pv210_gpios_4bit; - nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &samsung_gpio_cfgs[3]; - chip->group = group++; - } - } - samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO); -#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT) - s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR); -#endif - } else if (soc_is_exynos4210()) { -#ifdef CONFIG_CPU_EXYNOS4210 - void __iomem *gpx_base; - - /* gpio part1 */ - gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K); - if (gpio_base1 == NULL) { - pr_err("unable to ioremap for gpio_base1\n"); - goto err_ioremap1; - } - - chip = exynos4_gpios_1; - nr_chips = ARRAY_SIZE(exynos4_gpios_1); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS4_PA_GPIO1, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, - nr_chips, gpio_base1); - - /* gpio part2 */ - gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K); - if (gpio_base2 == NULL) { - pr_err("unable to ioremap for gpio_base2\n"); - goto err_ioremap2; - } - - /* need to set base address for gpx */ - chip = &exynos4_gpios_2[16]; - gpx_base = gpio_base2 + 0xC00; - for (i = 0; i < 4; i++, chip++, gpx_base += 0x20) - chip->base = gpx_base; - - chip = exynos4_gpios_2; - nr_chips = ARRAY_SIZE(exynos4_gpios_2); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS4_PA_GPIO2, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, - nr_chips, gpio_base2); - - /* gpio part3 */ - gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256); - if (gpio_base3 == NULL) { - pr_err("unable to ioremap for gpio_base3\n"); - goto err_ioremap3; - } - - chip = exynos4_gpios_3; - nr_chips = ARRAY_SIZE(exynos4_gpios_3); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS4_PA_GPIO3, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, - nr_chips, gpio_base3); - -#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT) - s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS); - s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS); -#endif - -#endif /* CONFIG_CPU_EXYNOS4210 */ - } else if (soc_is_exynos5250()) { -#ifdef CONFIG_SOC_EXYNOS5250 - void __iomem *gpx_base; - - /* gpio part1 */ - gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); - if (gpio_base1 == NULL) { - pr_err("unable to ioremap for gpio_base1\n"); - goto err_ioremap1; - } - - /* need to set base address for gpx */ - chip = &exynos5_gpios_1[20]; - gpx_base = gpio_base1 + 0xC00; - for (i = 0; i < 4; i++, chip++, gpx_base += 0x20) - chip->base = gpx_base; - - chip = exynos5_gpios_1; - nr_chips = ARRAY_SIZE(exynos5_gpios_1); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS5_PA_GPIO1, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos5_gpios_1, - nr_chips, gpio_base1); - - /* gpio part2 */ - gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K); - if (gpio_base2 == NULL) { - pr_err("unable to ioremap for gpio_base2\n"); - goto err_ioremap2; - } - - chip = exynos5_gpios_2; - nr_chips = ARRAY_SIZE(exynos5_gpios_2); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS5_PA_GPIO2, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos5_gpios_2, - nr_chips, gpio_base2); - - /* gpio part3 */ - gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K); - if (gpio_base3 == NULL) { - pr_err("unable to ioremap for gpio_base3\n"); - goto err_ioremap3; - } - - /* need to set base address for gpv */ - exynos5_gpios_3[0].base = gpio_base3; - exynos5_gpios_3[1].base = gpio_base3 + 0x20; - exynos5_gpios_3[2].base = gpio_base3 + 0x60; - exynos5_gpios_3[3].base = gpio_base3 + 0x80; - exynos5_gpios_3[4].base = gpio_base3 + 0xC0; - - chip = exynos5_gpios_3; - nr_chips = ARRAY_SIZE(exynos5_gpios_3); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS5_PA_GPIO3, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos5_gpios_3, - nr_chips, gpio_base3); - - /* gpio part4 */ - gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K); - if (gpio_base4 == NULL) { - pr_err("unable to ioremap for gpio_base4\n"); - goto err_ioremap4; - } - - chip = exynos5_gpios_4; - nr_chips = ARRAY_SIZE(exynos5_gpios_4); - - for (i = 0; i < nr_chips; i++, chip++) { - if (!chip->config) { - chip->config = &exynos_gpio_cfg; - chip->group = group++; - } - exynos_gpiolib_attach_ofnode(chip, - EXYNOS5_PA_GPIO4, i * 0x20); - } - samsung_gpiolib_add_4bit_chips(exynos5_gpios_4, - nr_chips, gpio_base4); -#endif /* CONFIG_SOC_EXYNOS5250 */ - } else { - WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n"); - return -ENODEV; - } - - return 0; - -#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250) -err_ioremap4: - iounmap(gpio_base3); -err_ioremap3: - iounmap(gpio_base2); -err_ioremap2: - iounmap(gpio_base1); -err_ioremap1: - return -ENOMEM; -#endif -} -core_initcall(samsung_gpiolib_init); - -int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned long flags; - int offset; - int ret; - - if (!chip) - return -EINVAL; - - offset = pin - chip->chip.base; - - samsung_gpio_lock(chip, flags); - ret = samsung_gpio_do_setcfg(chip, offset, config); - samsung_gpio_unlock(chip, flags); - - return ret; -} -EXPORT_SYMBOL(s3c_gpio_cfgpin); - -int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, - unsigned int cfg) -{ - int ret; - - for (; nr > 0; nr--, start++) { - ret = s3c_gpio_cfgpin(start, cfg); - if (ret != 0) - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range); - -int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, - unsigned int cfg, samsung_gpio_pull_t pull) -{ - int ret; - - for (; nr > 0; nr--, start++) { - s3c_gpio_setpull(start, pull); - ret = s3c_gpio_cfgpin(start, cfg); - if (ret != 0) - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range); - -unsigned s3c_gpio_getcfg(unsigned int pin) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned long flags; - unsigned ret = 0; - int offset; - - if (chip) { - offset = pin - chip->chip.base; - - samsung_gpio_lock(chip, flags); - ret = samsung_gpio_do_getcfg(chip, offset); - samsung_gpio_unlock(chip, flags); - } - - return ret; -} -EXPORT_SYMBOL(s3c_gpio_getcfg); - -int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned long flags; - int offset, ret; - - if (!chip) - return -EINVAL; - - offset = pin - chip->chip.base; - - samsung_gpio_lock(chip, flags); - ret = samsung_gpio_do_setpull(chip, offset, pull); - samsung_gpio_unlock(chip, flags); - - return ret; -} -EXPORT_SYMBOL(s3c_gpio_setpull); - -samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned long flags; - int offset; - u32 pup = 0; - - if (chip) { - offset = pin - chip->chip.base; - - samsung_gpio_lock(chip, flags); - pup = samsung_gpio_do_getpull(chip, offset); - samsung_gpio_unlock(chip, flags); - } - - return (__force samsung_gpio_pull_t)pup; -} -EXPORT_SYMBOL(s3c_gpio_getpull); - -/* gpiolib wrappers until these are totally eliminated */ - -void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) -{ - int ret; - - WARN_ON(to); /* should be none of these left */ - - if (!to) { - /* if pull is enabled, try first with up, and if that - * fails, try using down */ - - ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP); - if (ret) - s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN); - } else { - s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE); - } -} -EXPORT_SYMBOL(s3c2410_gpio_pullup); - -void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) -{ - /* do this via gpiolib until all users removed */ - - gpio_request(pin, "temporary"); - gpio_set_value(pin, to); - gpio_free(pin); -} -EXPORT_SYMBOL(s3c2410_gpio_setpin); - -unsigned int s3c2410_gpio_getpin(unsigned int pin) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned long offs = pin - chip->chip.base; - - return __raw_readl(chip->base + 0x04) & (1 << offs); -} -EXPORT_SYMBOL(s3c2410_gpio_getpin); - -#ifdef CONFIG_S5P_GPIO_DRVSTR -s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned int off; - void __iomem *reg; - int shift; - u32 drvstr; - - if (!chip) - return -EINVAL; - - off = pin - chip->chip.base; - shift = off * 2; - reg = chip->base + 0x0C; - - drvstr = __raw_readl(reg); - drvstr = drvstr >> shift; - drvstr &= 0x3; - - return (__force s5p_gpio_drvstr_t)drvstr; -} -EXPORT_SYMBOL(s5p_gpio_get_drvstr); - -int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) -{ - struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); - unsigned int off; - void __iomem *reg; - int shift; - u32 tmp; - - if (!chip) - return -EINVAL; - - off = pin - chip->chip.base; - shift = off * 2; - reg = chip->base + 0x0C; - - tmp = __raw_readl(reg); - tmp &= ~(0x3 << shift); - tmp |= drvstr << shift; - - __raw_writel(tmp, reg); - - return 0; -} -EXPORT_SYMBOL(s5p_gpio_set_drvstr); -#endif /* CONFIG_S5P_GPIO_DRVSTR */ - -#ifdef CONFIG_PLAT_S3C24XX -unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) -{ - unsigned long flags; - unsigned long misccr; - - local_irq_save(flags); - misccr = __raw_readl(S3C24XX_MISCCR); - misccr &= ~clear; - misccr ^= change; - __raw_writel(misccr, S3C24XX_MISCCR); - local_irq_restore(flags); - - return misccr; -} -EXPORT_SYMBOL(s3c2410_modify_misccr); -#endif diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-sch.c b/ANDROID_3.4.5/drivers/gpio/gpio-sch.c deleted file mode 100644 index 8cadf4d6..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-sch.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * GPIO interface for Intel Poulsbo SCH - * - * Copyright (c) 2010 CompuLab Ltd - * Author: Denis Turischev <denis@compulab.co.il> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/errno.h> -#include <linux/acpi.h> -#include <linux/platform_device.h> -#include <linux/pci_ids.h> - -#include <linux/gpio.h> - -static DEFINE_SPINLOCK(gpio_lock); - -#define CGEN (0x00) -#define CGIO (0x04) -#define CGLV (0x08) - -#define RGEN (0x20) -#define RGIO (0x24) -#define RGLV (0x28) - -static unsigned short gpio_ba; - -static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num) -{ - u8 curr_dirs; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - - if (!(curr_dirs & (1 << bit))) - outb(curr_dirs | (1 << bit), gpio_ba + offset); - - spin_unlock(&gpio_lock); - return 0; -} - -static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num) -{ - int res; - unsigned short offset, bit; - - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; - - res = !!(inb(gpio_ba + offset) & (1 << bit)); - return res; -} - -static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val) -{ - u8 curr_vals; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; - - curr_vals = inb(gpio_ba + offset); - - if (val) - outb(curr_vals | (1 << bit), gpio_ba + offset); - else - outb((curr_vals & ~(1 << bit)), gpio_ba + offset); - spin_unlock(&gpio_lock); -} - -static int sch_gpio_core_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_dirs; - unsigned short offset, bit; - - sch_gpio_core_set(gc, gpio_num, val); - - spin_lock(&gpio_lock); - - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - if (curr_dirs & (1 << bit)) - outb(curr_dirs & ~(1 << bit), gpio_ba + offset); - - spin_unlock(&gpio_lock); - return 0; -} - -static struct gpio_chip sch_gpio_core = { - .label = "sch_gpio_core", - .owner = THIS_MODULE, - .direction_input = sch_gpio_core_direction_in, - .get = sch_gpio_core_get, - .direction_output = sch_gpio_core_direction_out, - .set = sch_gpio_core_set, -}; - -static int sch_gpio_resume_direction_in(struct gpio_chip *gc, - unsigned gpio_num) -{ - u8 curr_dirs; - - spin_lock(&gpio_lock); - - curr_dirs = inb(gpio_ba + RGIO); - - if (!(curr_dirs & (1 << gpio_num))) - outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO); - - spin_unlock(&gpio_lock); - return 0; -} - -static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) -{ - return !!(inb(gpio_ba + RGLV) & (1 << gpio_num)); -} - -static void sch_gpio_resume_set(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_vals; - - spin_lock(&gpio_lock); - - curr_vals = inb(gpio_ba + RGLV); - - if (val) - outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV); - else - outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV); - - spin_unlock(&gpio_lock); -} - -static int sch_gpio_resume_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_dirs; - - sch_gpio_resume_set(gc, gpio_num, val); - - spin_lock(&gpio_lock); - - curr_dirs = inb(gpio_ba + RGIO); - if (curr_dirs & (1 << gpio_num)) - outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO); - - spin_unlock(&gpio_lock); - return 0; -} - -static struct gpio_chip sch_gpio_resume = { - .label = "sch_gpio_resume", - .owner = THIS_MODULE, - .direction_input = sch_gpio_resume_direction_in, - .get = sch_gpio_resume_get, - .direction_output = sch_gpio_resume_direction_out, - .set = sch_gpio_resume_set, -}; - -static int __devinit sch_gpio_probe(struct platform_device *pdev) -{ - struct resource *res; - int err, id; - - id = pdev->id; - if (!id) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) - return -EBUSY; - - if (!request_region(res->start, resource_size(res), pdev->name)) - return -EBUSY; - - gpio_ba = res->start; - - switch (id) { - case PCI_DEVICE_ID_INTEL_SCH_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 10; - - sch_gpio_resume.base = 10; - sch_gpio_resume.ngpio = 4; - - /* - * GPIO[6:0] enabled by default - * GPIO7 is configured by the CMC as SLPIOVR - * Enable GPIO[9:8] core powered gpios explicitly - */ - outb(0x3, gpio_ba + CGEN + 1); - /* - * SUS_GPIO[2:0] enabled by default - * Enable SUS_GPIO3 resume powered gpio explicitly - */ - outb(0x8, gpio_ba + RGEN); - break; - - case PCI_DEVICE_ID_INTEL_ITC_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 5; - - sch_gpio_resume.base = 5; - sch_gpio_resume.ngpio = 9; - break; - - default: - return -ENODEV; - } - - sch_gpio_core.dev = &pdev->dev; - sch_gpio_resume.dev = &pdev->dev; - - err = gpiochip_add(&sch_gpio_core); - if (err < 0) - goto err_sch_gpio_core; - - err = gpiochip_add(&sch_gpio_resume); - if (err < 0) - goto err_sch_gpio_resume; - - return 0; - -err_sch_gpio_resume: - err = gpiochip_remove(&sch_gpio_core); - if (err) - dev_err(&pdev->dev, "%s failed, %d\n", - "gpiochip_remove()", err); - -err_sch_gpio_core: - release_region(res->start, resource_size(res)); - gpio_ba = 0; - - return err; -} - -static int __devexit sch_gpio_remove(struct platform_device *pdev) -{ - struct resource *res; - if (gpio_ba) { - int err; - - err = gpiochip_remove(&sch_gpio_core); - if (err) - dev_err(&pdev->dev, "%s failed, %d\n", - "gpiochip_remove()", err); - err = gpiochip_remove(&sch_gpio_resume); - if (err) - dev_err(&pdev->dev, "%s failed, %d\n", - "gpiochip_remove()", err); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - - release_region(res->start, resource_size(res)); - gpio_ba = 0; - - return err; - } - - return 0; -} - -static struct platform_driver sch_gpio_driver = { - .driver = { - .name = "sch_gpio", - .owner = THIS_MODULE, - }, - .probe = sch_gpio_probe, - .remove = __devexit_p(sch_gpio_remove), -}; - -module_platform_driver(sch_gpio_driver); - -MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); -MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:sch_gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-sodaville.c b/ANDROID_3.4.5/drivers/gpio/gpio-sodaville.c deleted file mode 100644 index 031e5d24..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-sodaville.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * GPIO interface for Intel Sodaville SoCs. - * - * Copyright (c) 2010, 2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 2 as published - * by the Free Software Foundation. - * - */ - -#include <linux/errno.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/of_irq.h> -#include <linux/basic_mmio_gpio.h> - -#define DRV_NAME "sdv_gpio" -#define SDV_NUM_PUB_GPIOS 12 -#define PCI_DEVICE_ID_SDV_GPIO 0x2e67 -#define GPIO_BAR 0 - -#define GPOUTR 0x00 -#define GPOER 0x04 -#define GPINR 0x08 - -#define GPSTR 0x0c -#define GPIT1R0 0x10 -#define GPIO_INT 0x14 -#define GPIT1R1 0x18 - -#define GPMUXCTL 0x1c - -struct sdv_gpio_chip_data { - int irq_base; - void __iomem *gpio_pub_base; - struct irq_domain *id; - struct irq_chip_generic *gc; - struct bgpio_chip bgpio; -}; - -static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct sdv_gpio_chip_data *sd = gc->private; - void __iomem *type_reg; - u32 reg; - - if (d->hwirq < 8) - type_reg = sd->gpio_pub_base + GPIT1R0; - else - type_reg = sd->gpio_pub_base + GPIT1R1; - - reg = readl(type_reg); - - switch (type) { - case IRQ_TYPE_LEVEL_HIGH: - reg &= ~BIT(4 * (d->hwirq % 8)); - break; - - case IRQ_TYPE_LEVEL_LOW: - reg |= BIT(4 * (d->hwirq % 8)); - break; - - default: - return -EINVAL; - } - - writel(reg, type_reg); - return 0; -} - -static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data) -{ - struct sdv_gpio_chip_data *sd = data; - u32 irq_stat = readl(sd->gpio_pub_base + GPSTR); - - irq_stat &= readl(sd->gpio_pub_base + GPIO_INT); - if (!irq_stat) - return IRQ_NONE; - - while (irq_stat) { - u32 irq_bit = __fls(irq_stat); - - irq_stat &= ~BIT(irq_bit); - generic_handle_irq(irq_find_mapping(sd->id, irq_bit)); - } - - return IRQ_HANDLED; -} - -static int sdv_xlate(struct irq_domain *h, struct device_node *node, - const u32 *intspec, u32 intsize, irq_hw_number_t *out_hwirq, - u32 *out_type) -{ - u32 line, type; - - if (node != h->of_node) - return -EINVAL; - - if (intsize < 2) - return -EINVAL; - - line = *intspec; - *out_hwirq = line; - - intspec++; - type = *intspec; - - switch (type) { - case IRQ_TYPE_LEVEL_LOW: - case IRQ_TYPE_LEVEL_HIGH: - *out_type = type; - break; - default: - return -EINVAL; - } - return 0; -} - -static struct irq_domain_ops irq_domain_sdv_ops = { - .xlate = sdv_xlate, -}; - -static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, - struct pci_dev *pdev) -{ - struct irq_chip_type *ct; - int ret; - - sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1); - if (sd->irq_base < 0) - return sd->irq_base; - - /* mask + ACK all interrupt sources */ - writel(0, sd->gpio_pub_base + GPIO_INT); - writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR); - - ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED, - "sdv_gpio", sd); - if (ret) - goto out_free_desc; - - /* - * This gpio irq controller latches level irqs. Testing shows that if - * we unmask & ACK the IRQ before the source of the interrupt is gone - * then the interrupt is active again. - */ - sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base, - sd->gpio_pub_base, handle_fasteoi_irq); - if (!sd->gc) { - ret = -ENOMEM; - goto out_free_irq; - } - - sd->gc->private = sd; - ct = sd->gc->chip_types; - ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; - ct->regs.eoi = GPSTR; - ct->regs.mask = GPIO_INT; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; - ct->chip.irq_eoi = irq_gc_eoi; - ct->chip.irq_set_type = sdv_gpio_pub_set_type; - - irq_setup_generic_chip(sd->gc, IRQ_MSK(SDV_NUM_PUB_GPIOS), - IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, - IRQ_LEVEL | IRQ_NOPROBE); - - sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, - sd->irq_base, 0, &irq_domain_sdv_ops, sd); - if (!sd->id) - goto out_free_irq; - return 0; -out_free_irq: - free_irq(pdev->irq, sd); -out_free_desc: - irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); - return ret; -} - -static int __devinit sdv_gpio_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_id) -{ - struct sdv_gpio_chip_data *sd; - unsigned long addr; - const void *prop; - int len; - int ret; - u32 mux_val; - - sd = kzalloc(sizeof(struct sdv_gpio_chip_data), GFP_KERNEL); - if (!sd) - return -ENOMEM; - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device.\n"); - goto done; - } - - ret = pci_request_region(pdev, GPIO_BAR, DRV_NAME); - if (ret) { - dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR); - goto disable_pci; - } - - addr = pci_resource_start(pdev, GPIO_BAR); - if (!addr) - goto release_reg; - sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR)); - - prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len); - if (prop && len == 4) { - mux_val = of_read_number(prop, 1); - writel(mux_val, sd->gpio_pub_base + GPMUXCTL); - } - - ret = bgpio_init(&sd->bgpio, &pdev->dev, 4, - sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR, - NULL, sd->gpio_pub_base + GPOER, NULL, false); - if (ret) - goto unmap; - sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS; - - ret = gpiochip_add(&sd->bgpio.gc); - if (ret < 0) { - dev_err(&pdev->dev, "gpiochip_add() failed.\n"); - goto unmap; - } - - ret = sdv_register_irqsupport(sd, pdev); - if (ret) - goto unmap; - - pci_set_drvdata(pdev, sd); - dev_info(&pdev->dev, "Sodaville GPIO driver registered.\n"); - return 0; - -unmap: - iounmap(sd->gpio_pub_base); -release_reg: - pci_release_region(pdev, GPIO_BAR); -disable_pci: - pci_disable_device(pdev); -done: - kfree(sd); - return ret; -} - -static void sdv_gpio_remove(struct pci_dev *pdev) -{ - struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev); - - free_irq(pdev->irq, sd); - irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); - - if (gpiochip_remove(&sd->bgpio.gc)) - dev_err(&pdev->dev, "gpiochip_remove() failed.\n"); - - pci_release_region(pdev, GPIO_BAR); - iounmap(sd->gpio_pub_base); - pci_disable_device(pdev); - kfree(sd); -} - -static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, - { 0, }, -}; - -static struct pci_driver sdv_gpio_driver = { - .name = DRV_NAME, - .id_table = sdv_gpio_pci_ids, - .probe = sdv_gpio_probe, - .remove = sdv_gpio_remove, -}; - -static int __init sdv_gpio_init(void) -{ - return pci_register_driver(&sdv_gpio_driver); -} -module_init(sdv_gpio_init); - -static void __exit sdv_gpio_exit(void) -{ - pci_unregister_driver(&sdv_gpio_driver); -} -module_exit(sdv_gpio_exit); - -MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>"); -MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-stmpe.c b/ANDROID_3.4.5/drivers/gpio/gpio-stmpe.c deleted file mode 100644 index dce34727..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-stmpe.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License, version 2 - * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/mfd/stmpe.h> - -/* - * These registers are modified under the irq bus lock and cached to avoid - * unnecessary writes in bus_sync_unlock. - */ -enum { REG_RE, REG_FE, REG_IE }; - -#define CACHE_NR_REGS 3 -#define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) - -struct stmpe_gpio { - struct gpio_chip chip; - struct stmpe *stmpe; - struct device *dev; - struct mutex irq_lock; - - int irq_base; - unsigned norequest_mask; - - /* Caches of interrupt control registers for bus_lock */ - u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; - u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; -}; - -static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct stmpe_gpio, chip); -} - -static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - struct stmpe *stmpe = stmpe_gpio->stmpe; - u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); - u8 mask = 1 << (offset % 8); - int ret; - - ret = stmpe_reg_read(stmpe, reg); - if (ret < 0) - return ret; - - return !!(ret & mask); -} - -static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - struct stmpe *stmpe = stmpe_gpio->stmpe; - int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; - u8 reg = stmpe->regs[which] - (offset / 8); - u8 mask = 1 << (offset % 8); - - /* - * Some variants have single register for gpio set/clear functionality. - * For them we need to write 0 to clear and 1 to set. - */ - if (stmpe->regs[STMPE_IDX_GPSR_LSB] == stmpe->regs[STMPE_IDX_GPCR_LSB]) - stmpe_set_bits(stmpe, reg, mask, val ? mask : 0); - else - stmpe_reg_write(stmpe, reg, mask); -} - -static int stmpe_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int val) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - struct stmpe *stmpe = stmpe_gpio->stmpe; - u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); - u8 mask = 1 << (offset % 8); - - stmpe_gpio_set(chip, offset, val); - - return stmpe_set_bits(stmpe, reg, mask, mask); -} - -static int stmpe_gpio_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - struct stmpe *stmpe = stmpe_gpio->stmpe; - u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); - u8 mask = 1 << (offset % 8); - - return stmpe_set_bits(stmpe, reg, mask, 0); -} - -static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - - return stmpe_gpio->irq_base + offset; -} - -static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); - struct stmpe *stmpe = stmpe_gpio->stmpe; - - if (stmpe_gpio->norequest_mask & (1 << offset)) - return -EINVAL; - - return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); -} - -static struct gpio_chip template_chip = { - .label = "stmpe", - .owner = THIS_MODULE, - .direction_input = stmpe_gpio_direction_input, - .get = stmpe_gpio_get, - .direction_output = stmpe_gpio_direction_output, - .set = stmpe_gpio_set, - .to_irq = stmpe_gpio_to_irq, - .request = stmpe_gpio_request, - .can_sleep = 1, -}; - -static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - stmpe_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) - return -EINVAL; - - /* STMPE801 doesn't have RE and FE registers */ - if (stmpe_gpio->stmpe->partnum == STMPE801) - return 0; - - if (type == IRQ_TYPE_EDGE_RISING) - stmpe_gpio->regs[REG_RE][regoffset] |= mask; - else - stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; - - if (type == IRQ_TYPE_EDGE_FALLING) - stmpe_gpio->regs[REG_FE][regoffset] |= mask; - else - stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; - - return 0; -} - -static void stmpe_gpio_irq_lock(struct irq_data *d) -{ - struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); - - mutex_lock(&stmpe_gpio->irq_lock); -} - -static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) -{ - struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); - struct stmpe *stmpe = stmpe_gpio->stmpe; - int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); - static const u8 regmap[] = { - [REG_RE] = STMPE_IDX_GPRER_LSB, - [REG_FE] = STMPE_IDX_GPFER_LSB, - [REG_IE] = STMPE_IDX_IEGPIOR_LSB, - }; - int i, j; - - for (i = 0; i < CACHE_NR_REGS; i++) { - /* STMPE801 doesn't have RE and FE registers */ - if ((stmpe->partnum == STMPE801) && - (i != REG_IE)) - continue; - - for (j = 0; j < num_banks; j++) { - u8 old = stmpe_gpio->oldregs[i][j]; - u8 new = stmpe_gpio->regs[i][j]; - - if (new == old) - continue; - - stmpe_gpio->oldregs[i][j] = new; - stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); - } - } - - mutex_unlock(&stmpe_gpio->irq_lock); -} - -static void stmpe_gpio_irq_mask(struct irq_data *d) -{ - struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - stmpe_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; -} - -static void stmpe_gpio_irq_unmask(struct irq_data *d) -{ - struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - stmpe_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - stmpe_gpio->regs[REG_IE][regoffset] |= mask; -} - -static struct irq_chip stmpe_gpio_irq_chip = { - .name = "stmpe-gpio", - .irq_bus_lock = stmpe_gpio_irq_lock, - .irq_bus_sync_unlock = stmpe_gpio_irq_sync_unlock, - .irq_mask = stmpe_gpio_irq_mask, - .irq_unmask = stmpe_gpio_irq_unmask, - .irq_set_type = stmpe_gpio_irq_set_type, -}; - -static irqreturn_t stmpe_gpio_irq(int irq, void *dev) -{ - struct stmpe_gpio *stmpe_gpio = dev; - struct stmpe *stmpe = stmpe_gpio->stmpe; - u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; - int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); - u8 status[num_banks]; - int ret; - int i; - - ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); - if (ret < 0) - return IRQ_NONE; - - for (i = 0; i < num_banks; i++) { - int bank = num_banks - i - 1; - unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; - unsigned int stat = status[i]; - - stat &= enabled; - if (!stat) - continue; - - while (stat) { - int bit = __ffs(stat); - int line = bank * 8 + bit; - - handle_nested_irq(stmpe_gpio->irq_base + line); - stat &= ~(1 << bit); - } - - stmpe_reg_write(stmpe, statmsbreg + i, status[i]); - - /* Edge detect register is not present on 801 */ - if (stmpe->partnum != STMPE801) - stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] - + i, status[i]); - } - - return IRQ_HANDLED; -} - -static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) -{ - int base = stmpe_gpio->irq_base; - int irq; - - for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { - irq_set_chip_data(irq, stmpe_gpio); - irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip, - handle_simple_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - return 0; -} - -static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) -{ - int base = stmpe_gpio->irq_base; - int irq; - - for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); - } -} - -static int __devinit stmpe_gpio_probe(struct platform_device *pdev) -{ - struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); - struct stmpe_gpio_platform_data *pdata; - struct stmpe_gpio *stmpe_gpio; - int ret; - int irq = 0; - - pdata = stmpe->pdata->gpio; - - irq = platform_get_irq(pdev, 0); - - stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); - if (!stmpe_gpio) - return -ENOMEM; - - mutex_init(&stmpe_gpio->irq_lock); - - stmpe_gpio->dev = &pdev->dev; - stmpe_gpio->stmpe = stmpe; - stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0; - - stmpe_gpio->chip = template_chip; - stmpe_gpio->chip.ngpio = stmpe->num_gpios; - stmpe_gpio->chip.dev = &pdev->dev; - stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; - - if (irq >= 0) - stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); - else - dev_info(&pdev->dev, - "device configured in no-irq mode; " - "irqs are not available\n"); - - ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); - if (ret) - goto out_free; - - if (irq >= 0) { - ret = stmpe_gpio_irq_init(stmpe_gpio); - if (ret) - goto out_disable; - - ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, - IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_removeirq; - } - } - - ret = gpiochip_add(&stmpe_gpio->chip); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_freeirq; - } - - if (pdata && pdata->setup) - pdata->setup(stmpe, stmpe_gpio->chip.base); - - platform_set_drvdata(pdev, stmpe_gpio); - - return 0; - -out_freeirq: - if (irq >= 0) - free_irq(irq, stmpe_gpio); -out_removeirq: - if (irq >= 0) - stmpe_gpio_irq_remove(stmpe_gpio); -out_disable: - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); -out_free: - kfree(stmpe_gpio); - return ret; -} - -static int __devexit stmpe_gpio_remove(struct platform_device *pdev) -{ - struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); - struct stmpe *stmpe = stmpe_gpio->stmpe; - struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; - int irq = platform_get_irq(pdev, 0); - int ret; - - if (pdata && pdata->remove) - pdata->remove(stmpe, stmpe_gpio->chip.base); - - ret = gpiochip_remove(&stmpe_gpio->chip); - if (ret < 0) { - dev_err(stmpe_gpio->dev, - "unable to remove gpiochip: %d\n", ret); - return ret; - } - - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - - if (irq >= 0) { - free_irq(irq, stmpe_gpio); - stmpe_gpio_irq_remove(stmpe_gpio); - } - platform_set_drvdata(pdev, NULL); - kfree(stmpe_gpio); - - return 0; -} - -static struct platform_driver stmpe_gpio_driver = { - .driver.name = "stmpe-gpio", - .driver.owner = THIS_MODULE, - .probe = stmpe_gpio_probe, - .remove = __devexit_p(stmpe_gpio_remove), -}; - -static int __init stmpe_gpio_init(void) -{ - return platform_driver_register(&stmpe_gpio_driver); -} -subsys_initcall(stmpe_gpio_init); - -static void __exit stmpe_gpio_exit(void) -{ - platform_driver_unregister(&stmpe_gpio_driver); -} -module_exit(stmpe_gpio_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("STMPExxxx GPIO driver"); -MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-sx150x.c b/ANDROID_3.4.5/drivers/gpio/gpio-sx150x.c deleted file mode 100644 index a4f73534..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-sx150x.c +++ /dev/null @@ -1,680 +0,0 @@ -/* 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/i2c.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/workqueue.h> -#include <linux/i2c/sx150x.h> - -#define NO_UPDATE_PENDING -1 - -struct sx150x_device_data { - u8 reg_pullup; - u8 reg_pulldn; - u8 reg_drain; - u8 reg_polarity; - u8 reg_dir; - u8 reg_data; - u8 reg_irq_mask; - u8 reg_irq_src; - u8 reg_sense; - u8 reg_clock; - u8 reg_misc; - u8 reg_reset; - u8 ngpios; -}; - -struct sx150x_chip { - struct gpio_chip gpio_chip; - struct i2c_client *client; - const struct sx150x_device_data *dev_cfg; - int irq_summary; - int irq_base; - int irq_update; - u32 irq_sense; - u32 irq_masked; - u32 dev_sense; - u32 dev_masked; - struct irq_chip irq_chip; - struct mutex lock; -}; - -static const struct sx150x_device_data sx150x_devices[] = { - [0] = { /* sx1508q */ - .reg_pullup = 0x03, - .reg_pulldn = 0x04, - .reg_drain = 0x05, - .reg_polarity = 0x06, - .reg_dir = 0x07, - .reg_data = 0x08, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0c, - .reg_sense = 0x0b, - .reg_clock = 0x0f, - .reg_misc = 0x10, - .reg_reset = 0x7d, - .ngpios = 8 - }, - [1] = { /* sx1509q */ - .reg_pullup = 0x07, - .reg_pulldn = 0x09, - .reg_drain = 0x0b, - .reg_polarity = 0x0d, - .reg_dir = 0x0f, - .reg_data = 0x11, - .reg_irq_mask = 0x13, - .reg_irq_src = 0x19, - .reg_sense = 0x17, - .reg_clock = 0x1e, - .reg_misc = 0x1f, - .reg_reset = 0x7d, - .ngpios = 16 - }, -}; - -static const struct i2c_device_id sx150x_id[] = { - {"sx1508q", 0}, - {"sx1509q", 1}, - {} -}; -MODULE_DEVICE_TABLE(i2c, sx150x_id); - -static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) -{ - s32 err = i2c_smbus_write_byte_data(client, reg, val); - - if (err < 0) - dev_warn(&client->dev, - "i2c write fail: can't write %02x to %02x: %d\n", - val, reg, err); - return err; -} - -static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) -{ - s32 err = i2c_smbus_read_byte_data(client, reg); - - if (err >= 0) - *val = err; - else - dev_warn(&client->dev, - "i2c read fail: can't read from %02x: %d\n", - reg, err); - return err; -} - -static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) -{ - return (chip->dev_cfg->ngpios == offset); -} - -/* - * These utility functions solve the common problem of locating and setting - * configuration bits. Configuration bits are grouped into registers - * whose indexes increase downwards. For example, with eight-bit registers, - * sixteen gpios would have their config bits grouped in the following order: - * REGISTER N-1 [ f e d c b a 9 8 ] - * N [ 7 6 5 4 3 2 1 0 ] - * - * For multi-bit configurations, the pattern gets wider: - * REGISTER N-3 [ f f e e d d c c ] - * N-2 [ b b a a 9 9 8 8 ] - * N-1 [ 7 7 6 6 5 5 4 4 ] - * N [ 3 3 2 2 1 1 0 0 ] - * - * Given the address of the starting register 'N', the index of the gpio - * whose configuration we seek to change, and the width in bits of that - * configuration, these functions allow us to locate the correct - * register and mask the correct bits. - */ -static inline void sx150x_find_cfg(u8 offset, u8 width, - u8 *reg, u8 *mask, u8 *shift) -{ - *reg -= offset * width / 8; - *mask = (1 << width) - 1; - *shift = (offset * width) % 8; - *mask <<= *shift; -} - -static s32 sx150x_write_cfg(struct sx150x_chip *chip, - u8 offset, u8 width, u8 reg, u8 val) -{ - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err < 0) - return err; - - data &= ~mask; - data |= (val << shift) & mask; - return sx150x_i2c_write(chip->client, reg, data); -} - -static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) -{ - u8 reg = chip->dev_cfg->reg_data; - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, 1, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err >= 0) - err = (data & mask) != 0 ? 1 : 0; - - return err; -} - -static void sx150x_set_oscio(struct sx150x_chip *chip, int val) -{ - sx150x_i2c_write(chip->client, - chip->dev_cfg->reg_clock, - (val ? 0x1f : 0x10)); -} - -static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) -{ - sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); -} - -static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) -{ - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 1); -} - -static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) -{ - int err; - - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); - if (err >= 0) - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 0); - return err; -} - -static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip; - int status = -EINVAL; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_get_io(chip, offset); - mutex_unlock(&chip->lock); - } - - return status; -} - -static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) -{ - struct sx150x_chip *chip; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); - - mutex_lock(&chip->lock); - if (offset_is_oscio(chip, offset)) - sx150x_set_oscio(chip, val); - else - sx150x_set_io(chip, offset, val); - mutex_unlock(&chip->lock); -} - -static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip; - int status = -EINVAL; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_input(chip, offset); - mutex_unlock(&chip->lock); - } - return status; -} - -static int sx150x_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, - int val) -{ - struct sx150x_chip *chip; - int status = 0; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_output(chip, offset, val); - mutex_unlock(&chip->lock); - } - return status; -} - -static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); - - if (offset >= chip->dev_cfg->ngpios) - return -EINVAL; - - if (chip->irq_base < 0) - return -EINVAL; - - return chip->irq_base + offset; -} - -static void sx150x_irq_mask(struct irq_data *d) -{ - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct sx150x_chip *chip; - unsigned n; - - chip = container_of(ic, struct sx150x_chip, irq_chip); - n = d->irq - chip->irq_base; - chip->irq_masked |= (1 << n); - chip->irq_update = n; -} - -static void sx150x_irq_unmask(struct irq_data *d) -{ - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct sx150x_chip *chip; - unsigned n; - - chip = container_of(ic, struct sx150x_chip, irq_chip); - n = d->irq - chip->irq_base; - - chip->irq_masked &= ~(1 << n); - chip->irq_update = n; -} - -static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct sx150x_chip *chip; - unsigned n, val = 0; - - if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) - return -EINVAL; - - chip = container_of(ic, struct sx150x_chip, irq_chip); - n = d->irq - chip->irq_base; - - if (flow_type & IRQ_TYPE_EDGE_RISING) - val |= 0x1; - if (flow_type & IRQ_TYPE_EDGE_FALLING) - val |= 0x2; - - chip->irq_sense &= ~(3UL << (n * 2)); - chip->irq_sense |= val << (n * 2); - chip->irq_update = n; - return 0; -} - -static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) -{ - struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; - unsigned nhandled = 0; - unsigned sub_irq; - unsigned n; - s32 err; - u8 val; - int i; - - for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { - err = sx150x_i2c_read(chip->client, - chip->dev_cfg->reg_irq_src - i, - &val); - if (err < 0) - continue; - - sx150x_i2c_write(chip->client, - chip->dev_cfg->reg_irq_src - i, - val); - for (n = 0; n < 8; ++n) { - if (val & (1 << n)) { - sub_irq = chip->irq_base + (i * 8) + n; - handle_nested_irq(sub_irq); - ++nhandled; - } - } - } - - return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); -} - -static void sx150x_irq_bus_lock(struct irq_data *d) -{ - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct sx150x_chip *chip; - - chip = container_of(ic, struct sx150x_chip, irq_chip); - - mutex_lock(&chip->lock); -} - -static void sx150x_irq_bus_sync_unlock(struct irq_data *d) -{ - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct sx150x_chip *chip; - unsigned n; - - chip = container_of(ic, struct sx150x_chip, irq_chip); - - if (chip->irq_update == NO_UPDATE_PENDING) - goto out; - - n = chip->irq_update; - chip->irq_update = NO_UPDATE_PENDING; - - /* Avoid updates if nothing changed */ - if (chip->dev_sense == chip->irq_sense && - chip->dev_sense == chip->irq_masked) - goto out; - - chip->dev_sense = chip->irq_sense; - chip->dev_masked = chip->irq_masked; - - if (chip->irq_masked & (1 << n)) { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); - } else { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, - chip->irq_sense >> (n * 2)); - } -out: - mutex_unlock(&chip->lock); -} - -static void sx150x_init_chip(struct sx150x_chip *chip, - struct i2c_client *client, - kernel_ulong_t driver_data, - struct sx150x_platform_data *pdata) -{ - mutex_init(&chip->lock); - - chip->client = client; - chip->dev_cfg = &sx150x_devices[driver_data]; - chip->gpio_chip.label = client->name; - chip->gpio_chip.direction_input = sx150x_gpio_direction_input; - chip->gpio_chip.direction_output = sx150x_gpio_direction_output; - chip->gpio_chip.get = sx150x_gpio_get; - chip->gpio_chip.set = sx150x_gpio_set; - chip->gpio_chip.to_irq = sx150x_gpio_to_irq; - chip->gpio_chip.base = pdata->gpio_base; - chip->gpio_chip.can_sleep = 1; - chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; - if (pdata->oscio_is_gpo) - ++chip->gpio_chip.ngpio; - - chip->irq_chip.name = client->name; - chip->irq_chip.irq_mask = sx150x_irq_mask; - chip->irq_chip.irq_unmask = sx150x_irq_unmask; - chip->irq_chip.irq_set_type = sx150x_irq_set_type; - chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; - chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; - chip->irq_summary = -1; - chip->irq_base = -1; - chip->irq_masked = ~0; - chip->irq_sense = 0; - chip->dev_masked = ~0; - chip->dev_sense = 0; - chip->irq_update = NO_UPDATE_PENDING; -} - -static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) -{ - int err = 0; - unsigned n; - - for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) - err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); - return err; -} - -static int sx150x_reset(struct sx150x_chip *chip) -{ - int err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->reg_reset, - 0x12); - if (err < 0) - return err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->reg_reset, - 0x34); - return err; -} - -static int sx150x_init_hw(struct sx150x_chip *chip, - struct sx150x_platform_data *pdata) -{ - int err = 0; - - if (pdata->reset_during_probe) { - err = sx150x_reset(chip); - if (err < 0) - return err; - } - - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->reg_misc, - 0x01); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, - pdata->io_pullup_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, - pdata->io_pulldn_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_drain, - pdata->io_open_drain_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity, - pdata->io_polarity); - if (err < 0) - return err; - - if (pdata->oscio_is_gpo) - sx150x_set_oscio(chip, 0); - - return err; -} - -static int sx150x_install_irq_chip(struct sx150x_chip *chip, - int irq_summary, - int irq_base) -{ - int err; - unsigned n; - unsigned irq; - - chip->irq_summary = irq_summary; - chip->irq_base = irq_base; - - for (n = 0; n < chip->dev_cfg->ngpios; ++n) { - irq = irq_base + n; - irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - err = request_threaded_irq(irq_summary, - NULL, - sx150x_irq_thread_fn, - IRQF_SHARED | IRQF_TRIGGER_FALLING, - chip->irq_chip.name, - chip); - if (err < 0) { - chip->irq_summary = -1; - chip->irq_base = -1; - } - - return err; -} - -static void sx150x_remove_irq_chip(struct sx150x_chip *chip) -{ - unsigned n; - unsigned irq; - - free_irq(chip->irq_summary, chip); - - for (n = 0; n < chip->dev_cfg->ngpios; ++n) { - irq = chip->irq_base + n; - irq_set_chip_and_handler(irq, NULL, NULL); - } -} - -static int __devinit sx150x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA; - struct sx150x_platform_data *pdata; - struct sx150x_chip *chip; - int rc; - - pdata = client->dev.platform_data; - if (!pdata) - return -EINVAL; - - if (!i2c_check_functionality(client->adapter, i2c_funcs)) - return -ENOSYS; - - chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - sx150x_init_chip(chip, client, id->driver_data, pdata); - rc = sx150x_init_hw(chip, pdata); - if (rc < 0) - goto probe_fail_pre_gpiochip_add; - - rc = gpiochip_add(&chip->gpio_chip); - if (rc < 0) - goto probe_fail_pre_gpiochip_add; - - if (pdata->irq_summary >= 0) { - rc = sx150x_install_irq_chip(chip, - pdata->irq_summary, - pdata->irq_base); - if (rc < 0) - goto probe_fail_post_gpiochip_add; - } - - i2c_set_clientdata(client, chip); - - return 0; -probe_fail_post_gpiochip_add: - WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0); -probe_fail_pre_gpiochip_add: - kfree(chip); - return rc; -} - -static int __devexit sx150x_remove(struct i2c_client *client) -{ - struct sx150x_chip *chip; - int rc; - - chip = i2c_get_clientdata(client); - rc = gpiochip_remove(&chip->gpio_chip); - if (rc < 0) - return rc; - - if (chip->irq_summary >= 0) - sx150x_remove_irq_chip(chip); - - kfree(chip); - - return 0; -} - -static struct i2c_driver sx150x_driver = { - .driver = { - .name = "sx150x", - .owner = THIS_MODULE - }, - .probe = sx150x_probe, - .remove = __devexit_p(sx150x_remove), - .id_table = sx150x_id, -}; - -static int __init sx150x_init(void) -{ - return i2c_add_driver(&sx150x_driver); -} -subsys_initcall(sx150x_init); - -static void __exit sx150x_exit(void) -{ - return i2c_del_driver(&sx150x_driver); -} -module_exit(sx150x_exit); - -MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); -MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("i2c:sx150x"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-tc3589x.c b/ANDROID_3.4.5/drivers/gpio/gpio-tc3589x.c deleted file mode 100644 index 2a82e899..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-tc3589x.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License, version 2 - * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson - * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/mfd/tc3589x.h> - -/* - * These registers are modified under the irq bus lock and cached to avoid - * unnecessary writes in bus_sync_unlock. - */ -enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; - -#define CACHE_NR_REGS 4 -#define CACHE_NR_BANKS 3 - -struct tc3589x_gpio { - struct gpio_chip chip; - struct tc3589x *tc3589x; - struct device *dev; - struct mutex irq_lock; - - int irq_base; - - /* Caches of interrupt control registers for bus_lock */ - u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; - u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; -}; - -static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct tc3589x_gpio, chip); -} - -static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; - u8 mask = 1 << (offset % 8); - int ret; - - ret = tc3589x_reg_read(tc3589x, reg); - if (ret < 0) - return ret; - - return ret & mask; -} - -static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; - unsigned pos = offset % 8; - u8 data[] = {!!val << pos, 1 << pos}; - - tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); -} - -static int tc3589x_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int val) -{ - struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - u8 reg = TC3589x_GPIODIR0 + offset / 8; - unsigned pos = offset % 8; - - tc3589x_gpio_set(chip, offset, val); - - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); -} - -static int tc3589x_gpio_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - u8 reg = TC3589x_GPIODIR0 + offset / 8; - unsigned pos = offset % 8; - - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); -} - -static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - - return tc3589x_gpio->irq_base + offset; -} - -static struct gpio_chip template_chip = { - .label = "tc3589x", - .owner = THIS_MODULE, - .direction_input = tc3589x_gpio_direction_input, - .get = tc3589x_gpio_get, - .direction_output = tc3589x_gpio_direction_output, - .set = tc3589x_gpio_set, - .to_irq = tc3589x_gpio_to_irq, - .can_sleep = 1, -}; - -static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tc3589x_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - if (type == IRQ_TYPE_EDGE_BOTH) { - tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; - return 0; - } - - tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask; - - if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) - tc3589x_gpio->regs[REG_IS][regoffset] |= mask; - else - tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask; - - if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) - tc3589x_gpio->regs[REG_IEV][regoffset] |= mask; - else - tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask; - - return 0; -} - -static void tc3589x_gpio_irq_lock(struct irq_data *d) -{ - struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); - - mutex_lock(&tc3589x_gpio->irq_lock); -} - -static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) -{ - struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - static const u8 regmap[] = { - [REG_IBE] = TC3589x_GPIOIBE0, - [REG_IEV] = TC3589x_GPIOIEV0, - [REG_IS] = TC3589x_GPIOIS0, - [REG_IE] = TC3589x_GPIOIE0, - }; - int i, j; - - for (i = 0; i < CACHE_NR_REGS; i++) { - for (j = 0; j < CACHE_NR_BANKS; j++) { - u8 old = tc3589x_gpio->oldregs[i][j]; - u8 new = tc3589x_gpio->regs[i][j]; - - if (new == old) - continue; - - tc3589x_gpio->oldregs[i][j] = new; - tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new); - } - } - - mutex_unlock(&tc3589x_gpio->irq_lock); -} - -static void tc3589x_gpio_irq_mask(struct irq_data *d) -{ - struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tc3589x_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; -} - -static void tc3589x_gpio_irq_unmask(struct irq_data *d) -{ - struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tc3589x_gpio->irq_base; - int regoffset = offset / 8; - int mask = 1 << (offset % 8); - - tc3589x_gpio->regs[REG_IE][regoffset] |= mask; -} - -static struct irq_chip tc3589x_gpio_irq_chip = { - .name = "tc3589x-gpio", - .irq_bus_lock = tc3589x_gpio_irq_lock, - .irq_bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, - .irq_mask = tc3589x_gpio_irq_mask, - .irq_unmask = tc3589x_gpio_irq_unmask, - .irq_set_type = tc3589x_gpio_irq_set_type, -}; - -static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) -{ - struct tc3589x_gpio *tc3589x_gpio = dev; - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - u8 status[CACHE_NR_BANKS]; - int ret; - int i; - - ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0, - ARRAY_SIZE(status), status); - if (ret < 0) - return IRQ_NONE; - - for (i = 0; i < ARRAY_SIZE(status); i++) { - unsigned int stat = status[i]; - if (!stat) - continue; - - while (stat) { - int bit = __ffs(stat); - int line = i * 8 + bit; - - handle_nested_irq(tc3589x_gpio->irq_base + line); - stat &= ~(1 << bit); - } - - tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]); - } - - return IRQ_HANDLED; -} - -static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) -{ - int base = tc3589x_gpio->irq_base; - int irq; - - for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { - irq_set_chip_data(irq, tc3589x_gpio); - irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip, - handle_simple_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - return 0; -} - -static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio) -{ - int base = tc3589x_gpio->irq_base; - int irq; - - for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); - } -} - -static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) -{ - struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); - struct tc3589x_gpio_platform_data *pdata; - struct tc3589x_gpio *tc3589x_gpio; - int ret; - int irq; - - pdata = tc3589x->pdata->gpio; - if (!pdata) - return -ENODEV; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL); - if (!tc3589x_gpio) - return -ENOMEM; - - mutex_init(&tc3589x_gpio->irq_lock); - - tc3589x_gpio->dev = &pdev->dev; - tc3589x_gpio->tc3589x = tc3589x; - - tc3589x_gpio->chip = template_chip; - tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; - tc3589x_gpio->chip.dev = &pdev->dev; - tc3589x_gpio->chip.base = pdata->gpio_base; - - tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); - - /* Bring the GPIO module out of reset */ - ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, - TC3589x_RSTCTRL_GPIRST, 0); - if (ret < 0) - goto out_free; - - ret = tc3589x_gpio_irq_init(tc3589x_gpio); - if (ret) - goto out_free; - - ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, - "tc3589x-gpio", tc3589x_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_removeirq; - } - - ret = gpiochip_add(&tc3589x_gpio->chip); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_freeirq; - } - - if (pdata->setup) - pdata->setup(tc3589x, tc3589x_gpio->chip.base); - - platform_set_drvdata(pdev, tc3589x_gpio); - - return 0; - -out_freeirq: - free_irq(irq, tc3589x_gpio); -out_removeirq: - tc3589x_gpio_irq_remove(tc3589x_gpio); -out_free: - kfree(tc3589x_gpio); - return ret; -} - -static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) -{ - struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev); - struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; - struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio; - int irq = platform_get_irq(pdev, 0); - int ret; - - if (pdata->remove) - pdata->remove(tc3589x, tc3589x_gpio->chip.base); - - ret = gpiochip_remove(&tc3589x_gpio->chip); - if (ret < 0) { - dev_err(tc3589x_gpio->dev, - "unable to remove gpiochip: %d\n", ret); - return ret; - } - - free_irq(irq, tc3589x_gpio); - tc3589x_gpio_irq_remove(tc3589x_gpio); - - platform_set_drvdata(pdev, NULL); - kfree(tc3589x_gpio); - - return 0; -} - -static struct platform_driver tc3589x_gpio_driver = { - .driver.name = "tc3589x-gpio", - .driver.owner = THIS_MODULE, - .probe = tc3589x_gpio_probe, - .remove = __devexit_p(tc3589x_gpio_remove), -}; - -static int __init tc3589x_gpio_init(void) -{ - return platform_driver_register(&tc3589x_gpio_driver); -} -subsys_initcall(tc3589x_gpio_init); - -static void __exit tc3589x_gpio_exit(void) -{ - platform_driver_unregister(&tc3589x_gpio_driver); -} -module_exit(tc3589x_gpio_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TC3589x GPIO driver"); -MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-tegra.c b/ANDROID_3.4.5/drivers/gpio/gpio-tegra.c deleted file mode 100644 index 12f349b3..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-tegra.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * arch/arm/mach-tegra/gpio.c - * - * Copyright (c) 2010 Google, Inc - * - * Author: - * Erik Gilling <konkers@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/irqdomain.h> - -#include <asm/mach/irq.h> - -#include <mach/gpio-tegra.h> -#include <mach/iomap.h> -#include <mach/suspend.h> - -#define GPIO_BANK(x) ((x) >> 5) -#define GPIO_PORT(x) (((x) >> 3) & 0x3) -#define GPIO_BIT(x) ((x) & 0x7) - -#define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \ - GPIO_PORT(x) * 4) - -#define GPIO_CNF(x) (GPIO_REG(x) + 0x00) -#define GPIO_OE(x) (GPIO_REG(x) + 0x10) -#define GPIO_OUT(x) (GPIO_REG(x) + 0X20) -#define GPIO_IN(x) (GPIO_REG(x) + 0x30) -#define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40) -#define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50) -#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) -#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) - -#define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00) -#define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10) -#define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20) -#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40) -#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50) -#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60) - -#define GPIO_INT_LVL_MASK 0x010101 -#define GPIO_INT_LVL_EDGE_RISING 0x000101 -#define GPIO_INT_LVL_EDGE_FALLING 0x000100 -#define GPIO_INT_LVL_EDGE_BOTH 0x010100 -#define GPIO_INT_LVL_LEVEL_HIGH 0x000001 -#define GPIO_INT_LVL_LEVEL_LOW 0x000000 - -struct tegra_gpio_bank { - int bank; - int irq; - spinlock_t lvl_lock[4]; -#ifdef CONFIG_PM - u32 cnf[4]; - u32 out[4]; - u32 oe[4]; - u32 int_enb[4]; - u32 int_lvl[4]; -#endif -}; - -static struct irq_domain *irq_domain; -static void __iomem *regs; -static u32 tegra_gpio_bank_count; -static u32 tegra_gpio_bank_stride; -static u32 tegra_gpio_upper_offset; -static struct tegra_gpio_bank *tegra_gpio_banks; - -static inline void tegra_gpio_writel(u32 val, u32 reg) -{ - __raw_writel(val, regs + reg); -} - -static inline u32 tegra_gpio_readl(u32 reg) -{ - return __raw_readl(regs + reg); -} - -static int tegra_gpio_compose(int bank, int port, int bit) -{ - return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7); -} - -static void tegra_gpio_mask_write(u32 reg, int gpio, int value) -{ - u32 val; - - val = 0x100 << GPIO_BIT(gpio); - if (value) - val |= 1 << GPIO_BIT(gpio); - tegra_gpio_writel(val, reg); -} - -void tegra_gpio_enable(int gpio) -{ - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); -} -EXPORT_SYMBOL_GPL(tegra_gpio_enable); - -void tegra_gpio_disable(int gpio) -{ - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); -} -EXPORT_SYMBOL_GPL(tegra_gpio_disable); - -static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value); -} - -static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; -} - -static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0); - return 0; -} - -static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - tegra_gpio_set(chip, offset, value); - tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1); - return 0; -} - -static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return irq_find_mapping(irq_domain, offset); -} - -static struct gpio_chip tegra_gpio_chip = { - .label = "tegra-gpio", - .direction_input = tegra_gpio_direction_input, - .get = tegra_gpio_get, - .direction_output = tegra_gpio_direction_output, - .set = tegra_gpio_set, - .to_irq = tegra_gpio_to_irq, - .base = 0, - .ngpio = TEGRA_NR_GPIOS, -}; - -static void tegra_gpio_irq_ack(struct irq_data *d) -{ - int gpio = d->hwirq; - - tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); -} - -static void tegra_gpio_irq_mask(struct irq_data *d) -{ - int gpio = d->hwirq; - - tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0); -} - -static void tegra_gpio_irq_unmask(struct irq_data *d) -{ - int gpio = d->hwirq; - - tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1); -} - -static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) -{ - int gpio = d->hwirq; - struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); - int port = GPIO_PORT(gpio); - int lvl_type; - int val; - unsigned long flags; - - switch (type & IRQ_TYPE_SENSE_MASK) { - case IRQ_TYPE_EDGE_RISING: - lvl_type = GPIO_INT_LVL_EDGE_RISING; - break; - - case IRQ_TYPE_EDGE_FALLING: - lvl_type = GPIO_INT_LVL_EDGE_FALLING; - break; - - case IRQ_TYPE_EDGE_BOTH: - lvl_type = GPIO_INT_LVL_EDGE_BOTH; - break; - - case IRQ_TYPE_LEVEL_HIGH: - lvl_type = GPIO_INT_LVL_LEVEL_HIGH; - break; - - case IRQ_TYPE_LEVEL_LOW: - lvl_type = GPIO_INT_LVL_LEVEL_LOW; - break; - - default: - return -EINVAL; - } - - spin_lock_irqsave(&bank->lvl_lock[port], flags); - - val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); - val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); - val |= lvl_type << GPIO_BIT(gpio); - tegra_gpio_writel(val, GPIO_INT_LVL(gpio)); - - spin_unlock_irqrestore(&bank->lvl_lock[port], flags); - - if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __irq_set_handler_locked(d->irq, handle_level_irq); - else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - __irq_set_handler_locked(d->irq, handle_edge_irq); - - return 0; -} - -static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct tegra_gpio_bank *bank; - int port; - int pin; - int unmasked = 0; - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - bank = irq_get_handler_data(irq); - - for (port = 0; port < 4; port++) { - int gpio = tegra_gpio_compose(bank->bank, port, 0); - unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & - tegra_gpio_readl(GPIO_INT_ENB(gpio)); - u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio)); - - for_each_set_bit(pin, &sta, 8) { - tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio)); - - /* if gpio is edge triggered, clear condition - * before executing the hander so that we don't - * miss edges - */ - if (lvl & (0x100 << pin)) { - unmasked = 1; - chained_irq_exit(chip, desc); - } - - generic_handle_irq(gpio_to_irq(gpio + pin)); - } - } - - if (!unmasked) - chained_irq_exit(chip, desc); - -} - -#ifdef CONFIG_PM -void tegra_gpio_resume(void) -{ - unsigned long flags; - int b; - int p; - - local_irq_save(flags); - - for (b = 0; b < tegra_gpio_bank_count; b++) { - struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; - - for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - unsigned int gpio = (b<<5) | (p<<3); - tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio)); - tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio)); - tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio)); - tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); - tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); - } - } - - local_irq_restore(flags); -} - -void tegra_gpio_suspend(void) -{ - unsigned long flags; - int b; - int p; - - local_irq_save(flags); - for (b = 0; b < tegra_gpio_bank_count; b++) { - struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; - - for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - unsigned int gpio = (b<<5) | (p<<3); - bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio)); - bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio)); - bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); - bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); - bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); - } - } - local_irq_restore(flags); -} - -static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) -{ - struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); - return irq_set_irq_wake(bank->irq, enable); -} -#endif - -static struct irq_chip tegra_gpio_irq_chip = { - .name = "GPIO", - .irq_ack = tegra_gpio_irq_ack, - .irq_mask = tegra_gpio_irq_mask, - .irq_unmask = tegra_gpio_irq_unmask, - .irq_set_type = tegra_gpio_irq_set_type, -#ifdef CONFIG_PM - .irq_set_wake = tegra_gpio_wake_enable, -#endif -}; - -struct tegra_gpio_soc_config { - u32 bank_stride; - u32 upper_offset; -}; - -static struct tegra_gpio_soc_config tegra20_gpio_config = { - .bank_stride = 0x80, - .upper_offset = 0x800, -}; - -static struct tegra_gpio_soc_config tegra30_gpio_config = { - .bank_stride = 0x100, - .upper_offset = 0x80, -}; - -static struct of_device_id tegra_gpio_of_match[] __devinitdata = { - { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, - { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, - { }, -}; - -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - -static int __devinit tegra_gpio_probe(struct platform_device *pdev) -{ - const struct of_device_id *match; - struct tegra_gpio_soc_config *config; - int irq_base; - struct resource *res; - struct tegra_gpio_bank *bank; - int gpio; - int i; - int j; - - match = of_match_device(tegra_gpio_of_match, &pdev->dev); - if (match) - config = (struct tegra_gpio_soc_config *)match->data; - else - config = &tegra20_gpio_config; - - tegra_gpio_bank_stride = config->bank_stride; - tegra_gpio_upper_offset = config->upper_offset; - - for (;;) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count); - if (!res) - break; - tegra_gpio_bank_count++; - } - if (!tegra_gpio_bank_count) { - dev_err(&pdev->dev, "Missing IRQ resource\n"); - return -ENODEV; - } - - tegra_gpio_chip.ngpio = tegra_gpio_bank_count * 32; - - tegra_gpio_banks = devm_kzalloc(&pdev->dev, - tegra_gpio_bank_count * sizeof(*tegra_gpio_banks), - GFP_KERNEL); - if (!tegra_gpio_banks) { - dev_err(&pdev->dev, "Couldn't allocate bank structure\n"); - return -ENODEV; - } - - irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0); - if (irq_base < 0) { - dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n"); - return -ENODEV; - } - irq_domain = irq_domain_add_legacy(pdev->dev.of_node, - tegra_gpio_chip.ngpio, irq_base, 0, - &irq_domain_simple_ops, NULL); - - for (i = 0; i < tegra_gpio_bank_count; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - dev_err(&pdev->dev, "Missing IRQ resource\n"); - return -ENODEV; - } - - bank = &tegra_gpio_banks[i]; - bank->bank = i; - bank->irq = res->start; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Missing MEM resource\n"); - return -ENODEV; - } - - regs = devm_request_and_ioremap(&pdev->dev, res); - if (!regs) { - dev_err(&pdev->dev, "Couldn't ioremap regs\n"); - return -ENODEV; - } - - for (i = 0; i < tegra_gpio_bank_count; i++) { - for (j = 0; j < 4; j++) { - int gpio = tegra_gpio_compose(i, j, 0); - tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); - } - } - -#ifdef CONFIG_OF_GPIO - tegra_gpio_chip.of_node = pdev->dev.of_node; -#endif - - gpiochip_add(&tegra_gpio_chip); - - for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { - int irq = irq_find_mapping(irq_domain, gpio); - /* No validity check; all Tegra GPIOs are valid IRQs */ - - bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; - - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_data(irq, bank); - irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, - handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); - } - - for (i = 0; i < tegra_gpio_bank_count; i++) { - bank = &tegra_gpio_banks[i]; - - irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler); - irq_set_handler_data(bank->irq, bank); - - for (j = 0; j < 4; j++) - spin_lock_init(&bank->lvl_lock[j]); - } - - return 0; -} - -static struct platform_driver tegra_gpio_driver = { - .driver = { - .name = "tegra-gpio", - .owner = THIS_MODULE, - .of_match_table = tegra_gpio_of_match, - }, - .probe = tegra_gpio_probe, -}; - -static int __init tegra_gpio_init(void) -{ - return platform_driver_register(&tegra_gpio_driver); -} -postcore_initcall(tegra_gpio_init); - -void tegra_gpio_config(struct tegra_gpio_table *table, int num) -{ - int i; - - for (i = 0; i < num; i++) { - int gpio = table[i].gpio; - - if (table[i].enable) - tegra_gpio_enable(gpio); - else - tegra_gpio_disable(gpio); - } -} - -#ifdef CONFIG_DEBUG_FS - -#include <linux/debugfs.h> -#include <linux/seq_file.h> - -static int dbg_gpio_show(struct seq_file *s, void *unused) -{ - int i; - int j; - - for (i = 0; i < tegra_gpio_bank_count; i++) { - for (j = 0; j < 4; j++) { - int gpio = tegra_gpio_compose(i, j, 0); - seq_printf(s, - "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", - i, j, - tegra_gpio_readl(GPIO_CNF(gpio)), - tegra_gpio_readl(GPIO_OE(gpio)), - tegra_gpio_readl(GPIO_OUT(gpio)), - tegra_gpio_readl(GPIO_IN(gpio)), - tegra_gpio_readl(GPIO_INT_STA(gpio)), - tegra_gpio_readl(GPIO_INT_ENB(gpio)), - tegra_gpio_readl(GPIO_INT_LVL(gpio))); - } - } - return 0; -} - -static int dbg_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_gpio_show, &inode->i_private); -} - -static const struct file_operations debug_fops = { - .open = dbg_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init tegra_gpio_debuginit(void) -{ - (void) debugfs_create_file("tegra_gpio", S_IRUGO, - NULL, NULL, &debug_fops); - return 0; -} -late_initcall(tegra_gpio_debuginit); -#endif diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-timberdale.c b/ANDROID_3.4.5/drivers/gpio/gpio-timberdale.c deleted file mode 100644 index 031c6adf..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-timberdale.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Timberdale FPGA GPIO driver - * Copyright (c) 2009 Intel Corporation - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Timberdale FPGA GPIO - */ - -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/platform_device.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/timb_gpio.h> -#include <linux/interrupt.h> -#include <linux/slab.h> - -#define DRIVER_NAME "timb-gpio" - -#define TGPIOVAL 0x00 -#define TGPIODIR 0x04 -#define TGPIO_IER 0x08 -#define TGPIO_ISR 0x0c -#define TGPIO_IPR 0x10 -#define TGPIO_ICR 0x14 -#define TGPIO_FLR 0x18 -#define TGPIO_LVR 0x1c -#define TGPIO_VER 0x20 -#define TGPIO_BFLR 0x24 - -struct timbgpio { - void __iomem *membase; - spinlock_t lock; /* mutual exclusion */ - struct gpio_chip gpio; - int irq_base; - unsigned long last_ier; -}; - -static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, - unsigned offset, bool enabled) -{ - struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); - u32 reg; - - spin_lock(&tgpio->lock); - reg = ioread32(tgpio->membase + offset); - - if (enabled) - reg |= (1 << index); - else - reg &= ~(1 << index); - - iowrite32(reg, tgpio->membase + offset); - spin_unlock(&tgpio->lock); - - return 0; -} - -static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) -{ - return timbgpio_update_bit(gpio, nr, TGPIODIR, true); -} - -static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) -{ - struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); - u32 value; - - value = ioread32(tgpio->membase + TGPIOVAL); - return (value & (1 << nr)) ? 1 : 0; -} - -static int timbgpio_gpio_direction_output(struct gpio_chip *gpio, - unsigned nr, int val) -{ - return timbgpio_update_bit(gpio, nr, TGPIODIR, false); -} - -static void timbgpio_gpio_set(struct gpio_chip *gpio, - unsigned nr, int val) -{ - timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); -} - -static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) -{ - struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); - - if (tgpio->irq_base <= 0) - return -EINVAL; - - return tgpio->irq_base + offset; -} - -/* - * GPIO IRQ - */ -static void timbgpio_irq_disable(struct irq_data *d) -{ - struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tgpio->irq_base; - unsigned long flags; - - spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); - iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); - spin_unlock_irqrestore(&tgpio->lock, flags); -} - -static void timbgpio_irq_enable(struct irq_data *d) -{ - struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tgpio->irq_base; - unsigned long flags; - - spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; - iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); - spin_unlock_irqrestore(&tgpio->lock, flags); -} - -static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) -{ - struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); - int offset = d->irq - tgpio->irq_base; - unsigned long flags; - u32 lvr, flr, bflr = 0; - u32 ver; - int ret = 0; - - if (offset < 0 || offset > tgpio->gpio.ngpio) - return -EINVAL; - - ver = ioread32(tgpio->membase + TGPIO_VER); - - spin_lock_irqsave(&tgpio->lock, flags); - - lvr = ioread32(tgpio->membase + TGPIO_LVR); - flr = ioread32(tgpio->membase + TGPIO_FLR); - if (ver > 2) - bflr = ioread32(tgpio->membase + TGPIO_BFLR); - - if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - bflr &= ~(1 << offset); - flr &= ~(1 << offset); - if (trigger & IRQ_TYPE_LEVEL_HIGH) - lvr |= 1 << offset; - else - lvr &= ~(1 << offset); - } - - if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { - if (ver < 3) { - ret = -EINVAL; - goto out; - } - else { - flr |= 1 << offset; - bflr |= 1 << offset; - } - } else { - bflr &= ~(1 << offset); - flr |= 1 << offset; - if (trigger & IRQ_TYPE_EDGE_FALLING) - lvr &= ~(1 << offset); - else - lvr |= 1 << offset; - } - - iowrite32(lvr, tgpio->membase + TGPIO_LVR); - iowrite32(flr, tgpio->membase + TGPIO_FLR); - if (ver > 2) - iowrite32(bflr, tgpio->membase + TGPIO_BFLR); - - iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); - -out: - spin_unlock_irqrestore(&tgpio->lock, flags); - return ret; -} - -static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) -{ - struct timbgpio *tgpio = irq_get_handler_data(irq); - unsigned long ipr; - int offset; - - desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); - ipr = ioread32(tgpio->membase + TGPIO_IPR); - iowrite32(ipr, tgpio->membase + TGPIO_ICR); - - /* - * Some versions of the hardware trash the IER register if more than - * one interrupt is received simultaneously. - */ - iowrite32(0, tgpio->membase + TGPIO_IER); - - for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) - generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); - - iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); -} - -static struct irq_chip timbgpio_irqchip = { - .name = "GPIO", - .irq_enable = timbgpio_irq_enable, - .irq_disable = timbgpio_irq_disable, - .irq_set_type = timbgpio_irq_type, -}; - -static int __devinit timbgpio_probe(struct platform_device *pdev) -{ - int err, i; - struct gpio_chip *gc; - struct timbgpio *tgpio; - struct resource *iomem; - struct timbgpio_platform_data *pdata = pdev->dev.platform_data; - int irq = platform_get_irq(pdev, 0); - - if (!pdata || pdata->nr_pins > 32) { - err = -EINVAL; - goto err_mem; - } - - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) { - err = -EINVAL; - goto err_mem; - } - - tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL); - if (!tgpio) { - err = -EINVAL; - goto err_mem; - } - tgpio->irq_base = pdata->irq_base; - - spin_lock_init(&tgpio->lock); - - if (!request_mem_region(iomem->start, resource_size(iomem), - DRIVER_NAME)) { - err = -EBUSY; - goto err_request; - } - - tgpio->membase = ioremap(iomem->start, resource_size(iomem)); - if (!tgpio->membase) { - err = -ENOMEM; - goto err_ioremap; - } - - gc = &tgpio->gpio; - - gc->label = dev_name(&pdev->dev); - gc->owner = THIS_MODULE; - gc->dev = &pdev->dev; - gc->direction_input = timbgpio_gpio_direction_input; - gc->get = timbgpio_gpio_get; - gc->direction_output = timbgpio_gpio_direction_output; - gc->set = timbgpio_gpio_set; - gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; - gc->dbg_show = NULL; - gc->base = pdata->gpio_base; - gc->ngpio = pdata->nr_pins; - gc->can_sleep = 0; - - err = gpiochip_add(gc); - if (err) - goto err_chipadd; - - platform_set_drvdata(pdev, tgpio); - - /* make sure to disable interrupts */ - iowrite32(0x0, tgpio->membase + TGPIO_IER); - - if (irq < 0 || tgpio->irq_base <= 0) - return 0; - - for (i = 0; i < pdata->nr_pins; i++) { - irq_set_chip_and_handler_name(tgpio->irq_base + i, - &timbgpio_irqchip, handle_simple_irq, "mux"); - irq_set_chip_data(tgpio->irq_base + i, tgpio); -#ifdef CONFIG_ARM - set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); -#endif - } - - irq_set_handler_data(irq, tgpio); - irq_set_chained_handler(irq, timbgpio_irq); - - return 0; - -err_chipadd: - iounmap(tgpio->membase); -err_ioremap: - release_mem_region(iomem->start, resource_size(iomem)); -err_request: - kfree(tgpio); -err_mem: - printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err); - - return err; -} - -static int __devexit timbgpio_remove(struct platform_device *pdev) -{ - int err; - struct timbgpio_platform_data *pdata = pdev->dev.platform_data; - struct timbgpio *tgpio = platform_get_drvdata(pdev); - struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int irq = platform_get_irq(pdev, 0); - - if (irq >= 0 && tgpio->irq_base > 0) { - int i; - for (i = 0; i < pdata->nr_pins; i++) { - irq_set_chip(tgpio->irq_base + i, NULL); - irq_set_chip_data(tgpio->irq_base + i, NULL); - } - - irq_set_handler(irq, NULL); - irq_set_handler_data(irq, NULL); - } - - err = gpiochip_remove(&tgpio->gpio); - if (err) - printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n"); - - iounmap(tgpio->membase); - release_mem_region(iomem->start, resource_size(iomem)); - kfree(tgpio); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver timbgpio_platform_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = timbgpio_probe, - .remove = timbgpio_remove, -}; - -/*--------------------------------------------------------------------------*/ - -module_platform_driver(timbgpio_platform_driver); - -MODULE_DESCRIPTION("Timberdale GPIO driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Mocean Laboratories"); -MODULE_ALIAS("platform:"DRIVER_NAME); - diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-tnetv107x.c b/ANDROID_3.4.5/drivers/gpio/gpio-tnetv107x.c deleted file mode 100644 index 3fa3e286..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-tnetv107x.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Texas Instruments TNETV107X GPIO Controller - * - * Copyright (C) 2010 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/gpio.h> - -#include <mach/common.h> -#include <mach/tnetv107x.h> - -struct tnetv107x_gpio_regs { - u32 idver; - u32 data_in[3]; - u32 data_out[3]; - u32 direction[3]; - u32 enable[3]; -}; - -#define gpio_reg_index(gpio) ((gpio) >> 5) -#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f) - -#define gpio_reg_rmw(reg, mask, val) \ - __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg)) - -#define gpio_reg_set_bit(reg, gpio) \ - gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio)) - -#define gpio_reg_clear_bit(reg, gpio) \ - gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0) - -#define gpio_reg_get_bit(reg, gpio) \ - (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio)) - -#define chip2controller(chip) \ - container_of(chip, struct davinci_gpio_controller, chip) - -#define TNETV107X_GPIO_CTLRS DIV_ROUND_UP(TNETV107X_N_GPIO, 32) - -static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS]; - -static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_set_bit(regs->enable, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_clear_bit(regs->enable, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - gpio_reg_set_bit(regs->direction, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static int tnetv107x_gpio_dir_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - if (value) - gpio_reg_set_bit(regs->data_out, gpio); - else - gpio_reg_clear_bit(regs->data_out, gpio); - - gpio_reg_clear_bit(regs->direction, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); - - return 0; -} - -static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - int ret; - - ret = gpio_reg_get_bit(regs->data_in, gpio); - - return ret ? 1 : 0; -} - -static void tnetv107x_gpio_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct davinci_gpio_controller *ctlr = chip2controller(chip); - struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; - unsigned gpio = chip->base + offset; - unsigned long flags; - - spin_lock_irqsave(&ctlr->lock, flags); - - if (value) - gpio_reg_set_bit(regs->data_out, gpio); - else - gpio_reg_clear_bit(regs->data_out, gpio); - - spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int __init tnetv107x_gpio_setup(void) -{ - int i, base; - unsigned ngpio; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct tnetv107x_gpio_regs *regs; - struct davinci_gpio_controller *ctlr; - - if (soc_info->gpio_type != GPIO_TYPE_TNETV107X) - return 0; - - ngpio = soc_info->gpio_num; - if (ngpio == 0) { - pr_err("GPIO setup: how many GPIOs?\n"); - return -EINVAL; - } - - if (WARN_ON(TNETV107X_N_GPIO < ngpio)) - ngpio = TNETV107X_N_GPIO; - - regs = ioremap(soc_info->gpio_base, SZ_4K); - if (WARN_ON(!regs)) - return -EINVAL; - - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - ctlr = &chips[i]; - - ctlr->chip.label = "tnetv107x"; - ctlr->chip.can_sleep = 0; - ctlr->chip.base = base; - ctlr->chip.ngpio = ngpio - base; - if (ctlr->chip.ngpio > 32) - ctlr->chip.ngpio = 32; - - ctlr->chip.request = tnetv107x_gpio_request; - ctlr->chip.free = tnetv107x_gpio_free; - ctlr->chip.direction_input = tnetv107x_gpio_dir_in; - ctlr->chip.get = tnetv107x_gpio_get; - ctlr->chip.direction_output = tnetv107x_gpio_dir_out; - ctlr->chip.set = tnetv107x_gpio_set; - - spin_lock_init(&ctlr->lock); - - ctlr->regs = regs; - ctlr->set_data = ®s->data_out[i]; - ctlr->clr_data = ®s->data_out[i]; - ctlr->in_data = ®s->data_in[i]; - - gpiochip_add(&ctlr->chip); - } - - soc_info->gpio_ctlrs = chips; - soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - return 0; -} -pure_initcall(tnetv107x_gpio_setup); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-tps65910.c b/ANDROID_3.4.5/drivers/gpio/gpio-tps65910.c deleted file mode 100644 index 7eef648a..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-tps65910.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * TI TPS6591x GPIO driver - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Graeme Gregory <gg@slimlogic.co.uk> - * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/gpio.h> -#include <linux/i2c.h> -#include <linux/mfd/tps65910.h> - -static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - uint8_t val; - - tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val); - - if (val & GPIO_STS_MASK) - return 1; - - return 0; -} - -static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - if (value) - tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_SET_MASK); - else - tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_SET_MASK); -} - -static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - /* Set the initial value */ - tps65910_gpio_set(gc, offset, value); - - return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_CFG_MASK); -} - -static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_CFG_MASK); -} - -void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) -{ - int ret; - struct tps65910_board *board_data; - - if (!gpio_base) - return; - - tps65910->gpio.owner = THIS_MODULE; - tps65910->gpio.label = tps65910->i2c_client->name; - tps65910->gpio.dev = tps65910->dev; - tps65910->gpio.base = gpio_base; - - switch(tps65910_chip_id(tps65910)) { - case TPS65910: - tps65910->gpio.ngpio = TPS65910_NUM_GPIO; - break; - case TPS65911: - tps65910->gpio.ngpio = TPS65911_NUM_GPIO; - break; - default: - return; - } - tps65910->gpio.can_sleep = 1; - - tps65910->gpio.direction_input = tps65910_gpio_input; - tps65910->gpio.direction_output = tps65910_gpio_output; - tps65910->gpio.set = tps65910_gpio_set; - tps65910->gpio.get = tps65910_gpio_get; - - /* Configure sleep control for gpios */ - board_data = dev_get_platdata(tps65910->dev); - if (board_data) { - int i; - for (i = 0; i < tps65910->gpio.ngpio; ++i) { - if (board_data->en_gpio_sleep[i]) { - ret = tps65910_set_bits(tps65910, - TPS65910_GPIO0 + i, GPIO_SLEEP_MASK); - if (ret < 0) - dev_warn(tps65910->dev, - "GPIO Sleep setting failed\n"); - } - } - } - - ret = gpiochip_add(&tps65910->gpio); - - if (ret) - dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret); -} diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-tps65912.c b/ANDROID_3.4.5/drivers/gpio/gpio-tps65912.c deleted file mode 100644 index 79e66c00..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-tps65912.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya <magi@slimlogic.co.uk> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This driver is based on wm8350 implementation. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/gpio.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/seq_file.h> -#include <linux/slab.h> -#include <linux/mfd/tps65912.h> - -struct tps65912_gpio_data { - struct tps65912 *tps65912; - struct gpio_chip gpio_chip; -}; - -static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); - int val; - - val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset); - - if (val & GPIO_STS_MASK) - return 1; - - return 0; -} - -static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); - - if (value) - tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_SET_MASK); - else - tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_SET_MASK); -} - -static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); - - /* Set the initial value */ - tps65912_gpio_set(gc, offset, value); - - return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_CFG_MASK); -} - -static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) -{ - struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); - - return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_CFG_MASK); - -} - -static struct gpio_chip template_chip = { - .label = "tps65912", - .owner = THIS_MODULE, - .direction_input = tps65912_gpio_input, - .direction_output = tps65912_gpio_output, - .get = tps65912_gpio_get, - .set = tps65912_gpio_set, - .can_sleep = 1, - .ngpio = 5, - .base = -1, -}; - -static int __devinit tps65912_gpio_probe(struct platform_device *pdev) -{ - struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); - struct tps65912_board *pdata = tps65912->dev->platform_data; - struct tps65912_gpio_data *tps65912_gpio; - int ret; - - tps65912_gpio = kzalloc(sizeof(*tps65912_gpio), GFP_KERNEL); - if (tps65912_gpio == NULL) - return -ENOMEM; - - tps65912_gpio->tps65912 = tps65912; - tps65912_gpio->gpio_chip = template_chip; - tps65912_gpio->gpio_chip.dev = &pdev->dev; - if (pdata && pdata->gpio_base) - tps65912_gpio->gpio_chip.base = pdata->gpio_base; - - ret = gpiochip_add(&tps65912_gpio->gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - goto err; - } - - platform_set_drvdata(pdev, tps65912_gpio); - - return ret; - -err: - kfree(tps65912_gpio); - return ret; -} - -static int __devexit tps65912_gpio_remove(struct platform_device *pdev) -{ - struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&tps65912_gpio->gpio_chip); - if (ret == 0) - kfree(tps65912_gpio); - - return ret; -} - -static struct platform_driver tps65912_gpio_driver = { - .driver = { - .name = "tps65912-gpio", - .owner = THIS_MODULE, - }, - .probe = tps65912_gpio_probe, - .remove = __devexit_p(tps65912_gpio_remove), -}; - -static int __init tps65912_gpio_init(void) -{ - return platform_driver_register(&tps65912_gpio_driver); -} -subsys_initcall(tps65912_gpio_init); - -static void __exit tps65912_gpio_exit(void) -{ - platform_driver_unregister(&tps65912_gpio_driver); -} -module_exit(tps65912_gpio_exit); - -MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>"); -MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65912-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-twl4030.c b/ANDROID_3.4.5/drivers/gpio/gpio-twl4030.c deleted file mode 100644 index 94256fe7..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-twl4030.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Access to GPIOs on TWL4030/TPS659x0 chips - * - * Copyright (C) 2006-2007 Texas Instruments, Inc. - * Copyright (C) 2006 MontaVista Software, Inc. - * - * Code re-arranged and cleaned up by: - * Syed Mohammed Khasim <x0khasim@ti.com> - * - * Initial Code: - * Andy Lowe / Nishanth Menon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kthread.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/platform_device.h> -#include <linux/of.h> -#include <linux/irqdomain.h> - -#include <linux/i2c/twl.h> - - -/* - * The GPIO "subchip" supports 18 GPIOs which can be configured as - * inputs or outputs, with pullups or pulldowns on each pin. Each - * GPIO can trigger interrupts on either or both edges. - * - * GPIO interrupts can be fed to either of two IRQ lines; this is - * intended to support multiple hosts. - * - * There are also two LED pins used sometimes as output-only GPIOs. - */ - - -static struct gpio_chip twl_gpiochip; -static int twl4030_gpio_irq_base; - -/* genirq interfaces are not available to modules */ -#ifdef MODULE -#define is_module() true -#else -#define is_module() false -#endif - -/* GPIO_CTRL Fields */ -#define MASK_GPIO_CTRL_GPIO0CD1 BIT(0) -#define MASK_GPIO_CTRL_GPIO1CD2 BIT(1) -#define MASK_GPIO_CTRL_GPIO_ON BIT(2) - -/* Mask for GPIO registers when aggregated into a 32-bit integer */ -#define GPIO_32_MASK 0x0003ffff - -/* Data structures */ -static DEFINE_MUTEX(gpio_lock); - -/* store usage of each GPIO. - each bit represents one GPIO */ -static unsigned int gpio_usage_count; - -/*----------------------------------------------------------------------*/ - -/* - * To configure TWL4030 GPIO module registers - */ -static inline int gpio_twl4030_write(u8 address, u8 data) -{ - return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); -} - -/*----------------------------------------------------------------------*/ - -/* - * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB})) - * PWMs A and B are dedicated to LEDs A and B, respectively. - */ - -#define TWL4030_LED_LEDEN 0x0 - -/* LEDEN bits */ -#define LEDEN_LEDAON BIT(0) -#define LEDEN_LEDBON BIT(1) -#define LEDEN_LEDAEXT BIT(2) -#define LEDEN_LEDBEXT BIT(3) -#define LEDEN_LEDAPWM BIT(4) -#define LEDEN_LEDBPWM BIT(5) -#define LEDEN_PWM_LENGTHA BIT(6) -#define LEDEN_PWM_LENGTHB BIT(7) - -#define TWL4030_PWMx_PWMxON 0x0 -#define TWL4030_PWMx_PWMxOFF 0x1 - -#define PWMxON_LENGTH BIT(7) - -/*----------------------------------------------------------------------*/ - -/* - * To read a TWL4030 GPIO module register - */ -static inline int gpio_twl4030_read(u8 address) -{ - u8 data; - int ret = 0; - - ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); - return (ret < 0) ? ret : data; -} - -/*----------------------------------------------------------------------*/ - -static u8 cached_leden; /* protected by gpio_lock */ - -/* The LED lines are open drain outputs ... a FET pulls to GND, so an - * external pullup is needed. We could also expose the integrated PWM - * as a LED brightness control; we initialize it as "always on". - */ -static void twl4030_led_set_value(int led, int value) -{ - u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM; - int status; - - if (led) - mask <<= 1; - - mutex_lock(&gpio_lock); - if (value) - cached_leden &= ~mask; - else - cached_leden |= mask; - status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, - TWL4030_LED_LEDEN); - mutex_unlock(&gpio_lock); -} - -static int twl4030_set_gpio_direction(int gpio, int is_input) -{ - u8 d_bnk = gpio >> 3; - u8 d_msk = BIT(gpio & 0x7); - u8 reg = 0; - u8 base = REG_GPIODATADIR1 + d_bnk; - int ret = 0; - - mutex_lock(&gpio_lock); - ret = gpio_twl4030_read(base); - if (ret >= 0) { - if (is_input) - reg = ret & ~d_msk; - else - reg = ret | d_msk; - - ret = gpio_twl4030_write(base, reg); - } - mutex_unlock(&gpio_lock); - return ret; -} - -static int twl4030_set_gpio_dataout(int gpio, int enable) -{ - u8 d_bnk = gpio >> 3; - u8 d_msk = BIT(gpio & 0x7); - u8 base = 0; - - if (enable) - base = REG_SETGPIODATAOUT1 + d_bnk; - else - base = REG_CLEARGPIODATAOUT1 + d_bnk; - - return gpio_twl4030_write(base, d_msk); -} - -static int twl4030_get_gpio_datain(int gpio) -{ - u8 d_bnk = gpio >> 3; - u8 d_off = gpio & 0x7; - u8 base = 0; - int ret = 0; - - if (unlikely((gpio >= TWL4030_GPIO_MAX) - || !(gpio_usage_count & BIT(gpio)))) - return -EPERM; - - base = REG_GPIODATAIN1 + d_bnk; - ret = gpio_twl4030_read(base); - if (ret > 0) - ret = (ret >> d_off) & 0x1; - - return ret; -} - -/*----------------------------------------------------------------------*/ - -static int twl_request(struct gpio_chip *chip, unsigned offset) -{ - int status = 0; - - mutex_lock(&gpio_lock); - - /* Support the two LED outputs as output-only GPIOs. */ - if (offset >= TWL4030_GPIO_MAX) { - u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT - | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA; - u8 module = TWL4030_MODULE_PWMA; - - offset -= TWL4030_GPIO_MAX; - if (offset) { - ledclr_mask <<= 1; - module = TWL4030_MODULE_PWMB; - } - - /* initialize PWM to always-drive */ - status = twl_i2c_write_u8(module, 0x7f, - TWL4030_PWMx_PWMxOFF); - if (status < 0) - goto done; - status = twl_i2c_write_u8(module, 0x7f, - TWL4030_PWMx_PWMxON); - if (status < 0) - goto done; - - /* init LED to not-driven (high) */ - module = TWL4030_MODULE_LED; - status = twl_i2c_read_u8(module, &cached_leden, - TWL4030_LED_LEDEN); - if (status < 0) - goto done; - cached_leden &= ~ledclr_mask; - status = twl_i2c_write_u8(module, cached_leden, - TWL4030_LED_LEDEN); - if (status < 0) - goto done; - - status = 0; - goto done; - } - - /* on first use, turn GPIO module "on" */ - if (!gpio_usage_count) { - struct twl4030_gpio_platform_data *pdata; - u8 value = MASK_GPIO_CTRL_GPIO_ON; - - /* optionally have the first two GPIOs switch vMMC1 - * and vMMC2 power supplies based on card presence. - */ - pdata = chip->dev->platform_data; - if (pdata) - value |= pdata->mmc_cd & 0x03; - - status = gpio_twl4030_write(REG_GPIO_CTRL, value); - } - - if (!status) - gpio_usage_count |= (0x1 << offset); - -done: - mutex_unlock(&gpio_lock); - return status; -} - -static void twl_free(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= TWL4030_GPIO_MAX) { - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); - return; - } - - mutex_lock(&gpio_lock); - - gpio_usage_count &= ~BIT(offset); - - /* on last use, switch off GPIO module */ - if (!gpio_usage_count) - gpio_twl4030_write(REG_GPIO_CTRL, 0x0); - - mutex_unlock(&gpio_lock); -} - -static int twl_direction_in(struct gpio_chip *chip, unsigned offset) -{ - return (offset < TWL4030_GPIO_MAX) - ? twl4030_set_gpio_direction(offset, 1) - : -EINVAL; -} - -static int twl_get(struct gpio_chip *chip, unsigned offset) -{ - int status = 0; - - if (offset < TWL4030_GPIO_MAX) - status = twl4030_get_gpio_datain(offset); - else if (offset == TWL4030_GPIO_MAX) - status = cached_leden & LEDEN_LEDAON; - else - status = cached_leden & LEDEN_LEDBON; - return (status < 0) ? 0 : status; -} - -static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) -{ - if (offset < TWL4030_GPIO_MAX) { - twl4030_set_gpio_dataout(offset, value); - return twl4030_set_gpio_direction(offset, 0); - } else { - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); - return 0; - } -} - -static void twl_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (offset < TWL4030_GPIO_MAX) - twl4030_set_gpio_dataout(offset, value); - else - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); -} - -static int twl_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX)) - ? (twl4030_gpio_irq_base + offset) - : -EINVAL; -} - -static struct gpio_chip twl_gpiochip = { - .label = "twl4030", - .owner = THIS_MODULE, - .request = twl_request, - .free = twl_free, - .direction_input = twl_direction_in, - .get = twl_get, - .direction_output = twl_direction_out, - .set = twl_set, - .to_irq = twl_to_irq, - .can_sleep = 1, -}; - -/*----------------------------------------------------------------------*/ - -static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs) -{ - u8 message[6]; - unsigned i, gpio_bit; - - /* For most pins, a pulldown was enabled by default. - * We should have data that's specific to this board. - */ - for (gpio_bit = 1, i = 1; i < 6; i++) { - u8 bit_mask; - unsigned j; - - for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) { - if (ups & gpio_bit) - bit_mask |= 1 << (j + 1); - else if (downs & gpio_bit) - bit_mask |= 1 << (j + 0); - } - message[i] = bit_mask; - } - - return twl_i2c_write(TWL4030_MODULE_GPIO, message, - REG_GPIOPUPDCTR1, 5); -} - -static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) -{ - u8 message[4]; - - /* 30 msec of debouncing is always used for MMC card detect, - * and is optional for everything else. - */ - message[1] = (debounce & 0xff) | (mmc_cd & 0x03); - debounce >>= 8; - message[2] = (debounce & 0xff); - debounce >>= 8; - message[3] = (debounce & 0x03); - - return twl_i2c_write(TWL4030_MODULE_GPIO, message, - REG_GPIO_DEBEN1, 3); -} - -static int gpio_twl4030_remove(struct platform_device *pdev); - -static int __devinit gpio_twl4030_probe(struct platform_device *pdev) -{ - struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; - struct device_node *node = pdev->dev.of_node; - int ret, irq_base; - - /* maybe setup IRQs */ - if (is_module()) { - dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); - goto no_irqs; - } - - irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0); - if (irq_base < 0) { - dev_err(&pdev->dev, "Failed to alloc irq_descs\n"); - return irq_base; - } - - irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0, - &irq_domain_simple_ops, NULL); - - ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); - if (ret < 0) - return ret; - - twl4030_gpio_irq_base = irq_base; - -no_irqs: - twl_gpiochip.base = -1; - twl_gpiochip.ngpio = TWL4030_GPIO_MAX; - twl_gpiochip.dev = &pdev->dev; - - if (pdata) { - twl_gpiochip.base = pdata->gpio_base; - - /* - * NOTE: boards may waste power if they don't set pullups - * and pulldowns correctly ... default for non-ULPI pins is - * pulldown, and some other pins may have external pullups - * or pulldowns. Careful! - */ - ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); - if (ret) - dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", - pdata->pullups, pdata->pulldowns, - ret); - - ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd); - if (ret) - dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n", - pdata->debounce, pdata->mmc_cd, - ret); - - /* - * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE, - * is (still) clear if use_leds is set. - */ - if (pdata->use_leds) - twl_gpiochip.ngpio += 2; - } - - ret = gpiochip_add(&twl_gpiochip); - if (ret < 0) { - dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); - twl_gpiochip.ngpio = 0; - gpio_twl4030_remove(pdev); - } else if (pdata && pdata->setup) { - int status; - - status = pdata->setup(&pdev->dev, - pdata->gpio_base, TWL4030_GPIO_MAX); - if (status) - dev_dbg(&pdev->dev, "setup --> %d\n", status); - } - - return ret; -} - -/* Cannot use __devexit as gpio_twl4030_probe() calls us */ -static int gpio_twl4030_remove(struct platform_device *pdev) -{ - struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; - int status; - - if (pdata && pdata->teardown) { - status = pdata->teardown(&pdev->dev, - pdata->gpio_base, TWL4030_GPIO_MAX); - if (status) { - dev_dbg(&pdev->dev, "teardown --> %d\n", status); - return status; - } - } - - status = gpiochip_remove(&twl_gpiochip); - if (status < 0) - return status; - - if (is_module()) - return 0; - - /* REVISIT no support yet for deregistering all the IRQs */ - WARN_ON(1); - return -EIO; -} - -static const struct of_device_id twl_gpio_match[] = { - { .compatible = "ti,twl4030-gpio", }, - { }, -}; -MODULE_DEVICE_TABLE(of, twl_gpio_match); - -/* Note: this hardware lives inside an I2C-based multi-function device. */ -MODULE_ALIAS("platform:twl4030_gpio"); - -static struct platform_driver gpio_twl4030_driver = { - .driver = { - .name = "twl4030_gpio", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(twl_gpio_match), - }, - .probe = gpio_twl4030_probe, - .remove = gpio_twl4030_remove, -}; - -static int __init gpio_twl4030_init(void) -{ - return platform_driver_register(&gpio_twl4030_driver); -} -subsys_initcall(gpio_twl4030_init); - -static void __exit gpio_twl4030_exit(void) -{ - platform_driver_unregister(&gpio_twl4030_driver); -} -module_exit(gpio_twl4030_exit); - -MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("GPIO interface for TWL4030"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-ucb1400.c b/ANDROID_3.4.5/drivers/gpio/gpio-ucb1400.c deleted file mode 100644 index 26405efe..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-ucb1400.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Philips UCB1400 GPIO driver - * - * Author: Marek Vasut <marek.vasut@gmail.com> - * - * 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/module.h> -#include <linux/ucb1400.h> - -struct ucb1400_gpio_data *ucbdata; - -static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_direction(gpio->ac97, off, 0); - return 0; -} - -static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_direction(gpio->ac97, off, 1); - ucb1400_gpio_set_value(gpio->ac97, off, val); - return 0; -} - -static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - return ucb1400_gpio_get_value(gpio->ac97, off); -} - -static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_value(gpio->ac97, off, val); -} - -static int ucb1400_gpio_probe(struct platform_device *dev) -{ - struct ucb1400_gpio *ucb = dev->dev.platform_data; - int err = 0; - - if (!(ucbdata && ucbdata->gpio_offset)) { - err = -EINVAL; - goto err; - } - - platform_set_drvdata(dev, ucb); - - ucb->gc.label = "ucb1400_gpio"; - ucb->gc.base = ucbdata->gpio_offset; - ucb->gc.ngpio = 10; - ucb->gc.owner = THIS_MODULE; - - ucb->gc.direction_input = ucb1400_gpio_dir_in; - ucb->gc.direction_output = ucb1400_gpio_dir_out; - ucb->gc.get = ucb1400_gpio_get; - ucb->gc.set = ucb1400_gpio_set; - ucb->gc.can_sleep = 1; - - err = gpiochip_add(&ucb->gc); - if (err) - goto err; - - if (ucbdata && ucbdata->gpio_setup) - err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio); - -err: - return err; - -} - -static int ucb1400_gpio_remove(struct platform_device *dev) -{ - int err = 0; - struct ucb1400_gpio *ucb = platform_get_drvdata(dev); - - if (ucbdata && ucbdata->gpio_teardown) { - err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio); - if (err) - return err; - } - - err = gpiochip_remove(&ucb->gc); - return err; -} - -static struct platform_driver ucb1400_gpio_driver = { - .probe = ucb1400_gpio_probe, - .remove = ucb1400_gpio_remove, - .driver = { - .name = "ucb1400_gpio" - }, -}; - -void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data) -{ - ucbdata = data; -} - -module_platform_driver(ucb1400_gpio_driver); - -MODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-vr41xx.c b/ANDROID_3.4.5/drivers/gpio/gpio-vr41xx.c deleted file mode 100644 index 82d5c20a..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-vr41xx.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Driver for NEC VR4100 series General-purpose I/O Unit. - * - * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <source@mvista.com> - * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <asm/vr41xx/giu.h> -#include <asm/vr41xx/irq.h> -#include <asm/vr41xx/vr41xx.h> - -MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); -MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); -MODULE_LICENSE("GPL"); - -#define GIUIOSELL 0x00 -#define GIUIOSELH 0x02 -#define GIUPIODL 0x04 -#define GIUPIODH 0x06 -#define GIUINTSTATL 0x08 -#define GIUINTSTATH 0x0a -#define GIUINTENL 0x0c -#define GIUINTENH 0x0e -#define GIUINTTYPL 0x10 -#define GIUINTTYPH 0x12 -#define GIUINTALSELL 0x14 -#define GIUINTALSELH 0x16 -#define GIUINTHTSELL 0x18 -#define GIUINTHTSELH 0x1a -#define GIUPODATL 0x1c -#define GIUPODATEN 0x1c -#define GIUPODATH 0x1e - #define PIOEN0 0x0100 - #define PIOEN1 0x0200 -#define GIUPODAT 0x1e -#define GIUFEDGEINHL 0x20 -#define GIUFEDGEINHH 0x22 -#define GIUREDGEINHL 0x24 -#define GIUREDGEINHH 0x26 - -#define GIUUSEUPDN 0x1e0 -#define GIUTERMUPDN 0x1e2 - -#define GPIO_HAS_PULLUPDOWN_IO 0x0001 -#define GPIO_HAS_OUTPUT_ENABLE 0x0002 -#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 - -enum { - GPIO_INPUT, - GPIO_OUTPUT, -}; - -static DEFINE_SPINLOCK(giu_lock); -static unsigned long giu_flags; - -static void __iomem *giu_base; - -#define giu_read(offset) readw(giu_base + (offset)) -#define giu_write(offset, value) writew((value), giu_base + (offset)) - -#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) -#define GIUINT_HIGH_OFFSET 16 -#define GIUINT_HIGH_MAX 32 - -static inline u16 giu_set(u16 offset, u16 set) -{ - u16 data; - - data = giu_read(offset); - data |= set; - giu_write(offset, data); - - return data; -} - -static inline u16 giu_clear(u16 offset, u16 clear) -{ - u16 data; - - data = giu_read(offset); - data &= ~clear; - giu_write(offset, data); - - return data; -} - -static void ack_giuint_low(struct irq_data *d) -{ - giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq)); -} - -static void mask_giuint_low(struct irq_data *d) -{ - giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); -} - -static void mask_ack_giuint_low(struct irq_data *d) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(d->irq); - giu_clear(GIUINTENL, 1 << pin); - giu_write(GIUINTSTATL, 1 << pin); -} - -static void unmask_giuint_low(struct irq_data *d) -{ - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); -} - -static struct irq_chip giuint_low_irq_chip = { - .name = "GIUINTL", - .irq_ack = ack_giuint_low, - .irq_mask = mask_giuint_low, - .irq_mask_ack = mask_ack_giuint_low, - .irq_unmask = unmask_giuint_low, -}; - -static void ack_giuint_high(struct irq_data *d) -{ - giu_write(GIUINTSTATH, - 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_giuint_high(struct irq_data *d) -{ - giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_ack_giuint_high(struct irq_data *d) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET; - giu_clear(GIUINTENH, 1 << pin); - giu_write(GIUINTSTATH, 1 << pin); -} - -static void unmask_giuint_high(struct irq_data *d) -{ - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); -} - -static struct irq_chip giuint_high_irq_chip = { - .name = "GIUINTH", - .irq_ack = ack_giuint_high, - .irq_mask = mask_giuint_high, - .irq_mask_ack = mask_ack_giuint_high, - .irq_unmask = unmask_giuint_high, -}; - -static int giu_get_irq(unsigned int irq) -{ - u16 pendl, pendh, maskl, maskh; - int i; - - pendl = giu_read(GIUINTSTATL); - pendh = giu_read(GIUINTSTATH); - maskl = giu_read(GIUINTENL); - maskh = giu_read(GIUINTENH); - - maskl &= pendl; - maskh &= pendh; - - if (maskl) { - for (i = 0; i < 16; i++) { - if (maskl & (1 << i)) - return GIU_IRQ(i); - } - } else if (maskh) { - for (i = 0; i < 16; i++) { - if (maskh & (1 << i)) - return GIU_IRQ(i + GIUINT_HIGH_OFFSET); - } - } - - printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", - maskl, pendl, maskh, pendh); - - atomic_inc(&irq_err_count); - - return -EINVAL; -} - -void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, - irq_signal_t signal) -{ - u16 mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPL, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELL, mask); - else - giu_clear(GIUINTHTSELL, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHL, mask); - giu_clear(GIUREDGEINHL, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - default: - giu_set(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - } - } - irq_set_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPL, mask); - giu_clear(GIUINTHTSELL, mask); - irq_set_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPH, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELH, mask); - else - giu_clear(GIUINTHTSELH, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHH, mask); - giu_clear(GIUREDGEINHH, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - default: - giu_set(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - } - } - irq_set_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPH, mask); - giu_clear(GIUINTHTSELH, mask); - irq_set_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); - -void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) -{ - u16 mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELL, mask); - else - giu_clear(GIUINTALSELL, mask); - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELH, mask); - else - giu_clear(GIUINTALSELH, mask); - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); - -static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) -{ - u16 offset, mask, reg; - unsigned long flags; - - if (pin >= chip->ngpio) - return -EINVAL; - - if (pin < 16) { - offset = GIUIOSELL; - mask = 1 << pin; - } else if (pin < 32) { - offset = GIUIOSELH; - mask = 1 << (pin - 16); - } else { - if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { - offset = GIUPODATEN; - mask = 1 << (pin - 32); - } else { - switch (pin) { - case 48: - offset = GIUPODATH; - mask = PIOEN0; - break; - case 49: - offset = GIUPODATH; - mask = PIOEN1; - break; - default: - return -EINVAL; - } - } - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (dir == GPIO_OUTPUT) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} - -int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) -{ - u16 reg, mask; - unsigned long flags; - - if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) - return -EPERM; - - if (pin >= 15) - return -EINVAL; - - mask = 1 << pin; - - spin_lock_irqsave(&giu_lock, flags); - - if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { - reg = giu_read(GIUTERMUPDN); - if (pull == GPIO_PULL_UP) - reg |= mask; - else - reg &= ~mask; - giu_write(GIUTERMUPDN, reg); - - reg = giu_read(GIUUSEUPDN); - reg |= mask; - giu_write(GIUUSEUPDN, reg); - } else { - reg = giu_read(GIUUSEUPDN); - reg &= ~mask; - giu_write(GIUUSEUPDN, reg); - } - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); - -static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) -{ - u16 reg, mask; - - if (pin >= chip->ngpio) - return -EINVAL; - - if (pin < 16) { - reg = giu_read(GIUPIODL); - mask = 1 << pin; - } else if (pin < 32) { - reg = giu_read(GIUPIODH); - mask = 1 << (pin - 16); - } else if (pin < 48) { - reg = giu_read(GIUPODATL); - mask = 1 << (pin - 32); - } else { - reg = giu_read(GIUPODATH); - mask = 1 << (pin - 48); - } - - if (reg & mask) - return 1; - - return 0; -} - -static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, - int value) -{ - u16 offset, mask, reg; - unsigned long flags; - - if (pin >= chip->ngpio) - return; - - if (pin < 16) { - offset = GIUPIODL; - mask = 1 << pin; - } else if (pin < 32) { - offset = GIUPIODH; - mask = 1 << (pin - 16); - } else if (pin < 48) { - offset = GIUPODATL; - mask = 1 << (pin - 32); - } else { - offset = GIUPODATH; - mask = 1 << (pin - 48); - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (value) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); -} - - -static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - return giu_set_direction(chip, offset, GPIO_INPUT); -} - -static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - vr41xx_gpio_set(chip, offset, value); - - return giu_set_direction(chip, offset, GPIO_OUTPUT); -} - -static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= chip->ngpio) - return -EINVAL; - - return GIU_IRQ_BASE + offset; -} - -static struct gpio_chip vr41xx_gpio_chip = { - .label = "vr41xx", - .owner = THIS_MODULE, - .direction_input = vr41xx_gpio_direction_input, - .get = vr41xx_gpio_get, - .direction_output = vr41xx_gpio_direction_output, - .set = vr41xx_gpio_set, - .to_irq = vr41xx_gpio_to_irq, -}; - -static int __devinit giu_probe(struct platform_device *pdev) -{ - struct resource *res; - unsigned int trigger, i, pin; - struct irq_chip *chip; - int irq, retval; - - switch (pdev->id) { - case GPIO_50PINS_PULLUPDOWN: - giu_flags = GPIO_HAS_PULLUPDOWN_IO; - vr41xx_gpio_chip.ngpio = 50; - break; - case GPIO_36PINS: - vr41xx_gpio_chip.ngpio = 36; - break; - case GPIO_48PINS_EDGE_SELECT: - giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; - vr41xx_gpio_chip.ngpio = 48; - break; - default: - dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); - return -ENODEV; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EBUSY; - - giu_base = ioremap(res->start, resource_size(res)); - if (!giu_base) - return -ENOMEM; - - vr41xx_gpio_chip.dev = &pdev->dev; - - retval = gpiochip_add(&vr41xx_gpio_chip); - - giu_write(GIUINTENL, 0); - giu_write(GIUINTENH, 0); - - trigger = giu_read(GIUINTTYPH) << 16; - trigger |= giu_read(GIUINTTYPL); - for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { - pin = GPIO_PIN_OF_IRQ(i); - if (pin < GIUINT_HIGH_OFFSET) - chip = &giuint_low_irq_chip; - else - chip = &giuint_high_irq_chip; - - if (trigger & (1 << pin)) - irq_set_chip_and_handler(i, chip, handle_edge_irq); - else - irq_set_chip_and_handler(i, chip, handle_level_irq); - - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0 || irq >= nr_irqs) - return -EBUSY; - - return cascade_irq(irq, giu_get_irq); -} - -static int __devexit giu_remove(struct platform_device *pdev) -{ - if (giu_base) { - iounmap(giu_base); - giu_base = NULL; - } - - return 0; -} - -static struct platform_driver giu_device_driver = { - .probe = giu_probe, - .remove = __devexit_p(giu_remove), - .driver = { - .name = "GIU", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(giu_device_driver); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-vx855.c b/ANDROID_3.4.5/drivers/gpio/gpio-vx855.c deleted file mode 100644 index 76ebfe5f..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-vx855.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO - * - * Copyright (C) 2009 VIA Technologies, Inc. - * Copyright (C) 2010 One Laptop per Child - * Author: Harald Welte <HaraldWelte@viatech.com> - * 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 as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/pci.h> -#include <linux/io.h> - -#define MODULE_NAME "vx855_gpio" - -/* The VX855 south bridge has the following GPIO pins: - * GPI 0...13 General Purpose Input - * GPO 0...12 General Purpose Output - * GPIO 0...14 General Purpose I/O (Open-Drain) - */ - -#define NR_VX855_GPI 14 -#define NR_VX855_GPO 13 -#define NR_VX855_GPIO 15 - -#define NR_VX855_GPInO (NR_VX855_GPI + NR_VX855_GPO) -#define NR_VX855_GP (NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO) - -struct vx855_gpio { - struct gpio_chip gpio; - spinlock_t lock; - u32 io_gpi; - u32 io_gpo; - bool gpi_reserved; - bool gpo_reserved; -}; - -/* resolve a GPIx into the corresponding bit position */ -static inline u_int32_t gpi_i_bit(int i) -{ - if (i < 10) - return 1 << i; - else - return 1 << (i + 14); -} - -static inline u_int32_t gpo_o_bit(int i) -{ - if (i < 11) - return 1 << i; - else - return 1 << (i + 14); -} - -static inline u_int32_t gpio_i_bit(int i) -{ - if (i < 14) - return 1 << (i + 10); - else - return 1 << (i + 14); -} - -static inline u_int32_t gpio_o_bit(int i) -{ - if (i < 14) - return 1 << (i + 11); - else - return 1 << (i + 13); -} - -/* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering: - * 0..13 GPI 0..13 - * 14..26 GPO 0..12 - * 27..41 GPIO 0..14 - */ - -static int vx855gpio_direction_input(struct gpio_chip *gpio, - unsigned int nr) -{ - struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); - unsigned long flags; - u_int32_t reg_out; - - /* Real GPI bits are always in input direction */ - if (nr < NR_VX855_GPI) - return 0; - - /* Real GPO bits cannot be put in output direction */ - if (nr < NR_VX855_GPInO) - return -EINVAL; - - /* Open Drain GPIO have to be set to one */ - spin_lock_irqsave(&vg->lock, flags); - reg_out = inl(vg->io_gpo); - reg_out |= gpio_o_bit(nr - NR_VX855_GPInO); - outl(reg_out, vg->io_gpo); - spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - -static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr) -{ - struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); - u_int32_t reg_in; - int ret = 0; - - if (nr < NR_VX855_GPI) { - reg_in = inl(vg->io_gpi); - if (reg_in & gpi_i_bit(nr)) - ret = 1; - } else if (nr < NR_VX855_GPInO) { - /* GPO don't have an input bit, we need to read it - * back from the output register */ - reg_in = inl(vg->io_gpo); - if (reg_in & gpo_o_bit(nr - NR_VX855_GPI)) - ret = 1; - } else { - reg_in = inl(vg->io_gpi); - if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO)) - ret = 1; - } - - return ret; -} - -static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr, - int val) -{ - struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); - unsigned long flags; - u_int32_t reg_out; - - /* True GPI cannot be switched to output mode */ - if (nr < NR_VX855_GPI) - return; - - spin_lock_irqsave(&vg->lock, flags); - reg_out = inl(vg->io_gpo); - if (nr < NR_VX855_GPInO) { - if (val) - reg_out |= gpo_o_bit(nr - NR_VX855_GPI); - else - reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI); - } else { - if (val) - reg_out |= gpio_o_bit(nr - NR_VX855_GPInO); - else - reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO); - } - outl(reg_out, vg->io_gpo); - spin_unlock_irqrestore(&vg->lock, flags); -} - -static int vx855gpio_direction_output(struct gpio_chip *gpio, - unsigned int nr, int val) -{ - /* True GPI cannot be switched to output mode */ - if (nr < NR_VX855_GPI) - return -EINVAL; - - /* True GPO don't need to be switched to output mode, - * and GPIO are open-drain, i.e. also need no switching, - * so all we do is set the level */ - vx855gpio_set(gpio, nr, val); - - return 0; -} - -static const char *vx855gpio_names[NR_VX855_GP] = { - "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4", - "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9", - "VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13", - "VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4", - "VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9", - "VX855_GPO10", "VX855_GPO11", "VX855_GPO12", - "VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3", - "VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7", - "VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11", - "VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14" -}; - -static void vx855gpio_gpio_setup(struct vx855_gpio *vg) -{ - struct gpio_chip *c = &vg->gpio; - - c->label = "VX855 South Bridge"; - c->owner = THIS_MODULE; - c->direction_input = vx855gpio_direction_input; - c->direction_output = vx855gpio_direction_output; - c->get = vx855gpio_get; - c->set = vx855gpio_set; - c->dbg_show = NULL; - c->base = 0; - c->ngpio = NR_VX855_GP; - c->can_sleep = 0; - c->names = vx855gpio_names; -} - -/* This platform device is ordinarily registered by the vx855 mfd driver */ -static __devinit int vx855gpio_probe(struct platform_device *pdev) -{ - struct resource *res_gpi; - struct resource *res_gpo; - struct vx855_gpio *vg; - int ret; - - res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0); - res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1); - if (!res_gpi || !res_gpo) - return -EBUSY; - - vg = kzalloc(sizeof(*vg), GFP_KERNEL); - if (!vg) - return -ENOMEM; - - platform_set_drvdata(pdev, vg); - - dev_info(&pdev->dev, "found VX855 GPIO controller\n"); - vg->io_gpi = res_gpi->start; - vg->io_gpo = res_gpo->start; - spin_lock_init(&vg->lock); - - /* - * A single byte is used to control various GPIO ports on the VX855, - * and in the case of the OLPC XO-1.5, some of those ports are used - * for switches that are interpreted and exposed through ACPI. ACPI - * will have reserved the region, so our own reservation will not - * succeed. Ignore and continue. - */ - - if (!request_region(res_gpi->start, resource_size(res_gpi), - MODULE_NAME "_gpi")) - dev_warn(&pdev->dev, - "GPI I/O resource busy, probably claimed by ACPI\n"); - else - vg->gpi_reserved = true; - - if (!request_region(res_gpo->start, resource_size(res_gpo), - MODULE_NAME "_gpo")) - dev_warn(&pdev->dev, - "GPO I/O resource busy, probably claimed by ACPI\n"); - else - vg->gpo_reserved = true; - - vx855gpio_gpio_setup(vg); - - ret = gpiochip_add(&vg->gpio); - if (ret) { - dev_err(&pdev->dev, "failed to register GPIOs\n"); - goto out_release; - } - - return 0; - -out_release: - if (vg->gpi_reserved) - release_region(res_gpi->start, resource_size(res_gpi)); - if (vg->gpo_reserved) - release_region(res_gpi->start, resource_size(res_gpo)); - platform_set_drvdata(pdev, NULL); - kfree(vg); - return ret; -} - -static int __devexit vx855gpio_remove(struct platform_device *pdev) -{ - struct vx855_gpio *vg = platform_get_drvdata(pdev); - struct resource *res; - - if (gpiochip_remove(&vg->gpio)) - dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); - - if (vg->gpi_reserved) { - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, resource_size(res)); - } - if (vg->gpo_reserved) { - res = platform_get_resource(pdev, IORESOURCE_IO, 1); - release_region(res->start, resource_size(res)); - } - - platform_set_drvdata(pdev, NULL); - kfree(vg); - return 0; -} - -static struct platform_driver vx855gpio_driver = { - .driver = { - .name = MODULE_NAME, - .owner = THIS_MODULE, - }, - .probe = vx855gpio_probe, - .remove = __devexit_p(vx855gpio_remove), -}; - -module_platform_driver(vx855gpio_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); -MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset"); -MODULE_ALIAS("platform:vx855_gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-wm831x.c b/ANDROID_3.4.5/drivers/gpio/gpio-wm831x.c deleted file mode 100644 index deb949e7..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-wm831x.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * gpiolib support for Wolfson WM831x PMICs - * - * Copyright 2009 Wolfson Microelectronics PLC. - * - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/seq_file.h> - -#include <linux/mfd/wm831x/core.h> -#include <linux/mfd/wm831x/pdata.h> -#include <linux/mfd/wm831x/gpio.h> -#include <linux/mfd/wm831x/irq.h> - -struct wm831x_gpio { - struct wm831x *wm831x; - struct gpio_chip gpio_chip; -}; - -static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct wm831x_gpio, gpio_chip); -} - -static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - int val = WM831X_GPN_DIR; - - if (wm831x->has_gpio_ena) - val |= WM831X_GPN_TRI; - - return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, - WM831X_GPN_DIR | WM831X_GPN_TRI | - WM831X_GPN_FN_MASK, val); -} - -static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - int ret; - - ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); - if (ret < 0) - return ret; - - if (ret & 1 << offset) - return 1; - else - return 0; -} - -static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - - wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset, - value << offset); -} - -static int wm831x_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - int val = 0; - int ret; - - if (wm831x->has_gpio_ena) - val |= WM831X_GPN_TRI; - - ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, - WM831X_GPN_DIR | WM831X_GPN_TRI | - WM831X_GPN_FN_MASK, val); - if (ret < 0) - return ret; - - /* Can only set GPIO state once it's in output mode */ - wm831x_gpio_set(chip, offset, value); - - return 0; -} - -static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - - if (!wm831x->irq_base) - return -EINVAL; - - return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; -} - -static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, - unsigned debounce) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - int reg = WM831X_GPIO1_CONTROL + offset; - int ret, fn; - - ret = wm831x_reg_read(wm831x, reg); - if (ret < 0) - return ret; - - switch (ret & WM831X_GPN_FN_MASK) { - case 0: - case 1: - break; - default: - /* Not in GPIO mode */ - return -EBUSY; - } - - if (debounce >= 32 && debounce <= 64) - fn = 0; - else if (debounce >= 4000 && debounce <= 8000) - fn = 1; - else - return -EINVAL; - - return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); -} - -#ifdef CONFIG_DEBUG_FS -static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); - struct wm831x *wm831x = wm831x_gpio->wm831x; - int i, tristated; - - for (i = 0; i < chip->ngpio; i++) { - int gpio = i + chip->base; - int reg; - const char *label, *pull, *powerdomain; - - /* We report the GPIO even if it's not requested since - * we're also reporting things like alternate - * functions which apply even when the GPIO is not in - * use as a GPIO. - */ - label = gpiochip_is_requested(chip, i); - if (!label) - label = "Unrequested"; - - seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label); - - reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i); - if (reg < 0) { - dev_err(wm831x->dev, - "GPIO control %d read failed: %d\n", - gpio, reg); - seq_printf(s, "\n"); - continue; - } - - switch (reg & WM831X_GPN_PULL_MASK) { - case WM831X_GPIO_PULL_NONE: - pull = "nopull"; - break; - case WM831X_GPIO_PULL_DOWN: - pull = "pulldown"; - break; - case WM831X_GPIO_PULL_UP: - pull = "pullup"; - break; - default: - pull = "INVALID PULL"; - break; - } - - switch (i + 1) { - case 1 ... 3: - case 7 ... 9: - if (reg & WM831X_GPN_PWR_DOM) - powerdomain = "VPMIC"; - else - powerdomain = "DBVDD"; - break; - - case 4 ... 6: - case 10 ... 12: - if (reg & WM831X_GPN_PWR_DOM) - powerdomain = "SYSVDD"; - else - powerdomain = "DBVDD"; - break; - - case 13 ... 16: - powerdomain = "TPVDD"; - break; - - default: - BUG(); - break; - } - - tristated = reg & WM831X_GPN_TRI; - if (wm831x->has_gpio_ena) - tristated = !tristated; - - seq_printf(s, " %s %s %s %s%s\n" - " %s%s (0x%4x)\n", - reg & WM831X_GPN_DIR ? "in" : "out", - wm831x_gpio_get(chip, i) ? "high" : "low", - pull, - powerdomain, - reg & WM831X_GPN_POL ? "" : " inverted", - reg & WM831X_GPN_OD ? "open-drain" : "CMOS", - tristated ? " tristated" : "", - reg); - } -} -#else -#define wm831x_gpio_dbg_show NULL -#endif - -static struct gpio_chip template_chip = { - .label = "wm831x", - .owner = THIS_MODULE, - .direction_input = wm831x_gpio_direction_in, - .get = wm831x_gpio_get, - .direction_output = wm831x_gpio_direction_out, - .set = wm831x_gpio_set, - .to_irq = wm831x_gpio_to_irq, - .set_debounce = wm831x_gpio_set_debounce, - .dbg_show = wm831x_gpio_dbg_show, - .can_sleep = 1, -}; - -static int __devinit wm831x_gpio_probe(struct platform_device *pdev) -{ - struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; - struct wm831x_gpio *wm831x_gpio; - int ret; - - wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL); - if (wm831x_gpio == NULL) - return -ENOMEM; - - wm831x_gpio->wm831x = wm831x; - wm831x_gpio->gpio_chip = template_chip; - wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; - wm831x_gpio->gpio_chip.dev = &pdev->dev; - if (pdata && pdata->gpio_base) - wm831x_gpio->gpio_chip.base = pdata->gpio_base; - else - wm831x_gpio->gpio_chip.base = -1; - - ret = gpiochip_add(&wm831x_gpio->gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - goto err; - } - - platform_set_drvdata(pdev, wm831x_gpio); - - return ret; - -err: - kfree(wm831x_gpio); - return ret; -} - -static int __devexit wm831x_gpio_remove(struct platform_device *pdev) -{ - struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&wm831x_gpio->gpio_chip); - if (ret == 0) - kfree(wm831x_gpio); - - return ret; -} - -static struct platform_driver wm831x_gpio_driver = { - .driver.name = "wm831x-gpio", - .driver.owner = THIS_MODULE, - .probe = wm831x_gpio_probe, - .remove = __devexit_p(wm831x_gpio_remove), -}; - -static int __init wm831x_gpio_init(void) -{ - return platform_driver_register(&wm831x_gpio_driver); -} -subsys_initcall(wm831x_gpio_init); - -static void __exit wm831x_gpio_exit(void) -{ - platform_driver_unregister(&wm831x_gpio_driver); -} -module_exit(wm831x_gpio_exit); - -MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); -MODULE_DESCRIPTION("GPIO interface for WM831x PMICs"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm831x-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-wm8350.c b/ANDROID_3.4.5/drivers/gpio/gpio-wm8350.c deleted file mode 100644 index a06af515..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-wm8350.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * gpiolib support for Wolfson WM835x PMICs - * - * Copyright 2009 Wolfson Microelectronics PLC. - * - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/seq_file.h> - -#include <linux/mfd/wm8350/core.h> -#include <linux/mfd/wm8350/gpio.h> - -struct wm8350_gpio_data { - struct wm8350 *wm8350; - struct gpio_chip gpio_chip; -}; - -static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8350_gpio_data, gpio_chip); -} - -static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); - struct wm8350 *wm8350 = wm8350_gpio->wm8350; - - return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O, - 1 << offset); -} - -static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); - struct wm8350 *wm8350 = wm8350_gpio->wm8350; - int ret; - - ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL); - if (ret < 0) - return ret; - - if (ret & (1 << offset)) - return 1; - else - return 0; -} - -static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); - struct wm8350 *wm8350 = wm8350_gpio->wm8350; - - if (value) - wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset); - else - wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset); -} - -static int wm8350_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); - struct wm8350 *wm8350 = wm8350_gpio->wm8350; - int ret; - - ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O, - 1 << offset); - if (ret < 0) - return ret; - - /* Don't have an atomic direction/value setup */ - wm8350_gpio_set(chip, offset, value); - - return 0; -} - -static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); - struct wm8350 *wm8350 = wm8350_gpio->wm8350; - - if (!wm8350->irq_base) - return -EINVAL; - - return wm8350->irq_base + WM8350_IRQ_GPIO(offset); -} - -static struct gpio_chip template_chip = { - .label = "wm8350", - .owner = THIS_MODULE, - .direction_input = wm8350_gpio_direction_in, - .get = wm8350_gpio_get, - .direction_output = wm8350_gpio_direction_out, - .set = wm8350_gpio_set, - .to_irq = wm8350_gpio_to_irq, - .can_sleep = 1, -}; - -static int __devinit wm8350_gpio_probe(struct platform_device *pdev) -{ - struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); - struct wm8350_platform_data *pdata = wm8350->dev->platform_data; - struct wm8350_gpio_data *wm8350_gpio; - int ret; - - wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL); - if (wm8350_gpio == NULL) - return -ENOMEM; - - wm8350_gpio->wm8350 = wm8350; - wm8350_gpio->gpio_chip = template_chip; - wm8350_gpio->gpio_chip.ngpio = 13; - wm8350_gpio->gpio_chip.dev = &pdev->dev; - if (pdata && pdata->gpio_base) - wm8350_gpio->gpio_chip.base = pdata->gpio_base; - else - wm8350_gpio->gpio_chip.base = -1; - - ret = gpiochip_add(&wm8350_gpio->gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - goto err; - } - - platform_set_drvdata(pdev, wm8350_gpio); - - return ret; - -err: - kfree(wm8350_gpio); - return ret; -} - -static int __devexit wm8350_gpio_remove(struct platform_device *pdev) -{ - struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&wm8350_gpio->gpio_chip); - if (ret == 0) - kfree(wm8350_gpio); - - return ret; -} - -static struct platform_driver wm8350_gpio_driver = { - .driver.name = "wm8350-gpio", - .driver.owner = THIS_MODULE, - .probe = wm8350_gpio_probe, - .remove = __devexit_p(wm8350_gpio_remove), -}; - -static int __init wm8350_gpio_init(void) -{ - return platform_driver_register(&wm8350_gpio_driver); -} -subsys_initcall(wm8350_gpio_init); - -static void __exit wm8350_gpio_exit(void) -{ - platform_driver_unregister(&wm8350_gpio_driver); -} -module_exit(wm8350_gpio_exit); - -MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); -MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8350-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-wm8994.c b/ANDROID_3.4.5/drivers/gpio/gpio-wm8994.c deleted file mode 100644 index aa61ad2f..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-wm8994.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * gpiolib support for Wolfson WM8994 - * - * Copyright 2009 Wolfson Microelectronics PLC. - * - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/gpio.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/seq_file.h> - -#include <linux/mfd/wm8994/core.h> -#include <linux/mfd/wm8994/pdata.h> -#include <linux/mfd/wm8994/gpio.h> -#include <linux/mfd/wm8994/registers.h> - -struct wm8994_gpio { - struct wm8994 *wm8994; - struct gpio_chip gpio_chip; -}; - -static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8994_gpio, gpio_chip); -} - -static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - - switch (wm8994->type) { - case WM8958: - switch (offset) { - case 1: - case 2: - case 3: - case 4: - case 6: - return -EINVAL; - } - break; - default: - break; - } - - return 0; -} - -static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - - return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, - WM8994_GPN_DIR, WM8994_GPN_DIR); -} - -static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - int ret; - - ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset); - if (ret < 0) - return ret; - - if (ret & WM8994_GPN_LVL) - return 1; - else - return 0; -} - -static int wm8994_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - - if (value) - value = WM8994_GPN_LVL; - - return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, - WM8994_GPN_DIR | WM8994_GPN_LVL, value); -} - -static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - - if (value) - value = WM8994_GPN_LVL; - - wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); -} - -static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - - if (!wm8994->irq_base) - return -EINVAL; - - return wm8994->irq_base + offset; -} - - -#ifdef CONFIG_DEBUG_FS -static const char *wm8994_gpio_fn(u16 fn) -{ - switch (fn) { - case WM8994_GP_FN_PIN_SPECIFIC: - return "pin-specific"; - case WM8994_GP_FN_GPIO: - return "GPIO"; - case WM8994_GP_FN_SDOUT: - return "SDOUT"; - case WM8994_GP_FN_IRQ: - return "IRQ"; - case WM8994_GP_FN_TEMPERATURE: - return "Temperature"; - case WM8994_GP_FN_MICBIAS1_DET: - return "MICBIAS1 detect"; - case WM8994_GP_FN_MICBIAS1_SHORT: - return "MICBIAS1 short"; - case WM8994_GP_FN_MICBIAS2_DET: - return "MICBIAS2 detect"; - case WM8994_GP_FN_MICBIAS2_SHORT: - return "MICBIAS2 short"; - case WM8994_GP_FN_FLL1_LOCK: - return "FLL1 lock"; - case WM8994_GP_FN_FLL2_LOCK: - return "FLL2 lock"; - case WM8994_GP_FN_SRC1_LOCK: - return "SRC1 lock"; - case WM8994_GP_FN_SRC2_LOCK: - return "SRC2 lock"; - case WM8994_GP_FN_DRC1_ACT: - return "DRC1 activity"; - case WM8994_GP_FN_DRC2_ACT: - return "DRC2 activity"; - case WM8994_GP_FN_DRC3_ACT: - return "DRC3 activity"; - case WM8994_GP_FN_WSEQ_STATUS: - return "Write sequencer"; - case WM8994_GP_FN_FIFO_ERROR: - return "FIFO error"; - case WM8994_GP_FN_OPCLK: - return "OPCLK"; - case WM8994_GP_FN_THW: - return "Thermal warning"; - case WM8994_GP_FN_DCS_DONE: - return "DC servo"; - case WM8994_GP_FN_FLL1_OUT: - return "FLL1 output"; - case WM8994_GP_FN_FLL2_OUT: - return "FLL1 output"; - default: - return "Unknown"; - } -} - -static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); - struct wm8994 *wm8994 = wm8994_gpio->wm8994; - int i; - - for (i = 0; i < chip->ngpio; i++) { - int gpio = i + chip->base; - int reg; - const char *label; - - /* We report the GPIO even if it's not requested since - * we're also reporting things like alternate - * functions which apply even when the GPIO is not in - * use as a GPIO. - */ - label = gpiochip_is_requested(chip, i); - if (!label) - label = "Unrequested"; - - seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label); - - reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i); - if (reg < 0) { - dev_err(wm8994->dev, - "GPIO control %d read failed: %d\n", - gpio, reg); - seq_printf(s, "\n"); - continue; - } - - if (reg & WM8994_GPN_DIR) - seq_printf(s, "in "); - else - seq_printf(s, "out "); - - if (reg & WM8994_GPN_PU) - seq_printf(s, "pull up "); - - if (reg & WM8994_GPN_PD) - seq_printf(s, "pull down "); - - if (reg & WM8994_GPN_POL) - seq_printf(s, "inverted "); - else - seq_printf(s, "noninverted "); - - if (reg & WM8994_GPN_OP_CFG) - seq_printf(s, "open drain "); - else - seq_printf(s, "CMOS "); - - seq_printf(s, "%s (%x)\n", - wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg); - } -} -#else -#define wm8994_gpio_dbg_show NULL -#endif - -static struct gpio_chip template_chip = { - .label = "wm8994", - .owner = THIS_MODULE, - .request = wm8994_gpio_request, - .direction_input = wm8994_gpio_direction_in, - .get = wm8994_gpio_get, - .direction_output = wm8994_gpio_direction_out, - .set = wm8994_gpio_set, - .to_irq = wm8994_gpio_to_irq, - .dbg_show = wm8994_gpio_dbg_show, - .can_sleep = 1, -}; - -static int __devinit wm8994_gpio_probe(struct platform_device *pdev) -{ - struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); - struct wm8994_pdata *pdata = wm8994->dev->platform_data; - struct wm8994_gpio *wm8994_gpio; - int ret; - - wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL); - if (wm8994_gpio == NULL) - return -ENOMEM; - - wm8994_gpio->wm8994 = wm8994; - wm8994_gpio->gpio_chip = template_chip; - wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX; - wm8994_gpio->gpio_chip.dev = &pdev->dev; - if (pdata && pdata->gpio_base) - wm8994_gpio->gpio_chip.base = pdata->gpio_base; - else - wm8994_gpio->gpio_chip.base = -1; - - ret = gpiochip_add(&wm8994_gpio->gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - goto err; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; - -err: - kfree(wm8994_gpio); - return ret; -} - -static int __devexit wm8994_gpio_remove(struct platform_device *pdev) -{ - struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&wm8994_gpio->gpio_chip); - if (ret == 0) - kfree(wm8994_gpio); - - return ret; -} - -static struct platform_driver wm8994_gpio_driver = { - .driver.name = "wm8994-gpio", - .driver.owner = THIS_MODULE, - .probe = wm8994_gpio_probe, - .remove = __devexit_p(wm8994_gpio_remove), -}; - -static int __init wm8994_gpio_init(void) -{ - return platform_driver_register(&wm8994_gpio_driver); -} -subsys_initcall(wm8994_gpio_init); - -static void __exit wm8994_gpio_exit(void) -{ - platform_driver_unregister(&wm8994_gpio_driver); -} -module_exit(wm8994_gpio_exit); - -MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); -MODULE_DESCRIPTION("GPIO interface for WM8994"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8994-gpio"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpio-xilinx.c b/ANDROID_3.4.5/drivers/gpio/gpio-xilinx.c deleted file mode 100644 index 79b0fe8a..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpio-xilinx.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Xilinx gpio driver - * - * Copyright 2008 Xilinx, Inc. - * - * 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. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#include <linux/of_gpio.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/slab.h> - -/* Register Offset Definitions */ -#define XGPIO_DATA_OFFSET (0x0) /* Data register */ -#define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ - -struct xgpio_instance { - struct of_mm_gpio_chip mmchip; - u32 gpio_state; /* GPIO state shadow register */ - u32 gpio_dir; /* GPIO direction shadow register */ - spinlock_t gpio_lock; /* Lock used for synchronization */ -}; - -/** - * xgpio_get - Read the specified signal of the GPIO device. - * @gc: Pointer to gpio_chip device structure. - * @gpio: GPIO signal number. - * - * This function reads the specified signal of the GPIO device. It returns 0 if - * the signal clear, 1 if signal is set or negative value on error. - */ -static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - - return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; -} - -/** - * xgpio_set - Write the specified signal of the GPIO device. - * @gc: Pointer to gpio_chip device structure. - * @gpio: GPIO signal number. - * @val: Value to be written to specified signal. - * - * This function writes the specified value in to the specified signal of the - * GPIO device. - */ -static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - - spin_lock_irqsave(&chip->gpio_lock, flags); - - /* Write to GPIO signal and set its direction to output */ - if (val) - chip->gpio_state |= 1 << gpio; - else - chip->gpio_state &= ~(1 << gpio); - out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); - - spin_unlock_irqrestore(&chip->gpio_lock, flags); -} - -/** - * xgpio_dir_in - Set the direction of the specified GPIO signal as input. - * @gc: Pointer to gpio_chip device structure. - * @gpio: GPIO signal number. - * - * This function sets the direction of specified GPIO signal as input. - * It returns 0 if direction of GPIO signals is set as input otherwise it - * returns negative error value. - */ -static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - - spin_lock_irqsave(&chip->gpio_lock, flags); - - /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir |= (1 << gpio); - out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); - - spin_unlock_irqrestore(&chip->gpio_lock, flags); - - return 0; -} - -/** - * xgpio_dir_out - Set the direction of the specified GPIO signal as output. - * @gc: Pointer to gpio_chip device structure. - * @gpio: GPIO signal number. - * @val: Value to be written to specified signal. - * - * This function sets the direction of specified GPIO signal as output. If all - * GPIO signals of GPIO chip is configured as input then it returns - * error otherwise it returns 0. - */ -static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - - spin_lock_irqsave(&chip->gpio_lock, flags); - - /* Write state of GPIO signal */ - if (val) - chip->gpio_state |= 1 << gpio; - else - chip->gpio_state &= ~(1 << gpio); - out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); - - /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir &= (~(1 << gpio)); - out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); - - spin_unlock_irqrestore(&chip->gpio_lock, flags); - - return 0; -} - -/** - * xgpio_save_regs - Set initial values of GPIO pins - * @mm_gc: pointer to memory mapped GPIO chip structure - */ -static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) -{ - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - - out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); - out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); -} - -/** - * xgpio_of_probe - Probe method for the GPIO device. - * @np: pointer to device tree node - * - * This function probes the GPIO device in the device tree. It initializes the - * driver data structure. It returns 0, if the driver is bound to the GPIO - * device, or a negative value if there is an error. - */ -static int __devinit xgpio_of_probe(struct device_node *np) -{ - struct xgpio_instance *chip; - int status = 0; - const u32 *tree_info; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - /* Update GPIO state shadow register with default value */ - tree_info = of_get_property(np, "xlnx,dout-default", NULL); - if (tree_info) - chip->gpio_state = be32_to_cpup(tree_info); - - /* Update GPIO direction shadow register with default value */ - chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ - tree_info = of_get_property(np, "xlnx,tri-default", NULL); - if (tree_info) - chip->gpio_dir = be32_to_cpup(tree_info); - - /* Check device node and parent device node for device width */ - chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */ - tree_info = of_get_property(np, "xlnx,gpio-width", NULL); - if (!tree_info) - tree_info = of_get_property(np->parent, - "xlnx,gpio-width", NULL); - if (tree_info) - chip->mmchip.gc.ngpio = be32_to_cpup(tree_info); - - spin_lock_init(&chip->gpio_lock); - - chip->mmchip.gc.direction_input = xgpio_dir_in; - chip->mmchip.gc.direction_output = xgpio_dir_out; - chip->mmchip.gc.get = xgpio_get; - chip->mmchip.gc.set = xgpio_set; - - chip->mmchip.save_regs = xgpio_save_regs; - - /* Call the OF gpio helper to setup and register the GPIO device */ - status = of_mm_gpiochip_add(np, &chip->mmchip); - if (status) { - kfree(chip); - pr_err("%s: error in probe function with status %d\n", - np->full_name, status); - return status; - } - return 0; -} - -static struct of_device_id xgpio_of_match[] __devinitdata = { - { .compatible = "xlnx,xps-gpio-1.00.a", }, - { /* end of list */ }, -}; - -static int __init xgpio_init(void) -{ - struct device_node *np; - - for_each_matching_node(np, xgpio_of_match) - xgpio_of_probe(np); - - return 0; -} - -/* Make sure we get initialized before anyone else tries to use us */ -subsys_initcall(xgpio_init); -/* No exit call at the moment as we cannot unregister of GPIO chips */ - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx GPIO driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/gpio/gpiolib.c b/ANDROID_3.4.5/drivers/gpio/gpiolib.c deleted file mode 100644 index c4c68359..00000000 --- a/ANDROID_3.4.5/drivers/gpio/gpiolib.c +++ /dev/null @@ -1,1866 +0,0 @@ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> -#include <linux/idr.h> -#include <linux/slab.h> - -#define CREATE_TRACE_POINTS -#include <trace/events/gpio.h> - -/* Optional implementation infrastructure for GPIO interfaces. - * - * Platforms may want to use this if they tend to use very many GPIOs - * that aren't part of a System-On-Chip core; or across I2C/SPI/etc. - * - * When kernel footprint or instruction count is an issue, simpler - * implementations may be preferred. The GPIO programming interface - * allows for inlining speed-critical get/set operations for common - * cases, so that access to SOC-integrated GPIOs can sometimes cost - * only an instruction or two per bit. - */ - - -/* When debugging, extend minimal trust to callers and platform code. - * Also emit diagnostic messages that may help initial bringup, when - * board setup or driver bugs are most common. - * - * Otherwise, minimize overhead in what may be bitbanging codepaths. - */ -#ifdef DEBUG -#define extra_checks 1 -#else -#define extra_checks 0 -#endif - -/* gpio_lock prevents conflicts during gpio_desc[] table updates. - * While any GPIO is requested, its gpio_chip is not removable; - * each GPIO's "requested" flag serves as a lock and refcount. - */ -static DEFINE_SPINLOCK(gpio_lock); - -struct gpio_desc { - struct gpio_chip *chip; - unsigned long flags; -/* flag symbols are bit numbers */ -#define FLAG_REQUESTED 0 -#define FLAG_IS_OUT 1 -#define FLAG_RESERVED 2 -#define FLAG_EXPORT 3 /* protected by sysfs_lock */ -#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ -#define FLAG_TRIG_FALL 5 /* trigger on falling edge */ -#define FLAG_TRIG_RISE 6 /* trigger on rising edge */ -#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ -#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ -#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */ - -#define ID_SHIFT 16 /* add new flags before this one */ - -#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1) -#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) - -#ifdef CONFIG_DEBUG_FS - const char *label; -#endif -}; -static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; - -#ifdef CONFIG_GPIO_SYSFS -static DEFINE_IDR(dirent_idr); -#endif - -static inline void desc_set_label(struct gpio_desc *d, const char *label) -{ -#ifdef CONFIG_DEBUG_FS - d->label = label; -#endif -} - -/* Warn when drivers omit gpio_request() calls -- legal but ill-advised - * when setting direction, and otherwise illegal. Until board setup code - * and drivers use explicit requests everywhere (which won't happen when - * those calls have no teeth) we can't avoid autorequesting. This nag - * message should motivate switching to explicit requests... so should - * the weaker cleanup after faults, compared to gpio_request(). - * - * NOTE: the autorequest mechanism is going away; at this point it's - * only "legal" in the sense that (old) code using it won't break yet, - * but instead only triggers a WARN() stack dump. - */ -static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset) -{ - const struct gpio_chip *chip = desc->chip; - const int gpio = chip->base + offset; - - if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0, - "autorequest GPIO-%d\n", gpio)) { - if (!try_module_get(chip->owner)) { - pr_err("GPIO-%d: module can't be gotten \n", gpio); - clear_bit(FLAG_REQUESTED, &desc->flags); - /* lose */ - return -EIO; - } - desc_set_label(desc, "[auto]"); - /* caller must chip->request() w/o spinlock */ - if (chip->request) - return 1; - } - return 0; -} - -/* caller holds gpio_lock *OR* gpio is marked as requested */ -struct gpio_chip *gpio_to_chip(unsigned gpio) -{ - return gpio_desc[gpio].chip; -} - -/* dynamic allocation of GPIOs, e.g. on a hotplugged device */ -static int gpiochip_find_base(int ngpio) -{ - int i; - int spare = 0; - int base = -ENOSPC; - - for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) { - struct gpio_desc *desc = &gpio_desc[i]; - struct gpio_chip *chip = desc->chip; - - if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) { - spare++; - if (spare == ngpio) { - base = i; - break; - } - } else { - spare = 0; - if (chip) - i -= chip->ngpio - 1; - } - } - - if (gpio_is_valid(base)) - pr_debug("%s: found new base at %d\n", __func__, base); - return base; -} - -/** - * gpiochip_reserve() - reserve range of gpios to use with platform code only - * @start: starting gpio number - * @ngpio: number of gpios to reserve - * Context: platform init, potentially before irqs or kmalloc will work - * - * Returns a negative errno if any gpio within the range is already reserved - * or registered, else returns zero as a success code. Use this function - * to mark a range of gpios as unavailable for dynamic gpio number allocation, - * for example because its driver support is not yet loaded. - */ -int __init gpiochip_reserve(int start, int ngpio) -{ - int ret = 0; - unsigned long flags; - int i; - - if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1)) - return -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - - for (i = start; i < start + ngpio; i++) { - struct gpio_desc *desc = &gpio_desc[i]; - - if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) { - ret = -EBUSY; - goto err; - } - - set_bit(FLAG_RESERVED, &desc->flags); - } - - pr_debug("%s: reserved gpios from %d to %d\n", - __func__, start, start + ngpio - 1); -err: - spin_unlock_irqrestore(&gpio_lock, flags); - - return ret; -} - -#ifdef CONFIG_GPIO_SYSFS - -/* lock protects against unexport_gpio() being called while - * sysfs files are active. - */ -static DEFINE_MUTEX(sysfs_lock); - -/* - * /sys/class/gpio/gpioN... only for GPIOs that are exported - * /direction - * * MAY BE OMITTED if kernel won't allow direction changes - * * is read/write as "in" or "out" - * * may also be written as "high" or "low", initializing - * output value as specified ("out" implies "low") - * /value - * * always readable, subject to hardware behavior - * * may be writable, as zero/nonzero - * /edge - * * configures behavior of poll(2) on /value - * * available only if pin can generate IRQs on input - * * is read/write as "none", "falling", "rising", or "both" - * /active_low - * * configures polarity of /value - * * is read/write as zero/nonzero - * * also affects existing and subsequent "falling" and "rising" - * /edge configuration - */ - -static ssize_t gpio_direction_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else - status = sprintf(buf, "%s\n", - test_bit(FLAG_IS_OUT, &desc->flags) - ? "out" : "in"); - - mutex_unlock(&sysfs_lock); - return status; -} - -static ssize_t gpio_direction_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - unsigned gpio = desc - gpio_desc; - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else if (sysfs_streq(buf, "high")) - status = gpio_direction_output(gpio, 1); - else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low")) - status = gpio_direction_output(gpio, 0); - else if (sysfs_streq(buf, "in")) - status = gpio_direction_input(gpio); - else - status = -EINVAL; - - mutex_unlock(&sysfs_lock); - return status ? : size; -} - -static /* const */ DEVICE_ATTR(direction, 0644, - gpio_direction_show, gpio_direction_store); - -static ssize_t gpio_value_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - unsigned gpio = desc - gpio_desc; - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) { - status = -EIO; - } else { - int value; - - value = !!gpio_get_value_cansleep(gpio); - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - value = !value; - - status = sprintf(buf, "%d\n", value); - } - - mutex_unlock(&sysfs_lock); - return status; -} - -static ssize_t gpio_value_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - unsigned gpio = desc - gpio_desc; - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else if (!test_bit(FLAG_IS_OUT, &desc->flags)) - status = -EPERM; - else { - long value; - - status = strict_strtol(buf, 0, &value); - if (status == 0) { - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - value = !value; - printk("[GPIO] %d, %ld\n", gpio, value); - gpio_set_value_cansleep(gpio, value != 0); - status = size; - } - } - - mutex_unlock(&sysfs_lock); - return status; -} - -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - -static irqreturn_t gpio_sysfs_irq(int irq, void *priv) -{ - struct sysfs_dirent *value_sd = priv; - - sysfs_notify_dirent(value_sd); - return IRQ_HANDLED; -} - -static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, - unsigned long gpio_flags) -{ - struct sysfs_dirent *value_sd; - unsigned long irq_flags; - int ret, irq, id; - - if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags) - return 0; - - irq = gpio_to_irq(desc - gpio_desc); - if (irq < 0) - return -EIO; - - id = desc->flags >> ID_SHIFT; - value_sd = idr_find(&dirent_idr, id); - if (value_sd) - free_irq(irq, value_sd); - - desc->flags &= ~GPIO_TRIGGER_MASK; - - if (!gpio_flags) { - ret = 0; - goto free_id; - } - - irq_flags = IRQF_SHARED; - if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) - irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? - IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; - if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) - irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? - IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; - - if (!value_sd) { - value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); - if (!value_sd) { - ret = -ENODEV; - goto err_out; - } - - do { - ret = -ENOMEM; - if (idr_pre_get(&dirent_idr, GFP_KERNEL)) - ret = idr_get_new_above(&dirent_idr, value_sd, - 1, &id); - } while (ret == -EAGAIN); - - if (ret) - goto free_sd; - - desc->flags &= GPIO_FLAGS_MASK; - desc->flags |= (unsigned long)id << ID_SHIFT; - - if (desc->flags >> ID_SHIFT != id) { - ret = -ERANGE; - goto free_id; - } - } - - ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags, - "gpiolib", value_sd); - if (ret < 0) - goto free_id; - - desc->flags |= gpio_flags; - return 0; - -free_id: - idr_remove(&dirent_idr, id); - desc->flags &= GPIO_FLAGS_MASK; -free_sd: - if (value_sd) - sysfs_put(value_sd); -err_out: - return ret; -} - -static const struct { - const char *name; - unsigned long flags; -} trigger_types[] = { - { "none", 0 }, - { "falling", BIT(FLAG_TRIG_FALL) }, - { "rising", BIT(FLAG_TRIG_RISE) }, - { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) }, -}; - -static ssize_t gpio_edge_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else { - int i; - - status = 0; - for (i = 0; i < ARRAY_SIZE(trigger_types); i++) - if ((desc->flags & GPIO_TRIGGER_MASK) - == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", - trigger_types[i].name); - break; - } - } - - mutex_unlock(&sysfs_lock); - return status; -} - -static ssize_t gpio_edge_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - int i; - - for (i = 0; i < ARRAY_SIZE(trigger_types); i++) - if (sysfs_streq(trigger_types[i].name, buf)) - goto found; - return -EINVAL; - -found: - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else { - status = gpio_setup_irq(desc, dev, trigger_types[i].flags); - if (!status) - status = size; - } - - mutex_unlock(&sysfs_lock); - - return status; -} - -static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); - -static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev, - int value) -{ - int status = 0; - - if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) - return 0; - - if (value) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - else - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); - - /* reconfigure poll(2) support if enabled on one edge only */ - if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^ - !!test_bit(FLAG_TRIG_FALL, &desc->flags))) { - unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK; - - gpio_setup_irq(desc, dev, 0); - status = gpio_setup_irq(desc, dev, trigger_flags); - } - - return status; -} - -static ssize_t gpio_active_low_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else - status = sprintf(buf, "%d\n", - !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); - - mutex_unlock(&sysfs_lock); - - return status; -} - -static ssize_t gpio_active_low_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) { - status = -EIO; - } else { - long value; - - status = strict_strtol(buf, 0, &value); - if (status == 0) - status = sysfs_set_active_low(desc, dev, value != 0); - } - - mutex_unlock(&sysfs_lock); - - return status ? : size; -} - -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - &dev_attr_value.attr, - &dev_attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - -/* - * /sys/class/gpio/gpiochipN/ - * /base ... matching gpio_chip.base (N) - * /label ... matching gpio_chip.label - * /ngpio ... matching gpio_chip.ngpio - */ - -static ssize_t chip_base_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->base); -} -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); - -static ssize_t chip_label_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", chip->label ? : ""); -} -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); - -static ssize_t chip_ngpio_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", chip->ngpio); -} -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - &dev_attr_base.attr, - &dev_attr_label.attr, - &dev_attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; - -/* - * /sys/class/gpio/export ... write-only - * integer N ... number of GPIO to export (full access) - * /sys/class/gpio/unexport ... write-only - * integer N ... number of GPIO to unexport - */ -static ssize_t export_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t len) -{ - long gpio; - int status; - - status = strict_strtol(buf, 0, &gpio); - if (status < 0) - goto done; - - /* No extra locking here; FLAG_SYSFS just signifies that the - * request and export were done by on behalf of userspace, so - * they may be undone on its behalf too. - */ - - status = gpio_request(gpio, "sysfs"); - if (status < 0) - goto done; - - status = gpio_export(gpio, true); - if (status < 0) - gpio_free(gpio); - else - set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags); - -done: - if (status) - pr_debug("%s: status %d\n", __func__, status); - return status ? : len; -} - -static ssize_t unexport_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t len) -{ - long gpio; - int status; - - status = strict_strtol(buf, 0, &gpio); - if (status < 0) - goto done; - - status = -EINVAL; - - /* reject bogus commands (gpio_unexport ignores them) */ - if (!gpio_is_valid(gpio)) - goto done; - - /* No extra locking here; FLAG_SYSFS just signifies that the - * request and export were done by on behalf of userspace, so - * they may be undone on its behalf too. - */ - if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) { - status = 0; - gpio_free(gpio); - } -done: - if (status) - pr_debug("%s: status %d\n", __func__, status); - return status ? : len; -} - -static struct class_attribute gpio_class_attrs[] = { - __ATTR(export, 0200, NULL, export_store), - __ATTR(unexport, 0200, NULL, unexport_store), - __ATTR_NULL, -}; - -static struct class gpio_class = { - .name = "gpio", - .owner = THIS_MODULE, - - .class_attrs = gpio_class_attrs, -}; - - -/** - * gpio_export - export a GPIO through sysfs - * @gpio: gpio to make available, already requested - * @direction_may_change: true if userspace may change gpio direction - * Context: arch_initcall or later - * - * When drivers want to make a GPIO accessible to userspace after they - * have requested it -- perhaps while debugging, or as part of their - * public interface -- they may use this routine. If the GPIO can - * change direction (some can't) and the caller allows it, userspace - * will see "direction" sysfs attribute which may be used to change - * the gpio's direction. A "value" attribute will always be provided. - * - * Returns zero on success, else an error. - */ -int gpio_export(unsigned gpio, bool direction_may_change) -{ - unsigned long flags; - struct gpio_desc *desc; - int status = -EINVAL; - const char *ioname = NULL; - - /* can't export until sysfs is available ... */ - if (!gpio_class.p) { - pr_debug("%s: called too early!\n", __func__); - return -ENOENT; - } - - if (!gpio_is_valid(gpio)) - goto done; - - mutex_lock(&sysfs_lock); - - spin_lock_irqsave(&gpio_lock, flags); - desc = &gpio_desc[gpio]; - if (test_bit(FLAG_REQUESTED, &desc->flags) - && !test_bit(FLAG_EXPORT, &desc->flags)) { - status = 0; - if (!desc->chip->direction_input - || !desc->chip->direction_output) - direction_may_change = false; - } - spin_unlock_irqrestore(&gpio_lock, flags); - - if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) - ioname = desc->chip->names[gpio - desc->chip->base]; - - if (status == 0) { - struct device *dev; - - dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), - desc, ioname ? ioname : "gpio%u", gpio); - if (!IS_ERR(dev)) { - status = sysfs_create_group(&dev->kobj, - &gpio_attr_group); - - if (!status && direction_may_change) - status = device_create_file(dev, - &dev_attr_direction); - - if (!status && gpio_to_irq(gpio) >= 0 - && (direction_may_change - || !test_bit(FLAG_IS_OUT, - &desc->flags))) - status = device_create_file(dev, - &dev_attr_edge); - - if (status != 0) - device_unregister(dev); - } else - status = PTR_ERR(dev); - if (status == 0) - set_bit(FLAG_EXPORT, &desc->flags); - } - - mutex_unlock(&sysfs_lock); - -done: - if (status) - pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); - - return status; -} -EXPORT_SYMBOL_GPL(gpio_export); - -static int match_export(struct device *dev, void *data) -{ - return dev_get_drvdata(dev) == data; -} - -/** - * gpio_export_link - create a sysfs link to an exported GPIO node - * @dev: device under which to create symlink - * @name: name of the symlink - * @gpio: gpio to create symlink to, already exported - * - * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN - * node. Caller is responsible for unlinking. - * - * Returns zero on success, else an error. - */ -int gpio_export_link(struct device *dev, const char *name, unsigned gpio) -{ - struct gpio_desc *desc; - int status = -EINVAL; - - if (!gpio_is_valid(gpio)) - goto done; - - mutex_lock(&sysfs_lock); - - desc = &gpio_desc[gpio]; - - if (test_bit(FLAG_EXPORT, &desc->flags)) { - struct device *tdev; - - tdev = class_find_device(&gpio_class, NULL, desc, match_export); - if (tdev != NULL) { - status = sysfs_create_link(&dev->kobj, &tdev->kobj, - name); - } else { - status = -ENODEV; - } - } - - mutex_unlock(&sysfs_lock); - -done: - if (status) - pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); - - return status; -} -EXPORT_SYMBOL_GPL(gpio_export_link); - - -/** - * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value - * @gpio: gpio to change - * @value: non-zero to use active low, i.e. inverted values - * - * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute. - * The GPIO does not have to be exported yet. If poll(2) support has - * been enabled for either rising or falling edge, it will be - * reconfigured to follow the new polarity. - * - * Returns zero on success, else an error. - */ -int gpio_sysfs_set_active_low(unsigned gpio, int value) -{ - struct gpio_desc *desc; - struct device *dev = NULL; - int status = -EINVAL; - - if (!gpio_is_valid(gpio)) - goto done; - - mutex_lock(&sysfs_lock); - - desc = &gpio_desc[gpio]; - - if (test_bit(FLAG_EXPORT, &desc->flags)) { - dev = class_find_device(&gpio_class, NULL, desc, match_export); - if (dev == NULL) { - status = -ENODEV; - goto unlock; - } - } - - status = sysfs_set_active_low(desc, dev, value); - -unlock: - mutex_unlock(&sysfs_lock); - -done: - if (status) - pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); - - return status; -} -EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low); - -/** - * gpio_unexport - reverse effect of gpio_export() - * @gpio: gpio to make unavailable - * - * This is implicit on gpio_free(). - */ -void gpio_unexport(unsigned gpio) -{ - struct gpio_desc *desc; - int status = 0; - struct device *dev = NULL; - - if (!gpio_is_valid(gpio)) { - status = -EINVAL; - goto done; - } - - mutex_lock(&sysfs_lock); - - desc = &gpio_desc[gpio]; - - if (test_bit(FLAG_EXPORT, &desc->flags)) { - - dev = class_find_device(&gpio_class, NULL, desc, match_export); - if (dev) { - gpio_setup_irq(desc, dev, 0); - clear_bit(FLAG_EXPORT, &desc->flags); - } else - status = -ENODEV; - } - - mutex_unlock(&sysfs_lock); - if (dev) { - device_unregister(dev); - put_device(dev); - } -done: - if (status) - pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); -} -EXPORT_SYMBOL_GPL(gpio_unexport); - -static int gpiochip_export(struct gpio_chip *chip) -{ - int status; - struct device *dev; - - /* Many systems register gpio chips for SOC support very early, - * before driver model support is available. In those cases we - * export this later, in gpiolib_sysfs_init() ... here we just - * verify that _some_ field of gpio_class got initialized. - */ - if (!gpio_class.p) - return 0; - - /* use chip->base for the ID; it's already known to be unique */ - mutex_lock(&sysfs_lock); - dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, - "gpiochip%d", chip->base); - if (!IS_ERR(dev)) { - status = sysfs_create_group(&dev->kobj, - &gpiochip_attr_group); - } else - status = PTR_ERR(dev); - chip->exported = (status == 0); - mutex_unlock(&sysfs_lock); - - if (status) { - unsigned long flags; - unsigned gpio; - - spin_lock_irqsave(&gpio_lock, flags); - gpio = chip->base; - while (gpio_desc[gpio].chip == chip) - gpio_desc[gpio++].chip = NULL; - spin_unlock_irqrestore(&gpio_lock, flags); - - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); - } - - return status; -} - -static void gpiochip_unexport(struct gpio_chip *chip) -{ - int status; - struct device *dev; - - mutex_lock(&sysfs_lock); - dev = class_find_device(&gpio_class, NULL, chip, match_export); - if (dev) { - put_device(dev); - device_unregister(dev); - chip->exported = 0; - status = 0; - } else - status = -ENODEV; - mutex_unlock(&sysfs_lock); - - if (status) - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); -} - -static int __init gpiolib_sysfs_init(void) -{ - int status; - unsigned long flags; - unsigned gpio; - - status = class_register(&gpio_class); - if (status < 0) - return status; - - /* Scan and register the gpio_chips which registered very - * early (e.g. before the class_register above was called). - * - * We run before arch_initcall() so chip->dev nodes can have - * registered, and so arch_initcall() can always gpio_export(). - */ - spin_lock_irqsave(&gpio_lock, flags); - for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { - struct gpio_chip *chip; - - chip = gpio_desc[gpio].chip; - if (!chip || chip->exported) - continue; - - spin_unlock_irqrestore(&gpio_lock, flags); - status = gpiochip_export(chip); - spin_lock_irqsave(&gpio_lock, flags); - } - spin_unlock_irqrestore(&gpio_lock, flags); - - - return status; -} -postcore_initcall(gpiolib_sysfs_init); - -#else -static inline int gpiochip_export(struct gpio_chip *chip) -{ - return 0; -} - -static inline void gpiochip_unexport(struct gpio_chip *chip) -{ -} - -#endif /* CONFIG_GPIO_SYSFS */ - -/** - * gpiochip_add() - register a gpio_chip - * @chip: the chip to register, with chip->base initialized - * Context: potentially before irqs or kmalloc will work - * - * Returns a negative errno if the chip can't be registered, such as - * because the chip->base is invalid or already associated with a - * different chip. Otherwise it returns zero as a success code. - * - * When gpiochip_add() is called very early during boot, so that GPIOs - * can be freely used, the chip->dev device must be registered before - * the gpio framework's arch_initcall(). Otherwise sysfs initialization - * for GPIOs will fail rudely. - * - * If chip->base is negative, this requests dynamic assignment of - * a range of valid GPIOs. - */ -int gpiochip_add(struct gpio_chip *chip) -{ - unsigned long flags; - int status = 0; - unsigned id; - int base = chip->base; - - if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1)) - && base >= 0) { - status = -EINVAL; - goto fail; - } - - spin_lock_irqsave(&gpio_lock, flags); - - if (base < 0) { - base = gpiochip_find_base(chip->ngpio); - if (base < 0) { - status = base; - goto unlock; - } - chip->base = base; - } - - /* these GPIO numbers must not be managed by another gpio_chip */ - for (id = base; id < base + chip->ngpio; id++) { - if (gpio_desc[id].chip != NULL) { - status = -EBUSY; - break; - } - } - if (status == 0) { - for (id = base; id < base + chip->ngpio; id++) { - gpio_desc[id].chip = chip; - - /* REVISIT: most hardware initializes GPIOs as - * inputs (often with pullups enabled) so power - * usage is minimized. Linux code should set the - * gpio direction first thing; but until it does, - * we may expose the wrong direction in sysfs. - */ - gpio_desc[id].flags = !chip->direction_input - ? (1 << FLAG_IS_OUT) - : 0; - } - } - - of_gpiochip_add(chip); - -unlock: - spin_unlock_irqrestore(&gpio_lock, flags); - - if (status) - goto fail; - - status = gpiochip_export(chip); - if (status) - goto fail; - - pr_info("gpiochip_add: registered GPIOs %d to %d on device: %s\n", - chip->base, chip->base + chip->ngpio - 1, - chip->label ? : "generic"); - - return 0; -fail: - /* failures here can mean systems won't boot... */ - pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", - chip->base, chip->base + chip->ngpio - 1, - chip->label ? : "generic"); - return status; -} -EXPORT_SYMBOL_GPL(gpiochip_add); - -/** - * gpiochip_remove() - unregister a gpio_chip - * @chip: the chip to unregister - * - * A gpio_chip with any GPIOs still requested may not be removed. - */ -int gpiochip_remove(struct gpio_chip *chip) -{ - unsigned long flags; - int status = 0; - unsigned id; - - spin_lock_irqsave(&gpio_lock, flags); - - of_gpiochip_remove(chip); - - for (id = chip->base; id < chip->base + chip->ngpio; id++) { - if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { - status = -EBUSY; - break; - } - } - if (status == 0) { - for (id = chip->base; id < chip->base + chip->ngpio; id++) - gpio_desc[id].chip = NULL; - } - - spin_unlock_irqrestore(&gpio_lock, flags); - - if (status == 0) - gpiochip_unexport(chip); - - return status; -} -EXPORT_SYMBOL_GPL(gpiochip_remove); - -/** - * gpiochip_find() - iterator for locating a specific gpio_chip - * @data: data to pass to match function - * @callback: Callback function to check gpio_chip - * - * Similar to bus_find_device. It returns a reference to a gpio_chip as - * determined by a user supplied @match callback. The callback should return - * 0 if the device doesn't match and non-zero if it does. If the callback is - * non-zero, this function will return to the caller and not iterate over any - * more gpio_chips. - */ -struct gpio_chip *gpiochip_find(const void *data, - int (*match)(struct gpio_chip *chip, - const void *data)) -{ - struct gpio_chip *chip = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&gpio_lock, flags); - for (i = 0; i < ARCH_NR_GPIOS; i++) { - if (!gpio_desc[i].chip) - continue; - - if (match(gpio_desc[i].chip, data)) { - chip = gpio_desc[i].chip; - break; - } - } - spin_unlock_irqrestore(&gpio_lock, flags); - - return chip; -} -EXPORT_SYMBOL_GPL(gpiochip_find); - -/* These "optional" allocation calls help prevent drivers from stomping - * on each other, and help provide better diagnostics in debugfs. - * They're called even less than the "set direction" calls. - */ -int gpio_request(unsigned gpio, const char *label) -{ - struct gpio_desc *desc; - struct gpio_chip *chip; - int status = -EINVAL; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - if (!gpio_is_valid(gpio)) - goto done; - desc = &gpio_desc[gpio]; - chip = desc->chip; - if (chip == NULL) - goto done; - - if (!try_module_get(chip->owner)) - goto done; - - /* NOTE: gpio_request() can be called in early boot, - * before IRQs are enabled, for non-sleeping (SOC) GPIOs. - */ - - if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { - desc_set_label(desc, label ? : "?"); - status = 0; - } else { - status = -EBUSY; - module_put(chip->owner); - goto done; - } - - if (chip->request) { - /* chip->request may sleep */ - spin_unlock_irqrestore(&gpio_lock, flags); - status = chip->request(chip, gpio - chip->base); - spin_lock_irqsave(&gpio_lock, flags); - - if (status < 0) { - desc_set_label(desc, NULL); - module_put(chip->owner); - clear_bit(FLAG_REQUESTED, &desc->flags); - } - } - -done: - if (status) - pr_debug("gpio_request: gpio-%d (%s) status %d\n", - gpio, label ? : "?", status); - spin_unlock_irqrestore(&gpio_lock, flags); - return status; -} -EXPORT_SYMBOL_GPL(gpio_request); - -void gpio_free(unsigned gpio) -{ - unsigned long flags; - struct gpio_desc *desc; - struct gpio_chip *chip; - - might_sleep(); - - if (!gpio_is_valid(gpio)) { - WARN_ON(extra_checks); - return; - } - - gpio_unexport(gpio); - - spin_lock_irqsave(&gpio_lock, flags); - - desc = &gpio_desc[gpio]; - chip = desc->chip; - if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { - if (chip->free) { - spin_unlock_irqrestore(&gpio_lock, flags); - might_sleep_if(chip->can_sleep); - chip->free(chip, gpio - chip->base); - spin_lock_irqsave(&gpio_lock, flags); - } - desc_set_label(desc, NULL); - module_put(desc->chip->owner); - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); - clear_bit(FLAG_REQUESTED, &desc->flags); - clear_bit(FLAG_OPEN_DRAIN, &desc->flags); - clear_bit(FLAG_OPEN_SOURCE, &desc->flags); - } else - WARN_ON(extra_checks); - - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL_GPL(gpio_free); - -/** - * gpio_request_one - request a single GPIO with initial configuration - * @gpio: the GPIO number - * @flags: GPIO configuration as specified by GPIOF_* - * @label: a literal description string of this GPIO - */ -int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) -{ - int err; - - err = gpio_request(gpio, label); - if (err) - return err; - - if (flags & GPIOF_OPEN_DRAIN) - set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); - - if (flags & GPIOF_OPEN_SOURCE) - set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags); - - if (flags & GPIOF_DIR_IN) - err = gpio_direction_input(gpio); - else - err = gpio_direction_output(gpio, - (flags & GPIOF_INIT_HIGH) ? 1 : 0); - - if (err) - gpio_free(gpio); - - return err; -} -EXPORT_SYMBOL_GPL(gpio_request_one); - -/** - * gpio_request_array - request multiple GPIOs in a single call - * @array: array of the 'struct gpio' - * @num: how many GPIOs in the array - */ -int gpio_request_array(const struct gpio *array, size_t num) -{ - int i, err; - - for (i = 0; i < num; i++, array++) { - err = gpio_request_one(array->gpio, array->flags, array->label); - if (err) - goto err_free; - } - return 0; - -err_free: - while (i--) - gpio_free((--array)->gpio); - return err; -} -EXPORT_SYMBOL_GPL(gpio_request_array); - -/** - * gpio_free_array - release multiple GPIOs in a single call - * @array: array of the 'struct gpio' - * @num: how many GPIOs in the array - */ -void gpio_free_array(const struct gpio *array, size_t num) -{ - while (num--) - gpio_free((array++)->gpio); -} -EXPORT_SYMBOL_GPL(gpio_free_array); - -/** - * gpiochip_is_requested - return string iff signal was requested - * @chip: controller managing the signal - * @offset: of signal within controller's 0..(ngpio - 1) range - * - * Returns NULL if the GPIO is not currently requested, else a string. - * If debugfs support is enabled, the string returned is the label passed - * to gpio_request(); otherwise it is a meaningless constant. - * - * This function is for use by GPIO controller drivers. The label can - * help with diagnostics, and knowing that the signal is used as a GPIO - * can help avoid accidentally multiplexing it to another controller. - */ -const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) -{ - unsigned gpio = chip->base + offset; - - if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip) - return NULL; - if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) - return NULL; -#ifdef CONFIG_DEBUG_FS - return gpio_desc[gpio].label; -#else - return "?"; -#endif -} -EXPORT_SYMBOL_GPL(gpiochip_is_requested); - - -/* Drivers MUST set GPIO direction before making get/set calls. In - * some cases this is done in early boot, before IRQs are enabled. - * - * As a rule these aren't called more than once (except for drivers - * using the open-drain emulation idiom) so these are natural places - * to accumulate extra debugging checks. Note that we can't (yet) - * rely on gpio_request() having been called beforehand. - */ - -int gpio_direction_input(unsigned gpio) -{ - unsigned long flags; - struct gpio_chip *chip; - struct gpio_desc *desc = &gpio_desc[gpio]; - int status = -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - - if (!gpio_is_valid(gpio)) - goto fail; - chip = desc->chip; - if (!chip || !chip->get || !chip->direction_input) - goto fail; - gpio -= chip->base; - if (gpio >= chip->ngpio) - goto fail; - status = gpio_ensure_requested(desc, gpio); - if (status < 0) - goto fail; - - /* now we know the gpio is valid and chip won't vanish */ - - spin_unlock_irqrestore(&gpio_lock, flags); - - might_sleep_if(chip->can_sleep); - - if (status) { - status = chip->request(chip, gpio); - if (status < 0) { - pr_debug("GPIO-%d: chip request fail, %d\n", - chip->base + gpio, status); - /* and it's not available to anyone else ... - * gpio_request() is the fully clean solution. - */ - goto lose; - } - } - - status = chip->direction_input(chip, gpio); - if (status == 0) - clear_bit(FLAG_IS_OUT, &desc->flags); - - trace_gpio_direction(chip->base + gpio, 1, status); -lose: - return status; -fail: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", - __func__, gpio, status); - return status; -} -EXPORT_SYMBOL_GPL(gpio_direction_input); - -int gpio_direction_output(unsigned gpio, int value) -{ - unsigned long flags; - struct gpio_chip *chip; - struct gpio_desc *desc = &gpio_desc[gpio]; - int status = -EINVAL; - - /* Open drain pin should not be driven to 1 */ - if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - return gpio_direction_input(gpio); - - /* Open source pin should not be driven to 0 */ - if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - return gpio_direction_input(gpio); - - spin_lock_irqsave(&gpio_lock, flags); - - if (!gpio_is_valid(gpio)) - goto fail; - chip = desc->chip; - if (!chip || !chip->set || !chip->direction_output) - goto fail; - gpio -= chip->base; - if (gpio >= chip->ngpio) - goto fail; - status = gpio_ensure_requested(desc, gpio); - if (status < 0) - goto fail; - - /* now we know the gpio is valid and chip won't vanish */ - - spin_unlock_irqrestore(&gpio_lock, flags); - - might_sleep_if(chip->can_sleep); - - if (status) { - status = chip->request(chip, gpio); - if (status < 0) { - pr_debug("GPIO-%d: chip request fail, %d\n", - chip->base + gpio, status); - /* and it's not available to anyone else ... - * gpio_request() is the fully clean solution. - */ - goto lose; - } - } - - status = chip->direction_output(chip, gpio, value); - if (status == 0) - set_bit(FLAG_IS_OUT, &desc->flags); - trace_gpio_value(chip->base + gpio, 0, value); - trace_gpio_direction(chip->base + gpio, 0, status); -lose: - return status; -fail: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", - __func__, gpio, status); - return status; -} -EXPORT_SYMBOL_GPL(gpio_direction_output); - -int gpio_re_enabled(unsigned gpio) -{ - unsigned long flags; - struct gpio_chip *chip; - struct gpio_desc *desc = &gpio_desc[gpio]; - int status = -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) - goto fail; - chip = desc->chip; - if (!chip || !chip->set || !chip->direction_output) - goto fail; - gpio -= chip->base; - if (gpio >= chip->ngpio) - goto fail; - status = gpio_ensure_requested(desc, gpio); - if (status < 0) - goto fail; - - spin_unlock_irqrestore(&gpio_lock, flags); - - status = chip->request(chip, gpio); - if (status < 0) { - pr_debug("GPIO-%d: chip request fail, %d\n", - chip->base + gpio, status); - } - return status; - -fail: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", - __func__, gpio, status); - return status; -} -EXPORT_SYMBOL_GPL(gpio_re_enabled); - -/** - * gpio_set_debounce - sets @debounce time for a @gpio - * @gpio: the gpio to set debounce time - * @debounce: debounce time is microseconds - */ -int gpio_set_debounce(unsigned gpio, unsigned debounce) -{ - unsigned long flags; - struct gpio_chip *chip; - struct gpio_desc *desc = &gpio_desc[gpio]; - int status = -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - - if (!gpio_is_valid(gpio)) - goto fail; - chip = desc->chip; - if (!chip || !chip->set || !chip->set_debounce) - goto fail; - gpio -= chip->base; - if (gpio >= chip->ngpio) - goto fail; - status = gpio_ensure_requested(desc, gpio); - if (status < 0) - goto fail; - - /* now we know the gpio is valid and chip won't vanish */ - - spin_unlock_irqrestore(&gpio_lock, flags); - - might_sleep_if(chip->can_sleep); - - return chip->set_debounce(chip, gpio, debounce); - -fail: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", - __func__, gpio, status); - - return status; -} -EXPORT_SYMBOL_GPL(gpio_set_debounce); - -/* I/O calls are only valid after configuration completed; the relevant - * "is this a valid GPIO" error checks should already have been done. - * - * "Get" operations are often inlinable as reading a pin value register, - * and masking the relevant bit in that register. - * - * When "set" operations are inlinable, they involve writing that mask to - * one register to set a low value, or a different register to set it high. - * Otherwise locking is needed, so there may be little value to inlining. - * - *------------------------------------------------------------------------ - * - * IMPORTANT!!! The hot paths -- get/set value -- assume that callers - * have requested the GPIO. That can include implicit requesting by - * a direction setting call. Marking a gpio as requested locks its chip - * in memory, guaranteeing that these table lookups need no more locking - * and that gpiochip_remove() will fail. - * - * REVISIT when debugging, consider adding some instrumentation to ensure - * that the GPIO was actually requested. - */ - -/** - * __gpio_get_value() - return a gpio's value - * @gpio: gpio whose value will be returned - * Context: any - * - * This is used directly or indirectly to implement gpio_get_value(). - * It returns the zero or nonzero value provided by the associated - * gpio_chip.get() method; or zero if no such method is provided. - */ -int __gpio_get_value(unsigned gpio) -{ - struct gpio_chip *chip; - int value; - - chip = gpio_to_chip(gpio); - /* Should be using gpio_get_value_cansleep() */ - WARN_ON(chip->can_sleep); - value = chip->get ? chip->get(chip, gpio - chip->base) : 0; - trace_gpio_value(gpio, 1, value); - return value; -} -EXPORT_SYMBOL_GPL(__gpio_get_value); - -/* - * _gpio_set_open_drain_value() - Set the open drain gpio's value. - * @gpio: Gpio whose state need to be set. - * @chip: Gpio chip. - * @value: Non-zero for setting it HIGH otherise it will set to LOW. - */ -static void _gpio_set_open_drain_value(unsigned gpio, - struct gpio_chip *chip, int value) -{ - int err = 0; - if (value) { - err = chip->direction_input(chip, gpio - chip->base); - if (!err) - clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); - } else { - err = chip->direction_output(chip, gpio - chip->base, 0); - if (!err) - set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); - } - trace_gpio_direction(gpio, value, err); - if (err < 0) - pr_err("%s: Error in set_value for open drain gpio%d err %d\n", - __func__, gpio, err); -} - -/* - * _gpio_set_open_source() - Set the open source gpio's value. - * @gpio: Gpio whose state need to be set. - * @chip: Gpio chip. - * @value: Non-zero for setting it HIGH otherise it will set to LOW. - */ -static void _gpio_set_open_source_value(unsigned gpio, - struct gpio_chip *chip, int value) -{ - int err = 0; - if (value) { - err = chip->direction_output(chip, gpio - chip->base, 1); - if (!err) - set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); - } else { - err = chip->direction_input(chip, gpio - chip->base); - if (!err) - clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); - } - trace_gpio_direction(gpio, !value, err); - if (err < 0) - pr_err("%s: Error in set_value for open source gpio%d err %d\n", - __func__, gpio, err); -} - - -/** - * __gpio_set_value() - assign a gpio's value - * @gpio: gpio whose value will be assigned - * @value: value to assign - * Context: any - * - * This is used directly or indirectly to implement gpio_set_value(). - * It invokes the associated gpio_chip.set() method. - */ -void __gpio_set_value(unsigned gpio, int value) -{ - struct gpio_chip *chip; - - chip = gpio_to_chip(gpio); - /* Should be using gpio_set_value_cansleep() */ - WARN_ON(chip->can_sleep); - trace_gpio_value(gpio, 0, value); - if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) - _gpio_set_open_drain_value(gpio, chip, value); - else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) - _gpio_set_open_source_value(gpio, chip, value); - else - chip->set(chip, gpio - chip->base, value); -} -EXPORT_SYMBOL_GPL(__gpio_set_value); - -/** - * __gpio_cansleep() - report whether gpio value access will sleep - * @gpio: gpio in question - * Context: any - * - * This is used directly or indirectly to implement gpio_cansleep(). It - * returns nonzero if access reading or writing the GPIO value can sleep. - */ -int __gpio_cansleep(unsigned gpio) -{ - struct gpio_chip *chip; - - /* only call this on GPIOs that are valid! */ - chip = gpio_to_chip(gpio); - - return chip->can_sleep; -} -EXPORT_SYMBOL_GPL(__gpio_cansleep); - -/** - * __gpio_to_irq() - return the IRQ corresponding to a GPIO - * @gpio: gpio whose IRQ will be returned (already requested) - * Context: any - * - * This is used directly or indirectly to implement gpio_to_irq(). - * It returns the number of the IRQ signaled by this (input) GPIO, - * or a negative errno. - */ -int __gpio_to_irq(unsigned gpio) -{ - struct gpio_chip *chip; - - chip = gpio_to_chip(gpio); - return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO; -} -EXPORT_SYMBOL_GPL(__gpio_to_irq); - - - -/* There's no value in making it easy to inline GPIO calls that may sleep. - * Common examples include ones connected to I2C or SPI chips. - */ - -int gpio_get_value_cansleep(unsigned gpio) -{ - struct gpio_chip *chip; - int value; - - might_sleep_if(extra_checks); - chip = gpio_to_chip(gpio); - value = chip->get ? chip->get(chip, gpio - chip->base) : 0; - trace_gpio_value(gpio, 1, value); - return value; -} -EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); - -void gpio_set_value_cansleep(unsigned gpio, int value) -{ - struct gpio_chip *chip; - - might_sleep_if(extra_checks); - chip = gpio_to_chip(gpio); - trace_gpio_value(gpio, 0, value); - if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) - _gpio_set_open_drain_value(gpio, chip, value); - else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) - _gpio_set_open_source_value(gpio, chip, value); - else - chip->set(chip, gpio - chip->base, value); -} -EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); - - -#ifdef CONFIG_DEBUG_FS - -static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - unsigned i; - unsigned gpio = chip->base; - struct gpio_desc *gdesc = &gpio_desc[gpio]; - int is_out; - - for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { - if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) - continue; - - is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); - seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", - gpio, gdesc->label, - is_out ? "out" : "in ", - chip->get - ? (chip->get(chip, i) ? "hi" : "lo") - : "? "); - seq_printf(s, "\n"); - } -} - -static int gpiolib_show(struct seq_file *s, void *unused) -{ - struct gpio_chip *chip = NULL; - unsigned gpio; - int started = 0; - - /* REVISIT this isn't locked against gpio_chip removal ... */ - - for (gpio = 0; gpio_is_valid(gpio); gpio++) { - struct device *dev; - - if (chip == gpio_desc[gpio].chip) - continue; - chip = gpio_desc[gpio].chip; - if (!chip) - continue; - - seq_printf(s, "%sGPIOs %d-%d", - started ? "\n" : "", - chip->base, chip->base + chip->ngpio - 1); - dev = chip->dev; - if (dev) - seq_printf(s, ", %s/%s", - dev->bus ? dev->bus->name : "no-bus", - dev_name(dev)); - if (chip->label) - seq_printf(s, ", %s", chip->label); - if (chip->can_sleep) - seq_printf(s, ", can sleep"); - seq_printf(s, ":\n"); - - started = 1; - if (chip->dbg_show) - chip->dbg_show(s, chip); - else - gpiolib_dbg_show(s, chip); - } - return 0; -} - -static int gpiolib_open(struct inode *inode, struct file *file) -{ - return single_open(file, gpiolib_show, NULL); -} - -static const struct file_operations gpiolib_operations = { - .open = gpiolib_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init gpiolib_debugfs_init(void) -{ - /* /sys/kernel/debug/gpio */ - (void) debugfs_create_file("gpio", S_IFREG | S_IRUGO, - NULL, NULL, &gpiolib_operations); - return 0; -} -subsys_initcall(gpiolib_debugfs_init); - -#endif /* DEBUG_FS */ |