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