提交 04830fcc 编写于 作者: L 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
......@@ -13,7 +13,7 @@ obj- :=
# Core support for EXYNOS4 system
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_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
......
......@@ -6,7 +6,6 @@ config MACH_NOMADIK_8815NHK
bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
select NOMADIK_8815
select HAS_MTU
select NOMADIK_GPIO
endmenu
......
......@@ -11,7 +11,7 @@ obj- :=
# 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) += dma.o
......
......@@ -12,7 +12,7 @@ obj- :=
# 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_S5PV210_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
......
......@@ -2,7 +2,7 @@
# 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-n :=
obj- :=
......
......@@ -5,7 +5,6 @@ config UX500_SOC_COMMON
default y
select ARM_GIC
select HAS_MTU
select NOMADIK_GPIO
select ARM_ERRATA_753970
menu "Ux500 SoC"
......
......@@ -21,9 +21,4 @@ config HAS_MTU
to multiple interrupt generating programmable
32-bit free running decrementing counters.
config NOMADIK_GPIO
bool
help
Support for the Nomadik GPIO controller.
endif
......@@ -3,4 +3,3 @@
# Licensed under GPLv2
obj-$(CONFIG_HAS_MTU) += timer.o
obj-$(CONFIG_NOMADIK_GPIO) += gpio.o
......@@ -78,6 +78,8 @@ extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(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.
*/
......
......@@ -3,7 +3,7 @@
#
# 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
obj-m :=
obj-n :=
......
......@@ -52,6 +52,109 @@
#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_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES)
......
......@@ -19,7 +19,6 @@ obj-y += gpio.o
obj-y += gpio-config.o
obj-y += dev-asocdma.o
obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT) += gpiolib.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
......
......@@ -86,6 +86,30 @@ config GPIO_IT8761E
help
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
bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA
......@@ -303,7 +327,7 @@ comment "PCI GPIO expanders:"
config GPIO_CS5535
tristate "AMD CS5535/CS5536 GPIO support"
depends on PCI && X86 && !CS5535_GPIO
depends on PCI && X86 && !CS5535_GPIO && MFD_CS5535
help
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
can be used for quite a number of things. The CS5535/6 is found on
......@@ -334,13 +358,19 @@ config GPIO_LANGWELL
Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH
tristate "PCH GPIO of Intel Topcliff"
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
depends on PCI && X86
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device.
This driver also can be used for 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
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on PCI
......
......@@ -8,6 +8,10 @@ obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += 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_MAX730X) += max730x.o
obj-$(CONFIG_GPIO_MAX7300) += max7300.o
......@@ -16,6 +20,7 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_74X164) += 74x164.o
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
......@@ -34,6 +39,8 @@ obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
obj-$(CONFIG_GPIO_WM8994) += wm8994-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_JANZ_TTL) += janz-ttl.o
obj-$(CONFIG_GPIO_SX150X) += sx150x.o
......
......@@ -57,6 +57,7 @@ struct nmk_gpio_chip {
u32 fwimsc;
u32 slpm;
u32 enabled;
u32 pull_up;
};
static struct nmk_gpio_chip *
......@@ -103,16 +104,22 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
u32 pdis;
pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
if (pull == NMK_GPIO_PULL_NONE)
if (pull == NMK_GPIO_PULL_NONE) {
pdis |= bit;
else
nmk_chip->pull_up &= ~bit;
} else {
pdis &= ~bit;
}
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);
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);
}
}
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)
bool pull;
u32 bit = 1 << i;
if (!label)
continue;
is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
mode = nmk_gpio_get_mode(gpio);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
gpio, label,
gpio, label ?: "(none)",
is_out ? "out" : "in ",
chip->get
? (chip->get(chip, i) ? "hi" : "lo")
: "? ",
(mode < 0) ? "unknown" : modes[mode],
pull ? "pull" : "none");
if (label && !is_out) {
int irq = gpio_to_irq(gpio);
struct irq_desc *desc = irq_to_desc(irq);
/* This races with request_irq(), set_irq_type(),
* and set_irq_wake() ... but those are "rare".
*/
if (irq >= 0 && desc->action) {
char *trigger;
u32 bitmask = nmk_gpio_get_bitmask(gpio);
if (nmk_chip->edge_rising & bitmask)
trigger = "edge-rising";
else if (nmk_chip->edge_falling & bitmask)
trigger = "edge-falling";
else
trigger = "edge-undefined";
seq_printf(s, " irq-%d %s%s",
irq, trigger,
irqd_is_wakeup_set(&desc->irq_data)
? " wakeup" : "");
}
}
seq_printf(s, "\n");
}
}
......@@ -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)
{
struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
......
/*
* linux/arch/arm/plat-omap/gpio.c
*
* Support functions for OMAP GPIO
*
* Copyright (C) 2003-2005 Nokia Corporation
......@@ -30,109 +28,6 @@
#include <mach/gpio.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 {
unsigned long pbase;
void __iomem *base;
......
......@@ -1296,7 +1296,7 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
* @array: array of the 'struct gpio'
* @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;
......@@ -1319,7 +1319,7 @@ EXPORT_SYMBOL_GPL(gpio_request_array);
* @array: array of the 'struct gpio'
* @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--)
gpio_free((array++)->gpio);
......
......@@ -33,6 +33,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
/*
* Langwell chip has 64 pins and thus there are 2 32bit registers to control
......@@ -63,6 +64,7 @@ struct lnw_gpio {
void *reg_base;
spinlock_t lock;
unsigned irq_base;
struct pci_dev *pdev;
};
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)
u32 value;
unsigned long flags;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr);
value &= ~BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
......@@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
unsigned long flags;
lnw_gpio_set(chip, offset, value);
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr);
value |= BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
......@@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
if (gpio >= lnw->chip.ngpio)
return -EINVAL;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
if (type & IRQ_TYPE_EDGE_RISING)
value = readl(grer) | BIT(gpio % 32);
......@@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
writel(value, gfer);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
......@@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
chip->irq_eoi(data);
}
#ifdef CONFIG_PM
static int lnw_gpio_runtime_resume(struct device *dev)
{
return 0;
}
static int lnw_gpio_runtime_suspend(struct device *dev)
{
return 0;
}
static int lnw_gpio_runtime_idle(struct device *dev)
{
int err = pm_schedule_suspend(dev, 500);
if (!err)
return 0;
return -EBUSY;
}
#else
#define lnw_gpio_runtime_suspend NULL
#define lnw_gpio_runtime_resume NULL
#define lnw_gpio_runtime_idle NULL
#endif
static const struct dev_pm_ops lnw_gpio_pm_ops = {
.runtime_suspend = lnw_gpio_runtime_suspend,
.runtime_resume = lnw_gpio_runtime_resume,
.runtime_idle = lnw_gpio_runtime_idle,
};
static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
......@@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
lnw->chip.base = gpio_base;
lnw->chip.ngpio = id->driver_data;
lnw->chip.can_sleep = 0;
lnw->pdev = pdev;
pci_set_drvdata(pdev, lnw);
retval = gpiochip_add(&lnw->chip);
if (retval) {
......@@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
}
spin_lock_init(&lnw->lock);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
goto done;
err5:
kfree(lnw);
......@@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = {
.name = "langwell_gpio",
.id_table = lnw_gpio_ids,
.probe = lnw_gpio_probe,
.driver = {
.pm = &lnw_gpio_pm_ops,
},
};
......
......@@ -24,33 +24,46 @@
#include <linux/of_gpio.h>
#endif
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
#define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3
#define PCA953X_GPIOS 0x00FF
#define PCA953X_INT 0x0100
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
#define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3
#define PCA957X_IN 0
#define PCA957X_INVRT 1
#define PCA957X_BKEN 2
#define PCA957X_PUPD 3
#define PCA957X_CFG 4
#define PCA957X_OUT 5
#define PCA957X_MSK 6
#define PCA957X_INTS 7
#define PCA_GPIO_MASK 0x00FF
#define PCA_INT 0x0100
#define PCA953X_TYPE 0x1000
#define PCA957X_TYPE 0x2000
static const struct i2c_device_id pca953x_id[] = {
{ "pca9534", 8 | PCA953X_INT, },
{ "pca9535", 16 | PCA953X_INT, },
{ "pca9536", 4, },
{ "pca9537", 4 | PCA953X_INT, },
{ "pca9538", 8 | PCA953X_INT, },
{ "pca9539", 16 | PCA953X_INT, },
{ "pca9554", 8 | PCA953X_INT, },
{ "pca9555", 16 | PCA953X_INT, },
{ "pca9556", 8, },
{ "pca9557", 8, },
{ "max7310", 8, },
{ "max7312", 16 | PCA953X_INT, },
{ "max7313", 16 | PCA953X_INT, },
{ "max7315", 8 | PCA953X_INT, },
{ "pca6107", 8 | PCA953X_INT, },
{ "tca6408", 8 | PCA953X_INT, },
{ "tca6416", 16 | PCA953X_INT, },
{ "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9536", 4 | PCA953X_TYPE, },
{ "pca9537", 4 | PCA953X_TYPE | PCA_INT, },
{ "pca9538", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9554", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9556", 8 | PCA953X_TYPE, },
{ "pca9557", 8 | PCA953X_TYPE, },
{ "pca9574", 8 | PCA957X_TYPE | PCA_INT, },
{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
{ "max7310", 8 | PCA953X_TYPE, },
{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
{ "max7315", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
/* NYET: { "tca6424", 24, }, */
{ }
};
......@@ -75,16 +88,32 @@ struct pca953x_chip {
struct pca953x_platform_data *dyn_pdata;
struct gpio_chip gpio_chip;
const char *const *names;
int chip_type;
};
static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
{
int ret;
int ret = 0;
if (chip->gpio_chip.ngpio <= 8)
ret = i2c_smbus_write_byte_data(chip->client, reg, val);
else
ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
else {
switch (chip->chip_type) {
case PCA953X_TYPE:
ret = i2c_smbus_write_word_data(chip->client,
reg << 1, val);
break;
case PCA957X_TYPE:
ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
val & 0xff);
if (ret < 0)
break;
ret = i2c_smbus_write_byte_data(chip->client,
(reg << 1) + 1,
(val & 0xff00) >> 8);
break;
}
}
if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n");
......@@ -116,13 +145,22 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{
struct pca953x_chip *chip;
uint16_t reg_val;
int ret;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock);
reg_val = chip->reg_direction | (1u << off);
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)
goto exit;
......@@ -138,7 +176,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
{
struct pca953x_chip *chip;
uint16_t reg_val;
int ret;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
......@@ -149,7 +187,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
else
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)
goto exit;
......@@ -157,7 +203,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
/* then direction */
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)
goto exit;
......@@ -172,12 +226,20 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{
struct pca953x_chip *chip;
uint16_t reg_val;
int ret;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
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);
if (ret < 0) {
/* 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)
{
struct pca953x_chip *chip;
uint16_t reg_val;
int ret;
int ret, offset = 0;
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)
else
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)
goto exit;
......@@ -322,9 +392,17 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
uint16_t old_stat;
uint16_t pending;
uint16_t trigger;
int ret;
ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
int ret, offset = 0;
switch (chip->chip_type) {
case PCA953X_TYPE:
offset = PCA953X_INPUT;
break;
case PCA957X_TYPE:
offset = PCA957X_IN;
break;
}
ret = pca953x_read_reg(chip, offset, &cur_stat);
if (ret)
return 0;
......@@ -372,14 +450,21 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
{
struct i2c_client *client = chip->client;
struct pca953x_platform_data *pdata = client->dev.platform_data;
int ret;
int ret, offset = 0;
if (pdata->irq_base != -1
&& (id->driver_data & PCA953X_INT)) {
&& (id->driver_data & PCA_INT)) {
int lvl;
ret = pca953x_read_reg(chip, PCA953X_INPUT,
&chip->irq_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, &chip->irq_stat);
if (ret)
goto out_failed;
......@@ -439,7 +524,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
struct i2c_client *client = chip->client;
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");
return 0;
......@@ -499,12 +584,65 @@ pca953x_get_alt_pdata(struct i2c_client *client)
}
#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,
const struct i2c_device_id *id)
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
int ret;
int ret = 0;
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
......@@ -531,25 +669,20 @@ static int __devinit pca953x_probe(struct i2c_client *client,
chip->gpio_start = pdata->gpio_base;
chip->names = pdata->names;
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
mutex_init(&chip->i2c_lock);
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS);
pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
if (ret)
goto out_failed;
ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
if (ret)
goto out_failed;
/* set platform specific polarity inversion */
ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
if (ret)
if (chip->chip_type == PCA953X_TYPE)
device_pca953x_init(chip, pdata->invert);
else if (chip->chip_type == PCA957X_TYPE)
device_pca957x_init(chip, pdata->invert);
else
goto out_failed;
ret = pca953x_irq_setup(chip, id);
......
......@@ -283,8 +283,10 @@ static int pch_gpio_resume(struct pci_dev *pdev)
#define pch_gpio_resume NULL
#endif
#define PCI_VENDOR_ID_ROHM 0x10DB
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
......
......@@ -35,9 +35,9 @@
* 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;
......@@ -193,8 +193,8 @@ struct gpio {
};
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 void gpio_free_array(struct gpio *array, size_t num);
extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(const struct gpio *array, size_t num);
#ifdef CONFIG_GPIO_SYSFS
......@@ -212,7 +212,7 @@ extern void gpio_unexport(unsigned gpio);
#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 */
return number >= 0;
......
......@@ -25,9 +25,9 @@ struct gpio_chip;
* 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)
......@@ -41,7 +41,7 @@ static inline int gpio_request_one(unsigned gpio,
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;
}
......@@ -54,7 +54,7 @@ static inline void gpio_free(unsigned gpio)
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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册