aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/avr32/mach-at32ap/pio.c172
-rw-r--r--arch/avr32/mach-at32ap/pio.h2
-rw-r--r--include/asm-avr32/arch-at32ap/at32ap700x.h2
-rw-r--r--include/asm-avr32/arch-at32ap/gpio.h34
-rw-r--r--include/asm-avr32/arch-at32ap/irq.h4
6 files changed, 121 insertions, 94 deletions
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c816f29154c9..28e0caf4156c 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -82,6 +82,7 @@ config PLATFORM_AT32AP
82 select SUBARCH_AVR32B 82 select SUBARCH_AVR32B
83 select MMU 83 select MMU
84 select PERFORMANCE_COUNTERS 84 select PERFORMANCE_COUNTERS
85 select HAVE_GPIO_LIB
85 86
86# 87#
87# CPU types 88# CPU types
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d61a02da898c..38a8fa31c0b5 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -24,11 +24,11 @@
24#define MAX_NR_PIO_DEVICES 8 24#define MAX_NR_PIO_DEVICES 8
25 25
26struct pio_device { 26struct pio_device {
27 struct gpio_chip chip;
27 void __iomem *regs; 28 void __iomem *regs;
28 const struct platform_device *pdev; 29 const struct platform_device *pdev;
29 struct clk *clk; 30 struct clk *clk;
30 u32 pinmux_mask; 31 u32 pinmux_mask;
31 u32 gpio_mask;
32 char name[8]; 32 char name[8];
33}; 33};
34 34
@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
64 goto fail; 64 goto fail;
65 } 65 }
66 66
67 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { 67 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
68 || gpiochip_is_requested(&pio->chip, pin_index))) {
68 printk("%s: pin %u is busy\n", pio->name, pin_index); 69 printk("%s: pin %u is busy\n", pio->name, pin_index);
69 goto fail; 70 goto fail;
70 } 71 }
@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
79 if (!(flags & AT32_GPIOF_PULLUP)) 80 if (!(flags & AT32_GPIOF_PULLUP))
80 pio_writel(pio, PUDR, mask); 81 pio_writel(pio, PUDR, mask);
81 82
82 /* gpio_request NOT allowed */
83 set_bit(pin_index, &pio->gpio_mask);
84
85 return; 83 return;
86 84
87fail: 85fail:
@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
130 128
131 pio_writel(pio, PER, mask); 129 pio_writel(pio, PER, mask);
132 130
133 /* gpio_request now allowed */
134 clear_bit(pin_index, &pio->gpio_mask);
135
136 return; 131 return;
137 132
138fail: 133fail:
@@ -166,96 +161,50 @@ fail:
166 161
167/* GPIO API */ 162/* GPIO API */
168 163
169int gpio_request(unsigned int gpio, const char *label) 164static int direction_input(struct gpio_chip *chip, unsigned offset)
170{ 165{
171 struct pio_device *pio; 166 struct pio_device *pio = container_of(chip, struct pio_device, chip);
172 unsigned int pin; 167 u32 mask = 1 << offset;
173
174 pio = gpio_to_pio(gpio);
175 if (!pio)
176 return -ENODEV;
177 168
178 pin = gpio & 0x1f; 169 if (!(pio_readl(pio, PSR) & mask))
179 if (test_and_set_bit(pin, &pio->gpio_mask)) 170 return -EINVAL;
180 return -EBUSY;
181 171
172 pio_writel(pio, ODR, mask);
182 return 0; 173 return 0;
183} 174}
184EXPORT_SYMBOL(gpio_request);
185 175
186void gpio_free(unsigned int gpio) 176static int gpio_get(struct gpio_chip *chip, unsigned offset)
187{ 177{
188 struct pio_device *pio; 178 struct pio_device *pio = container_of(chip, struct pio_device, chip);
189 unsigned int pin;
190 179
191 pio = gpio_to_pio(gpio); 180 return (pio_readl(pio, PDSR) >> offset) & 1;
192 if (!pio) {
193 printk(KERN_ERR
194 "gpio: attempted to free invalid pin %u\n", gpio);
195 return;
196 }
197
198 pin = gpio & 0x1f;
199 if (!test_and_clear_bit(pin, &pio->gpio_mask))
200 printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
201 pio->name, pin);
202} 181}
203EXPORT_SYMBOL(gpio_free);
204 182
205int gpio_direction_input(unsigned int gpio) 183static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
206{
207 struct pio_device *pio;
208 unsigned int pin;
209
210 pio = gpio_to_pio(gpio);
211 if (!pio)
212 return -ENODEV;
213
214 pin = gpio & 0x1f;
215 pio_writel(pio, ODR, 1 << pin);
216
217 return 0;
218}
219EXPORT_SYMBOL(gpio_direction_input);
220 184
221int gpio_direction_output(unsigned int gpio, int value) 185static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
222{ 186{
223 struct pio_device *pio; 187 struct pio_device *pio = container_of(chip, struct pio_device, chip);
224 unsigned int pin; 188 u32 mask = 1 << offset;
225
226 pio = gpio_to_pio(gpio);
227 if (!pio)
228 return -ENODEV;
229 189
230 gpio_set_value(gpio, value); 190 if (!(pio_readl(pio, PSR) & mask))
231 191 return -EINVAL;
232 pin = gpio & 0x1f;
233 pio_writel(pio, OER, 1 << pin);
234 192
193 gpio_set(chip, offset, value);
194 pio_writel(pio, OER, mask);
235 return 0; 195 return 0;
236} 196}
237EXPORT_SYMBOL(gpio_direction_output);
238 197
239int gpio_get_value(unsigned int gpio) 198static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
240{ 199{
241 struct pio_device *pio = &pio_dev[gpio >> 5]; 200 struct pio_device *pio = container_of(chip, struct pio_device, chip);
201 u32 mask = 1 << offset;
242 202
243 return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
244}
245EXPORT_SYMBOL(gpio_get_value);
246
247void gpio_set_value(unsigned int gpio, int value)
248{
249 struct pio_device *pio = &pio_dev[gpio >> 5];
250 u32 mask;
251
252 mask = 1 << (gpio & 0x1f);
253 if (value) 203 if (value)
254 pio_writel(pio, SODR, mask); 204 pio_writel(pio, SODR, mask);
255 else 205 else
256 pio_writel(pio, CODR, mask); 206 pio_writel(pio, CODR, mask);
257} 207}
258EXPORT_SYMBOL(gpio_set_value);
259 208
260/*--------------------------------------------------------------------------*/ 209/*--------------------------------------------------------------------------*/
261 210
@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
339 288
340/*--------------------------------------------------------------------------*/ 289/*--------------------------------------------------------------------------*/
341 290
291#ifdef CONFIG_DEBUG_FS
292
293#include <linux/seq_file.h>
294
295/*
296 * This shows more info than the generic gpio dump code:
297 * pullups, deglitching, open drain drive.
298 */
299static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
300{
301 struct pio_device *pio = container_of(chip, struct pio_device, chip);
302 u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
303 unsigned i;
304 u32 mask;
305 char bank;
306
307 psr = pio_readl(pio, PSR);
308 osr = pio_readl(pio, OSR);
309 imr = pio_readl(pio, IMR);
310 pdsr = pio_readl(pio, PDSR);
311 pusr = pio_readl(pio, PUSR);
312 ifsr = pio_readl(pio, IFSR);
313 mdsr = pio_readl(pio, MDSR);
314
315 bank = 'A' + pio->pdev->id;
316
317 for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
318 const char *label;
319
320 label = gpiochip_is_requested(chip, i);
321 if (!label)
322 continue;
323
324 seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
325 chip->base + i, bank, i,
326 label,
327 (osr & mask) ? "out" : "in ",
328 (mask & pdsr) ? "hi" : "lo",
329 (mask & pusr) ? " " : "up");
330 if (ifsr & mask)
331 seq_printf(s, " deglitch");
332 if ((osr & mdsr) & mask)
333 seq_printf(s, " open-drain");
334 if (imr & mask)
335 seq_printf(s, " irq-%d edge-both",
336 gpio_to_irq(chip->base + i));
337 seq_printf(s, "\n");
338 }
339}
340
341#else
342#define pio_bank_show NULL
343#endif
344
345
346/*--------------------------------------------------------------------------*/
347
342static int __init pio_probe(struct platform_device *pdev) 348static int __init pio_probe(struct platform_device *pdev)
343{ 349{
344 struct pio_device *pio = NULL; 350 struct pio_device *pio = NULL;
@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
349 pio = &pio_dev[pdev->id]; 355 pio = &pio_dev[pdev->id];
350 BUG_ON(!pio->regs); 356 BUG_ON(!pio->regs);
351 357
358 pio->chip.label = pio->name;
359 pio->chip.base = pdev->id * 32;
360 pio->chip.ngpio = 32;
361
362 pio->chip.direction_input = direction_input;
363 pio->chip.get = gpio_get;
364 pio->chip.direction_output = direction_output;
365 pio->chip.set = gpio_set;
366 pio->chip.dbg_show = pio_bank_show;
367
368 gpiochip_add(&pio->chip);
369
352 gpio_irq_setup(pio, irq, gpio_irq_base); 370 gpio_irq_setup(pio, irq, gpio_irq_base);
353 371
354 platform_set_drvdata(pdev, pio); 372 platform_set_drvdata(pdev, pio);
@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
406 pio->pdev = pdev; 424 pio->pdev = pdev;
407 pio->regs = ioremap(regs->start, regs->end - regs->start + 1); 425 pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
408 426
409 /*
410 * request_gpio() is only valid for pins that have been
411 * explicitly configured as GPIO and not previously requested
412 */
413 pio->gpio_mask = ~0UL;
414
415 /* start with irqs disabled and acked */ 427 /* start with irqs disabled and acked */
416 pio_writel(pio, IDR, ~0UL); 428 pio_writel(pio, IDR, ~0UL);
417 (void) pio_readl(pio, ISR); 429 (void) pio_readl(pio, ISR);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 50fa3aca32c5..7795116a483a 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -19,7 +19,7 @@
19#define PIO_OSR 0x0018 19#define PIO_OSR 0x0018
20#define PIO_IFER 0x0020 20#define PIO_IFER 0x0020
21#define PIO_IFDR 0x0024 21#define PIO_IFDR 0x0024
22#define PIO_ISFR 0x0028 22#define PIO_IFSR 0x0028
23#define PIO_SODR 0x0030 23#define PIO_SODR 0x0030
24#define PIO_CODR 0x0034 24#define PIO_CODR 0x0034
25#define PIO_ODSR 0x0038 25#define PIO_ODSR 0x0038
diff --git a/include/asm-avr32/arch-at32ap/at32ap700x.h b/include/asm-avr32/arch-at32ap/at32ap700x.h
index 99684d6f3967..31e48b0e7324 100644
--- a/include/asm-avr32/arch-at32ap/at32ap700x.h
+++ b/include/asm-avr32/arch-at32ap/at32ap700x.h
@@ -13,8 +13,6 @@
13#define GPIO_PERIPH_A 0 13#define GPIO_PERIPH_A 0
14#define GPIO_PERIPH_B 1 14#define GPIO_PERIPH_B 1
15 15
16#define NR_GPIO_CONTROLLERS 4
17
18/* 16/*
19 * Pin numbers identifying specific GPIO pins on the chip. They can 17 * Pin numbers identifying specific GPIO pins on the chip. They can
20 * also be converted to IRQ numbers by passing them through 18 * also be converted to IRQ numbers by passing them through
diff --git a/include/asm-avr32/arch-at32ap/gpio.h b/include/asm-avr32/arch-at32ap/gpio.h
index af7f9535bab3..0180f584ef03 100644
--- a/include/asm-avr32/arch-at32ap/gpio.h
+++ b/include/asm-avr32/arch-at32ap/gpio.h
@@ -5,20 +5,36 @@
5#include <asm/irq.h> 5#include <asm/irq.h>
6 6
7 7
8/* Arch-neutral GPIO API */ 8/* Some GPIO chips can manage IRQs; some can't. The exact numbers can
9int __must_check gpio_request(unsigned int gpio, const char *label); 9 * be changed if needed, but for the moment they're not configurable.
10void gpio_free(unsigned int gpio); 10 */
11#define ARCH_NR_GPIOS (NR_GPIO_IRQS + 2 * 32)
11 12
12int gpio_direction_input(unsigned int gpio);
13int gpio_direction_output(unsigned int gpio, int value);
14int gpio_get_value(unsigned int gpio);
15void gpio_set_value(unsigned int gpio, int value);
16 13
17#include <asm-generic/gpio.h> /* cansleep wrappers */ 14/* Arch-neutral GPIO API, supporting both "native" and external GPIOs. */
15#include <asm-generic/gpio.h>
16
17static inline int gpio_get_value(unsigned int gpio)
18{
19 return __gpio_get_value(gpio);
20}
21
22static inline void gpio_set_value(unsigned int gpio, int value)
23{
24 __gpio_set_value(gpio, value);
25}
26
27static inline int gpio_cansleep(unsigned int gpio)
28{
29 return __gpio_cansleep(gpio);
30}
31
18 32
19static inline int gpio_to_irq(unsigned int gpio) 33static inline int gpio_to_irq(unsigned int gpio)
20{ 34{
21 return gpio + GPIO_IRQ_BASE; 35 if (gpio < NR_GPIO_IRQS)
36 return gpio + GPIO_IRQ_BASE;
37 return -EINVAL;
22} 38}
23 39
24static inline int irq_to_gpio(unsigned int irq) 40static inline int irq_to_gpio(unsigned int irq)
diff --git a/include/asm-avr32/arch-at32ap/irq.h b/include/asm-avr32/arch-at32ap/irq.h
index 5adffab9a577..608e350368c7 100644
--- a/include/asm-avr32/arch-at32ap/irq.h
+++ b/include/asm-avr32/arch-at32ap/irq.h
@@ -3,11 +3,11 @@
3 3
4#define EIM_IRQ_BASE NR_INTERNAL_IRQS 4#define EIM_IRQ_BASE NR_INTERNAL_IRQS
5#define NR_EIM_IRQS 32 5#define NR_EIM_IRQS 32
6
7#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n)) 6#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n))
8 7
9#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS) 8#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS)
10#define NR_GPIO_IRQS (5 * 32) 9#define NR_GPIO_CTLR (5 /*internal*/ + 1 /*external*/)
10#define NR_GPIO_IRQS (NR_GPIO_CTLR * 32)
11 11
12#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS) 12#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS)
13 13