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/alchemy | |
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/alchemy')
-rw-r--r-- | arch/mips/alchemy/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/alchemy/common/gpio.c | 203 |
2 files changed, 129 insertions, 75 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 | |||