Commit 7bf97e1d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6

Pull GPIO changes for v3.4 from Grant Likely:
 "Primarily gpio device driver changes with some minor side effects
  under arch/arm and arch/x86.  Also includes a few core changes such as
  explicitly supporting (electrical) open source and open drain outputs
  and some help for parsing gpio devicetree properties."

Fix up context conflict due to Laxman Dewangan adding sleep control for
the tps65910 driver separately for gpio's and regulators.

* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6: (34 commits)
  gpio/ep93xx: Remove unused inline function and useless pr_err message
  gpio/sodaville: Mark broken due to core irqdomain migration
  gpio/omap: fix redundant decoding of gpio offset
  gpio/omap: fix incorrect update to context.irqenable1
  gpio/omap: fix incorrect context restore logic in omap_gpio_runtime_*
  gpio/omap: fix missing dataout context save in _set_gpio_dataout_reg
  gpio/omap: fix _set_gpio_irqenable implementation
  gpio/omap: fix trigger type to unsigned
  gpio/omap: fix wakeup_en register update in _set_gpio_wakeup()
  gpio: tegra: tegra_gpio_config shouldn't be __init
  gpio/davinci: fix enabling unbanked GPIO IRQs
  gpio/davinci: fix oops on unbanked gpio irq request
  gpio/omap: Fix section warning for omap_mpuio_alloc_gc()
  ARM: tegra: export tegra_gpio_{en,dis}able
  gpio/gpio-stmpe: Fix the value returned by _get_value routine
  Documentation/gpio.txt: Explain expected pinctrl interaction
  GPIO: LPC32xx: Add output reading to GPO P3
  GPIO: LPC32xx: Fix missing bit selection mask
  gpio/omap: fix wakeups on level-triggered GPIOs
  gpio/omap: Fix IRQ handling for SPARSE_IRQ
  ...
