Commit 04830fcc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6

* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6:
  gpio/pch_gpio: Support new device ML7223
  gpio: make gpio_{request,free}_array gpio array parameter const
  GPIO: OMAP: move to drivers/gpio
  GPIO: OMAP: move register offset defines into <plat/gpio.h>
  gpio: Convert gpio_is_valid to return bool
  gpio: Move the s5pc100 GPIO to drivers/gpio
  gpio: Move the s5pv210 GPIO to drivers/gpio
  gpio: Move the exynos4 GPIO to drivers/gpio
  gpio: Move to Samsung common GPIO library to drivers/gpio
  gpio/nomadik: add function to read GPIO pull down status
  gpio/nomadik: show all pins in debug
  gpio: move Nomadik GPIO driver to drivers/gpio
  gpio: move U300 GPIO driver to drivers/gpio
  langwell_gpio: add runtime pm support
  gpio/pca953x: Add support for pca9574 and pca9575 devices
  gpio/cs5535: Show explicit dependency between gpio_cs5535 and mfd_cs5535
parents 571503e1 1486a740
...@@ -13,7 +13,7 @@ obj- := ...@@ -13,7 +13,7 @@ obj- :=
# Core support for EXYNOS4 system # Core support for EXYNOS4 system
obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o
obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o gpiolib.o irq-eint.o dma.o obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o
obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o
......
...@@ -6,7 +6,6 @@ config MACH_NOMADIK_8815NHK ...@@ -6,7 +6,6 @@ config MACH_NOMADIK_8815NHK
bool "ST 8815 Nomadik Hardware Kit (evaluation board)" bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
select NOMADIK_8815 select NOMADIK_8815
select HAS_MTU select HAS_MTU
select NOMADIK_GPIO
endmenu endmenu
......
...@@ -11,7 +11,7 @@ obj- := ...@@ -11,7 +11,7 @@ obj- :=
# Core support for S5PC100 system # Core support for S5PC100 system
obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o
obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o
obj-$(CONFIG_CPU_S5PC100) += dma.o obj-$(CONFIG_CPU_S5PC100) += dma.o
......
...@@ -12,7 +12,7 @@ obj- := ...@@ -12,7 +12,7 @@ obj- :=
# Core support for S5PV210 system # Core support for S5PV210 system
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o
obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the linux kernel, U300 machine. # Makefile for the linux kernel, U300 machine.
# #
obj-y := core.o clock.o timer.o gpio.o padmux.o obj-y := core.o clock.o timer.o padmux.o
obj-m := obj-m :=
obj-n := obj-n :=
obj- := obj- :=
......
...@@ -5,7 +5,6 @@ config UX500_SOC_COMMON ...@@ -5,7 +5,6 @@ config UX500_SOC_COMMON
default y default y
select ARM_GIC select ARM_GIC
select HAS_MTU select HAS_MTU
select NOMADIK_GPIO
select ARM_ERRATA_753970 select ARM_ERRATA_753970
menu "Ux500 SoC" menu "Ux500 SoC"
......
...@@ -21,9 +21,4 @@ config HAS_MTU ...@@ -21,9 +21,4 @@ config HAS_MTU
to multiple interrupt generating programmable to multiple interrupt generating programmable
32-bit free running decrementing counters. 32-bit free running decrementing counters.
config NOMADIK_GPIO
bool
help
Support for the Nomadik GPIO controller.
endif endif
...@@ -3,4 +3,3 @@ ...@@ -3,4 +3,3 @@
# Licensed under GPLv2 # Licensed under GPLv2
obj-$(CONFIG_HAS_MTU) += timer.o obj-$(CONFIG_HAS_MTU) += timer.o
obj-$(CONFIG_NOMADIK_GPIO) += gpio.o
...@@ -78,6 +78,8 @@ extern int nmk_gpio_get_mode(int gpio); ...@@ -78,6 +78,8 @@ extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(void); extern void nmk_gpio_wakeups_suspend(void);
extern void nmk_gpio_wakeups_resume(void); extern void nmk_gpio_wakeups_resume(void);
extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
/* /*
* Platform data to register a block: only the initial gpio/irq number. * Platform data to register a block: only the initial gpio/irq number.
*/ */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
# Common support # Common support
obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \ obj-y := common.o sram.o clock.o devices.o dma.o mux.o \
usb.o fb.o io.o counter_32k.o usb.o fb.o io.o counter_32k.o
obj-m := obj-m :=
obj-n := obj-n :=
......
...@@ -52,6 +52,109 @@ ...@@ -52,6 +52,109 @@
#define OMAP34XX_NR_GPIOS 6 #define OMAP34XX_NR_GPIOS 6
/*
* OMAP1510 GPIO registers
*/
#define OMAP1510_GPIO_DATA_INPUT 0x00
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
#define OMAP1510_GPIO_DIR_CONTROL 0x08
#define OMAP1510_GPIO_INT_CONTROL 0x0c
#define OMAP1510_GPIO_INT_MASK 0x10
#define OMAP1510_GPIO_INT_STATUS 0x14
#define OMAP1510_GPIO_PIN_CONTROL 0x18
#define OMAP1510_IH_GPIO_BASE 64
/*
* OMAP1610 specific GPIO registers
*/
#define OMAP1610_GPIO_REVISION 0x0000
#define OMAP1610_GPIO_SYSCONFIG 0x0010
#define OMAP1610_GPIO_SYSSTATUS 0x0014
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
#define OMAP1610_GPIO_IRQENABLE1 0x001c
#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
#define OMAP1610_GPIO_DATAIN 0x002c
#define OMAP1610_GPIO_DATAOUT 0x0030
#define OMAP1610_GPIO_DIRECTION 0x0034
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
/*
* OMAP7XX specific GPIO registers
*/
#define OMAP7XX_GPIO_DATA_INPUT 0x00
#define OMAP7XX_GPIO_DATA_OUTPUT 0x04
#define OMAP7XX_GPIO_DIR_CONTROL 0x08
#define OMAP7XX_GPIO_INT_CONTROL 0x0c
#define OMAP7XX_GPIO_INT_MASK 0x10
#define OMAP7XX_GPIO_INT_STATUS 0x14
/*
* omap2+ specific GPIO registers
*/
#define OMAP24XX_GPIO_REVISION 0x0000
#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
#define OMAP24XX_GPIO_IRQENABLE2 0x002c
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
#define OMAP24XX_GPIO_WAKE_EN 0x0020
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
#define OMAP24XX_GPIO_DATAOUT 0x003c
#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
#define OMAP24XX_GPIO_RISINGDETECT 0x0048
#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050
#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054
#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
#define OMAP24XX_GPIO_SETWKUENA 0x0084
#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
#define OMAP24XX_GPIO_SETDATAOUT 0x0094
#define OMAP4_GPIO_REVISION 0x0000
#define OMAP4_GPIO_EOI 0x0020
#define OMAP4_GPIO_IRQSTATUSRAW0 0x0024
#define OMAP4_GPIO_IRQSTATUSRAW1 0x0028
#define OMAP4_GPIO_IRQSTATUS0 0x002c
#define OMAP4_GPIO_IRQSTATUS1 0x0030
#define OMAP4_GPIO_IRQSTATUSSET0 0x0034
#define OMAP4_GPIO_IRQSTATUSSET1 0x0038
#define OMAP4_GPIO_IRQSTATUSCLR0 0x003c
#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040
#define OMAP4_GPIO_IRQWAKEN0 0x0044
#define OMAP4_GPIO_IRQWAKEN1 0x0048
#define OMAP4_GPIO_IRQENABLE1 0x011c
#define OMAP4_GPIO_WAKE_EN 0x0120
#define OMAP4_GPIO_IRQSTATUS2 0x0128
#define OMAP4_GPIO_IRQENABLE2 0x012c
#define OMAP4_GPIO_CTRL 0x0130
#define OMAP4_GPIO_OE 0x0134
#define OMAP4_GPIO_DATAIN 0x0138
#define OMAP4_GPIO_DATAOUT 0x013c
#define OMAP4_GPIO_LEVELDETECT0 0x0140
#define OMAP4_GPIO_LEVELDETECT1 0x0144
#define OMAP4_GPIO_RISINGDETECT 0x0148
#define OMAP4_GPIO_FALLINGDETECT 0x014c
#define OMAP4_GPIO_DEBOUNCENABLE 0x0150
#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154
#define OMAP4_GPIO_CLEARIRQENABLE1 0x0160
#define OMAP4_GPIO_SETIRQENABLE1 0x0164
#define OMAP4_GPIO_CLEARWKUENA 0x0180
#define OMAP4_GPIO_SETWKUENA 0x0184
#define OMAP4_GPIO_CLEARDATAOUT 0x0190
#define OMAP4_GPIO_SETDATAOUT 0x0194
#define OMAP_MPUIO(nr) (OMAP_MAX_GPIO_LINES + (nr)) #define OMAP_MPUIO(nr) (OMAP_MAX_GPIO_LINES + (nr))
#define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES) #define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES)
......
...@@ -19,7 +19,6 @@ obj-y += gpio.o ...@@ -19,7 +19,6 @@ obj-y += gpio.o
obj-y += gpio-config.o obj-y += gpio-config.o
obj-y += dev-asocdma.o obj-y += dev-asocdma.o
obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT) += gpiolib.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
......
...@@ -86,6 +86,30 @@ config GPIO_IT8761E ...@@ -86,6 +86,30 @@ config GPIO_IT8761E
help help
Say yes here to support GPIO functionality of IT8761E super I/O chip. Say yes here to support GPIO functionality of IT8761E super I/O chip.
config GPIO_EXYNOS4
bool "Samsung Exynos4 GPIO library support"
default y if CPU_EXYNOS4210
help
Say yes here to support Samsung Exynos4 series SoCs GPIO library
config GPIO_PLAT_SAMSUNG
bool "Samsung SoCs GPIO library support"
default y if SAMSUNG_GPIOLIB_4BIT
help
Say yes here to support Samsung SoCs GPIO library
config GPIO_S5PC100
bool "Samsung S5PC100 GPIO library support"
default y if CPU_S5PC100
help
Say yes here to support Samsung S5PC100 SoCs GPIO library
config GPIO_S5PV210
bool "Samsung S5PV210/S5PC110 GPIO library support"
default y if CPU_S5PV210
help
Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library
config GPIO_PL061 config GPIO_PL061
bool "PrimeCell PL061 GPIO support" bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA depends on ARM_AMBA
...@@ -303,7 +327,7 @@ comment "PCI GPIO expanders:" ...@@ -303,7 +327,7 @@ comment "PCI GPIO expanders:"
config GPIO_CS5535 config GPIO_CS5535
tristate "AMD CS5535/CS5536 GPIO support" tristate "AMD CS5535/CS5536 GPIO support"
depends on PCI && X86 && !CS5535_GPIO depends on PCI && X86 && !CS5535_GPIO && MFD_CS5535
help help
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that 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 can be used for quite a number of things. The CS5535/6 is found on
...@@ -334,13 +358,19 @@ config GPIO_LANGWELL ...@@ -334,13 +358,19 @@ config GPIO_LANGWELL
Say Y here to support Intel Langwell/Penwell GPIO. Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH config GPIO_PCH
tristate "PCH GPIO of Intel Topcliff" tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
depends on PCI && X86 depends on PCI && X86
help help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor. which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device. This driver can access PCH GPIO device.
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
Output Hub), ML7223.
ML7223 IOH is for MP(Media Phone) use.
ML7223 is companion chip for Intel Atom E6xx series.
ML7223 is completely compatible for Intel EG20T PCH.
config GPIO_ML_IOH config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on PCI depends on PCI
......
...@@ -8,6 +8,10 @@ obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o ...@@ -8,6 +8,10 @@ obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
obj-$(CONFIG_GPIO_MAX730X) += max730x.o obj-$(CONFIG_GPIO_MAX730X) += max730x.o
obj-$(CONFIG_GPIO_MAX7300) += max7300.o obj-$(CONFIG_GPIO_MAX7300) += max7300.o
...@@ -16,6 +20,7 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o ...@@ -16,6 +20,7 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o obj-$(CONFIG_GPIO_MC33880) += mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_74X164) += 74x164.o obj-$(CONFIG_GPIO_74X164) += 74x164.o
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_PCH) += pch_gpio.o obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
...@@ -34,6 +39,8 @@ obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o ...@@ -34,6 +39,8 @@ obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
obj-$(CONFIG_GPIO_SCH) += sch_gpio.o obj-$(CONFIG_GPIO_SCH) += sch_gpio.o
obj-$(CONFIG_MACH_U300) += gpio-u300.o
obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
obj-$(CONFIG_GPIO_SX150X) += sx150x.o obj-$(CONFIG_GPIO_SX150X) += sx150x.o
......
...@@ -57,6 +57,7 @@ struct nmk_gpio_chip { ...@@ -57,6 +57,7 @@ struct nmk_gpio_chip {
u32 fwimsc; u32 fwimsc;
u32 slpm; u32 slpm;
u32 enabled; u32 enabled;
u32 pull_up;
}; };
static struct nmk_gpio_chip * static struct nmk_gpio_chip *
...@@ -103,16 +104,22 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, ...@@ -103,16 +104,22 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
u32 pdis; u32 pdis;
pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS); pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
if (pull == NMK_GPIO_PULL_NONE) if (pull == NMK_GPIO_PULL_NONE) {
pdis |= bit; pdis |= bit;
else nmk_chip->pull_up &= ~bit;
} else {
pdis &= ~bit; pdis &= ~bit;
}
writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
if (pull == NMK_GPIO_PULL_UP) if (pull == NMK_GPIO_PULL_UP) {
nmk_chip->pull_up |= bit;
writel(bit, nmk_chip->addr + NMK_GPIO_DATS); writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
else if (pull == NMK_GPIO_PULL_DOWN) } else if (pull == NMK_GPIO_PULL_DOWN) {
nmk_chip->pull_up &= ~bit;
writel(bit, nmk_chip->addr + NMK_GPIO_DATC); writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
}
} }
static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
...@@ -811,20 +818,43 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -811,20 +818,43 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
bool pull; bool pull;
u32 bit = 1 << i; u32 bit = 1 << i;
if (!label)
continue;
is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit; is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
mode = nmk_gpio_get_mode(gpio); mode = nmk_gpio_get_mode(gpio);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
gpio, label, gpio, label ?: "(none)",
is_out ? "out" : "in ", is_out ? "out" : "in ",
chip->get chip->get
? (chip->get(chip, i) ? "hi" : "lo") ? (chip->get(chip, i) ? "hi" : "lo")
: "? ", : "? ",
(mode < 0) ? "unknown" : modes[mode], (mode < 0) ? "unknown" : modes[mode],
pull ? "pull" : "none"); 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"); seq_printf(s, "\n");
} }
} }
...@@ -898,6 +928,25 @@ void nmk_gpio_wakeups_resume(void) ...@@ -898,6 +928,25 @@ void nmk_gpio_wakeups_resume(void)
} }
} }
/*
* 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) static int __devinit nmk_gpio_probe(struct platform_device *dev)
{ {
struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
......
/* /*
* linux/arch/arm/plat-omap/gpio.c
*
* Support functions for OMAP GPIO * Support functions for OMAP GPIO
* *
* Copyright (C) 2003-2005 Nokia Corporation * Copyright (C) 2003-2005 Nokia Corporation
...@@ -30,109 +28,6 @@ ...@@ -30,109 +28,6 @@
#include <mach/gpio.h> #include <mach/gpio.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
/*
* OMAP1510 GPIO registers
*/
#define OMAP1510_GPIO_DATA_INPUT 0x00
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
#define OMAP1510_GPIO_DIR_CONTROL 0x08
#define OMAP1510_GPIO_INT_CONTROL 0x0c
#define OMAP1510_GPIO_INT_MASK 0x10
#define OMAP1510_GPIO_INT_STATUS 0x14
#define OMAP1510_GPIO_PIN_CONTROL 0x18
#define OMAP1510_IH_GPIO_BASE 64
/*
* OMAP1610 specific GPIO registers
*/
#define OMAP1610_GPIO_REVISION 0x0000
#define OMAP1610_GPIO_SYSCONFIG 0x0010
#define OMAP1610_GPIO_SYSSTATUS 0x0014
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
#define OMAP1610_GPIO_IRQENABLE1 0x001c
#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
#define OMAP1610_GPIO_DATAIN 0x002c
#define OMAP1610_GPIO_DATAOUT 0x0030
#define OMAP1610_GPIO_DIRECTION 0x0034
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
/*
* OMAP7XX specific GPIO registers
*/
#define OMAP7XX_GPIO_DATA_INPUT 0x00
#define OMAP7XX_GPIO_DATA_OUTPUT 0x04
#define OMAP7XX_GPIO_DIR_CONTROL 0x08
#define OMAP7XX_GPIO_INT_CONTROL 0x0c
#define OMAP7XX_GPIO_INT_MASK 0x10
#define OMAP7XX_GPIO_INT_STATUS 0x14
/*
* omap2+ specific GPIO registers
*/
#define OMAP24XX_GPIO_REVISION 0x0000
#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
#define OMAP24XX_GPIO_IRQENABLE2 0x002c
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
#define OMAP24XX_GPIO_WAKE_EN 0x0020
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
#define OMAP24XX_GPIO_DATAOUT 0x003c
#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
#define OMAP24XX_GPIO_RISINGDETECT 0x0048
#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050
#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054
#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
#define OMAP24XX_GPIO_SETWKUENA 0x0084
#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
#define OMAP24XX_GPIO_SETDATAOUT 0x0094
#define OMAP4_GPIO_REVISION 0x0000
#define OMAP4_GPIO_EOI 0x0020
#define OMAP4_GPIO_IRQSTATUSRAW0 0x0024
#define OMAP4_GPIO_IRQSTATUSRAW1 0x0028
#define OMAP4_GPIO_IRQSTATUS0 0x002c
#define OMAP4_GPIO_IRQSTATUS1 0x0030
#define OMAP4_GPIO_IRQSTATUSSET0 0x0034
#define OMAP4_GPIO_IRQSTATUSSET1 0x0038
#define OMAP4_GPIO_IRQSTATUSCLR0 0x003c
#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040
#define OMAP4_GPIO_IRQWAKEN0 0x0044
#define OMAP4_GPIO_IRQWAKEN1 0x0048
#define OMAP4_GPIO_IRQENABLE1 0x011c
#define OMAP4_GPIO_WAKE_EN 0x0120
#define OMAP4_GPIO_IRQSTATUS2 0x0128
#define OMAP4_GPIO_IRQENABLE2 0x012c
#define OMAP4_GPIO_CTRL 0x0130
#define OMAP4_GPIO_OE 0x0134
#define OMAP4_GPIO_DATAIN 0x0138
#define OMAP4_GPIO_DATAOUT 0x013c
#define OMAP4_GPIO_LEVELDETECT0 0x0140
#define OMAP4_GPIO_LEVELDETECT1 0x0144
#define OMAP4_GPIO_RISINGDETECT 0x0148
#define OMAP4_GPIO_FALLINGDETECT 0x014c
#define OMAP4_GPIO_DEBOUNCENABLE 0x0150
#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154
#define OMAP4_GPIO_CLEARIRQENABLE1 0x0160
#define OMAP4_GPIO_SETIRQENABLE1 0x0164
#define OMAP4_GPIO_CLEARWKUENA 0x0180
#define OMAP4_GPIO_SETWKUENA 0x0184
#define OMAP4_GPIO_CLEARDATAOUT 0x0190
#define OMAP4_GPIO_SETDATAOUT 0x0194
struct gpio_bank { struct gpio_bank {
unsigned long pbase; unsigned long pbase;
void __iomem *base; void __iomem *base;
......
...@@ -1296,7 +1296,7 @@ EXPORT_SYMBOL_GPL(gpio_request_one); ...@@ -1296,7 +1296,7 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
* @array: array of the 'struct gpio' * @array: array of the 'struct gpio'
* @num: how many GPIOs in the array * @num: how many GPIOs in the array
*/ */
int gpio_request_array(struct gpio *array, size_t num) int gpio_request_array(const struct gpio *array, size_t num)
{ {
int i, err; int i, err;
...@@ -1319,7 +1319,7 @@ EXPORT_SYMBOL_GPL(gpio_request_array); ...@@ -1319,7 +1319,7 @@ EXPORT_SYMBOL_GPL(gpio_request_array);
* @array: array of the 'struct gpio' * @array: array of the 'struct gpio'
* @num: how many GPIOs in the array * @num: how many GPIOs in the array
*/ */
void gpio_free_array(struct gpio *array, size_t num) void gpio_free_array(const struct gpio *array, size_t num)
{ {
while (num--) while (num--)
gpio_free((array++)->gpio); gpio_free((array++)->gpio);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h>
/* /*
* Langwell chip has 64 pins and thus there are 2 32bit registers to control * Langwell chip has 64 pins and thus there are 2 32bit registers to control
...@@ -63,6 +64,7 @@ struct lnw_gpio { ...@@ -63,6 +64,7 @@ struct lnw_gpio {
void *reg_base; void *reg_base;
spinlock_t lock; spinlock_t lock;
unsigned irq_base; unsigned irq_base;
struct pci_dev *pdev;
}; };
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
...@@ -104,11 +106,18 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -104,11 +106,18 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
u32 value; u32 value;
unsigned long flags; unsigned long flags;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags); spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr); value = readl(gpdr);
value &= ~BIT(offset % 32); value &= ~BIT(offset % 32);
writel(value, gpdr); writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags); spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0; return 0;
} }
...@@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip, ...@@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
unsigned long flags; unsigned long flags;
lnw_gpio_set(chip, offset, value); lnw_gpio_set(chip, offset, value);
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags); spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr); value = readl(gpdr);
value |= BIT(offset % 32); value |= BIT(offset % 32);
writel(value, gpdr); writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags); spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0; return 0;
} }
...@@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type) ...@@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
if (gpio >= lnw->chip.ngpio) if (gpio >= lnw->chip.ngpio)
return -EINVAL; return -EINVAL;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags); spin_lock_irqsave(&lnw->lock, flags);
if (type & IRQ_TYPE_EDGE_RISING) if (type & IRQ_TYPE_EDGE_RISING)
value = readl(grer) | BIT(gpio % 32); value = readl(grer) | BIT(gpio % 32);
...@@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type) ...@@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
writel(value, gfer); writel(value, gfer);
spin_unlock_irqrestore(&lnw->lock, flags); spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0; return 0;
} }
...@@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) ...@@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
chip->irq_eoi(data); 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, static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
...@@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, ...@@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
lnw->chip.base = gpio_base; lnw->chip.base = gpio_base;
lnw->chip.ngpio = id->driver_data; lnw->chip.ngpio = id->driver_data;
lnw->chip.can_sleep = 0; lnw->chip.can_sleep = 0;
lnw->pdev = pdev;
pci_set_drvdata(pdev, lnw); pci_set_drvdata(pdev, lnw);
retval = gpiochip_add(&lnw->chip); retval = gpiochip_add(&lnw->chip);
if (retval) { if (retval) {
...@@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, ...@@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
} }
spin_lock_init(&lnw->lock); spin_lock_init(&lnw->lock);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
goto done; goto done;
err5: err5:
kfree(lnw); kfree(lnw);
...@@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = { ...@@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = {
.name = "langwell_gpio", .name = "langwell_gpio",
.id_table = lnw_gpio_ids, .id_table = lnw_gpio_ids,
.probe = lnw_gpio_probe, .probe = lnw_gpio_probe,
.driver = {
.pm = &lnw_gpio_pm_ops,
},
}; };
......
...@@ -29,28 +29,41 @@ ...@@ -29,28 +29,41 @@
#define PCA953X_INVERT 2 #define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3 #define PCA953X_DIRECTION 3
#define PCA953X_GPIOS 0x00FF #define PCA957X_IN 0
#define PCA953X_INT 0x0100 #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[] = { static const struct i2c_device_id pca953x_id[] = {
{ "pca9534", 8 | PCA953X_INT, }, { "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9535", 16 | PCA953X_INT, }, { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9536", 4, }, { "pca9536", 4 | PCA953X_TYPE, },
{ "pca9537", 4 | PCA953X_INT, }, { "pca9537", 4 | PCA953X_TYPE | PCA_INT, },
{ "pca9538", 8 | PCA953X_INT, }, { "pca9538", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9539", 16 | PCA953X_INT, }, { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9554", 8 | PCA953X_INT, }, { "pca9554", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9555", 16 | PCA953X_INT, }, { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9556", 8, }, { "pca9556", 8 | PCA953X_TYPE, },
{ "pca9557", 8, }, { "pca9557", 8 | PCA953X_TYPE, },
{ "pca9574", 8 | PCA957X_TYPE | PCA_INT, },
{ "max7310", 8, }, { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
{ "max7312", 16 | PCA953X_INT, },
{ "max7313", 16 | PCA953X_INT, }, { "max7310", 8 | PCA953X_TYPE, },
{ "max7315", 8 | PCA953X_INT, }, { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca6107", 8 | PCA953X_INT, }, { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
{ "tca6408", 8 | PCA953X_INT, }, { "max7315", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_INT, }, { "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
/* NYET: { "tca6424", 24, }, */ /* NYET: { "tca6424", 24, }, */
{ } { }
}; };
...@@ -75,16 +88,32 @@ struct pca953x_chip { ...@@ -75,16 +88,32 @@ struct pca953x_chip {
struct pca953x_platform_data *dyn_pdata; struct pca953x_platform_data *dyn_pdata;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
const char *const *names; const char *const *names;
int chip_type;
}; };
static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
{ {
int ret; int ret = 0;
if (chip->gpio_chip.ngpio <= 8) if (chip->gpio_chip.ngpio <= 8)
ret = i2c_smbus_write_byte_data(chip->client, reg, val); ret = i2c_smbus_write_byte_data(chip->client, reg, val);
else else {
ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); 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) { if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n"); dev_err(&chip->client->dev, "failed writing register\n");
...@@ -116,13 +145,22 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) ...@@ -116,13 +145,22 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip; struct pca953x_chip *chip;
uint16_t reg_val; uint16_t reg_val;
int ret; int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip); chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
reg_val = chip->reg_direction | (1u << off); reg_val = chip->reg_direction | (1u << off);
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
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) if (ret)
goto exit; goto exit;
...@@ -138,7 +176,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, ...@@ -138,7 +176,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
{ {
struct pca953x_chip *chip; struct pca953x_chip *chip;
uint16_t reg_val; uint16_t reg_val;
int ret; int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip); chip = container_of(gc, struct pca953x_chip, gpio_chip);
...@@ -149,7 +187,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, ...@@ -149,7 +187,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
else else
reg_val = chip->reg_output & ~(1u << off); reg_val = chip->reg_output & ~(1u << off);
ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); 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) if (ret)
goto exit; goto exit;
...@@ -157,7 +203,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, ...@@ -157,7 +203,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
/* then direction */ /* then direction */
reg_val = chip->reg_direction & ~(1u << off); reg_val = chip->reg_direction & ~(1u << off);
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); 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) if (ret)
goto exit; goto exit;
...@@ -172,12 +226,20 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) ...@@ -172,12 +226,20 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip; struct pca953x_chip *chip;
uint16_t reg_val; uint16_t reg_val;
int ret; int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip); chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val); switch (chip->chip_type) {
case PCA953X_TYPE:
offset = PCA953X_INPUT;
break;
case PCA957X_TYPE:
offset = PCA957X_IN;
break;
}
ret = pca953x_read_reg(chip, offset, &reg_val);
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
if (ret < 0) { if (ret < 0) {
/* NOTE: diagnostic already emitted; that's all we should /* NOTE: diagnostic already emitted; that's all we should
...@@ -194,7 +256,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) ...@@ -194,7 +256,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{ {
struct pca953x_chip *chip; struct pca953x_chip *chip;
uint16_t reg_val; uint16_t reg_val;
int ret; int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip); chip = container_of(gc, struct pca953x_chip, gpio_chip);
...@@ -204,7 +266,15 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) ...@@ -204,7 +266,15 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
else else
reg_val = chip->reg_output & ~(1u << off); reg_val = chip->reg_output & ~(1u << off);
ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); 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) if (ret)
goto exit; goto exit;
...@@ -322,9 +392,17 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) ...@@ -322,9 +392,17 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
uint16_t old_stat; uint16_t old_stat;
uint16_t pending; uint16_t pending;
uint16_t trigger; uint16_t trigger;
int ret; int ret, offset = 0;
ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat); 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) if (ret)
return 0; return 0;
...@@ -372,14 +450,21 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -372,14 +450,21 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
{ {
struct i2c_client *client = chip->client; struct i2c_client *client = chip->client;
struct pca953x_platform_data *pdata = client->dev.platform_data; struct pca953x_platform_data *pdata = client->dev.platform_data;
int ret; int ret, offset = 0;
if (pdata->irq_base != -1 if (pdata->irq_base != -1
&& (id->driver_data & PCA953X_INT)) { && (id->driver_data & PCA_INT)) {
int lvl; int lvl;
ret = pca953x_read_reg(chip, PCA953X_INPUT, switch (chip->chip_type) {
&chip->irq_stat); 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) if (ret)
goto out_failed; goto out_failed;
...@@ -439,7 +524,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -439,7 +524,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
struct i2c_client *client = chip->client; struct i2c_client *client = chip->client;
struct pca953x_platform_data *pdata = client->dev.platform_data; struct pca953x_platform_data *pdata = client->dev.platform_data;
if (pdata->irq_base != -1 && (id->driver_data & PCA953X_INT)) if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n"); dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0; return 0;
...@@ -499,12 +584,65 @@ pca953x_get_alt_pdata(struct i2c_client *client) ...@@ -499,12 +584,65 @@ pca953x_get_alt_pdata(struct i2c_client *client)
} }
#endif #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);
if (ret)
goto out;
return 0;
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, static int __devinit pca953x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct pca953x_platform_data *pdata; struct pca953x_platform_data *pdata;
struct pca953x_chip *chip; struct pca953x_chip *chip;
int ret; int ret = 0;
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL) if (chip == NULL)
...@@ -531,25 +669,20 @@ static int __devinit pca953x_probe(struct i2c_client *client, ...@@ -531,25 +669,20 @@ static int __devinit pca953x_probe(struct i2c_client *client,
chip->gpio_start = pdata->gpio_base; chip->gpio_start = pdata->gpio_base;
chip->names = pdata->names; chip->names = pdata->names;
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
mutex_init(&chip->i2c_lock); mutex_init(&chip->i2c_lock);
/* initialize cached registers from their original values. /* initialize cached registers from their original values.
* we can't share this chip with another i2c master. * we can't share this chip with another i2c master.
*/ */
pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS); pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); if (chip->chip_type == PCA953X_TYPE)
if (ret) device_pca953x_init(chip, pdata->invert);
goto out_failed; else if (chip->chip_type == PCA957X_TYPE)
device_pca957x_init(chip, pdata->invert);
ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); else
if (ret)
goto out_failed;
/* set platform specific polarity inversion */
ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
if (ret)
goto out_failed; goto out_failed;
ret = pca953x_irq_setup(chip, id); ret = pca953x_irq_setup(chip, id);
......
...@@ -283,8 +283,10 @@ static int pch_gpio_resume(struct pci_dev *pdev) ...@@ -283,8 +283,10 @@ static int pch_gpio_resume(struct pci_dev *pdev)
#define pch_gpio_resume NULL #define pch_gpio_resume NULL
#endif #endif
#define PCI_VENDOR_ID_ROHM 0x10DB
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
......
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
* platform data and other tables. * platform data and other tables.
*/ */
static inline int gpio_is_valid(int number) static inline bool gpio_is_valid(int number)
{ {
return ((unsigned)number) < ARCH_NR_GPIOS; return number >= 0 && number < ARCH_NR_GPIOS;
} }
struct device; struct device;
...@@ -193,8 +193,8 @@ struct gpio { ...@@ -193,8 +193,8 @@ struct gpio {
}; };
extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
extern int gpio_request_array(struct gpio *array, size_t num); extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(struct gpio *array, size_t num); extern void gpio_free_array(const struct gpio *array, size_t num);
#ifdef CONFIG_GPIO_SYSFS #ifdef CONFIG_GPIO_SYSFS
...@@ -212,7 +212,7 @@ extern void gpio_unexport(unsigned gpio); ...@@ -212,7 +212,7 @@ extern void gpio_unexport(unsigned gpio);
#else /* !CONFIG_GPIOLIB */ #else /* !CONFIG_GPIOLIB */
static inline int gpio_is_valid(int number) static inline bool gpio_is_valid(int number)
{ {
/* only non-negative numbers are valid */ /* only non-negative numbers are valid */
return number >= 0; return number >= 0;
......
...@@ -25,9 +25,9 @@ struct gpio_chip; ...@@ -25,9 +25,9 @@ struct gpio_chip;
* warning when something is wrongly called. * warning when something is wrongly called.
*/ */
static inline int gpio_is_valid(int number) static inline bool gpio_is_valid(int number)
{ {
return 0; return false;
} }
static inline int gpio_request(unsigned gpio, const char *label) static inline int gpio_request(unsigned gpio, const char *label)
...@@ -41,7 +41,7 @@ static inline int gpio_request_one(unsigned gpio, ...@@ -41,7 +41,7 @@ static inline int gpio_request_one(unsigned gpio,
return -ENOSYS; return -ENOSYS;
} }
static inline int gpio_request_array(struct gpio *array, size_t num) static inline int gpio_request_array(const struct gpio *array, size_t num)
{ {
return -ENOSYS; return -ENOSYS;
} }
...@@ -54,7 +54,7 @@ static inline void gpio_free(unsigned gpio) ...@@ -54,7 +54,7 @@ static inline void gpio_free(unsigned gpio)
WARN_ON(1); WARN_ON(1);
} }
static inline void gpio_free_array(struct gpio *array, size_t num) static inline void gpio_free_array(const struct gpio *array, size_t num)
{ {
might_sleep(); might_sleep();
......
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