diff options
author | Manuel Lauss <manuel.lauss@googlemail.com> | 2011-08-02 13:51:03 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-10-24 18:34:23 -0400 |
commit | ce1d43b9a9e8a3db8fe91696c0b0e3ac1a154e34 (patch) | |
tree | 7e47005c61e98f44005c17a636457c4398c73fdd | |
parent | 2e8fd2e5efe6b7cebba0beec44c6c2f474c6b726 (diff) |
MIPS: Alchemy: support multiple GPIO styles in one kernel
For GPIOLIB=y decide at runtime which gpiochips to register;
in the GPIOLIB=n case, the gpio headers need to be reshuffled
a bit to make multiple implementations coexist peacefully.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
To: Linux-MIPS <linux-mips@linux-mips.org>
Patchwork: https://patchwork.linux-mips.org/patch/2679/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/alchemy/common/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/alchemy/common/gpiolib.c (renamed from arch/mips/alchemy/common/gpiolib-au1000.c) | 35 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-au1x00/gpio-au1000.h | 31 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-au1x00/gpio.h | 79 |
4 files changed, 100 insertions, 49 deletions
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile index 27811fe341d6..62f0d39e93cd 100644 --- a/arch/mips/alchemy/common/Makefile +++ b/arch/mips/alchemy/common/Makefile | |||
@@ -12,9 +12,7 @@ obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += irq.o | |||
12 | 12 | ||
13 | # optional gpiolib support | 13 | # optional gpiolib support |
14 | ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) | 14 | ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) |
15 | ifeq ($(CONFIG_GPIOLIB),y) | 15 | obj-$(CONFIG_GPIOLIB) += gpiolib.o |
16 | obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += gpiolib-au1000.o | ||
17 | endif | ||
18 | endif | 16 | endif |
19 | 17 | ||
20 | obj-$(CONFIG_PCI) += pci.o | 18 | obj-$(CONFIG_PCI) += pci.o |
diff --git a/arch/mips/alchemy/common/gpiolib-au1000.c b/arch/mips/alchemy/common/gpiolib.c index c8e1a94d4a95..91fb4d9e30fd 100644 --- a/arch/mips/alchemy/common/gpiolib-au1000.c +++ b/arch/mips/alchemy/common/gpiolib.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org> | 2 | * Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org> |
3 | * GPIOLIB support for Au1000, Au1500, Au1100, Au1550 and Au12x0. | 3 | * GPIOLIB support for Alchemy chips. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License as published by the | 6 | * under the terms of the GNU General Public License as published by the |
@@ -23,18 +23,18 @@ | |||
23 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | * | 24 | * |
25 | * Notes : | 25 | * Notes : |
26 | * au1000 SoC have only one GPIO block : GPIO1 | 26 | * This file must ONLY be built when CONFIG_GPIOLIB=y and |
27 | * Au1100, Au15x0, Au12x0 have a second one : GPIO2 | 27 | * CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail! |
28 | * au1000 SoC have only one GPIO block : GPIO1 | ||
29 | * Au1100, Au15x0, Au12x0 have a second one : GPIO2 | ||
28 | */ | 30 | */ |
29 | 31 | ||
32 | #include <linux/init.h> | ||
30 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 34 | #include <linux/module.h> |
32 | #include <linux/types.h> | 35 | #include <linux/types.h> |
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/gpio.h> | 36 | #include <linux/gpio.h> |
35 | 37 | #include <asm/mach-au1x00/gpio-au1000.h> | |
36 | #include <asm/mach-au1x00/au1000.h> | ||
37 | #include <asm/mach-au1x00/gpio.h> | ||
38 | 38 | ||
39 | static int gpio2_get(struct gpio_chip *chip, unsigned offset) | 39 | static int gpio2_get(struct gpio_chip *chip, unsigned offset) |
40 | { | 40 | { |
@@ -115,12 +115,19 @@ struct gpio_chip alchemy_gpio_chip[] = { | |||
115 | }, | 115 | }, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static int __init alchemy_gpiolib_init(void) | 118 | static int __init alchemy_gpiochip_init(void) |
119 | { | 119 | { |
120 | gpiochip_add(&alchemy_gpio_chip[0]); | 120 | int ret = 0; |
121 | if (alchemy_get_cputype() != ALCHEMY_CPU_AU1000) | 121 | |
122 | gpiochip_add(&alchemy_gpio_chip[1]); | 122 | switch (alchemy_get_cputype()) { |
123 | 123 | case ALCHEMY_CPU_AU1000: | |
124 | return 0; | 124 | ret = gpiochip_add(&alchemy_gpio_chip[0]); |
125 | break; | ||
126 | case ALCHEMY_CPU_AU1500...ALCHEMY_CPU_AU1200: | ||
127 | ret = gpiochip_add(&alchemy_gpio_chip[0]); | ||
128 | ret |= gpiochip_add(&alchemy_gpio_chip[1]); | ||
129 | break; | ||
130 | } | ||
131 | return ret; | ||
125 | } | 132 | } |
126 | arch_initcall(alchemy_gpiolib_init); | 133 | arch_initcall(alchemy_gpiochip_init); |
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h index 1f41a522906d..73853b5a2a31 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h | |||
@@ -347,17 +347,6 @@ static inline int alchemy_gpio2_to_irq(int gpio) | |||
347 | 347 | ||
348 | /**********************************************************************/ | 348 | /**********************************************************************/ |
349 | 349 | ||
350 | /* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before | ||
351 | * SYS_PININPUTEN is written to at least once. On Au1550/Au1200 this | ||
352 | * register enables use of GPIOs as wake source. | ||
353 | */ | ||
354 | static inline void alchemy_gpio1_input_enable(void) | ||
355 | { | ||
356 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); | ||
357 | __raw_writel(0, base + SYS_PININPUTEN); /* the write op is key */ | ||
358 | wmb(); | ||
359 | } | ||
360 | |||
361 | /* GPIO2 shared interrupts and control */ | 350 | /* GPIO2 shared interrupts and control */ |
362 | 351 | ||
363 | static inline void __alchemy_gpio2_mod_int(int gpio2, int en) | 352 | static inline void __alchemy_gpio2_mod_int(int gpio2, int en) |
@@ -561,6 +550,7 @@ static inline int alchemy_irq_to_gpio(int irq) | |||
561 | 550 | ||
562 | #ifndef CONFIG_GPIOLIB | 551 | #ifndef CONFIG_GPIOLIB |
563 | 552 | ||
553 | #ifdef CONFIG_ALCHEMY_GPIOINT_AU1000 | ||
564 | 554 | ||
565 | #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (4) */ | 555 | #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (4) */ |
566 | 556 | ||
@@ -665,24 +655,7 @@ static inline void gpio_unexport(unsigned gpio) | |||
665 | 655 | ||
666 | #endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ | 656 | #endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ |
667 | 657 | ||
668 | 658 | #endif /* CONFIG_ALCHEMY_GPIOINT_AU1000 */ | |
669 | #else /* CONFIG GPIOLIB */ | ||
670 | |||
671 | |||
672 | /* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */ | ||
673 | #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (2) */ | ||
674 | |||
675 | /* get everything through gpiolib */ | ||
676 | #define gpio_to_irq __gpio_to_irq | ||
677 | #define gpio_get_value __gpio_get_value | ||
678 | #define gpio_set_value __gpio_set_value | ||
679 | #define gpio_cansleep __gpio_cansleep | ||
680 | #define irq_to_gpio alchemy_irq_to_gpio | ||
681 | |||
682 | #include <asm-generic/gpio.h> | ||
683 | |||
684 | #endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ | ||
685 | |||
686 | 659 | ||
687 | #endif /* !CONFIG_GPIOLIB */ | 660 | #endif /* !CONFIG_GPIOLIB */ |
688 | 661 | ||
diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h index c3f60cdc3203..fcdc8c4809db 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio.h +++ b/arch/mips/include/asm/mach-au1x00/gpio.h | |||
@@ -1,10 +1,83 @@ | |||
1 | /* | ||
2 | * Alchemy GPIO support. | ||
3 | * | ||
4 | * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within | ||
5 | * the same kernel image. | ||
6 | * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the | ||
7 | * appropriate CPU type (AU1000 currently). | ||
8 | */ | ||
9 | |||
1 | #ifndef _ALCHEMY_GPIO_H_ | 10 | #ifndef _ALCHEMY_GPIO_H_ |
2 | #define _ALCHEMY_GPIO_H_ | 11 | #define _ALCHEMY_GPIO_H_ |
3 | 12 | ||
4 | #if defined(CONFIG_ALCHEMY_GPIOINT_AU1000) | 13 | #include <asm/mach-au1x00/au1000.h> |
5 | |||
6 | #include <asm/mach-au1x00/gpio-au1000.h> | 14 | #include <asm/mach-au1x00/gpio-au1000.h> |
7 | 15 | ||
8 | #endif | 16 | /* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before |
17 | * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this | ||
18 | * register enables use of GPIOs as wake source. | ||
19 | */ | ||
20 | static inline void alchemy_gpio1_input_enable(void) | ||
21 | { | ||
22 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); | ||
23 | __raw_writel(0, base + 0x110); /* the write op is key */ | ||
24 | wmb(); | ||
25 | } | ||
26 | |||
27 | |||
28 | /* Linux gpio framework integration. | ||
29 | * | ||
30 | * 4 use cases of Alchemy GPIOS: | ||
31 | *(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y: | ||
32 | * Board must register gpiochips. | ||
33 | *(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n: | ||
34 | * A gpiochip for the 75 GPIOs is registered. | ||
35 | * | ||
36 | *(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y: | ||
37 | * the boards' gpio.h must provide the linux gpio wrapper functions, | ||
38 | * | ||
39 | *(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n: | ||
40 | * inlinable gpio functions are provided which enable access to the | ||
41 | * Au1300 gpios only by using the numbers straight out of the data- | ||
42 | * sheets. | ||
43 | |||
44 | * Cases 1 and 3 are intended for boards which want to provide their own | ||
45 | * GPIO namespace and -operations (i.e. for example you have 8 GPIOs | ||
46 | * which are in part provided by spare Au1300 GPIO pins and in part by | ||
47 | * an external FPGA but you still want them to be accssible in linux | ||
48 | * as gpio0-7. The board can of course use the alchemy_gpioX_* functions | ||
49 | * as required). | ||
50 | */ | ||
51 | |||
52 | #ifdef CONFIG_GPIOLIB | ||
53 | |||
54 | /* wraps the cpu-dependent irq_to_gpio functions */ | ||
55 | /* FIXME: gpiolib needs an irq_to_gpio hook */ | ||
56 | static inline int __au_irq_to_gpio(unsigned int irq) | ||
57 | { | ||
58 | switch (alchemy_get_cputype()) { | ||
59 | case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200: | ||
60 | return alchemy_irq_to_gpio(irq); | ||
61 | } | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | |||
66 | /* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */ | ||
67 | #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (2) */ | ||
68 | |||
69 | /* get everything through gpiolib */ | ||
70 | #define gpio_to_irq __gpio_to_irq | ||
71 | #define gpio_get_value __gpio_get_value | ||
72 | #define gpio_set_value __gpio_set_value | ||
73 | #define gpio_cansleep __gpio_cansleep | ||
74 | #define irq_to_gpio __au_irq_to_gpio | ||
75 | |||
76 | #include <asm-generic/gpio.h> | ||
77 | |||
78 | #endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ | ||
79 | |||
80 | |||
81 | #endif /* CONFIG_GPIOLIB */ | ||
9 | 82 | ||
10 | #endif /* _ALCHEMY_GPIO_H_ */ | 83 | #endif /* _ALCHEMY_GPIO_H_ */ |