parents 30304e5a c77c8a6f
OMAP GPIO controller bindings
Required properties:
- compatible:
- "ti,omap2-gpio" for OMAP2 controllers
- "ti,omap3-gpio" for OMAP3 controllers
- "ti,omap4-gpio" for OMAP4 controllers
- #gpio-cells : Should be two.
- first cell is the pin number
- second cell is used to specify optional parameters (unused)
- gpio-controller : Marks the device node as a GPIO controller.
- #interrupt-cells : Should be 2.
- interrupt-controller: Mark the device node as an interrupt controller
The first cell is the GPIO number.
The second cell is used to specify flags:
bits[3:0] trigger type and level flags:
1 = low-to-high edge triggered.
2 = high-to-low edge triggered.
4 = active high level-sensitive.
8 = active low level-sensitive.
OMAP specific properties:
- ti,hwmods: Name of the hwmod associated to the GPIO:
"gpio<X>", <X> being the 1-based instance number from the HW spec
Example:
gpio4: gpio4 {
compatible = "ti,omap4-gpio";
ti,hwmods = "gpio4";
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};
GPIO controller on CE4100 / Sodaville SoCs
==========================================
The bindings for CE4100's GPIO controller match the generic description
which is covered by the gpio.txt file in this folder.
The only additional property is the intel,muxctl property which holds the
value which is written into the MUXCNTL register.
There is no compatible property for now because the driver is probed via
PCI id (vendor 0x8086 device 0x2e67).
The interrupt specifier consists of two cells encoded as follows:
- <1st cell>: The interrupt-number that identifies the interrupt source.
- <2nd cell>: The level-sense information, encoded as follows:
4 - active high level-sensitive
8 - active low level-sensitive
Example of the GPIO device and one user:
pcigpio: gpio@b,1 {
/* two cells for GPIO and interrupt */
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "pci8086,2e67.2",
"pci8086,2e67",
"pciclassff0000",
"pciclassff00";
reg = <0x15900 0x0 0x0 0x0 0x0>;
/* Interrupt line of the gpio device */
interrupts = <15 1>;
/* It is an interrupt and GPIO controller itself */
interrupt-controller;
gpio-controller;
intel,muxctl = <0>;
};
testuser@20 {
compatible = "example,testuser";
/* User the 11th GPIO line as an active high triggered
* level interrupt
*/
interrupts = <11 8>;
interrupt-parent = <&pcigpio>;
/* Use this GPIO also with the gpio functions */
gpios = <&pcigpio 11 0>;
};
...@@ -271,9 +271,26 @@ Some platforms may also use knowledge about what GPIOs are active for ...@@ -271,9 +271,26 @@ Some platforms may also use knowledge about what GPIOs are active for
power management, such as by powering down unused chip sectors and, more power management, such as by powering down unused chip sectors and, more
easily, gating off unused clocks. easily, gating off unused clocks.
Note that requesting a GPIO does NOT cause it to be configured in any For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
way; it just marks that GPIO as in use. Separate code must handle any be informed of their use; a gpiolib driver's .request() operation may call
pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown). pinctrl_request_gpio(), and a gpiolib driver's .free() operation may call
pinctrl_free_gpio(). The pinctrl subsystem allows a pinctrl_request_gpio()
to succeed concurrently with a pin or pingroup being "owned" by a device for
pin multiplexing.
Any programming of pin multiplexing hardware that is needed to route the
GPIO signal to the appropriate pin should occur within a GPIO driver's
.direction_input() or .direction_output() operations, and occur after any
setup of an output GPIO's value. This allows a glitch-free migration from a
pin's special function to GPIO. This is sometimes required when using a GPIO
to implement a workaround on signals typically driven by a non-GPIO HW block.
Some platforms allow some or all GPIO signals to be routed to different pins.
Similarly, other aspects of the GPIO or pin may need to be configured, such as
pullup/pulldown. Platform software should arrange that any such details are
configured prior to gpio_request() being called for those GPIOs, e.g. using
the pinctrl subsystem's mapping table, so that GPIO users need not be aware
of these details.
Also note that it's your responsibility to have stopped using a GPIO Also note that it's your responsibility to have stopped using a GPIO
before you free it. before you free it.
...@@ -302,6 +319,8 @@ where 'flags' is currently defined to specify the following properties: ...@@ -302,6 +319,8 @@ where 'flags' is currently defined to specify the following properties:
* GPIOF_INIT_LOW - as output, set initial level to LOW * GPIOF_INIT_LOW - as output, set initial level to LOW
* GPIOF_INIT_HIGH - as output, set initial level to HIGH * GPIOF_INIT_HIGH - as output, set initial level to HIGH
* GPIOF_OPEN_DRAIN - gpio pin is open drain type.
* GPIOF_OPEN_SOURCE - gpio pin is open source type.
since GPIOF_INIT_* are only valid when configured as output, so group valid since GPIOF_INIT_* are only valid when configured as output, so group valid
combinations as: combinations as:
...@@ -310,8 +329,19 @@ combinations as: ...@@ -310,8 +329,19 @@ combinations as:
* GPIOF_OUT_INIT_LOW - configured as output, initial level LOW * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW
* GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH
In the future, these flags can be extended to support more properties such When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is
as open-drain status. open drain type. Such pins will not be driven to 1 in output mode. It is
require to connect pull-up on such pins. By enabling this flag, gpio lib will
make the direction to input when it is asked to set value of 1 in output mode
to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode.
When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is
open source type. Such pins will not be driven to 0 in output mode. It is
require to connect pull-down on such pin. By enabling this flag, gpio lib will
make the direction to input when it is asked to set value of 0 in output mode
to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
In the future, these flags can be extended to support more properties.
Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
introduced to encapsulate all three fields as: introduced to encapsulate all three fields as:
......
...@@ -218,30 +218,14 @@ extern void omap_set_gpio_debounce(int gpio, int enable); ...@@ -218,30 +218,14 @@ extern void omap_set_gpio_debounce(int gpio, int enable);
extern void omap_set_gpio_debounce_time(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Wrappers for "new style" GPIO calls, using the new infrastructure /*
* Wrappers for "new style" GPIO calls, using the new infrastructure
* which lets us plug in FPGA, I2C, and other implementations. * which lets us plug in FPGA, I2C, and other implementations.
* * *
* The original OMAP-specific calls should eventually be removed. * The original OMAP-specific calls should eventually be removed.
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>
static inline int irq_to_gpio(unsigned irq)
{
int tmp;
/* omap1 SOC mpuio */
if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
/* SOC gpio */
tmp = irq - IH_GPIO_BASE;
if (tmp < OMAP_MAX_GPIO_LINES)
return tmp;
/* we don't supply reverse mappings for non-SOC gpios */
return -EIO;
}
#endif #endif
...@@ -208,16 +208,19 @@ serial@b,0 { ...@@ -208,16 +208,19 @@ serial@b,0 {
interrupts = <14 1>; interrupts = <14 1>;
}; };
gpio@b,1 { pcigpio: gpio@b,1 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "pci8086,2e67.2", compatible = "pci8086,2e67.2",
"pci8086,2e67", "pci8086,2e67",
"pciclassff0000", "pciclassff0000",
"pciclassff00"; "pciclassff00";
#gpio-cells = <2>;
reg = <0x15900 0x0 0x0 0x0 0x0>; reg = <0x15900 0x0 0x0 0x0 0x0>;
interrupts = <15 1>; interrupts = <15 1>;
interrupt-controller;
gpio-controller; gpio-controller;
intel,muxctl = <0>;
}; };
i2c-controller@b,2 { i2c-controller@b,2 {
......
...@@ -236,6 +236,12 @@ config GPIO_MAX732X_IRQ ...@@ -236,6 +236,12 @@ config GPIO_MAX732X_IRQ
Say yes here to enable the max732x to be used as an interrupt Say yes here to enable the max732x to be used as an interrupt
controller. It requires the driver to be built in the kernel. 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 config GPIO_PCA953X
tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
depends on I2C depends on I2C
...@@ -422,6 +428,14 @@ config GPIO_ML_IOH ...@@ -422,6 +428,14 @@ config GPIO_ML_IOH
Hub) which is for IVI(In-Vehicle Infotainment) use. Hub) which is for IVI(In-Vehicle Infotainment) use.
This driver can access the IOH's GPIO device. This driver can access the IOH's GPIO device.
config GPIO_SODAVILLE
bool "Intel Sodaville GPIO support"
depends on X86 && PCI && OF && BROKEN
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
help
Say Y here to support Intel Sodaville GPIO.
config GPIO_TIMBERDALE config GPIO_TIMBERDALE
bool "Support for timberdale GPIO IP" bool "Support for timberdale GPIO IP"
depends on MFD_TIMBERDALE && HAS_IOMEM depends on MFD_TIMBERDALE && HAS_IOMEM
......
...@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o ...@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.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_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
...@@ -46,6 +47,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o ...@@ -46,6 +47,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.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_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
......
...@@ -313,10 +313,16 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) ...@@ -313,10 +313,16 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
return -ENODEV; return -ENODEV;
} }
static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger) static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
{ {
struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); struct davinci_gpio_controller *d;
u32 mask = (u32) irq_data_get_irq_handler_data(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)) if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL; return -EINVAL;
...@@ -380,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void) ...@@ -380,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void)
* IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
*/ */
if (soc_info->gpio_unbanked) { if (soc_info->gpio_unbanked) {
static struct irq_chip gpio_irqchip_unbanked; static struct irq_chip_type gpio_unbanked;
/* pass "bank 0" GPIO IRQs to AINTC */ /* pass "bank 0" GPIO IRQs to AINTC */
chips[0].chip.to_irq = gpio_to_irq_unbanked; chips[0].chip.to_irq = gpio_to_irq_unbanked;
...@@ -388,9 +394,10 @@ static int __init davinci_gpio_irq_setup(void) ...@@ -388,9 +394,10 @@ static int __init davinci_gpio_irq_setup(void)
/* AINTC handles mask/unmask; GPIO handles triggering */ /* AINTC handles mask/unmask; GPIO handles triggering */
irq = bank_irq; irq = bank_irq;
gpio_irqchip_unbanked = *irq_get_chip(irq); gpio_unbanked = *container_of(irq_get_chip(irq),
gpio_irqchip_unbanked.name = "GPIO-AINTC"; struct irq_chip_type, chip);
gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked; gpio_unbanked.chip.name = "GPIO-AINTC";
gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
/* default trigger: both edges */ /* default trigger: both edges */
g = gpio2regs(0); g = gpio2regs(0);
...@@ -399,9 +406,8 @@ static int __init davinci_gpio_irq_setup(void) ...@@ -399,9 +406,8 @@ static int __init davinci_gpio_irq_setup(void)
/* set the direct IRQs up to use that irqchip */ /* set the direct IRQs up to use that irqchip */
for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
irq_set_chip(irq, &gpio_irqchip_unbanked); irq_set_chip(irq, &gpio_unbanked.chip);
irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); irq_set_handler_data(irq, &chips[gpio / 32]);
irq_set_chip_data(irq, (__force void *)g);
irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
} }
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -65,11 +63,6 @@ static void ep93xx_gpio_update_int_params(unsigned port) ...@@ -65,11 +63,6 @@ static void ep93xx_gpio_update_int_params(unsigned port)
EP93XX_GPIO_REG(int_en_register_offset[port])); EP93XX_GPIO_REG(int_en_register_offset[port]));
} }
static inline void ep93xx_gpio_int_mask(unsigned line)
{
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
}
static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable) static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
{ {
int line = irq_to_gpio(irq); int line = irq_to_gpio(irq);
...@@ -212,7 +205,6 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type) ...@@ -212,7 +205,6 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
handler = handle_edge_irq; handler = handle_edge_irq;
break; break;
default: default:
pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
return -EINVAL; return -EINVAL;
} }
......
...@@ -59,12 +59,14 @@ ...@@ -59,12 +59,14 @@
#define GPO3_PIN_TO_BIT(x) (1 << (x)) #define GPO3_PIN_TO_BIT(x) (1 << (x))
#define GPIO012_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) #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_SHIFT(x) ((x) == 5 ? 24 : 10 + (x))
#define GPIO3_PIN_IN_SEL(x, y) ((x) >> GPIO3_PIN_IN_SHIFT(y)) #define GPIO3_PIN_IN_SEL(x, y) (((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
#define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1) #define GPIO3_PIN5_IN_SEL(x) (((x) >> 24) & 1)
#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1) #define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
#define GPO3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
struct gpio_regs { struct gpio_regs {
void __iomem *inp_state; void __iomem *inp_state;
void __iomem *outp_state;
void __iomem *outp_set; void __iomem *outp_set;
void __iomem *outp_clr; void __iomem *outp_clr;
void __iomem *dir_set; void __iomem *dir_set;
...@@ -145,6 +147,7 @@ static struct gpio_regs gpio_grp_regs_p2 = { ...@@ -145,6 +147,7 @@ static struct gpio_regs gpio_grp_regs_p2 = {
static struct gpio_regs gpio_grp_regs_p3 = { static struct gpio_regs gpio_grp_regs_p3 = {
.inp_state = LPC32XX_GPIO_P3_INP_STATE, .inp_state = LPC32XX_GPIO_P3_INP_STATE,
.outp_state = LPC32XX_GPIO_P3_OUTP_STATE,
.outp_set = LPC32XX_GPIO_P3_OUTP_SET, .outp_set = LPC32XX_GPIO_P3_OUTP_SET,
.outp_clr = LPC32XX_GPIO_P3_OUTP_CLR, .outp_clr = LPC32XX_GPIO_P3_OUTP_CLR,
.dir_set = LPC32XX_GPIO_P2_DIR_SET, .dir_set = LPC32XX_GPIO_P2_DIR_SET,
...@@ -240,6 +243,12 @@ static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, ...@@ -240,6 +243,12 @@ static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), 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. * GENERIC_GPIO primitives.
*/ */
...@@ -340,6 +349,13 @@ static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin, ...@@ -340,6 +349,13 @@ static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
__set_gpo_level_p3(group, pin, value); __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) static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
{ {
if (pin < chip->ngpio) if (pin < chip->ngpio)
...@@ -427,6 +443,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { ...@@ -427,6 +443,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
.label = "gpo_p3", .label = "gpo_p3",
.direction_output = lpc32xx_gpio_dir_out_always, .direction_output = lpc32xx_gpio_dir_out_always,
.set = lpc32xx_gpo_set_value, .set = lpc32xx_gpo_set_value,
.get = lpc32xx_gpo_get_value,
.request = lpc32xx_gpio_request, .request = lpc32xx_gpio_request,
.base = LPC32XX_GPO_P3_GRP, .base = LPC32XX_GPO_P3_GRP,
.ngpio = LPC32XX_GPO_P3_MAX, .ngpio = LPC32XX_GPO_P3_MAX,
......
/*
* 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, &reg, &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, &reg, &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");
This diff is collapsed.
...@@ -352,7 +352,12 @@ static int pl061_resume(struct device *dev) ...@@ -352,7 +352,12 @@ static int pl061_resume(struct device *dev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume); static const struct dev_pm_ops pl061_dev_pm_ops = {
.suspend = pl061_suspend,
.resume = pl061_resume,
.freeze = pl061_suspend,
.restore = pl061_resume,
};
#endif #endif
static struct amba_id pl061_ids[] = { static struct amba_id pl061_ids[] = {
......
/*
* 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 irq_offs = d->irq - sd->irq_base;
u32 reg;
if (irq_offs < 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 * (irq_offs % 8));
break;
case IRQ_TYPE_LEVEL_LOW:
reg |= BIT(4 * (irq_offs % 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(sd->irq_base + 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 = {
.dt_translate = 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;
sd->id.irq_base = sd->irq_base;
sd->id.of_node = of_node_get(pdev->dev.of_node);
sd->id.ops = &irq_domain_sdv_ops;
/*
* 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);
irq_domain_add(&sd->id);
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);
irq_domain_del(&sd->id);
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");
...@@ -54,7 +54,7 @@ static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -54,7 +54,7 @@ static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
if (ret < 0) if (ret < 0)
return ret; return ret;
return ret & mask; return !!(ret & mask);
} }
static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
......
...@@ -109,11 +109,13 @@ void tegra_gpio_enable(int gpio) ...@@ -109,11 +109,13 @@ void tegra_gpio_enable(int gpio)
{ {
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
} }
EXPORT_SYMBOL_GPL(tegra_gpio_enable);
void tegra_gpio_disable(int gpio) void tegra_gpio_disable(int gpio)
{ {
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); 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) static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
...@@ -459,7 +461,7 @@ static int __init tegra_gpio_init(void) ...@@ -459,7 +461,7 @@ static int __init tegra_gpio_init(void)
} }
postcore_initcall(tegra_gpio_init); postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num) void tegra_gpio_config(struct tegra_gpio_table *table, int num)
{ {
int i; int i;
......
...@@ -69,6 +69,7 @@ static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) ...@@ -69,6 +69,7 @@ static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
{ {
int ret; int ret;
struct tps65910_board *board_data;
if (!gpio_base) if (!gpio_base)
return; return;
...@@ -80,10 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) ...@@ -80,10 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
switch(tps65910_chip_id(tps65910)) { switch(tps65910_chip_id(tps65910)) {
case TPS65910: case TPS65910:
tps65910->gpio.ngpio = 6; tps65910->gpio.ngpio = TPS65910_NUM_GPIO;
break; break;
case TPS65911: case TPS65911:
tps65910->gpio.ngpio = 9; tps65910->gpio.ngpio = TPS65911_NUM_GPIO;
break; break;
default: default:
return; return;
...@@ -95,6 +96,21 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) ...@@ -95,6 +96,21 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
tps65910->gpio.set = tps65910_gpio_set; tps65910->gpio.set = tps65910_gpio_set;
tps65910->gpio.get = tps65910_gpio_get; 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); ret = gpiochip_add(&tps65910->gpio);
if (ret) if (ret)
......
...@@ -58,6 +58,8 @@ struct gpio_desc { ...@@ -58,6 +58,8 @@ struct gpio_desc {
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */ #define FLAG_TRIG_FALL 5 /* trigger on falling edge */
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */ #define FLAG_TRIG_RISE 6 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ #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 ID_SHIFT 16 /* add new flags before this one */
...@@ -873,6 +875,7 @@ void gpio_unexport(unsigned gpio) ...@@ -873,6 +875,7 @@ void gpio_unexport(unsigned gpio)
{ {
struct gpio_desc *desc; struct gpio_desc *desc;
int status = 0; int status = 0;
struct device *dev = NULL;
if (!gpio_is_valid(gpio)) { if (!gpio_is_valid(gpio)) {
status = -EINVAL; status = -EINVAL;
...@@ -884,19 +887,20 @@ void gpio_unexport(unsigned gpio) ...@@ -884,19 +887,20 @@ void gpio_unexport(unsigned gpio)
desc = &gpio_desc[gpio]; desc = &gpio_desc[gpio];
if (test_bit(FLAG_EXPORT, &desc->flags)) { if (test_bit(FLAG_EXPORT, &desc->flags)) {
struct device *dev = NULL;
dev = class_find_device(&gpio_class, NULL, desc, match_export); dev = class_find_device(&gpio_class, NULL, desc, match_export);
if (dev) { if (dev) {
gpio_setup_irq(desc, dev, 0); gpio_setup_irq(desc, dev, 0);
clear_bit(FLAG_EXPORT, &desc->flags); clear_bit(FLAG_EXPORT, &desc->flags);
put_device(dev);
device_unregister(dev);
} else } else
status = -ENODEV; status = -ENODEV;
} }
mutex_unlock(&sysfs_lock); mutex_unlock(&sysfs_lock);
if (dev) {
device_unregister(dev);
put_device(dev);
}
done: done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
...@@ -1150,8 +1154,9 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); ...@@ -1150,8 +1154,9 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
* non-zero, this function will return to the caller and not iterate over any * non-zero, this function will return to the caller and not iterate over any
* more gpio_chips. * more gpio_chips.
*/ */
struct gpio_chip *gpiochip_find(void *data, struct gpio_chip *gpiochip_find(const void *data,
int (*match)(struct gpio_chip *chip, void *data)) int (*match)(struct gpio_chip *chip,
const void *data))
{ {
struct gpio_chip *chip = NULL; struct gpio_chip *chip = NULL;
unsigned long flags; unsigned long flags;
...@@ -1261,6 +1266,8 @@ void gpio_free(unsigned gpio) ...@@ -1261,6 +1266,8 @@ void gpio_free(unsigned gpio)
module_put(desc->chip->owner); module_put(desc->chip->owner);
clear_bit(FLAG_ACTIVE_LOW, &desc->flags); clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
clear_bit(FLAG_REQUESTED, &desc->flags); clear_bit(FLAG_REQUESTED, &desc->flags);
clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
} else } else
WARN_ON(extra_checks); WARN_ON(extra_checks);
...@@ -1282,6 +1289,12 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) ...@@ -1282,6 +1289,12 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (err) if (err)
return 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) if (flags & GPIOF_DIR_IN)
err = gpio_direction_input(gpio); err = gpio_direction_input(gpio);
else else
...@@ -1431,6 +1444,14 @@ int gpio_direction_output(unsigned gpio, int value) ...@@ -1431,6 +1444,14 @@ int gpio_direction_output(unsigned gpio, int value)
struct gpio_desc *desc = &gpio_desc[gpio]; struct gpio_desc *desc = &gpio_desc[gpio];
int status = -EINVAL; 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); spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio)) if (!gpio_is_valid(gpio))
...@@ -1560,6 +1581,7 @@ int __gpio_get_value(unsigned gpio) ...@@ -1560,6 +1581,7 @@ int __gpio_get_value(unsigned gpio)
int value; int value;
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
/* Should be using gpio_get_value_cansleep() */
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
value = chip->get ? chip->get(chip, gpio - chip->base) : 0; value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
trace_gpio_value(gpio, 1, value); trace_gpio_value(gpio, 1, value);
...@@ -1567,6 +1589,57 @@ int __gpio_get_value(unsigned gpio) ...@@ -1567,6 +1589,57 @@ int __gpio_get_value(unsigned gpio)
} }
EXPORT_SYMBOL_GPL(__gpio_get_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_set_value() - assign a gpio's value
* @gpio: gpio whose value will be assigned * @gpio: gpio whose value will be assigned
...@@ -1581,8 +1654,14 @@ void __gpio_set_value(unsigned gpio, int value) ...@@ -1581,8 +1654,14 @@ void __gpio_set_value(unsigned gpio, int value)
struct gpio_chip *chip; struct gpio_chip *chip;
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
/* Should be using gpio_set_value_cansleep() */
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
trace_gpio_value(gpio, 0, value); 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); chip->set(chip, gpio - chip->base, value);
} }
EXPORT_SYMBOL_GPL(__gpio_set_value); EXPORT_SYMBOL_GPL(__gpio_set_value);
...@@ -1650,6 +1729,11 @@ void gpio_set_value_cansleep(unsigned gpio, int value) ...@@ -1650,6 +1729,11 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
trace_gpio_value(gpio, 0, value); 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); chip->set(chip, gpio - chip->base, value);
} }
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
......
...@@ -78,8 +78,9 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, ...@@ -78,8 +78,9 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
EXPORT_SYMBOL(of_get_named_gpio_flags); EXPORT_SYMBOL(of_get_named_gpio_flags);
/** /**
* of_gpio_count - Count GPIOs for a device * of_gpio_named_count - Count GPIOs for a device
* @np: device node to count GPIOs for * @np: device node to count GPIOs for
* @propname: property name containing gpio specifier(s)
* *
* The function returns the count of GPIOs specified for a node. * The function returns the count of GPIOs specified for a node.
* *
...@@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags); ...@@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags);
* defines four GPIOs (so this function will return 4), two of which * defines four GPIOs (so this function will return 4), two of which
* are not specified. * are not specified.
*/ */
unsigned int of_gpio_count(struct device_node *np) unsigned int of_gpio_named_count(struct device_node *np, const char* propname)
{ {
unsigned int cnt = 0; unsigned int cnt = 0;
do { do {
int ret; int ret;
ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells", ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
cnt, NULL); cnt, NULL);
/* A hole in the gpios = <> counts anyway. */ /* A hole in the gpios = <> counts anyway. */
if (ret < 0 && ret != -EEXIST) if (ret < 0 && ret != -EEXIST)
...@@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np) ...@@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np)
return cnt; return cnt;
} }
EXPORT_SYMBOL(of_gpio_count); EXPORT_SYMBOL(of_gpio_named_count);
/** /**
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
...@@ -228,7 +229,7 @@ void of_gpiochip_remove(struct gpio_chip *chip) ...@@ -228,7 +229,7 @@ void of_gpiochip_remove(struct gpio_chip *chip)
} }
/* Private function for resolving node pointer to gpio_chip */ /* Private function for resolving node pointer to gpio_chip */
static int of_gpiochip_is_match(struct gpio_chip *chip, void *data) static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
{ {
return chip->of_node == data; return chip->of_node == data;
} }
......
...@@ -142,9 +142,9 @@ extern int __must_check gpiochip_reserve(int start, int ngpio); ...@@ -142,9 +142,9 @@ extern int __must_check gpiochip_reserve(int start, int ngpio);
/* add/remove chips */ /* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip); extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip); extern int __must_check gpiochip_remove(struct gpio_chip *chip);
extern struct gpio_chip *gpiochip_find(void *data, extern struct gpio_chip *gpiochip_find(const void *data,
int (*match)(struct gpio_chip *chip, int (*match)(struct gpio_chip *chip,
void *data)); const void *data));
/* Always use the library code for GPIO management calls, /* Always use the library code for GPIO management calls,
......
...@@ -14,6 +14,12 @@ ...@@ -14,6 +14,12 @@
#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
/* Gpio pin is open drain */
#define GPIOF_OPEN_DRAIN (1 << 2)
/* Gpio pin is open source */
#define GPIOF_OPEN_SOURCE (1 << 3)
/** /**
* struct gpio - a structure describing a GPIO with configuration * struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number * @gpio: the GPIO number
......
...@@ -659,6 +659,8 @@ ...@@ -659,6 +659,8 @@
/*Register GPIO (0x80) register.RegisterDescription */ /*Register GPIO (0x80) register.RegisterDescription */
#define GPIO_SLEEP_MASK 0x80
#define GPIO_SLEEP_SHIFT 7
#define GPIO_DEB_MASK 0x10 #define GPIO_DEB_MASK 0x10
#define GPIO_DEB_SHIFT 4 #define GPIO_DEB_SHIFT 4
#define GPIO_PUEN_MASK 0x08 #define GPIO_PUEN_MASK 0x08
...@@ -742,6 +744,11 @@ ...@@ -742,6 +744,11 @@
#define TPS65910_GPIO_STS BIT(1) #define TPS65910_GPIO_STS BIT(1)
#define TPS65910_GPIO_SET BIT(0) #define TPS65910_GPIO_SET BIT(0)
/* Max number of TPS65910/11 GPIOs */
#define TPS65910_NUM_GPIO 6
#define TPS65911_NUM_GPIO 9
#define TPS6591X_MAX_NUM_GPIO 9
/* Regulator Index Definitions */ /* Regulator Index Definitions */
#define TPS65910_REG_VRTC 0 #define TPS65910_REG_VRTC 0
#define TPS65910_REG_VIO 1 #define TPS65910_REG_VIO 1
...@@ -787,6 +794,7 @@ struct tps65910_board { ...@@ -787,6 +794,7 @@ struct tps65910_board {
int irq_base; int irq_base;
int vmbch_threshold; int vmbch_threshold;
int vmbch2_threshold; int vmbch2_threshold;
bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS]; unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
}; };
......
...@@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) ...@@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
extern int of_get_named_gpio_flags(struct device_node *np, extern int of_get_named_gpio_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags); const char *list_name, int index, enum of_gpio_flags *flags);
extern unsigned int of_gpio_count(struct device_node *np); extern unsigned int of_gpio_named_count(struct device_node *np,
const char* propname);
extern int of_mm_gpiochip_add(struct device_node *np, extern int of_mm_gpiochip_add(struct device_node *np,
struct of_mm_gpio_chip *mm_gc); struct of_mm_gpio_chip *mm_gc);
...@@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np, ...@@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
return -ENOSYS; return -ENOSYS;
} }
static inline unsigned int of_gpio_count(struct device_node *np) static inline unsigned int of_gpio_named_count(struct device_node *np,
const char* propname)
{ {
return 0; return 0;
} }
...@@ -88,6 +90,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { } ...@@ -88,6 +90,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */ #endif /* CONFIG_OF_GPIO */
/**
* of_gpio_count - Count GPIOs for a device
* @np: device node to count GPIOs for
*
* The function returns the count of GPIOs specified for a node.
*
* Note that the empty GPIO specifiers counts too. For example,
*
* gpios = <0
* &pio1 1 2
* 0
* &pio2 3 4>;
*
* defines four GPIOs (so this function will return 4), two of which
* are not specified.
*/
static inline unsigned int of_gpio_count(struct device_node *np)
{
return of_gpio_named_count(np, "gpios");
}
/** /**
* of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
* @np: device node to get GPIO from * @np: device node to get GPIO from
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment