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

* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6: (61 commits)
  gpio/mxc/mxs: fix build error introduced by the irq_gc_ack() renaming
  mcp23s08: add i2c support
  mcp23s08: isolate spi specific parts
  mcp23s08: get rid of setup/teardown callbacks
  gpio/tegra: dt: add binding for gpio polarity
  mcp23s08: remove unused work queue
  gpio/da9052: remove a redundant assignment for gpio->da9052
  gpio/mxc: add device tree probe support
  ARM: mxc: use ARCH_NR_GPIOS to define gpio number
  gpio/mxc: get rid of the uses of cpu_is_mx()
  gpio/mxc: add missing initialization of basic_mmio_gpio shadow variables
  gpio: Move mpc5200 gpio driver to drivers/gpio
  GPIO: DA9052 GPIO module v3
  gpio/tegra: Use engineering names in DT compatible property
  of/gpio: Add new method for getting gpios under different property names
  gpio/dt: Refine GPIO device tree binding
  gpio/ml-ioh: fix off-by-one for displaying variable i in dev_err
  gpio/pca953x: Deprecate meaningless device-tree bindings
  gpio/pca953x: Remove dynamic platform data pointer
  gpio/pca953x: Fix IRQ support.
  ...
This commit is contained in:
Linus Torvalds 2011-07-22 14:50:57 -07:00
commit c7c8518498
137 changed files with 2297 additions and 1923 deletions

View File

@ -0,0 +1,22 @@
* Freescale i.MX/MXC GPIO controller
Required properties:
- compatible : Should be "fsl,<soc>-gpio"
- reg : Address and length of the register set for the device
- interrupts : Should be the port interrupt shared by all 32 pins, if
one number. If two numbers, the first one is the interrupt shared
by low 16 pins and the second one is for high 16 pins.
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify optional parameters (currently
unused).
Example:
gpio0: gpio@73f84000 {
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
reg = <0x73f84000 0x4000>;
interrupts = <50 51>;
gpio-controller;
#gpio-cells = <2>;
};

View File

