gpio-wm8350.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * gpiolib support for Wolfson WM835x PMICs
  3. *
  4. * Copyright 2009 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/slab.h>
  16. #include <linux/module.h>
  17. #include <linux/gpio.h>
  18. #include <linux/mfd/core.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/seq_file.h>
  21. #include <linux/mfd/wm8350/core.h>
  22. #include <linux/mfd/wm8350/gpio.h>
  23. struct wm8350_gpio_data {
  24. struct wm8350 *wm8350;
  25. struct gpio_chip gpio_chip;
  26. };
  27. static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
  28. {
  29. struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  30. struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  31. return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  32. 1 << offset);
  33. }
  34. static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
  35. {
  36. struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  37. struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  38. int ret;
  39. ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
  40. if (ret < 0)
  41. return ret;
  42. if (ret & (1 << offset))
  43. return 1;
  44. else
  45. return 0;
  46. }
  47. static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  48. {
  49. struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  50. struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  51. if (value)
  52. wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  53. else
  54. wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  55. }
  56. static int wm8350_gpio_direction_out(struct gpio_chip *chip,
  57. unsigned offset, int value)
  58. {
  59. struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  60. struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  61. int ret;
  62. ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  63. 1 << offset);
  64. if (ret < 0)
  65. return ret;
  66. /* Don't have an atomic direction/value setup */
  67. wm8350_gpio_set(chip, offset, value);
  68. return 0;
  69. }
  70. static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  71. {
  72. struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  73. struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  74. if (!wm8350->irq_base)
  75. return -EINVAL;
  76. return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
  77. }
  78. static const struct gpio_chip template_chip = {
  79. .label = "wm8350",
  80. .owner = THIS_MODULE,
  81. .direction_input = wm8350_gpio_direction_in,
  82. .get = wm8350_gpio_get,
  83. .direction_output = wm8350_gpio_direction_out,
  84. .set = wm8350_gpio_set,
  85. .to_irq = wm8350_gpio_to_irq,
  86. .can_sleep = true,
  87. };
  88. static int wm8350_gpio_probe(struct platform_device *pdev)
  89. {
  90. struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
  91. struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev);
  92. struct wm8350_gpio_data *wm8350_gpio;
  93. int ret;
  94. wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
  95. GFP_KERNEL);
  96. if (wm8350_gpio == NULL)
  97. return -ENOMEM;
  98. wm8350_gpio->wm8350 = wm8350;
  99. wm8350_gpio->gpio_chip = template_chip;
  100. wm8350_gpio->gpio_chip.ngpio = 13;
  101. wm8350_gpio->gpio_chip.parent = &pdev->dev;
  102. if (pdata && pdata->gpio_base)
  103. wm8350_gpio->gpio_chip.base = pdata->gpio_base;
  104. else
  105. wm8350_gpio->gpio_chip.base = -1;
  106. ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip,
  107. wm8350_gpio);
  108. if (ret < 0) {
  109. dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
  110. return ret;
  111. }
  112. platform_set_drvdata(pdev, wm8350_gpio);
  113. return ret;
  114. }
  115. static struct platform_driver wm8350_gpio_driver = {
  116. .driver.name = "wm8350-gpio",
  117. .probe = wm8350_gpio_probe,
  118. };
  119. static int __init wm8350_gpio_init(void)
  120. {
  121. return platform_driver_register(&wm8350_gpio_driver);
  122. }
  123. subsys_initcall(wm8350_gpio_init);
  124. static void __exit wm8350_gpio_exit(void)
  125. {
  126. platform_driver_unregister(&wm8350_gpio_driver);
  127. }
  128. module_exit(wm8350_gpio_exit);
  129. MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  130. MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
  131. MODULE_LICENSE("GPL");
  132. MODULE_ALIAS("platform:wm8350-gpio");