gpio-clps711x.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * CLPS711X GPIO driver
  3. *
  4. * Copyright (C) 2012,2013 Alexander Shiyan <shc_work@mail.ru>
  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 as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/err.h>
  12. #include <linux/gpio.h>
  13. #include <linux/module.h>
  14. #include <linux/basic_mmio_gpio.h>
  15. #include <linux/platform_device.h>
  16. static int clps711x_gpio_probe(struct platform_device *pdev)
  17. {
  18. struct device_node *np = pdev->dev.of_node;
  19. void __iomem *dat, *dir;
  20. struct bgpio_chip *bgc;
  21. struct resource *res;
  22. int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
  23. if ((id < 0) || (id > 4))
  24. return -ENODEV;
  25. bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
  26. if (!bgc)
  27. return -ENOMEM;
  28. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  29. dat = devm_ioremap_resource(&pdev->dev, res);
  30. if (IS_ERR(dat))
  31. return PTR_ERR(dat);
  32. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  33. dir = devm_ioremap_resource(&pdev->dev, res);
  34. if (IS_ERR(dir))
  35. return PTR_ERR(dir);
  36. switch (id) {
  37. case 3:
  38. /* PORTD is inverted logic for direction register */
  39. err = bgpio_init(bgc, &pdev->dev, 1, dat, NULL, NULL,
  40. NULL, dir, 0);
  41. break;
  42. default:
  43. err = bgpio_init(bgc, &pdev->dev, 1, dat, NULL, NULL,
  44. dir, NULL, 0);
  45. break;
  46. }
  47. if (err)
  48. return err;
  49. switch (id) {
  50. case 4:
  51. /* PORTE is 3 lines only */
  52. bgc->gc.ngpio = 3;
  53. break;
  54. default:
  55. break;
  56. }
  57. bgc->gc.base = id * 8;
  58. bgc->gc.owner = THIS_MODULE;
  59. platform_set_drvdata(pdev, bgc);
  60. return gpiochip_add(&bgc->gc);
  61. }
  62. static int clps711x_gpio_remove(struct platform_device *pdev)
  63. {
  64. struct bgpio_chip *bgc = platform_get_drvdata(pdev);
  65. return bgpio_remove(bgc);
  66. }
  67. static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
  68. { .compatible = "cirrus,clps711x-gpio" },
  69. { }
  70. };
  71. MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
  72. static struct platform_driver clps711x_gpio_driver = {
  73. .driver = {
  74. .name = "clps711x-gpio",
  75. .of_match_table = of_match_ptr(clps711x_gpio_ids),
  76. },
  77. .probe = clps711x_gpio_probe,
  78. .remove = clps711x_gpio_remove,
  79. };
  80. module_platform_driver(clps711x_gpio_driver);
  81. MODULE_LICENSE("GPL");
  82. MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
  83. MODULE_DESCRIPTION("CLPS711X GPIO driver");
  84. MODULE_ALIAS("platform:clps711x-gpio");