diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/langwell_gpio.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 222de1292e2b..64db9dc3a275 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -18,10 +18,12 @@ | |||
18 | /* Supports: | 18 | /* Supports: |
19 | * Moorestown platform Langwell chip. | 19 | * Moorestown platform Langwell chip. |
20 | * Medfield platform Penwell chip. | 20 | * Medfield platform Penwell chip. |
21 | * Whitney point. | ||
21 | */ | 22 | */ |
22 | 23 | ||
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/platform_device.h> | ||
25 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
26 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
27 | #include <linux/stddef.h> | 29 | #include <linux/stddef.h> |
@@ -300,9 +302,88 @@ static struct pci_driver lnw_gpio_driver = { | |||
300 | .probe = lnw_gpio_probe, | 302 | .probe = lnw_gpio_probe, |
301 | }; | 303 | }; |
302 | 304 | ||
305 | |||
306 | static int __devinit wp_gpio_probe(struct platform_device *pdev) | ||
307 | { | ||
308 | struct lnw_gpio *lnw; | ||
309 | struct gpio_chip *gc; | ||
310 | struct resource *rc; | ||
311 | int retval = 0; | ||
312 | |||
313 | rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
314 | if (!rc) | ||
315 | return -EINVAL; | ||
316 | |||
317 | lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); | ||
318 | if (!lnw) { | ||
319 | dev_err(&pdev->dev, | ||
320 | "can't allocate whitneypoint_gpio chip data\n"); | ||
321 | return -ENOMEM; | ||
322 | } | ||
323 | lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc)); | ||
324 | if (lnw->reg_base == NULL) { | ||
325 | retval = -EINVAL; | ||
326 | goto err_kmalloc; | ||
327 | } | ||
328 | spin_lock_init(&lnw->lock); | ||
329 | gc = &lnw->chip; | ||
330 | gc->label = dev_name(&pdev->dev); | ||
331 | gc->owner = THIS_MODULE; | ||
332 | gc->direction_input = lnw_gpio_direction_input; | ||
333 | gc->direction_output = lnw_gpio_direction_output; | ||
334 | gc->get = lnw_gpio_get; | ||
335 | gc->set = lnw_gpio_set; | ||
336 | gc->to_irq = NULL; | ||
337 | gc->base = 0; | ||
338 | gc->ngpio = 64; | ||
339 | gc->can_sleep = 0; | ||
340 | retval = gpiochip_add(gc); | ||
341 | if (retval) { | ||
342 | dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n", | ||
343 | retval); | ||
344 | goto err_ioremap; | ||
345 | } | ||
346 | platform_set_drvdata(pdev, lnw); | ||
347 | return 0; | ||
348 | err_ioremap: | ||
349 | iounmap(lnw->reg_base); | ||
350 | err_kmalloc: | ||
351 | kfree(lnw); | ||
352 | return retval; | ||
353 | } | ||
354 | |||
355 | static int __devexit wp_gpio_remove(struct platform_device *pdev) | ||
356 | { | ||
357 | struct lnw_gpio *lnw = platform_get_drvdata(pdev); | ||
358 | int err; | ||
359 | err = gpiochip_remove(&lnw->chip); | ||
360 | if (err) | ||
361 | dev_err(&pdev->dev, "failed to remove gpio_chip.\n"); | ||
362 | iounmap(lnw->reg_base); | ||
363 | kfree(lnw); | ||
364 | platform_set_drvdata(pdev, NULL); | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static struct platform_driver wp_gpio_driver = { | ||
369 | .probe = wp_gpio_probe, | ||
370 | .remove = __devexit_p(wp_gpio_remove), | ||
371 | .driver = { | ||
372 | .name = "wp_gpio", | ||
373 | .owner = THIS_MODULE, | ||
374 | }, | ||
375 | }; | ||
376 | |||
303 | static int __init lnw_gpio_init(void) | 377 | static int __init lnw_gpio_init(void) |
304 | { | 378 | { |
305 | return pci_register_driver(&lnw_gpio_driver); | 379 | int ret; |
380 | ret = pci_register_driver(&lnw_gpio_driver); | ||
381 | if (ret < 0) | ||
382 | return ret; | ||
383 | ret = platform_driver_register(&wp_gpio_driver); | ||
384 | if (ret < 0) | ||
385 | pci_unregister_driver(&lnw_gpio_driver); | ||
386 | return ret; | ||
306 | } | 387 | } |
307 | 388 | ||
308 | device_initcall(lnw_gpio_init); | 389 | device_initcall(lnw_gpio_init); |