diff options
author | Florian Fainelli <florian@openwrt.org> | 2009-01-15 10:46:48 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-03-30 08:49:42 -0400 |
commit | 47c969ee54e142eba71626f99b3d99cc461b84f3 (patch) | |
tree | 79f23092fd31e4482477958a2b5fa081b7000d8a /arch/mips | |
parent | 12e22e8e60add9e1ccd61509ab7fd6fc1c214c52 (diff) |
MIPS: Au1000: convert to using gpiolib
This patch converts the GPIO board code to use gpiolib.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/alchemy/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/alchemy/common/gpio.c | 203 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-au1x00/gpio.h | 70 |
3 files changed, 146 insertions, 128 deletions
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index 7f8ef13d0014..2fc5c13e890f 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig | |||
@@ -135,3 +135,4 @@ config SOC_AU1X00 | |||
135 | select SYS_SUPPORTS_32BIT_KERNEL | 135 | select SYS_SUPPORTS_32BIT_KERNEL |
136 | select SYS_SUPPORTS_APM_EMULATION | 136 | select SYS_SUPPORTS_APM_EMULATION |
137 | select GENERIC_HARDIRQS_NO__DO_IRQ | 137 | select GENERIC_HARDIRQS_NO__DO_IRQ |
138 | select ARCH_REQUIRE_GPIOLIB | ||
diff --git a/arch/mips/alchemy/common/gpio.c b/arch/mips/alchemy/common/gpio.c index e660ddd611c4..91a9c4436c39 100644 --- a/arch/mips/alchemy/common/gpio.c +++ b/arch/mips/alchemy/common/gpio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org> | 2 | * Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org> |
3 | * Architecture specific GPIO support | 3 | * Architecture specific GPIO support |
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 |
@@ -27,122 +27,175 @@ | |||
27 | * others have a second one : GPIO2 | 27 | * others have a second one : GPIO2 |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/gpio.h> | ||
31 | 35 | ||
32 | #include <asm/mach-au1x00/au1000.h> | 36 | #include <asm/mach-au1x00/au1000.h> |
33 | #include <asm/gpio.h> | 37 | #include <asm/gpio.h> |
34 | 38 | ||
35 | #define gpio1 sys | 39 | struct au1000_gpio_chip { |
36 | #if !defined(CONFIG_SOC_AU1000) | 40 | struct gpio_chip chip; |
37 | 41 | void __iomem *regbase; | |
38 | static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE; | 42 | }; |
39 | #define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 | ||
40 | 43 | ||
41 | static int au1xxx_gpio2_read(unsigned gpio) | 44 | #if !defined(CONFIG_SOC_AU1000) |
45 | static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset) | ||
42 | { | 46 | { |
43 | gpio -= AU1XXX_GPIO_BASE; | 47 | u32 mask = 1 << offset; |
44 | return ((gpio2->pinstate >> gpio) & 0x01); | 48 | struct au1000_gpio_chip *gpch; |
49 | |||
50 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
51 | return readl(gpch->regbase + AU1000_GPIO2_ST) & mask; | ||
45 | } | 52 | } |
46 | 53 | ||
47 | static void au1xxx_gpio2_write(unsigned gpio, int value) | 54 | static void au1000_gpio2_set(struct gpio_chip *chip, |
55 | unsigned offset, int value) | ||
48 | { | 56 | { |
49 | gpio -= AU1XXX_GPIO_BASE; | 57 | u32 mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset)); |
58 | struct au1000_gpio_chip *gpch; | ||
59 | unsigned long flags; | ||
60 | |||
61 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
50 | 62 | ||
51 | gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); | 63 | local_irq_save(flags); |
64 | writel(mask, gpch->regbase + AU1000_GPIO2_OUT); | ||
65 | local_irq_restore(flags); | ||
52 | } | 66 | } |
53 | 67 | ||
54 | static int au1xxx_gpio2_direction_input(unsigned gpio) | 68 | static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset) |
55 | { | 69 | { |
56 | gpio -= AU1XXX_GPIO_BASE; | 70 | u32 mask = 1 << offset; |
57 | gpio2->dir &= ~(0x01 << gpio); | 71 | u32 tmp; |
72 | struct au1000_gpio_chip *gpch; | ||
73 | unsigned long flags; | ||
74 | |||
75 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
76 | |||
77 | local_irq_save(flags); | ||
78 | tmp = readl(gpch->regbase + AU1000_GPIO2_DIR); | ||
79 | tmp &= ~mask; | ||
80 | writel(tmp, gpch->regbase + AU1000_GPIO2_DIR); | ||
81 | local_irq_restore(flags); | ||
82 | |||
58 | return 0; | 83 | return 0; |
59 | } | 84 | } |
60 | 85 | ||
61 | static int au1xxx_gpio2_direction_output(unsigned gpio, int value) | 86 | static int au1000_gpio2_direction_output(struct gpio_chip *chip, |
87 | unsigned offset, int value) | ||
62 | { | 88 | { |
63 | gpio -= AU1XXX_GPIO_BASE; | 89 | u32 mask = 1 << offset; |
64 | gpio2->dir |= 0x01 << gpio; | 90 | u32 out_mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset)); |
65 | gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); | 91 | u32 tmp; |
92 | struct au1000_gpio_chip *gpch; | ||
93 | unsigned long flags; | ||
94 | |||
95 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
96 | |||
97 | local_irq_save(flags); | ||
98 | tmp = readl(gpch->regbase + AU1000_GPIO2_DIR); | ||
99 | tmp |= mask; | ||
100 | writel(tmp, gpch->regbase + AU1000_GPIO2_DIR); | ||
101 | writel(out_mask, gpch->regbase + AU1000_GPIO2_OUT); | ||
102 | local_irq_restore(flags); | ||
103 | |||
66 | return 0; | 104 | return 0; |
67 | } | 105 | } |
68 | |||
69 | #endif /* !defined(CONFIG_SOC_AU1000) */ | 106 | #endif /* !defined(CONFIG_SOC_AU1000) */ |
70 | 107 | ||
71 | static int au1xxx_gpio1_read(unsigned gpio) | 108 | static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset) |
72 | { | 109 | { |
73 | return (gpio1->pinstaterd >> gpio) & 0x01; | 110 | u32 mask = 1 << offset; |
111 | struct au1000_gpio_chip *gpch; | ||
112 | |||
113 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
114 | return readl(gpch->regbase + AU1000_GPIO1_ST) & mask; | ||
74 | } | 115 | } |
75 | 116 | ||
76 | static void au1xxx_gpio1_write(unsigned gpio, int value) | 117 | static void au1000_gpio1_set(struct gpio_chip *chip, |
118 | unsigned offset, int value) | ||
77 | { | 119 | { |
120 | u32 mask = 1 << offset; | ||
121 | u32 reg_offset; | ||
122 | struct au1000_gpio_chip *gpch; | ||
123 | unsigned long flags; | ||
124 | |||
125 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
126 | |||
78 | if (value) | 127 | if (value) |
79 | gpio1->outputset = (0x01 << gpio); | 128 | reg_offset = AU1000_GPIO1_OUT; |
80 | else | 129 | else |
81 | /* Output a zero */ | 130 | reg_offset = AU1000_GPIO1_CLR; |
82 | gpio1->outputclr = (0x01 << gpio); | ||
83 | } | ||
84 | 131 | ||
85 | static int au1xxx_gpio1_direction_input(unsigned gpio) | 132 | local_irq_save(flags); |
86 | { | 133 | writel(mask, gpch->regbase + reg_offset); |
87 | gpio1->pininputen = (0x01 << gpio); | 134 | local_irq_restore(flags); |
88 | return 0; | ||
89 | } | 135 | } |
90 | 136 | ||
91 | static int au1xxx_gpio1_direction_output(unsigned gpio, int value) | 137 | static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset) |
92 | { | 138 | { |
93 | gpio1->trioutclr = (0x01 & gpio); | 139 | u32 mask = 1 << offset; |
94 | au1xxx_gpio1_write(gpio, value); | 140 | struct au1000_gpio_chip *gpch; |
141 | |||
142 | gpch = container_of(chip, struct au1000_gpio_chip, chip); | ||
143 | writel(mask, gpch->regbase + AU1000_GPIO1_ST); | ||
144 | |||
95 | return 0; | 145 | return 0; |
96 | } | 146 | } |
97 | 147 | ||
98 | int au1xxx_gpio_get_value(unsigned gpio) | 148 | static int au1000_gpio1_direction_output(struct gpio_chip *chip, |
149 | unsigned offset, int value) | ||
99 | { | 150 | { |
100 | if (gpio >= AU1XXX_GPIO_BASE) | 151 | u32 mask = 1 << offset; |
101 | #if defined(CONFIG_SOC_AU1000) | 152 | struct au1000_gpio_chip *gpch; |
102 | return 0; | ||
103 | #else | ||
104 | return au1xxx_gpio2_read(gpio); | ||
105 | #endif | ||
106 | else | ||
107 | return au1xxx_gpio1_read(gpio); | ||
108 | } | ||
109 | EXPORT_SYMBOL(au1xxx_gpio_get_value); | ||
110 | 153 | ||
111 | void au1xxx_gpio_set_value(unsigned gpio, int value) | 154 | gpch = container_of(chip, struct au1000_gpio_chip, chip); |
112 | { | ||
113 | if (gpio >= AU1XXX_GPIO_BASE) | ||
114 | #if defined(CONFIG_SOC_AU1000) | ||
115 | ; | ||
116 | #else | ||
117 | au1xxx_gpio2_write(gpio, value); | ||
118 | #endif | ||
119 | else | ||
120 | au1xxx_gpio1_write(gpio, value); | ||
121 | } | ||
122 | EXPORT_SYMBOL(au1xxx_gpio_set_value); | ||
123 | 155 | ||
124 | int au1xxx_gpio_direction_input(unsigned gpio) | 156 | writel(mask, gpch->regbase + AU1000_GPIO1_TRI_OUT); |
125 | { | 157 | au1000_gpio1_set(chip, offset, value); |
126 | if (gpio >= AU1XXX_GPIO_BASE) | ||
127 | #if defined(CONFIG_SOC_AU1000) | ||
128 | return -ENODEV; | ||
129 | #else | ||
130 | return au1xxx_gpio2_direction_input(gpio); | ||
131 | #endif | ||
132 | 158 | ||
133 | return au1xxx_gpio1_direction_input(gpio); | 159 | return 0; |
134 | } | 160 | } |
135 | EXPORT_SYMBOL(au1xxx_gpio_direction_input); | ||
136 | 161 | ||
137 | int au1xxx_gpio_direction_output(unsigned gpio, int value) | 162 | struct au1000_gpio_chip au1000_gpio_chip[] = { |
163 | [0] = { | ||
164 | .regbase = (void __iomem *)SYS_BASE, | ||
165 | .chip = { | ||
166 | .label = "au1000-gpio1", | ||
167 | .direction_input = au1000_gpio1_direction_input, | ||
168 | .direction_output = au1000_gpio1_direction_output, | ||
169 | .get = au1000_gpio1_get, | ||
170 | .set = au1000_gpio1_set, | ||
171 | .base = 0, | ||
172 | .ngpio = 32, | ||
173 | }, | ||
174 | }, | ||
175 | #if !defined(CONFIG_SOC_AU1000) | ||
176 | [1] = { | ||
177 | .regbase = (void __iomem *)GPIO2_BASE, | ||
178 | .chip = { | ||
179 | .label = "au1000-gpio2", | ||
180 | .direction_input = au1000_gpio2_direction_input, | ||
181 | .direction_output = au1000_gpio2_direction_output, | ||
182 | .get = au1000_gpio2_get, | ||
183 | .set = au1000_gpio2_set, | ||
184 | .base = AU1XXX_GPIO_BASE, | ||
185 | .ngpio = 32, | ||
186 | }, | ||
187 | }, | ||
188 | #endif | ||
189 | }; | ||
190 | |||
191 | static int __init au1000_gpio_init(void) | ||
138 | { | 192 | { |
139 | if (gpio >= AU1XXX_GPIO_BASE) | 193 | gpiochip_add(&au1000_gpio_chip[0].chip); |
140 | #if defined(CONFIG_SOC_AU1000) | 194 | #if !defined(CONFIG_SOC_AU1000) |
141 | return -ENODEV; | 195 | gpiochip_add(&au1000_gpio_chip[1].chip); |
142 | #else | ||
143 | return au1xxx_gpio2_direction_output(gpio, value); | ||
144 | #endif | 196 | #endif |
145 | 197 | ||
146 | return au1xxx_gpio1_direction_output(gpio, value); | 198 | return 0; |
147 | } | 199 | } |
148 | EXPORT_SYMBOL(au1xxx_gpio_direction_output); | 200 | arch_initcall(au1000_gpio_init); |
201 | |||
diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h index 2dc61e009a08..34d9b7279024 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio.h +++ b/arch/mips/include/asm/mach-au1x00/gpio.h | |||
@@ -5,65 +5,29 @@ | |||
5 | 5 | ||
6 | #define AU1XXX_GPIO_BASE 200 | 6 | #define AU1XXX_GPIO_BASE 200 |
7 | 7 | ||
8 | struct au1x00_gpio2 { | 8 | /* GPIO bank 1 offsets */ |
9 | u32 dir; | 9 | #define AU1000_GPIO1_TRI_OUT 0x0100 |
10 | u32 reserved; | 10 | #define AU1000_GPIO1_OUT 0x0108 |
11 | u32 output; | 11 | #define AU1000_GPIO1_ST 0x0110 |
12 | u32 pinstate; | 12 | #define AU1000_GPIO1_CLR 0x010C |
13 | u32 inten; | ||
14 | u32 enable; | ||
15 | }; | ||
16 | 13 | ||
17 | extern int au1xxx_gpio_get_value(unsigned gpio); | 14 | /* GPIO bank 2 offsets */ |
18 | extern void au1xxx_gpio_set_value(unsigned gpio, int value); | 15 | #define AU1000_GPIO2_DIR 0x00 |
19 | extern int au1xxx_gpio_direction_input(unsigned gpio); | 16 | #define AU1000_GPIO2_RSVD 0x04 |
20 | extern int au1xxx_gpio_direction_output(unsigned gpio, int value); | 17 | #define AU1000_GPIO2_OUT 0x08 |
18 | #define AU1000_GPIO2_ST 0x0C | ||
19 | #define AU1000_GPIO2_INT 0x10 | ||
20 | #define AU1000_GPIO2_EN 0x14 | ||
21 | 21 | ||
22 | #define GPIO2_OUT_EN_MASK 0x00010000 | ||
22 | 23 | ||
23 | /* Wrappers for the arch-neutral GPIO API */ | 24 | #define gpio_to_irq(gpio) NULL |
24 | 25 | ||
25 | static inline int gpio_request(unsigned gpio, const char *label) | 26 | #define gpio_get_value __gpio_get_value |
26 | { | 27 | #define gpio_set_value __gpio_set_value |
27 | /* Not yet implemented */ | ||
28 | return 0; | ||
29 | } | ||
30 | 28 | ||
31 | static inline void gpio_free(unsigned gpio) | 29 | #define gpio_cansleep __gpio_cansleep |
32 | { | ||
33 | /* Not yet implemented */ | ||
34 | } | ||
35 | 30 | ||
36 | static inline int gpio_direction_input(unsigned gpio) | ||
37 | { | ||
38 | return au1xxx_gpio_direction_input(gpio); | ||
39 | } | ||
40 | |||
41 | static inline int gpio_direction_output(unsigned gpio, int value) | ||
42 | { | ||
43 | return au1xxx_gpio_direction_output(gpio, value); | ||
44 | } | ||
45 | |||
46 | static inline int gpio_get_value(unsigned gpio) | ||
47 | { | ||
48 | return au1xxx_gpio_get_value(gpio); | ||
49 | } | ||
50 | |||
51 | static inline void gpio_set_value(unsigned gpio, int value) | ||
52 | { | ||
53 | au1xxx_gpio_set_value(gpio, value); | ||
54 | } | ||
55 | |||
56 | static inline int gpio_to_irq(unsigned gpio) | ||
57 | { | ||
58 | return gpio; | ||
59 | } | ||
60 | |||
61 | static inline int irq_to_gpio(unsigned irq) | ||
62 | { | ||
63 | return irq; | ||
64 | } | ||
65 | |||
66 | /* For cansleep */ | ||
67 | #include <asm-generic/gpio.h> | 31 | #include <asm-generic/gpio.h> |
68 | 32 | ||
69 | #endif /* _AU1XXX_GPIO_H_ */ | 33 | #endif /* _AU1XXX_GPIO_H_ */ |