diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-11 18:57:17 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-11 18:57:51 -0400 |
commit | ea36b02269e49ad9dad926197de2ceab377c4c95 (patch) | |
tree | d80e510716a055d325d670238957854d2a6715d6 /drivers/gpio | |
parent | b67172ec0043bdc122aca334164979bd001450b6 (diff) | |
parent | 70423a379d5457f19b3b2ebc4239faebe64c602d (diff) |
Merge branch 'clps711x/soc' into next/soc
From Alexander Shiyan, this is a series of cleanups of clps711x, movig it
closer to multiplatform and cleans up a bunch of old code.
* clps711x/soc:
ARM: clps711x: Update defconfig
ARM: clps711x: Add support for SYSCON driver
ARM: clps711x: edb7211: Control LCD backlight via PWM
ARM: clps711x: edb7211: Add support for I2C
ARM: clps711x: Optimize interrupt handling
ARM: clps711x: Add clocksource framework
ARM: clps711x: Replace "arch_initcall" in common code with ".init_early"
ARM: clps711x: Move specific definitions from hardware.h to boards files
ARM: clps711x: p720t: Define PLD registers as GPIOs
ARM: clps711x: autcpu12: Move remaining specific definitions to board file
ARM: clps711x: autcpu12: Special driver for handling memory is removed
ARM: clps711x: autcpu12: Add support for NOR flash
ARM: clps711x: autcpu12: Move LCD DPOT definitions to board file
ARM: clps711x: Set PLL clock to zero if we work from 13 mHz source
ARM: clps711x: Remove NEED_MACH_MEMORY_H dependency
ARM: clps711x: Re-add GPIO support
GPIO: clps711x: Add DT support
GPIO: clps711x: Rewrite driver for using generic GPIO code
+ Linux 3.10-rc4
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-clps711x.c | 236 |
2 files changed, 72 insertions, 169 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 573c449c49b9..23d1d0155bb3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -109,8 +109,11 @@ config GPIO_MAX730X | |||
109 | comment "Memory mapped GPIO drivers:" | 109 | comment "Memory mapped GPIO drivers:" |
110 | 110 | ||
111 | config GPIO_CLPS711X | 111 | config GPIO_CLPS711X |
112 | def_bool y | 112 | tristate "CLPS711X GPIO support" |
113 | depends on ARCH_CLPS711X | 113 | depends on ARCH_CLPS711X |
114 | select GPIO_GENERIC | ||
115 | help | ||
116 | Say yes here to support GPIO on CLPS711X SoCs. | ||
114 | 117 | ||
115 | config GPIO_GENERIC_PLATFORM | 118 | config GPIO_GENERIC_PLATFORM |
116 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" | 119 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" |
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index ce63b75b13f5..0edaf2ce9266 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * CLPS711X GPIO driver | 2 | * CLPS711X GPIO driver |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru> | 4 | * Copyright (C) 2012,2013 Alexander Shiyan <shc_work@mail.ru> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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 | 7 | * it under the terms of the GNU General Public License as published by |
@@ -9,191 +9,91 @@ | |||
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/io.h> | 12 | #include <linux/err.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/gpio.h> | 13 | #include <linux/gpio.h> |
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/spinlock.h> | 15 | #include <linux/basic_mmio_gpio.h> |
17 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
18 | 17 | ||
19 | #include <mach/hardware.h> | 18 | static int clps711x_gpio_probe(struct platform_device *pdev) |
20 | |||
21 | #define CLPS711X_GPIO_PORTS 5 | ||
22 | #define CLPS711X_GPIO_NAME "gpio-clps711x" | ||
23 | |||
24 | struct clps711x_gpio { | ||
25 | struct gpio_chip chip[CLPS711X_GPIO_PORTS]; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static 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 | |||
37 | static 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 | |||
48 | static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset) | ||
49 | { | 19 | { |
50 | return !!(readb(clps711x_port(chip)) & (1 << offset)); | 20 | struct device_node *np = pdev->dev.of_node; |
51 | } | 21 | void __iomem *dat, *dir; |
22 | struct bgpio_chip *bgc; | ||
23 | struct resource *res; | ||
24 | int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id; | ||
52 | 25 | ||
53 | static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset, | 26 | if ((id < 0) || (id > 4)) |
54 | int value) | 27 | return -ENODEV; |
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 | |||
68 | static int gpio_clps711x_dir_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 | 28 | ||
74 | spin_lock_irqsave(&gpio->lock, flags); | 29 | bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); |
75 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | 30 | if (!bgc) |
76 | writeb(tmp, clps711x_pdir(chip)); | 31 | return -ENOMEM; |
77 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
78 | 32 | ||
79 | return 0; | 33 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
80 | } | 34 | dat = devm_ioremap_resource(&pdev->dev, res); |
35 | if (IS_ERR(dat)) | ||
36 | return PTR_ERR(dat); | ||
37 | |||
38 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
39 | dir = devm_ioremap_resource(&pdev->dev, res); | ||
40 | if (IS_ERR(dir)) | ||
41 | return PTR_ERR(dir); | ||
42 | |||
43 | switch (id) { | ||
44 | case 3: | ||
45 | /* PORTD is inverted logic for direction register */ | ||
46 | err = bgpio_init(bgc, &pdev->dev, 1, dat, NULL, NULL, | ||
47 | NULL, dir, 0); | ||
48 | break; | ||
49 | default: | ||
50 | err = bgpio_init(bgc, &pdev->dev, 1, dat, NULL, NULL, | ||
51 | dir, NULL, 0); | ||
52 | break; | ||
53 | } | ||
81 | 54 | ||
82 | static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset, | 55 | if (err) |
83 | int value) | 56 | return err; |
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 | 57 | ||
101 | static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset) | 58 | switch (id) { |
102 | { | 59 | case 4: |
103 | int tmp; | 60 | /* PORTE is 3 lines only */ |
104 | unsigned long flags; | 61 | bgc->gc.ngpio = 3; |
105 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | 62 | break; |
63 | default: | ||
64 | break; | ||
65 | } | ||
106 | 66 | ||
107 | spin_lock_irqsave(&gpio->lock, flags); | 67 | bgc->gc.base = id * 8; |
108 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | 68 | platform_set_drvdata(pdev, bgc); |
109 | writeb(tmp, clps711x_pdir(chip)); | ||
110 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
111 | 69 | ||
112 | return 0; | 70 | return gpiochip_add(&bgc->gc); |
113 | } | 71 | } |
114 | 72 | ||
115 | static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset, | 73 | static int clps711x_gpio_remove(struct platform_device *pdev) |
116 | int value) | ||
117 | { | 74 | { |
118 | int tmp; | 75 | struct bgpio_chip *bgc = platform_get_drvdata(pdev); |
119 | unsigned long flags; | 76 | |
120 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | 77 | return bgpio_remove(bgc); |
121 | |||
122 | spin_lock_irqsave(&gpio->lock, flags); | ||
123 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
124 | writeb(tmp, clps711x_pdir(chip)); | ||
125 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
126 | if (value) | ||
127 | tmp |= 1 << offset; | ||
128 | writeb(tmp, clps711x_port(chip)); | ||
129 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
130 | |||
131 | return 0; | ||
132 | } | 78 | } |
133 | 79 | ||
134 | static struct { | 80 | static const struct of_device_id clps711x_gpio_ids[] = { |
135 | char *name; | 81 | { .compatible = "cirrus,clps711x-gpio" }, |
136 | int nr; | 82 | { } |
137 | int inv_dir; | ||
138 | } clps711x_gpio_ports[] __initconst = { | ||
139 | { "PORTA", 8, 0, }, | ||
140 | { "PORTB", 8, 0, }, | ||
141 | { "PORTC", 8, 0, }, | ||
142 | { "PORTD", 8, 1, }, | ||
143 | { "PORTE", 3, 0, }, | ||
144 | }; | 83 | }; |
84 | MODULE_DEVICE_TABLE(of, clps711x_gpio_ids); | ||
85 | |||
86 | static struct platform_driver clps711x_gpio_driver = { | ||
87 | .driver = { | ||
88 | .name = "clps711x-gpio", | ||
89 | .owner = THIS_MODULE, | ||
90 | .of_match_table = of_match_ptr(clps711x_gpio_ids), | ||
91 | }, | ||
92 | .probe = clps711x_gpio_probe, | ||
93 | .remove = clps711x_gpio_remove, | ||
94 | }; | ||
95 | module_platform_driver(clps711x_gpio_driver); | ||
145 | 96 | ||
146 | static int __init gpio_clps711x_init(void) | 97 | MODULE_LICENSE("GPL"); |
147 | { | ||
148 | int i; | ||
149 | struct platform_device *pdev; | ||
150 | struct clps711x_gpio *gpio; | ||
151 | |||
152 | pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0); | ||
153 | if (!pdev) { | ||
154 | pr_err("Cannot create platform device: %s\n", | ||
155 | CLPS711X_GPIO_NAME); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | platform_device_add(pdev); | ||
160 | |||
161 | gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio), | ||
162 | GFP_KERNEL); | ||
163 | if (!gpio) { | ||
164 | dev_err(&pdev->dev, "GPIO allocating memory error\n"); | ||
165 | platform_device_unregister(pdev); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | platform_set_drvdata(pdev, gpio); | ||
170 | |||
171 | spin_lock_init(&gpio->lock); | ||
172 | |||
173 | for (i = 0; i < CLPS711X_GPIO_PORTS; i++) { | ||
174 | gpio->chip[i].owner = THIS_MODULE; | ||
175 | gpio->chip[i].dev = &pdev->dev; | ||
176 | gpio->chip[i].label = clps711x_gpio_ports[i].name; | ||
177 | gpio->chip[i].base = i * 8; | ||
178 | gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr; | ||
179 | gpio->chip[i].get = gpio_clps711x_get; | ||
180 | gpio->chip[i].set = gpio_clps711x_set; | ||
181 | if (!clps711x_gpio_ports[i].inv_dir) { | ||
182 | gpio->chip[i].direction_input = gpio_clps711x_dir_in; | ||
183 | gpio->chip[i].direction_output = gpio_clps711x_dir_out; | ||
184 | } else { | ||
185 | gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv; | ||
186 | gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv; | ||
187 | } | ||
188 | WARN_ON(gpiochip_add(&gpio->chip[i])); | ||
189 | } | ||
190 | |||
191 | dev_info(&pdev->dev, "GPIO driver initialized\n"); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | arch_initcall(gpio_clps711x_init); | ||
196 | |||
197 | MODULE_LICENSE("GPL v2"); | ||
198 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); | 98 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); |
199 | MODULE_DESCRIPTION("CLPS711X GPIO driver"); | 99 | MODULE_DESCRIPTION("CLPS711X GPIO driver"); |