3cd2550c |
1 | /* |
2 | * MPC52xx gpio driver |
3 | * |
4 | * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 |
8 | * as published by the Free Software Foundation. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ |
19 | |
20 | #include <linux/of.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/of_gpio.h> |
23 | #include <linux/io.h> |
24 | #include <linux/of_platform.h> |
25 | |
26 | #include <asm/gpio.h> |
27 | #include <asm/mpc52xx.h> |
28 | #include <sysdev/fsl_soc.h> |
29 | |
30 | static DEFINE_SPINLOCK(gpio_lock); |
31 | |
32 | struct mpc52xx_gpiochip { |
33 | struct of_mm_gpio_chip mmchip; |
34 | unsigned int shadow_dvo; |
35 | unsigned int shadow_gpioe; |
36 | unsigned int shadow_ddr; |
37 | }; |
38 | |
39 | /* |
40 | * GPIO LIB API implementation for wakeup GPIOs. |
41 | * |
42 | * There's a maximum of 8 wakeup GPIOs. Which of these are available |
43 | * for use depends on your board setup. |
44 | * |
45 | * 0 -> GPIO_WKUP_7 |
46 | * 1 -> GPIO_WKUP_6 |
47 | * 2 -> PSC6_1 |
48 | * 3 -> PSC6_0 |
49 | * 4 -> ETH_17 |
50 | * 5 -> PSC3_9 |
51 | * 6 -> PSC2_4 |
52 | * 7 -> PSC1_4 |
53 | * |
54 | */ |
55 | static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
56 | { |
57 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
58 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
59 | unsigned int ret; |
60 | |
61 | ret = (in_8(®s->wkup_ival) >> (7 - gpio)) & 1; |
62 | |
63 | pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret); |
64 | |
65 | return ret; |
66 | } |
67 | |
68 | static inline void |
69 | __mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
70 | { |
71 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
72 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
73 | struct mpc52xx_gpiochip, mmchip); |
74 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
75 | |
76 | if (val) |
77 | chip->shadow_dvo |= 1 << (7 - gpio); |
78 | else |
79 | chip->shadow_dvo &= ~(1 << (7 - gpio)); |
80 | |
81 | out_8(®s->wkup_dvo, chip->shadow_dvo); |
82 | } |
83 | |
84 | static void |
85 | mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
86 | { |
87 | unsigned long flags; |
88 | |
89 | spin_lock_irqsave(&gpio_lock, flags); |
90 | |
91 | __mpc52xx_wkup_gpio_set(gc, gpio, val); |
92 | |
93 | spin_unlock_irqrestore(&gpio_lock, flags); |
94 | |
95 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); |
96 | } |
97 | |
98 | static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) |
99 | { |
100 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
101 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
102 | struct mpc52xx_gpiochip, mmchip); |
93072457 |
103 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
3cd2550c |
104 | unsigned long flags; |
105 | |
106 | spin_lock_irqsave(&gpio_lock, flags); |
107 | |
108 | /* set the direction */ |
109 | chip->shadow_ddr &= ~(1 << (7 - gpio)); |
110 | out_8(®s->wkup_ddr, chip->shadow_ddr); |
111 | |
112 | /* and enable the pin */ |
113 | chip->shadow_gpioe |= 1 << (7 - gpio); |
114 | out_8(®s->wkup_gpioe, chip->shadow_gpioe); |
115 | |
116 | spin_unlock_irqrestore(&gpio_lock, flags); |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | static int |
122 | mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
123 | { |
124 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
93072457 |
125 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
3cd2550c |
126 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
127 | struct mpc52xx_gpiochip, mmchip); |
128 | unsigned long flags; |
129 | |
130 | spin_lock_irqsave(&gpio_lock, flags); |
131 | |
132 | __mpc52xx_wkup_gpio_set(gc, gpio, val); |
133 | |
134 | /* Then set direction */ |
135 | chip->shadow_ddr |= 1 << (7 - gpio); |
136 | out_8(®s->wkup_ddr, chip->shadow_ddr); |
137 | |
138 | /* Finally enable the pin */ |
139 | chip->shadow_gpioe |= 1 << (7 - gpio); |
140 | out_8(®s->wkup_gpioe, chip->shadow_gpioe); |
141 | |
142 | spin_unlock_irqrestore(&gpio_lock, flags); |
143 | |
144 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); |
145 | |
146 | return 0; |
147 | } |
148 | |
149 | static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev, |
150 | const struct of_device_id *match) |
151 | { |
152 | struct mpc52xx_gpiochip *chip; |
93072457 |
153 | struct mpc52xx_gpio_wkup __iomem *regs; |
3cd2550c |
154 | struct of_gpio_chip *ofchip; |
155 | int ret; |
156 | |
157 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
158 | if (!chip) |
159 | return -ENOMEM; |
160 | |
161 | ofchip = &chip->mmchip.of_gc; |
162 | |
163 | ofchip->gpio_cells = 2; |
164 | ofchip->gc.ngpio = 8; |
165 | ofchip->gc.direction_input = mpc52xx_wkup_gpio_dir_in; |
166 | ofchip->gc.direction_output = mpc52xx_wkup_gpio_dir_out; |
167 | ofchip->gc.get = mpc52xx_wkup_gpio_get; |
168 | ofchip->gc.set = mpc52xx_wkup_gpio_set; |
169 | |
170 | ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip); |
171 | if (ret) |
172 | return ret; |
173 | |
174 | regs = chip->mmchip.regs; |
175 | chip->shadow_gpioe = in_8(®s->wkup_gpioe); |
176 | chip->shadow_ddr = in_8(®s->wkup_ddr); |
177 | chip->shadow_dvo = in_8(®s->wkup_dvo); |
178 | |
179 | return 0; |
180 | } |
181 | |
182 | static int mpc52xx_gpiochip_remove(struct of_device *ofdev) |
183 | { |
184 | return -EBUSY; |
185 | } |
186 | |
187 | static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { |
188 | { |
189 | .compatible = "fsl,mpc5200-gpio-wkup", |
190 | }, |
191 | {} |
192 | }; |
193 | |
194 | static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = { |
195 | .name = "gpio_wkup", |
196 | .match_table = mpc52xx_wkup_gpiochip_match, |
197 | .probe = mpc52xx_wkup_gpiochip_probe, |
198 | .remove = mpc52xx_gpiochip_remove, |
199 | }; |
200 | |
201 | /* |
202 | * GPIO LIB API implementation for simple GPIOs |
203 | * |
204 | * There's a maximum of 32 simple GPIOs. Which of these are available |
205 | * for use depends on your board setup. |
206 | * The numbering reflects the bit numbering in the port registers: |
207 | * |
208 | * 0..1 > reserved |
209 | * 2..3 > IRDA |
210 | * 4..7 > ETHR |
211 | * 8..11 > reserved |
212 | * 12..15 > USB |
213 | * 16..17 > reserved |
214 | * 18..23 > PSC3 |
215 | * 24..27 > PSC2 |
216 | * 28..31 > PSC1 |
217 | */ |
218 | static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
219 | { |
220 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
221 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
222 | unsigned int ret; |
223 | |
224 | ret = (in_be32(®s->simple_ival) >> (31 - gpio)) & 1; |
225 | |
226 | return ret; |
227 | } |
228 | |
229 | static inline void |
230 | __mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
231 | { |
232 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
233 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
234 | struct mpc52xx_gpiochip, mmchip); |
235 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
236 | |
237 | if (val) |
238 | chip->shadow_dvo |= 1 << (31 - gpio); |
239 | else |
240 | chip->shadow_dvo &= ~(1 << (31 - gpio)); |
241 | out_be32(®s->simple_dvo, chip->shadow_dvo); |
242 | } |
243 | |
244 | static void |
245 | mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
246 | { |
247 | unsigned long flags; |
248 | |
249 | spin_lock_irqsave(&gpio_lock, flags); |
250 | |
251 | __mpc52xx_simple_gpio_set(gc, gpio, val); |
252 | |
253 | spin_unlock_irqrestore(&gpio_lock, flags); |
254 | |
255 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); |
256 | } |
257 | |
258 | static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) |
259 | { |
260 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
261 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
262 | struct mpc52xx_gpiochip, mmchip); |
93072457 |
263 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
3cd2550c |
264 | unsigned long flags; |
265 | |
266 | spin_lock_irqsave(&gpio_lock, flags); |
267 | |
268 | /* set the direction */ |
269 | chip->shadow_ddr &= ~(1 << (31 - gpio)); |
270 | out_be32(®s->simple_ddr, chip->shadow_ddr); |
271 | |
272 | /* and enable the pin */ |
273 | chip->shadow_gpioe |= 1 << (31 - gpio); |
274 | out_be32(®s->simple_gpioe, chip->shadow_gpioe); |
275 | |
276 | spin_unlock_irqrestore(&gpio_lock, flags); |
277 | |
278 | return 0; |
279 | } |
280 | |
281 | static int |
282 | mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
283 | { |
284 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
285 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
286 | struct mpc52xx_gpiochip, mmchip); |
93072457 |
287 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
3cd2550c |
288 | unsigned long flags; |
289 | |
290 | spin_lock_irqsave(&gpio_lock, flags); |
291 | |
292 | /* First set initial value */ |
293 | __mpc52xx_simple_gpio_set(gc, gpio, val); |
294 | |
295 | /* Then set direction */ |
296 | chip->shadow_ddr |= 1 << (31 - gpio); |
297 | out_be32(®s->simple_ddr, chip->shadow_ddr); |
298 | |
299 | /* Finally enable the pin */ |
300 | chip->shadow_gpioe |= 1 << (31 - gpio); |
301 | out_be32(®s->simple_gpioe, chip->shadow_gpioe); |
302 | |
303 | spin_unlock_irqrestore(&gpio_lock, flags); |
304 | |
305 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); |
306 | |
307 | return 0; |
308 | } |
309 | |
310 | static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, |
311 | const struct of_device_id *match) |
312 | { |
313 | struct mpc52xx_gpiochip *chip; |
314 | struct of_gpio_chip *ofchip; |
93072457 |
315 | struct mpc52xx_gpio __iomem *regs; |
3cd2550c |
316 | int ret; |
317 | |
318 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
319 | if (!chip) |
320 | return -ENOMEM; |
321 | |
322 | ofchip = &chip->mmchip.of_gc; |
323 | |
324 | ofchip->gpio_cells = 2; |
325 | ofchip->gc.ngpio = 32; |
326 | ofchip->gc.direction_input = mpc52xx_simple_gpio_dir_in; |
327 | ofchip->gc.direction_output = mpc52xx_simple_gpio_dir_out; |
328 | ofchip->gc.get = mpc52xx_simple_gpio_get; |
329 | ofchip->gc.set = mpc52xx_simple_gpio_set; |
330 | |
331 | ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip); |
332 | if (ret) |
333 | return ret; |
334 | |
335 | regs = chip->mmchip.regs; |
336 | chip->shadow_gpioe = in_be32(®s->simple_gpioe); |
337 | chip->shadow_ddr = in_be32(®s->simple_ddr); |
338 | chip->shadow_dvo = in_be32(®s->simple_dvo); |
339 | |
340 | return 0; |
341 | } |
342 | |
343 | static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { |
344 | { |
345 | .compatible = "fsl,mpc5200-gpio", |
346 | }, |
347 | {} |
348 | }; |
349 | |
350 | static struct of_platform_driver mpc52xx_simple_gpiochip_driver = { |
351 | .name = "gpio", |
352 | .match_table = mpc52xx_simple_gpiochip_match, |
353 | .probe = mpc52xx_simple_gpiochip_probe, |
354 | .remove = mpc52xx_gpiochip_remove, |
355 | }; |
356 | |
3cd2550c |
357 | static int __init mpc52xx_gpio_init(void) |
358 | { |
359 | if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver)) |
360 | printk(KERN_ERR "Unable to register wakeup GPIO driver\n"); |
361 | |
362 | if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver)) |
363 | printk(KERN_ERR "Unable to register simple GPIO driver\n"); |
364 | |
3cd2550c |
365 | return 0; |
366 | } |
367 | |
368 | |
369 | /* Make sure we get initialised before anyone else tries to use us */ |
370 | subsys_initcall(mpc52xx_gpio_init); |
371 | |
372 | /* No exit call at the moment as we cannot unregister of gpio chips */ |
373 | |
374 | MODULE_DESCRIPTION("Freescale MPC52xx gpio driver"); |
375 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); |
376 | MODULE_LICENSE("GPL v2"); |
377 | |