aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-clps711x/include/mach/gpio.h13
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-clps711x.c163
5 files changed, 182 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 73067efd4845..f456cf4ae3ca 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -364,6 +364,7 @@ config ARCH_CNS3XXX
364 364
365config ARCH_CLPS711X 365config ARCH_CLPS711X
366 bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" 366 bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
367 select ARCH_REQUIRE_GPIOLIB
367 select ARCH_USES_GETTIMEOFFSET 368 select ARCH_USES_GETTIMEOFFSET
368 select CLKDEV_LOOKUP 369 select CLKDEV_LOOKUP
369 select COMMON_CLK 370 select COMMON_CLK
diff --git a/arch/arm/mach-clps711x/include/mach/gpio.h b/arch/arm/mach-clps711x/include/mach/gpio.h
new file mode 100644
index 000000000000..8ac6889fabcd
--- /dev/null
+++ b/arch/arm/mach-clps711x/include/mach/gpio.h
@@ -0,0 +1,13 @@
1/*
2 * This file contains the CLPS711X GPIO definitions.
3 *
4 * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12/* Simple helper for convert port & pin to GPIO number */
13#define CLPS711X_GPIO(port, bit) ((port) * 8 + (bit))
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 150eeb705fbc..9e3fb3438718 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -102,6 +102,10 @@ config GPIO_MAX730X
102 102
103comment "Memory mapped GPIO drivers:" 103comment "Memory mapped GPIO drivers:"
104 104
105config GPIO_CLPS711X
106 def_bool y
107 depends on ARCH_CLPS711X
108
105config GPIO_GENERIC_PLATFORM 109config GPIO_GENERIC_PLATFORM
106 tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" 110 tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
107 select GPIO_GENERIC 111 select GPIO_GENERIC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e6f8e379a2ec..1c1b63fcaeb3 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
16obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o 16obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
17obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o 17obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
18obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o 18obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
19obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
19obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o 20obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
20obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 21obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
21obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o 22obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
new file mode 100644
index 000000000000..ea21822b3de9
--- /dev/null
+++ b/drivers/gpio/gpio-clps711x.c
@@ -0,0 +1,163 @@
1/*
2 * CLPS711X GPIO driver
3 *
4 * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/io.h>
13#include <linux/slab.h>
14#include <linux/gpio.h>
15#include <linux/module.h>
16#include <linux/spinlock.h>
17#include <linux/platform_device.h>
18
19#include <mach/hardware.h>
20
21#define CLPS711X_GPIO_PORTS 5
22#define CLPS711X_GPIO_NAME "gpio-clps711x"
23
24struct clps711x_gpio {
25 struct gpio_chip chip[CLPS711X_GPIO_PORTS];
26 spinlock_t lock;
27};
28
29static void __iomem *clps711x_ports[] = {
30 CLPS711X_VIRT_BASE + PADR,
31 CLPS711X_VIRT_BASE + PBDR,
32 CLPS711X_VIRT_BASE + PCDR,
33 CLPS711X_VIRT_BASE + PDDR,
34 CLPS711X_VIRT_BASE + PEDR,
35};
36
37static void __iomem *clps711x_pdirs[] = {
38 CLPS711X_VIRT_BASE + PADDR,
39 CLPS711X_VIRT_BASE + PBDDR,
40 CLPS711X_VIRT_BASE + PCDDR,
41 CLPS711X_VIRT_BASE + PDDDR,
42 CLPS711X_VIRT_BASE + PEDDR,
43};
44
45#define clps711x_port(x) clps711x_ports[x->base / 8]
46#define clps711x_pdir(x) clps711x_pdirs[x->base / 8]
47
48static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
49{
50 return !!readb(clps711x_port(chip)) & (1 << offset);
51}
52
53static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
54 int value)
55{
56 int tmp;
57 unsigned long flags;
58 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
59
60 spin_lock_irqsave(&gpio->lock, flags);
61 tmp = readb(clps711x_port(chip)) & ~(1 << offset);
62 if (value)
63 tmp |= 1 << offset;
64 writeb(tmp, clps711x_port(chip));
65 spin_unlock_irqrestore(&gpio->lock, flags);
66}
67
68static int gpio_clps711x_direction_in(struct gpio_chip *chip, unsigned offset)
69{
70 int tmp;
71 unsigned long flags;
72 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
73
74 spin_lock_irqsave(&gpio->lock, flags);
75 tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
76 writeb(tmp, clps711x_pdir(chip));
77 spin_unlock_irqrestore(&gpio->lock, flags);
78
79 return 0;
80}
81
82static int gpio_clps711x_direction_out(struct gpio_chip *chip, unsigned offset,
83 int value)
84{
85 int tmp;
86 unsigned long flags;
87 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
88
89 spin_lock_irqsave(&gpio->lock, flags);
90 tmp = readb(clps711x_pdir(chip)) | (1 << offset);
91 writeb(tmp, clps711x_pdir(chip));
92 tmp = readb(clps711x_port(chip)) & ~(1 << offset);
93 if (value)
94 tmp |= 1 << offset;
95 writeb(tmp, clps711x_port(chip));
96 spin_unlock_irqrestore(&gpio->lock, flags);
97
98 return 0;
99}
100
101struct clps711x_gpio_port {
102 char *name;
103 int nr;
104};
105
106static const struct clps711x_gpio_port clps711x_gpio_ports[] __initconst = {
107 { "PORTA", 8, },
108 { "PORTB", 8, },
109 { "PORTC", 8, },
110 { "PORTD", 8, },
111 { "PORTE", 3, },
112};
113
114static int __init gpio_clps711x_init(void)
115{
116 int i;
117 struct platform_device *pdev;
118 struct clps711x_gpio *gpio;
119
120 pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
121 if (!pdev) {
122 pr_err("Cannot create platform device: %s\n",
123 CLPS711X_GPIO_NAME);
124 return -ENOMEM;
125 }
126
127 platform_device_add(pdev);
128
129 gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
130 GFP_KERNEL);
131 if (!gpio) {
132 dev_err(&pdev->dev, "GPIO allocating memory error\n");
133 platform_device_del(pdev);
134 platform_device_put(pdev);
135 return -ENOMEM;
136 }
137
138 platform_set_drvdata(pdev, gpio);
139
140 spin_lock_init(&gpio->lock);
141
142 for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
143 gpio->chip[i].owner = THIS_MODULE;
144 gpio->chip[i].dev = &pdev->dev;
145 gpio->chip[i].label = clps711x_gpio_ports[i].name;
146 gpio->chip[i].base = i * 8;
147 gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr;
148 gpio->chip[i].direction_input = gpio_clps711x_direction_in;
149 gpio->chip[i].get = gpio_clps711x_get;
150 gpio->chip[i].direction_output = gpio_clps711x_direction_out;
151 gpio->chip[i].set = gpio_clps711x_set;
152 WARN_ON(gpiochip_add(&gpio->chip[i]));
153 }
154
155 dev_info(&pdev->dev, "GPIO driver initialized\n");
156
157 return 0;
158}
159arch_initcall(gpio_clps711x_init);
160
161MODULE_LICENSE("GPL v2");
162MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
163MODULE_DESCRIPTION("CLPS711X GPIO driver");