@ -4,17 +4,45 @@ Specifying GPIO information for devices
1) gpios property
-----------------
Nodes that makes use of GPIOs should define them using `gpios' property,
format of which is: <&gpio-controller1-phandle gpio1-specifier
&gpio-controller2-phandle gpio2-specifier
0 /* holes are permitted, means no GPIO 3 */
&gpio-controller4-phandle gpio4-specifier
...>;
Nodes that makes use of GPIOs should specify them using one or more
properties, each containing a 'gpio-list':
Note that gpio-specifier length is controller dependent.
gpio-list ::= <single-gpio> [gpio-list]
single-gpio ::= <gpio-phandle> <gpio-specifier>
gpio-phandle : phandle to gpio controller node
gpio-specifier : Array of #gpio-cells specifying specific gpio
(controller specific)
GPIO properties should be named "[<name>-]gpios". Exact
meaning of each gpios property must be documented in the device tree
binding for each device.
For example, the following could be used to describe gpios pins to use
as chip select lines; with chip selects 0, 1 and 3 populated, and chip
select 2 left empty:
gpio1: gpio1 {
gpio-controller
#gpio-cells = <2>;
};
gpio2: gpio2 {
gpio-controller
#gpio-cells = <1>;
};
[...]
chipsel-gpios = <&gpio1 12 0>,
<&gpio1 13 0>,
<0>, /* holes are permitted, means no GPIO 2 */
<&gpio2 2>;
Note that gpio-specifier length is controller dependent. In the
above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
only uses one.
gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted.
Exact meaning of each specifier cell is controller specific, and must
be documented in the device tree binding for the device.
Example of the node using GPIOs:
@ -28,8 +56,8 @@ and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
2) gpio-controller nodes
------------------------
Every GPIO controller node must have #gpio-cells property defined,
this information will be used to translate gpio-specifiers.
Every GPIO controller node must both an empty "gpio-controller"
property, and have #gpio-cells contain the size of the gpio-specifier.
Example of two SOC GPIO banks defined as gpio-controller nodes:

View File

@ -0,0 +1,8 @@
NVIDIA Tegra 2 GPIO controller
Required properties:
- compatible : "nvidia,tegra20-gpio"
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO controller.

View File

@ -1,7 +1,7 @@
#
# Makefile for the linux kernel.
#
obj-y := core.o clock.o dma-m2p.o gpio.o
obj-y := core.o clock.o dma-m2p.o
obj-m :=
obj-n :=
obj- :=

View File

@ -174,14 +174,10 @@ struct sys_timer ep93xx_timer = {
/*************************************************************************
* EP93xx IRQ handling
*************************************************************************/
extern void ep93xx_gpio_init_irq(void);
void __init ep93xx_init_irq(void)
{
vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
ep93xx_gpio_init_irq();
}
@ -240,6 +236,24 @@ unsigned int ep93xx_chip_revision(void)
return v;
}
/*************************************************************************
* EP93xx GPIO
*************************************************************************/
static struct resource ep93xx_gpio_resource[] = {
{
.start = EP93XX_GPIO_PHYS_BASE,
.end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device ep93xx_gpio_device = {
.name = "gpio-ep93xx",
.id = -1,
.num_resources = ARRAY_SIZE(ep93xx_gpio_resource),
.resource = ep93xx_gpio_resource,
};
/*************************************************************************
* EP93xx peripheral handling
*************************************************************************/
@ -870,14 +884,13 @@ void __init ep93xx_register_ac97(void)
platform_device_register(&ep93xx_pcm_device);
}
extern void ep93xx_gpio_init(void);
void __init ep93xx_init_devices(void)
{
/* Disallow access to MaverickCrunch initially */
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
ep93xx_gpio_init();
/* Get the GPIO working early, other devices need it */
platform_device_register(&ep93xx_gpio_device);
amba_device_register(&uart1_device, &iomem_resource);
amba_device_register(&uart2_device, &iomem_resource);

View File

@ -98,6 +98,7 @@
#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000)
#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)

View File

@ -115,6 +115,8 @@ static struct platform_device *devices[] __initdata = {
static void __init apf9328_init(void)
{
imx1_soc_init();
mxc_gpio_setup_multiple_pins(apf9328_pins,
ARRAY_SIZE(apf9328_pins),
"APF9328");

View File

@ -490,6 +490,8 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init armadillo5x0_init(void)
{
imx31_soc_init();
mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");

View File

@ -42,6 +42,8 @@ static const unsigned int bug_pins[] __initconst = {
static void __init bug_board_init(void)
{
imx31_soc_init();
mxc_iomux_setup_multiple_pins(bug_pins,
ARRAY_SIZE(bug_pins), "uart-4");
imx31_add_imx_uart4(&uart_pdata);

View File

@ -250,6 +250,8 @@ __setup("otg_mode=", eukrea_cpuimx27_otg_mode);
static void __init eukrea_cpuimx27_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,
ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27");

View File

@ -156,6 +156,8 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
*/
static void __init eukrea_cpuimx35_init(void)
{
imx35_soc_init();
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
ARRAY_SIZE(eukrea_cpuimx35_pads));

View File

@ -125,6 +125,8 @@ __setup("otg_mode=", eukrea_cpuimx25_otg_mode);
static void __init eukrea_cpuimx25_init(void)
{
imx25_soc_init();
if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
ARRAY_SIZE(eukrea_cpuimx25_pads)))
printk(KERN_ERR "error setting cpuimx25 pads !\n");

View File

@ -231,6 +231,8 @@ static void __init visstrim_m10_board_init(void)
{
int ret;
imx27_soc_init();
ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
if (ret)

View File

@ -50,6 +50,8 @@ static const int mx27ipcam_pins[] __initconst = {
static void __init mx27ipcam_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
"mx27ipcam");

View File

@ -59,6 +59,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mx27lite_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
"imx27lite");
imx27_add_imx_uart0(&uart_pdata);

View File

@ -223,6 +223,8 @@ static int kzm_pins[] __initdata = {
*/
static void __init kzm_board_init(void)
{
imx31_soc_init();
mxc_iomux_setup_multiple_pins(kzm_pins,
ARRAY_SIZE(kzm_pins), "kzm");
kzm_init_ext_uart();

View File

@ -115,6 +115,8 @@ static struct i2c_board_info mx1ads_i2c_devices[] = {
*/
static void __init mx1ads_init(void)
{
imx1_soc_init();
mxc_gpio_setup_multiple_pins(mx1ads_pins,
ARRAY_SIZE(mx1ads_pins), "mx1ads");

View File

@ -279,6 +279,8 @@ static struct platform_device *platform_devices[] __initdata = {
static void __init mx21ads_board_init(void)
{
imx21_soc_init();
mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
"mx21ads");

View File

@ -219,6 +219,8 @@ static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
static void __init mx25pdk_init(void)
{
imx25_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
ARRAY_SIZE(mx25pdk_pads));

View File

@ -267,6 +267,8 @@ static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
static void __init mx27pdk_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
"mx27pdk");
mx27_3ds_sdhc1_enable_level_translator();

View File

@ -288,6 +288,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mx27ads_board_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
"mx27ads");

View File

@ -690,6 +690,8 @@ static void __init mx31_3ds_init(void)
{
int ret;
imx31_soc_init();
mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
"mx31_3ds");

View File

@ -516,6 +516,8 @@ static void __init mx31ads_init_irq(void)
static void __init mx31ads_init(void)
{
imx31_soc_init();
mxc_init_extuart();
mxc_init_imx_uart();
mxc_init_i2c();

View File

@ -243,6 +243,8 @@ core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
static void __init mx31lilly_board_init(void)
{
imx31_soc_init();
switch (mx31lilly_baseboard) {
case MX31LILLY_NOBOARD:
break;

View File

@ -230,6 +230,8 @@ static void __init mx31lite_init(void)
{
int ret;
imx31_soc_init();
switch (mx31lite_baseboard) {
case MX31LITE_NOBOARD:
break;

View File

@ -507,6 +507,8 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
*/
static void __init mx31moboard_init(void)
{
imx31_soc_init();
mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
"moboard");

View File

@ -179,6 +179,8 @@ static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {
*/
static void __init mx35_3ds_init(void)
{
imx35_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
imx35_add_fec(NULL);

View File

@ -233,6 +233,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mxt_td60_board_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),
"MXT_TD60");

View File

@ -357,6 +357,8 @@ static void __init pca100_init(void)
{
int ret;
imx27_soc_init();
/* SSI unit */
mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */

View File

@ -576,6 +576,8 @@ static void __init pcm037_init(void)
{
int ret;
imx31_soc_init();
mxc_iomux_set_gpr(MUX_PGP_UH2, 1);
mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),

View File

@ -295,6 +295,8 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
static void __init pcm038_init(void)
{
imx27_soc_init();
mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
"PCM038");

View File

@ -356,6 +356,8 @@ static struct esdhc_platform_data sd1_pdata = {
*/
static void __init pcm043_init(void)
{
imx35_soc_init();
mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
mxc_audmux_v2_configure_port(3,

View File

@ -244,6 +244,8 @@ static void __init qong_init_fpga(void)
*/
static void __init qong_init(void)
{
imx31_soc_init();
mxc_init_imx_uart();
qong_init_nor_mtd();
qong_init_fpga();

View File

@ -129,6 +129,8 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init scb9328_init(void)
{
imx1_soc_init();
imx1_add_imx_uart0(&uart_pdata);
printk(KERN_INFO"Scb9328: Adding devices\n");

View File

@ -267,6 +267,8 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init vpr200_board_init(void)
{
imx35_soc_init();
mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
imx35_add_fec(NULL);

View File

@ -23,7 +23,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@ -44,15 +43,19 @@ void __init imx1_init_early(void)
MX1_NUM_GPIO_PORT);
}
static struct mxc_gpio_port imx1_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
};
void __init mx1_init_irq(void)
{
mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
mxc_gpio_init(imx1_gpio_ports, ARRAY_SIZE(imx1_gpio_ports));
}
void __init imx1_soc_init(void)
{
mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTA, 0);
mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTB, 0);
mxc_register_gpio("imx1-gpio", 2, MX1_GPIO3_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTC, 0);
mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTD, 0);
}

View File

@ -24,7 +24,6 @@
#include <mach/common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@ -70,17 +69,17 @@ void __init imx21_init_early(void)
MX21_NUM_GPIO_PORT);
}
static struct mxc_gpio_port imx21_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
};
void __init mx21_init_irq(void)
{
mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports));
}
void __init imx21_soc_init(void)
{
mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 3, MX21_GPIO4_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
}

View File

@ -27,7 +27,6 @@
#include <mach/hardware.h>
#include <mach/mx25.h>
#include <mach/iomux-v3.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
/*
@ -57,16 +56,16 @@ void __init imx25_init_early(void)
mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
}
static struct mxc_gpio_port imx25_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
};
void __init mx25_init_irq(void)
{
mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
mxc_gpio_init(imx25_gpio_ports, ARRAY_SIZE(imx25_gpio_ports));
}
void __init imx25_soc_init(void)
{
/* i.mx25 has the i.mx31 type gpio */
mxc_register_gpio("imx31-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
}

View File

@ -24,7 +24,6 @@
#include <mach/common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@ -70,17 +69,18 @@ void __init imx27_init_early(void)
MX27_NUM_GPIO_PORT);
}
static struct mxc_gpio_port imx27_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
};
void __init mx27_init_irq(void)
{
mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports));
}
void __init imx27_soc_init(void)
{
/* i.mx27 has the i.mx21 type gpio */
mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 2, MX27_GPIO3_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 3, MX27_GPIO4_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
}

View File

@ -26,7 +26,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-v3.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
static struct map_desc mx31_io_desc[] __initdata = {
@ -53,14 +52,14 @@ void __init imx31_init_early(void)
mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
}
static struct mxc_gpio_port imx31_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
};
void __init mx31_init_irq(void)
{
mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
mxc_gpio_init(imx31_gpio_ports, ARRAY_SIZE(imx31_gpio_ports));
}
void __init imx31_soc_init(void)
{
mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
}

View File

@ -27,7 +27,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-v3.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
static struct map_desc mx35_io_desc[] __initdata = {
@ -50,14 +49,15 @@ void __init imx35_init_early(void)
mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
}
static struct mxc_gpio_port imx35_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
};
void __init mx35_init_irq(void)
{
mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
mxc_gpio_init(imx35_gpio_ports, ARRAY_SIZE(imx35_gpio_ports));
}
void __init imx35_soc_init(void)
{
/* i.mx35 has the i.mx31 type gpio */
mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
}

View File

@ -245,6 +245,8 @@ __setup("otg_mode=", eukrea_cpuimx51_otg_mode);
*/
static void __init eukrea_cpuimx51_init(void)
{
imx51_soc_init();
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
ARRAY_SIZE(eukrea_cpuimx51_pads));

View File

@ -264,6 +264,8 @@ static struct platform_device *platform_devices[] __initdata = {
static void __init eukrea_cpuimx51sd_init(void)
{
imx51_soc_init();
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
ARRAY_SIZE(eukrea_cpuimx51sd_pads));

View File

@ -192,6 +192,8 @@ static const struct imxi2c_platform_data i2c_data __initconst = {
*/
static void __init mx50_rdp_board_init(void)
{
imx50_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
ARRAY_SIZE(mx50_rdp_pads));

View File

@ -135,6 +135,8 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = {
*/
static void __init mx51_3ds_init(void)
{
imx51_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
ARRAY_SIZE(mx51_3ds_pads));

View File

@ -340,6 +340,8 @@ static void __init mx51_babbage_init(void)
iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
imx51_soc_init();
#if defined(CONFIG_CPU_FREQ_IMX)
get_cpu_op = mx51_get_cpu_op;
#endif

View File

@ -236,6 +236,8 @@ late_initcall(mx51_efikamx_power_init);
static void __init mx51_efikamx_init(void)
{
imx51_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
ARRAY_SIZE(mx51efikamx_pads));
efika_board_common_init();

View File

@ -248,6 +248,8 @@ static void __init mx51_efikasb_board_id(void)
static void __init efikasb_board_init(void)
{
imx51_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
ARRAY_SIZE(mx51efikasb_pads));
efika_board_common_init();

View File

@ -117,6 +117,8 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {
static void __init mx53_evk_board_init(void)
{
imx53_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
ARRAY_SIZE(mx53_evk_pads));
mx53_evk_init_uart();

View File

@ -227,6 +227,8 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
static void __init mx53_loco_board_init(void)
{
imx53_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
ARRAY_SIZE(mx53_loco_pads));
imx53_add_imx_uart(0, NULL);

View File

@ -113,6 +113,8 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
static void __init mx53_smd_board_init(void)
{
imx53_soc_init();
mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
ARRAY_SIZE(mx53_smd_pads));
mx53_smd_init_uart();

View File

@ -12,7 +12,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/imx-uart.h>
#include <mach/irqs.h>
@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = {
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
static struct mxc_gpio_port mxc_gpio_ports[] = {
{
.chip.label = "gpio-0",
.base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
.irq = MX51_MXC_INT_GPIO1_LOW,
.irq_high = MX51_MXC_INT_GPIO1_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START
},
{
.chip.label = "gpio-1",
.base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
.irq = MX51_MXC_INT_GPIO2_LOW,
.irq_high = MX51_MXC_INT_GPIO2_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
},
{
.chip.label = "gpio-2",
.base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
.irq = MX51_MXC_INT_GPIO3_LOW,
.irq_high = MX51_MXC_INT_GPIO3_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
},
{
.chip.label = "gpio-3",
.base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
.irq = MX51_MXC_INT_GPIO4_LOW,
.irq_high = MX51_MXC_INT_GPIO4_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
},
{
.chip.label = "gpio-4",
.base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR),
.irq = MX53_INT_GPIO5_LOW,
.irq_high = MX53_INT_GPIO5_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
},
{
.chip.label = "gpio-5",
.base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR),
.irq = MX53_INT_GPIO6_LOW,
.irq_high = MX53_INT_GPIO6_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
},
{
.chip.label = "gpio-6",
.base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR),
.irq = MX53_INT_GPIO7_LOW,
.irq_high = MX53_INT_GPIO7_HIGH,
.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
},
};
int __init imx51_register_gpios(void)
{
return mxc_gpio_init(mxc_gpio_ports, 4);
}
int __init imx53_register_gpios(void)
{
return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
}

View File

@ -26,7 +26,6 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-v3.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
/*
@ -56,17 +55,18 @@ void __init imx50_init_early(void)
mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
}
static struct mxc_gpio_port imx50_gpio_ports[] = {
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
};
void __init mx50_init_irq(void)
{
tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
mxc_gpio_init(imx50_gpio_ports, ARRAY_SIZE(imx50_gpio_ports));
}
void __init imx50_soc_init(void)
{
/* i.mx50 has the i.mx31 type gpio */
mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
}

View File

@ -69,8 +69,6 @@ void __init imx53_init_early(void)
mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
}
int imx51_register_gpios(void);
void __init mx51_init_irq(void)
{
unsigned long tzic_addr;
@ -86,11 +84,8 @@ void __init mx51_init_irq(void)
panic("unable to map TZIC interrupt controller\n");
tzic_init_irq(tzic_virt);
imx51_register_gpios();
}
int imx53_register_gpios(void);
void __init mx53_init_irq(void)
{
unsigned long tzic_addr;
@ -103,5 +98,25 @@ void __init mx53_init_irq(void)
panic("unable to map TZIC interrupt controller\n");
tzic_init_irq(tzic_virt);
imx53_register_gpios();
}
void __init imx51_soc_init(void)
{
/* i.mx51 has the i.mx31 type gpio */
mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
}
void __init imx53_soc_init(void)
{
/* i.mx53 has the i.mx31 type gpio */
mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
}

View File

@ -1,5 +1,5 @@
# Common support
obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
obj-$(CONFIG_MXS_OCOTP) += ocotp.o
obj-$(CONFIG_PM) += pm.o

View File

@ -88,3 +88,14 @@ int __init mxs_add_amba_device(const struct amba_device *dev)
return amba_device_register(adev, &iomem_resource);
}
struct device mxs_apbh_bus = {
.init_name = "mxs_apbh",
.parent = &platform_bus,
};
static int __init mxs_device_init(void)
{
return device_register(&mxs_apbh_bus);
}
core_initcall(mxs_device_init);

View File

@ -6,4 +6,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
obj-y += platform-gpio-mxs.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o

View File

@ -0,0 +1,53 @@
/*
* Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/init.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
#include <mach/devices-common.h>
struct platform_device *__init mxs_add_gpio(
int id, resource_size_t iobase, int irq)
{
struct resource res[] = {
{
.start = iobase,
.end = iobase + SZ_8K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = irq,
.end = irq,
.flags = IORESOURCE_IRQ,
},
};
return platform_device_register_resndata(&mxs_apbh_bus,
"gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0);
}
static int __init mxs_add_mxs_gpio(void)
{
if (cpu_is_mx23()) {
mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
}
if (cpu_is_mx28()) {
mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
}
return 0;
}
postcore_initcall(mxs_add_mxs_gpio);

View File

@ -1,331 +0,0 @@
/*
* MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* Based on code from Freescale,
* Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
#include <asm-generic/bug.h>
#include "gpio.h"
static struct mxs_gpio_port *mxs_gpio_ports;
static int gpio_table_size;
#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
#define GPIO_INT_FALL_EDGE 0x0
#define GPIO_INT_LOW_LEV 0x1
#define GPIO_INT_RISE_EDGE 0x2
#define GPIO_INT_HIGH_LEV 0x3
#define GPIO_INT_LEV_MASK (1 << 0)
#define GPIO_INT_POL_MASK (1 << 1)
/* Note: This driver assumes 32 GPIOs are handled in one register */
static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
{
__mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id));
}
static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
int enable)
{
if (enable) {
__mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
__mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
} else {
__mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
}
}
static void mxs_gpio_ack_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
}
static void mxs_gpio_mask_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
}
static void mxs_gpio_unmask_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
}
static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
{
u32 gpio = irq_to_gpio(d->irq);
u32 pin_mask = 1 << (gpio & 31);
struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
void __iomem *pin_addr;
int edge;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
edge = GPIO_INT_RISE_EDGE;
break;
case IRQ_TYPE_EDGE_FALLING:
edge = GPIO_INT_FALL_EDGE;
break;
case IRQ_TYPE_LEVEL_LOW:
edge = GPIO_INT_LOW_LEV;
break;
case IRQ_TYPE_LEVEL_HIGH:
edge = GPIO_INT_HIGH_LEV;
break;
default:
return -EINVAL;
}
/* set level or edge */
pin_addr = port->base + PINCTRL_IRQLEV(port->id);
if (edge & GPIO_INT_LEV_MASK)
__mxs_setl(pin_mask, pin_addr);
else
__mxs_clrl(pin_mask, pin_addr);
/* set polarity */
pin_addr = port->base + PINCTRL_IRQPOL(port->id);
if (edge & GPIO_INT_POL_MASK)
__mxs_setl(pin_mask, pin_addr);
else
__mxs_clrl(pin_mask, pin_addr);
clear_gpio_irqstatus(port, gpio & 0x1f);
return 0;
}
/* MXS has one interrupt *per* gpio port */
static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_stat;
struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
u32 gpio_irq_no_base = port->virtual_irq_start;
desc->irq_data.chip->irq_ack(&desc->irq_data);
irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
__raw_readl(port->base + PINCTRL_IRQEN(port->id));
while (irq_stat != 0) {
int irqoffset = fls(irq_stat) - 1;
generic_handle_irq(gpio_irq_no_base + irqoffset);
irq_stat &= ~(1 << irqoffset);
}
}
/*
* Set interrupt number "irq" in the GPIO as a wake-up source.
* While system is running, all registered GPIO interrupts need to have
* wake-up enabled. When system is suspended, only selected GPIO interrupts
* need to have wake-up enabled.
* @param irq interrupt source number
* @param enable enable as wake-up if equal to non-zero
* @return This function returns 0 on success.
*/
static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
{
u32 gpio = irq_to_gpio(d->irq);
u32 gpio_idx = gpio & 0x1f;
struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
if (enable) {
if (port->irq_high && (gpio_idx >= 16))
enable_irq_wake(port->irq_high);
else
enable_irq_wake(port->irq);
} else {
if (port->irq_high && (gpio_idx >= 16))
disable_irq_wake(port->irq_high);
else
disable_irq_wake(port->irq);
}
return 0;
}
static struct irq_chip gpio_irq_chip = {
.name = "mxs gpio",
.irq_ack = mxs_gpio_ack_irq,
.irq_mask = mxs_gpio_mask_irq,
.irq_unmask = mxs_gpio_unmask_irq,
.irq_set_type = mxs_gpio_set_irq_type,
.irq_set_wake = mxs_gpio_set_wake_irq,
};
static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
int dir)
{
struct mxs_gpio_port *port =
container_of(chip, struct mxs_gpio_port, chip);
void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
if (dir)
__mxs_setl(1 << offset, pin_addr);
else
__mxs_clrl(1 << offset, pin_addr);
}
static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct mxs_gpio_port *port =
container_of(chip, struct mxs_gpio_port, chip);
return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
}
static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct mxs_gpio_port *port =
container_of(chip, struct mxs_gpio_port, chip);
void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
if (value)
__mxs_setl(1 << offset, pin_addr);
else
__mxs_clrl(1 << offset, pin_addr);
}
static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct mxs_gpio_port *port =
container_of(chip, struct mxs_gpio_port, chip);
return port->virtual_irq_start + offset;
}
static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
mxs_set_gpio_direction(chip, offset, 0);
return 0;
}
static int mxs_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
mxs_gpio_set(chip, offset, value);
mxs_set_gpio_direction(chip, offset, 1);
return 0;
}
int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
{
int i, j;
/* save for local usage */
mxs_gpio_ports = port;
gpio_table_size = cnt;
pr_info("MXS GPIO hardware\n");
for (i = 0; i < cnt; i++) {
/* disable the interrupt and clear the status */
__raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
__raw_writel(0, port[i].base + PINCTRL_IRQEN(i));
/* clear address has to be used to clear IRQSTAT bits */
__mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));
for (j = port[i].virtual_irq_start;
j < port[i].virtual_irq_start + 32; j++) {
irq_set_chip_and_handler(j, &gpio_irq_chip,
handle_level_irq);
set_irq_flags(j, IRQF_VALID);
}
/* setup one handler for each entry */
irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
irq_set_handler_data(port[i].irq, &port[i]);
/* register gpio chip */
port[i].chip.direction_input = mxs_gpio_direction_input;
port[i].chip.direction_output = mxs_gpio_direction_output;
port[i].chip.get = mxs_gpio_get;
port[i].chip.set = mxs_gpio_set;
port[i].chip.to_irq = mxs_gpio_to_irq;
port[i].chip.base = i * 32;
port[i].chip.ngpio = 32;
/* its a serious configuration bug when it fails */
BUG_ON(gpiochip_add(&port[i].chip) < 0);
}
return 0;
}
#define MX23_GPIO_BASE MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
#define MX28_GPIO_BASE MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id) \
{ \
.chip.label = "gpio-" #_id, \
.id = _id, \
.irq = _irq, \
.base = _base, \
.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32, \
}
#ifdef CONFIG_SOC_IMX23
static struct mxs_gpio_port mx23_gpio_ports[] = {
DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
};
int __init mx23_register_gpios(void)
{
return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
}
#endif
#ifdef CONFIG_SOC_IMX28
static struct mxs_gpio_port mx28_gpio_ports[] = {
DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
};
int __init mx28_register_gpios(void)
{
return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
}
#endif

View File

@ -1,34 +0,0 @@
/*
* Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef __MXS_GPIO_H__
#define __MXS_GPIO_H__
struct mxs_gpio_port {
void __iomem *base;
int id;
int irq;
int irq_high;
int virtual_irq_start;
struct gpio_chip chip;
};
int mxs_gpio_init(struct mxs_gpio_port*, int);
#endif /* __MXS_GPIO_H__ */

View File

@ -11,6 +11,8 @@
#include <linux/init.h>
#include <linux/amba/bus.h>
extern struct device mxs_apbh_bus;
struct platform_device *mxs_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,

View File

@ -26,7 +26,6 @@
#include <mach/iomux-mx28.h>
#include "devices-mx28.h"
#include "gpio.h"
#define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13)
#define MX28EVK_FEC_PHY_POWER MXS_GPIO_NR(2, 15)

View File

@ -41,5 +41,4 @@ void __init mx23_map_io(void)
void __init mx23_init_irq(void)
{
icoll_init_irq();
mx23_register_gpios();
}

View File

@ -41,5 +41,4 @@ void __init mx28_map_io(void)
void __init mx28_init_irq(void)
{
icoll_init_irq();
mx28_register_gpios();
}

View File

@ -34,11 +34,22 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
},
};
static struct omap_gpio_reg_offs omap15xx_mpuio_regs = {
.revision = USHRT_MAX,
.direction = OMAP_MPUIO_IO_CNTL,
.datain = OMAP_MPUIO_INPUT_LATCH,
.dataout = OMAP_MPUIO_OUTPUT,
.irqstatus = OMAP_MPUIO_GPIO_INT,
.irqenable = OMAP_MPUIO_GPIO_MASKIT,
.irqenable_inv = true,
};
static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 16,
.bank_stride = 1,
.regs = &omap15xx_mpuio_regs,
};
static struct platform_device omap15xx_mpu_gpio = {
@ -64,10 +75,21 @@ static struct __initdata resource omap15xx_gpio_resources[] = {
},
};
static struct omap_gpio_reg_offs omap15xx_gpio_regs = {
.revision = USHRT_MAX,
.direction = OMAP1510_GPIO_DIR_CONTROL,
.datain = OMAP1510_GPIO_DATA_INPUT,
.dataout = OMAP1510_GPIO_DATA_OUTPUT,
.irqstatus = OMAP1510_GPIO_INT_STATUS,
.irqenable = OMAP1510_GPIO_INT_MASK,
.irqenable_inv = true,
};
static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_1510,
.bank_width = 16,
.regs = &omap15xx_gpio_regs,
};
static struct platform_device omap15xx_gpio = {

View File

@ -37,11 +37,22 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
},
};
static struct omap_gpio_reg_offs omap16xx_mpuio_regs = {
.revision = USHRT_MAX,
.direction = OMAP_MPUIO_IO_CNTL,
.datain = OMAP_MPUIO_INPUT_LATCH,
.dataout = OMAP_MPUIO_OUTPUT,
.irqstatus = OMAP_MPUIO_GPIO_INT,
.irqenable = OMAP_MPUIO_GPIO_MASKIT,
.irqenable_inv = true,
};
static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 16,
.bank_stride = 1,
.regs = &omap16xx_mpuio_regs,
};
static struct platform_device omap16xx_mpu_gpio = {
@ -67,10 +78,24 @@ static struct __initdata resource omap16xx_gpio1_resources[] = {
},
};
static struct omap_gpio_reg_offs omap16xx_gpio_regs = {
.revision = OMAP1610_GPIO_REVISION,
.direction = OMAP1610_GPIO_DIRECTION,
.set_dataout = OMAP1610_GPIO_SET_DATAOUT,
.clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT,
.datain = OMAP1610_GPIO_DATAIN,
.dataout = OMAP1610_GPIO_DATAOUT,
.irqstatus = OMAP1610_GPIO_IRQSTATUS1,
.irqenable = OMAP1610_GPIO_IRQENABLE1,
.set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1,
.clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1,
};
static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
.regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio1 = {
@ -100,6 +125,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 16,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
.regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio2 = {
@ -129,6 +155,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
.regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio3 = {
@ -158,6 +185,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 48,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
.regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio4 = {

View File

@ -39,11 +39,22 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
},
};
static struct omap_gpio_reg_offs omap7xx_mpuio_regs = {
.revision = USHRT_MAX,
.direction = OMAP_MPUIO_IO_CNTL / 2,
.datain = OMAP_MPUIO_INPUT_LATCH / 2,
.dataout = OMAP_MPUIO_OUTPUT / 2,
.irqstatus = OMAP_MPUIO_GPIO_INT / 2,
.irqenable = OMAP_MPUIO_GPIO_MASKIT / 2,
.irqenable_inv = true,
};
static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 32,
.bank_stride = 2,
.regs = &omap7xx_mpuio_regs,
};
static struct platform_device omap7xx_mpu_gpio = {
@ -69,10 +80,21 @@ static struct __initdata resource omap7xx_gpio1_resources[] = {
},
};
static struct omap_gpio_reg_offs omap7xx_gpio_regs = {
.revision = USHRT_MAX,
.direction = OMAP7XX_GPIO_DIR_CONTROL,
.datain = OMAP7XX_GPIO_DATA_INPUT,
.dataout = OMAP7XX_GPIO_DATA_OUTPUT,
.irqstatus = OMAP7XX_GPIO_INT_STATUS,
.irqenable = OMAP7XX_GPIO_INT_MASK,
.irqenable_inv = true,
};
static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio1 = {
@ -102,6 +124,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio2 = {
@ -131,6 +154,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 64,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio3 = {
@ -160,6 +184,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 96,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio4 = {
@ -189,6 +214,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
.virtual_irq_start = IH_GPIO_BASE + 128,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio5 = {
@ -218,6 +244,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
.virtual_irq_start = IH_GPIO_BASE + 160,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
.regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio6 = {

View File

@ -61,13 +61,45 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
pdata->dbck_flag = dev_attr->dbck_flag;
pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
if (!pdata) {
pr_err("gpio%d: Memory allocation failed\n", id);
return -ENOMEM;
}
switch (oh->class->rev) {
case 0:
case 1:
pdata->bank_type = METHOD_GPIO_24XX;
pdata->regs->revision = OMAP24XX_GPIO_REVISION;
pdata->regs->direction = OMAP24XX_GPIO_OE;
pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
break;
case 2:
pdata->bank_type = METHOD_GPIO_44XX;
pdata->regs->revision = OMAP4_GPIO_REVISION;
pdata->regs->direction = OMAP4_GPIO_OE;
pdata->regs->datain = OMAP4_GPIO_DATAIN;
pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
break;
default:
WARN(1, "Invalid gpio bank_type\n");

View File

@ -4,7 +4,6 @@ obj-y += io.o
obj-y += irq.o
obj-y += clock.o
obj-y += timer.o
obj-y += gpio.o
obj-y += pinmux.o
obj-y += powergate.o
obj-y += fuse.o

View File

@ -3,7 +3,7 @@
#
# Common support
obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
# MX51 uses the TZIC interrupt controller, older platforms use AVIC
obj-$(CONFIG_MXC_TZIC) += tzic.o

View File

@ -89,3 +89,14 @@ err:
return pdev;
}
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
.parent = &platform_bus,
};
static int __init mxc_device_init(void)
{
return device_register(&mxc_aips_bus);
}
core_initcall(mxc_device_init);

View File

@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
obj-y += platform-gpio-mxc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o

View File

@ -0,0 +1,32 @@
/*
* Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2011 Linaro Limited
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#include <mach/devices-common.h>
struct platform_device *__init mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
{
struct resource res[] = {
{
.start = iobase,
.end = iobase + iosize - 1,
.flags = IORESOURCE_MEM,
}, {
.start = irq,
.end = irq,
.flags = IORESOURCE_IRQ,
}, {
.start = irq_high,
.end = irq_high,
.flags = IORESOURCE_IRQ,
},
};
return platform_device_register_resndata(&mxc_aips_bus,
name, id, res, ARRAY_SIZE(res), NULL, 0);
}

View File

@ -1,361 +0,0 @@
/*
* MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* Based on code from Freescale,
* Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <asm-generic/bug.h>
static struct mxc_gpio_port *mxc_gpio_ports;
static int gpio_table_size;
#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2())
#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00)
#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04)
#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08)
#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C)
#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10)
#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14)
#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18)
#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0)
#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1)
#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2)
#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3)
#define GPIO_INT_NONE 0x4
/* Note: This driver assumes 32 GPIOs are handled in one register */
static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)
{
__raw_writel(1 << index, port->base + GPIO_ISR);
}
static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,
int enable)
{
u32 l;
l = __raw_readl(port->base + GPIO_IMR);
l = (l & (~(1 << index))) | (!!enable << index);
__raw_writel(l, port->base + GPIO_IMR);
}
static void gpio_ack_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
_clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f);
}
static void gpio_mask_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0);
}
static void gpio_unmask_irq(struct irq_data *d)
{
u32 gpio = irq_to_gpio(d->irq);
_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
}
static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
static int gpio_set_irq_type(struct irq_data *d, u32 type)
{
u32 gpio = irq_to_gpio(d->irq);
struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
u32 bit, val;
int edge;
void __iomem *reg = port->base;
port->both_edges &= ~(1 << (gpio & 31));
switch (type) {
case IRQ_TYPE_EDGE_RISING:
edge = GPIO_INT_RISE_EDGE;
break;
case IRQ_TYPE_EDGE_FALLING:
edge = GPIO_INT_FALL_EDGE;
break;
case IRQ_TYPE_EDGE_BOTH:
val = mxc_gpio_get(&port->chip, gpio & 31);
if (val) {
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
} else {
edge = GPIO_INT_HIGH_LEV;
pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
}
port->both_edges |= 1 << (gpio & 31);
break;
case IRQ_TYPE_LEVEL_LOW:
edge = GPIO_INT_LOW_LEV;
break;
case IRQ_TYPE_LEVEL_HIGH:
edge = GPIO_INT_HIGH_LEV;
break;
default:
return -EINVAL;
}
reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
bit = gpio & 0xf;
val = __raw_readl(reg) & ~(0x3 << (bit << 1));
__raw_writel(val | (edge << (bit << 1)), reg);
_clear_gpio_irqstatus(port, gpio & 0x1f);
return 0;
}
static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
{
void __iomem *reg = port->base;
u32 bit, val;
int edge;
reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
bit = gpio & 0xf;
val = __raw_readl(reg);
edge = (val >> (bit << 1)) & 3;
val &= ~(0x3 << (bit << 1));
if (edge == GPIO_INT_HIGH_LEV) {
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
} else if (edge == GPIO_INT_LOW_LEV) {
edge = GPIO_INT_HIGH_LEV;
pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
} else {
pr_err("mxc: invalid configuration for GPIO %d: %x\n",
gpio, edge);
return;
}
__raw_writel(val | (edge << (bit << 1)), reg);
}
/* handle 32 interrupts in one status register */
static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
{
u32 gpio_irq_no_base = port->virtual_irq_start;
while (irq_stat != 0) {
int irqoffset = fls(irq_stat) - 1;
if (port->both_edges & (1 << irqoffset))
mxc_flip_edge(port, irqoffset);
generic_handle_irq(gpio_irq_no_base + irqoffset);
irq_stat &= ~(1 << irqoffset);
}
}
/* MX1 and MX3 has one interrupt *per* gpio port */
static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq);
irq_stat = __raw_readl(port->base + GPIO_ISR) &
__raw_readl(port->base + GPIO_IMR);
mxc_gpio_irq_handler(port, irq_stat);
}
/* MX2 has one interrupt *for all* gpio ports */
static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
int i;
u32 irq_msk, irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq);
/* walk through all interrupt status registers */
for (i = 0; i < gpio_table_size; i++) {
irq_msk = __raw_readl(port[i].base + GPIO_IMR);
if (!irq_msk)
continue;
irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk;
if (irq_stat)
mxc_gpio_irq_handler(&port[i], irq_stat);
}
}
/*
* Set interrupt number "irq" in the GPIO as a wake-up source.
* While system is running, all registered GPIO interrupts need to have
* wake-up enabled. When system is suspended, only selected GPIO interrupts
* need to have wake-up enabled.
* @param irq interrupt source number
* @param enable enable as wake-up if equal to non-zero
* @return This function returns 0 on success.
*/
static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
{
u32 gpio = irq_to_gpio(d->irq);
u32 gpio_idx = gpio & 0x1F;
struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
if (enable) {
if (port->irq_high && (gpio_idx >= 16))
enable_irq_wake(port->irq_high);
else
enable_irq_wake(port->irq);
} else {
if (port->irq_high && (gpio_idx >= 16))
disable_irq_wake(port->irq_high);
else
disable_irq_wake(port->irq);
}
return 0;
}
static struct irq_chip gpio_irq_chip = {
.name = "GPIO",
.irq_ack = gpio_ack_irq,
.irq_mask = gpio_mask_irq,
.irq_unmask = gpio_unmask_irq,
.irq_set_type = gpio_set_irq_type,
.irq_set_wake = gpio_set_wake_irq,
};
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
int dir)
{
struct mxc_gpio_port *port =
container_of(chip, struct mxc_gpio_port, chip);
u32 l;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
l = __raw_readl(port->base + GPIO_GDIR);
if (dir)
l |= 1 << offset;
else
l &= ~(1 << offset);
__raw_writel(l, port->base + GPIO_GDIR);
spin_unlock_irqrestore(&port->lock, flags);
}
static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct mxc_gpio_port *port =
container_of(chip, struct mxc_gpio_port, chip);
void __iomem *reg = port->base + GPIO_DR;
u32 l;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
__raw_writel(l, reg);
spin_unlock_irqrestore(&port->lock, flags);
}
static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct mxc_gpio_port *port =
container_of(chip, struct mxc_gpio_port, chip);
return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
}
static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
_set_gpio_direction(chip, offset, 0);
return 0;
}
static int mxc_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
mxc_gpio_set(chip, offset, value);
_set_gpio_direction(chip, offset, 1);
return 0;
}
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
{
int i, j;
/* save for local usage */
mxc_gpio_ports = port;
gpio_table_size = cnt;
printk(KERN_INFO "MXC GPIO hardware\n");
for (i = 0; i < cnt; i++) {
/* disable the interrupt and clear the status */
__raw_writel(0, port[i].base + GPIO_IMR);
__raw_writel(~0, port[i].base + GPIO_ISR);
for (j = port[i].virtual_irq_start;
j < port[i].virtual_irq_start + 32; j++) {
irq_set_lockdep_class(j, &gpio_lock_class);
irq_set_chip_and_handler(j, &gpio_irq_chip,
handle_level_irq);
set_irq_flags(j, IRQF_VALID);
}
/* register gpio chip */
port[i].chip.direction_input = mxc_gpio_direction_input;
port[i].chip.direction_output = mxc_gpio_direction_output;
port[i].chip.get = mxc_gpio_get;
port[i].chip.set = mxc_gpio_set;
port[i].chip.base = i * 32;
port[i].chip.ngpio = 32;
spin_lock_init(&port[i].lock);
/* its a serious configuration bug when it fails */
BUG_ON( gpiochip_add(&port[i].chip) < 0 );
if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
/* setup one handler for each entry */
irq_set_chained_handler(port[i].irq,
mx3_gpio_irq_handler);
irq_set_handler_data(port[i].irq, &port[i]);
if (port[i].irq_high) {
/* setup handler for GPIO 16 to 31 */
irq_set_chained_handler(port[i].irq_high,
mx3_gpio_irq_handler);
irq_set_handler_data(port[i].irq_high,
&port[i]);
}
}
}
if (cpu_is_mx2()) {
/* setup one handler for all GPIO interrupts */
irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
irq_set_handler_data(port[0].irq, port);
}
return 0;
}

View File

@ -43,6 +43,15 @@ extern void mx35_init_irq(void);
extern void mx50_init_irq(void);
extern void mx51_init_irq(void);
extern void mx53_init_irq(void);
extern void imx1_soc_init(void);
extern void imx21_soc_init(void);
extern void imx25_soc_init(void);
extern void imx27_soc_init(void);
extern void imx31_soc_init(void);
extern void imx35_soc_init(void);
extern void imx50_soc_init(void);
extern void imx51_soc_init(void);
extern void imx53_soc_init(void);
extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref);
@ -55,7 +64,8 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2);
extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2);
extern int mxc_register_gpios(void);
extern struct platform_device *mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
extern int mxc_register_device(struct platform_device *pdev, void *data);
extern void mxc_set_cpu_type(unsigned int type);
extern void mxc_arch_reset_init(void __iomem *);

View File

@ -10,6 +10,8 @@
#include <linux/platform_device.h>
#include <linux/init.h>
extern struct device mxc_aips_bus;
struct platform_device *imx_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,

View File

@ -36,31 +36,4 @@
#define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio))
#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
struct mxc_gpio_port {
void __iomem *base;
int irq;
int irq_high;
int virtual_irq_start;
struct gpio_chip chip;
u32 both_edges;
spinlock_t lock;
};
#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high) \
{ \
.chip.label = "gpio-" #_id, \
.irq = _irq, \
.irq_high = _irq_high, \
.base = soc ## _IO_ADDRESS( \
soc ## _GPIO ## _hwid ## _BASE_ADDR), \
.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32, \
}
#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq) \
DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid) \
DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
int mxc_gpio_init(struct mxc_gpio_port*, int);
#endif

View File

@ -11,6 +11,8 @@
#ifndef __ASM_ARCH_MXC_IRQS_H__
#define __ASM_ARCH_MXC_IRQS_H__
#include <asm-generic/gpio.h>
/*
* SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
*/
@ -22,30 +24,13 @@
#define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS
/* these are ordered by size to support multi-SoC kernels */
#if defined CONFIG_SOC_IMX53
#define MXC_GPIO_IRQS (32 * 7)
#elif defined CONFIG_ARCH_MX2
#define MXC_GPIO_IRQS (32 * 6)
#elif defined CONFIG_SOC_IMX50
#define MXC_GPIO_IRQS (32 * 6)
#elif defined CONFIG_ARCH_MX1
#define MXC_GPIO_IRQS (32 * 4)
#elif defined CONFIG_ARCH_MX25
#define MXC_GPIO_IRQS (32 * 4)
#elif defined CONFIG_SOC_IMX51
#define MXC_GPIO_IRQS (32 * 4)
#elif defined CONFIG_ARCH_MX3
#define MXC_GPIO_IRQS (32 * 3)
#endif
/*
* The next 16 interrupts are for board specific purposes. Since
* the kernel can only run on one machine at a time, we can re-use
* these. If you need more, increase MXC_BOARD_IRQS, but keep it
* within sensible limits.
*/
#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS)
#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + ARCH_NR_GPIOS)
#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
#define MXC_BOARD_IRQS 80

View File

@ -174,12 +174,32 @@ struct omap_gpio_dev_attr {
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
};
struct omap_gpio_reg_offs {
u16 revision;
u16 direction;
u16 datain;
u16 dataout;
u16 set_dataout;
u16 clr_dataout;
u16 irqstatus;
u16 irqstatus2;
u16 irqenable;
u16 set_irqenable;
u16 clr_irqenable;
u16 debounce;
u16 debounce_en;
bool irqenable_inv;
};
struct omap_gpio_platform_data {
u16 virtual_irq_start;
int bank_type;
int bank_width; /* GPIO bank width */
int bank_stride; /* Only needed for omap1 MPUIO */
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
struct omap_gpio_reg_offs *regs;
};
/* TODO: Analyze removing gpio_bank_count usage from driver code */

View File

@ -55,14 +55,6 @@ config PPC_MPC5200_BUGFIX
It is safe to say 'Y' here
config PPC_MPC5200_GPIO
bool "MPC5200 GPIO support"
depends on PPC_MPC52xx
select ARCH_REQUIRE_GPIOLIB
select GENERIC_GPIO
help
Enable gpiolib support for mpc5200 based boards
config PPC_MPC5200_LPBFIFO
tristate "MPC5200 LocalPlus bus FIFO driver"
depends on PPC_MPC52xx

View File

@ -14,5 +14,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y)
obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o
endif
obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o
obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o

View File

@ -63,33 +63,58 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
config GPIO_GENERIC
tristate
# put drivers in the right section, in alphabetical order
config GPIO_DA9052
tristate "Dialog DA9052 GPIO"
depends on PMIC_DA9052
help
Say yes here to enable the GPIO driver for the DA9052 chip.
config GPIO_MAX730X
tristate
comment "Memory mapped GPIO drivers:"
config GPIO_BASIC_MMIO_CORE
tristate
config GPIO_GENERIC_PLATFORM
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
select GPIO_GENERIC
help
Provides core functionality for basic memory-mapped GPIO controllers.
config GPIO_BASIC_MMIO
tristate "Basic memory-mapped GPIO controllers support"
select GPIO_BASIC_MMIO_CORE
help
Say yes here to support basic memory-mapped GPIO controllers.
Say yes here to support basic platform_device memory-mapped GPIO controllers.
config GPIO_IT8761E
tristate "IT8761E GPIO support"
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
config GPIO_EP93XX
def_bool y
depends on ARCH_EP93XX
select GPIO_GENERIC
config GPIO_EXYNOS4
def_bool y
depends on CPU_EXYNOS4210
config GPIO_MPC5200
def_bool y
depends on PPC_MPC52xx
config GPIO_MXC
def_bool y
depends on ARCH_MXC
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
config GPIO_MXS
def_bool y
depends on ARCH_MXS
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
config GPIO_PLAT_SAMSUNG
def_bool y
depends on SAMSUNG_GPIOLIB_4BIT
@ -137,9 +162,6 @@ config GPIO_SCH
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
This driver can also be built as a module. If so, the module
will be called sch-gpio.
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on MFD_SUPPORT && PCI
@ -202,9 +224,6 @@ config GPIO_PCA953X
16 bits: pca9535, pca9539, pca9555, tca6416
This driver can also be built as a module. If so, the module
will be called pca953x.
config GPIO_PCA953X_IRQ
bool "Interrupt controller support for PCA953x"
depends on GPIO_PCA953X=y
@ -296,17 +315,12 @@ config GPIO_ADP5520
This option enables support for on-chip GPIO found
on Analog Devices ADP5520 PMICs.
To compile this driver as a module, choose M here: the module will
be called adp5520-gpio.
config GPIO_ADP5588
tristate "ADP5588 I2C GPIO expander"
depends on I2C
help
This option enables support for 18 GPIOs found
on Analog Devices ADP5588 GPIO Expanders.
To compile this driver as a module, choose M here: the module will be
called adp5588-gpio.
config GPIO_ADP5588_IRQ
bool "Interrupt controller support for ADP5588"
@ -398,10 +412,11 @@ config GPIO_MAX7301
GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
config GPIO_MCP23S08
tristate "Microchip MCP23Sxx I/O expander"
depends on SPI_MASTER
tristate "Microchip MCP23xxx I/O expander"
depends on SPI_MASTER || I2C
help
SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
config GPIO_MC33880
@ -428,9 +443,6 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
To compile this driver as a module, choose M here: the
module will be called ucb1400_gpio.
comment "MODULbus GPIO expanders:"
config GPIO_JANZ_TTL
@ -441,7 +453,7 @@ config GPIO_JANZ_TTL
This driver provides support for driving the pins in output
mode only. Input mode is not supported.
config AB8500_GPIO
config GPIO_AB8500
bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
depends on AB8500_CORE && BROKEN
help

View File

@ -4,47 +4,56 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o
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
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.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
obj-$(CONFIG_GPIO_MAX7301) += max7301.o
obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_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
obj-$(CONFIG_GPIO_PL061) += pl061.o
obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o
obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
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_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.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
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o

View File

@ -16,9 +16,6 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#define GEN_74X164_GPIO_COUNT 8
struct gen_74x164_chip {
struct spi_device *spi;
struct gpio_chip gpio_chip;
@ -26,9 +23,7 @@ struct gen_74x164_chip {
u8 port_config;
};
static void gen_74x164_set_value(struct gpio_chip *, unsigned, int);
static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
{
return container_of(gc, struct gen_74x164_chip, gpio_chip);
}
@ -39,16 +34,9 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
&chip->port_config, sizeof(chip->port_config));
}
static int gen_74x164_direction_output(struct gpio_chip *gc,
unsigned offset, int val)
{
gen_74x164_set_value(gc, offset, val);
return 0;
}
static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{
struct gen_74x164_chip *chip = gpio_to_chip(gc);
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
int ret;
mutex_lock(&chip->lock);
@ -61,7 +49,7 @@ static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
struct gen_74x164_chip *chip = gpio_to_chip(gc);
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
mutex_lock(&chip->lock);
if (val)
@ -73,6 +61,13 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
mutex_unlock(&chip->lock);
}
static int gen_74x164_direction_output(struct gpio_chip *gc,
unsigned offset, int val)
{
gen_74x164_set_value(gc, offset, val);
return 0;
}
static int __devinit gen_74x164_probe(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
@ -104,12 +99,12 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
chip->spi = spi;
chip->gpio_chip.label = GEN_74X164_DRIVER_NAME,
chip->gpio_chip.label = spi->modalias;
chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT;
chip->gpio_chip.ngpio = 8;
chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
@ -157,7 +152,7 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
static struct spi_driver gen_74x164_driver = {
.driver = {
.name = GEN_74X164_DRIVER_NAME,
.name = "74x164",
.owner = THIS_MODULE,
},
.probe = gen_74x164_probe,

277
drivers/gpio/gpio-da9052.c Normal file
View File

@ -0,0 +1,277 @@
/*
* GPIO Driver for Dialog DA9052 PMICs.
*
* Copyright(c) 2011 Dialog Semiconductor Ltd.
*
* Author: David Dajun Chen <dchen@diasemi.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/syscalls.h>
#include <linux/seq_file.h>
#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h>
#include <linux/mfd/da9052/pdata.h>
#include <linux/mfd/da9052/gpio.h>
#define DA9052_INPUT 1
#define DA9052_OUTPUT_OPENDRAIN 2
#define DA9052_OUTPUT_PUSHPULL 3
#define DA9052_SUPPLY_VDD_IO1 0
#define DA9052_DEBOUNCING_OFF 0
#define DA9052_DEBOUNCING_ON 1
#define DA9052_OUTPUT_LOWLEVEL 0
#define DA9052_ACTIVE_LOW 0
#define DA9052_ACTIVE_HIGH 1
#define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8
#define DA9052_GPIO_SHIFT_COUNT(no) (no%8)
#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
#define DA9052_GPIO_NIBBLE_SHIFT 4
struct da9052_gpio {
struct da9052 *da9052;
struct gpio_chip gp;
};
static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct da9052_gpio, gp);
}
static unsigned char da9052_gpio_port_odd(unsigned offset)
{
return offset % 2;
}
static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct da9052_gpio *gpio = to_da9052_gpio(gc);
int da9052_port_direction = 0;
int ret;
ret = da9052_reg_read(gpio->da9052,
DA9052_GPIO_0_1_REG + (offset >> 1));
if (ret < 0)
return ret;
if (da9052_gpio_port_odd(offset)) {
da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
da9052_port_direction >>= 4;
} else {
da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
}
switch (da9052_port_direction) {
case DA9052_INPUT:
if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
ret = da9052_reg_read(gpio->da9052,
DA9052_STATUS_C_REG);
else
ret = da9052_reg_read(gpio->da9052,
DA9052_STATUS_D_REG);
if (ret < 0)
return ret;
if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)))
return 1;
else
return 0;
case DA9052_OUTPUT_PUSHPULL:
if (da9052_gpio_port_odd(offset))
return ret & DA9052_GPIO_ODD_PORT_MODE;
else
return ret & DA9052_GPIO_EVEN_PORT_MODE;
default:
return -EINVAL;
}
}
static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct da9052_gpio *gpio = to_da9052_gpio(gc);
unsigned char register_value = 0;
int ret;
if (da9052_gpio_port_odd(offset)) {
if (value) {
register_value = DA9052_GPIO_ODD_PORT_MODE;
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_ODD_PORT_MODE,
register_value);
if (ret != 0)
dev_err(gpio->da9052->dev,
"Failed to updated gpio odd reg,%d",
ret);
}
} else {
if (value) {
register_value = DA9052_GPIO_EVEN_PORT_MODE;
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_EVEN_PORT_MODE,
register_value);
if (ret != 0)
dev_err(gpio->da9052->dev,
"Failed to updated gpio even reg,%d",
ret);
}
}
}
static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct da9052_gpio *gpio = to_da9052_gpio(gc);
unsigned char register_value;
int ret;
/* Format: function - 2 bits type - 1 bit mode - 1 bit */
register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
DA9052_DEBOUNCING_ON << 3;
if (da9052_gpio_port_odd(offset))
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_MASK_UPPER_NIBBLE,
(register_value <<
DA9052_GPIO_NIBBLE_SHIFT));
else
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_MASK_LOWER_NIBBLE,
register_value);
return ret;
}
static int da9052_gpio_direction_output(struct gpio_chip *gc,
unsigned offset, int value)
{
struct da9052_gpio *gpio = to_da9052_gpio(gc);
unsigned char register_value;
int ret;
/* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
value << 3;
if (da9052_gpio_port_odd(offset))
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_MASK_UPPER_NIBBLE,
(register_value <<
DA9052_GPIO_NIBBLE_SHIFT));
else
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
DA9052_GPIO_0_1_REG,
DA9052_GPIO_MASK_LOWER_NIBBLE,
register_value);
return ret;
}
static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
{
struct da9052_gpio *gpio = to_da9052_gpio(gc);
struct da9052 *da9052 = gpio->da9052;
return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
}
static struct gpio_chip reference_gp __devinitdata = {
.label = "da9052-gpio",
.owner = THIS_MODULE,
.get = da9052_gpio_get,
.set = da9052_gpio_set,
.direction_input = da9052_gpio_direction_input,
.direction_output = da9052_gpio_direction_output,
.to_irq = da9052_gpio_to_irq,
.can_sleep = 1;
.ngpio = 16;
.base = -1;
};
static int __devinit da9052_gpio_probe(struct platform_device *pdev)
{
struct da9052_gpio *gpio;
struct da9052_pdata *pdata;
int ret;
gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL)
return -ENOMEM;
gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
pdata = gpio->da9052->dev->platform_data;
gpio->gp = reference_gp;
if (pdata && pdata->gpio_base)
gpio->gp.base = pdata->gpio_base;
ret = gpiochip_add(&gpio->gp);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
goto err_mem;
}
platform_set_drvdata(pdev, gpio);
return 0;
err_mem:
kfree(gpio);
return ret;
}
static int __devexit da9052_gpio_remove(struct platform_device *pdev)
{
struct da9052_gpio *gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&gpio->gp);
if (ret == 0)
kfree(gpio);
return ret;
}
static struct platform_driver da9052_gpio_driver = {
.probe = da9052_gpio_probe,
.remove = __devexit_p(da9052_gpio_remove),
.driver = {
.name = "da9052-gpio",
.owner = THIS_MODULE,
},
};
static int __init da9052_gpio_init(void)
{
return platform_driver_register(&da9052_gpio_driver);
}
module_init(da9052_gpio_init);
static void __exit da9052_gpio_exit(void)
{
return platform_driver_unregister(&da9052_gpio_driver);
}
module_exit(da9052_gpio_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9052-gpio");

View File

@ -1,9 +1,8 @@
/*
* linux/arch/arm/mach-ep93xx/gpio.c
*
* Generic EP93xx GPIO handling
*
* Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
* Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com>
*
* Based on code originally from:
* linux/arch/arm/mach-ep93xx/core.c
@ -13,17 +12,23 @@
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/basic_mmio_gpio.h>
#include <mach/hardware.h>
struct ep93xx_gpio {
void __iomem *mmio_base;
struct bgpio_chip bgc[8];
};
/*************************************************************************
* Interrupt handling for EP93xx on-chip GPIOs
*************************************************************************/
@ -225,7 +230,7 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
.irq_set_type = ep93xx_gpio_irq_type,
};
void __init ep93xx_gpio_init_irq(void)
static void ep93xx_gpio_init_irq(void)
{
int gpio_irq;
@ -260,87 +265,33 @@ void __init ep93xx_gpio_init_irq(void)
/*************************************************************************
* gpiolib interface for EP93xx on-chip GPIOs
*************************************************************************/
struct ep93xx_gpio_chip {
struct gpio_chip chip;
void __iomem *data_reg;
void __iomem *data_dir_reg;
struct ep93xx_gpio_bank {
const char *label;
int data;
int dir;
int base;
bool has_debounce;
};
#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
unsigned long flags;
u8 v;
local_irq_save(flags);
v = __raw_readb(ep93xx_chip->data_dir_reg);
v &= ~(1 << offset);
__raw_writeb(v, ep93xx_chip->data_dir_reg);
local_irq_restore(flags);
return 0;
#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce) \
{ \
.label = _label, \
.data = _data, \
.dir = _dir, \
.base = _base, \
.has_debounce = _debounce, \
}
static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int val)
{
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
unsigned long flags;
int line;
u8 v;
local_irq_save(flags);
/* Set the value */
v = __raw_readb(ep93xx_chip->data_reg);
if (val)
v |= (1 << offset);
else
v &= ~(1 << offset);
__raw_writeb(v, ep93xx_chip->data_reg);
/* Drive as an output */
line = chip->base + offset;
if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
/* Ports A/B/F */
ep93xx_gpio_int_mask(line);
ep93xx_gpio_update_int_params(line >> 3);
}
v = __raw_readb(ep93xx_chip->data_dir_reg);
v |= (1 << offset);
__raw_writeb(v, ep93xx_chip->data_dir_reg);
local_irq_restore(flags);
return 0;
}
static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
}
static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
{
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
unsigned long flags;
u8 v;
local_irq_save(flags);
v = __raw_readb(ep93xx_chip->data_reg);
if (val)
v |= (1 << offset);
else
v &= ~(1 << offset);
__raw_writeb(v, ep93xx_chip->data_reg);
local_irq_restore(flags);
}
static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true),
EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true),
EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true),
EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
};
static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
unsigned offset, unsigned debounce)
@ -356,37 +307,57 @@ static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
return 0;
}
#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \
{ \
.chip = { \
.label = name, \
.direction_input = ep93xx_gpio_direction_input, \
.direction_output = ep93xx_gpio_direction_output, \
.get = ep93xx_gpio_get, \
.set = ep93xx_gpio_set, \
.base = base_gpio, \
.ngpio = 8, \
}, \
.data_reg = EP93XX_GPIO_REG(dr), \
.data_dir_reg = EP93XX_GPIO_REG(ddr), \
static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
{
void __iomem *data = mmio_base + bank->data;
void __iomem *dir = mmio_base + bank->dir;
int err;
err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
if (err)
return err;
bgc->gc.label = bank->label;
bgc->gc.base = bank->base;
if (bank->has_debounce)
bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
return gpiochip_add(&bgc->gc);
}
static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
EP93XX_GPIO_BANK("C", 0x08, 0x18, 40),
EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
EP93XX_GPIO_BANK("F", 0x30, 0x34, 16),
EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
};
void __init ep93xx_gpio_init(void)
static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
{
struct ep93xx_gpio *ep93xx_gpio;
struct resource *res;
void __iomem *mmio;
int i;
int ret;
/* Set Ports C, D, E, G, and H for GPIO use */
ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
if (!ep93xx_gpio)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENXIO;
goto exit_free;
}
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
ret = -EBUSY;
goto exit_free;
}
mmio = ioremap(res->start, resource_size(res));
if (!mmio) {
ret = -ENXIO;
goto exit_release;
}
ep93xx_gpio->mmio_base = mmio;
/* Default all ports to GPIO */
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
EP93XX_SYSCON_DEVCFG_GONK |
EP93XX_SYSCON_DEVCFG_EONIDE |
@ -394,17 +365,41 @@ void __init ep93xx_gpio_init(void)
EP93XX_SYSCON_DEVCFG_HONIDE);
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
/*
* Ports A, B, and F support input debouncing when
* used as interrupts.
*/
if (!strcmp(chip->label, "A") ||
!strcmp(chip->label, "B") ||
!strcmp(chip->label, "F"))
chip->set_debounce = ep93xx_gpio_set_debounce;
if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
bank->label);
}
gpiochip_add(chip);
ep93xx_gpio_init_irq();
return 0;
exit_release:
release_mem_region(res->start, resource_size(res));
exit_free:
kfree(ep93xx_gpio);
dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
return ret;
}
static struct platform_driver ep93xx_gpio_driver = {
.driver = {
.name = "gpio-ep93xx",
.owner = THIS_MODULE,
},
.probe = ep93xx_gpio_probe,
};
static int __init ep93xx_gpio_init(void)
{
return platform_driver_register(&ep93xx_gpio_driver);
}
postcore_initcall(ep93xx_gpio_init);
MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> "
"H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_DESCRIPTION("EP93XX GPIO driver");
MODULE_LICENSE("GPL");

View File

@ -1,10 +1,9 @@
/* linux/arch/arm/mach-exynos4/gpiolib.c
/*
* EXYNOS4 - GPIOlib support
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS4 - GPIOlib support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.

View File

@ -1,5 +1,5 @@
/*
* Driver for basic memory-mapped GPIO controllers.
* Generic driver for memory-mapped GPIO controllers.
*
* Copyright 2008 MontaVista Software, Inc.
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
@ -404,7 +404,7 @@ int __devinit bgpio_init(struct bgpio_chip *bgc,
}
EXPORT_SYMBOL_GPL(bgpio_init);
#ifdef CONFIG_GPIO_BASIC_MMIO
#ifdef CONFIG_GPIO_GENERIC_PLATFORM
static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
@ -541,7 +541,7 @@ static void __exit bgpio_platform_exit(void)
}
module_exit(bgpio_platform_exit);
#endif /* CONFIG_GPIO_BASIC_MMIO */
#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");

View File

@ -1,5 +1,5 @@
/*
* it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
* GPIO interface for IT8761E Super I/O chip
*
* Author: Denis Turischev <denis@compulab.co.il>
*

View File

@ -1,4 +1,6 @@
/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
/*
* Moorestown platform Langwell chip GPIO driver
*
* Copyright (c) 2008 - 2009, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,6 +1,4 @@
/*
* drivers/gpio/max7300.c
*
* Copyright (C) 2009 Wolfram Sang, Pengutronix
*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,6 +1,4 @@
/*
* drivers/gpio/max7301.c
*
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix

View File

@ -1,6 +1,4 @@
/**
* drivers/gpio/max7301.c
*
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix

View File

@ -1,5 +1,5 @@
/*
* max732x.c - I2C Port Expander with 8/16 I/O
* MAX732x I2C Port Expander with 8/16 I/O
*
* Copyright (C) 2007 Marvell International Ltd.
* Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>

Some files were not shown because too many files have changed in this diff Show More