gpio-da9055.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * GPIO Driver for Dialog DA9055 PMICs.
  3. *
  4. * Copyright(c) 2012 Dialog Semiconductor Ltd.
  5. *
  6. * Author: David Dajun Chen <dchen@diasemi.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/module.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/gpio.h>
  17. #include <linux/mfd/da9055/core.h>
  18. #include <linux/mfd/da9055/reg.h>
  19. #include <linux/mfd/da9055/pdata.h>
  20. #define DA9055_VDD_IO 0x0
  21. #define DA9055_PUSH_PULL 0x3
  22. #define DA9055_ACT_LOW 0x0
  23. #define DA9055_GPI 0x1
  24. #define DA9055_PORT_MASK 0x3
  25. #define DA9055_PORT_SHIFT(offset) (4 * (offset % 2))
  26. #define DA9055_INPUT DA9055_GPI
  27. #define DA9055_OUTPUT DA9055_PUSH_PULL
  28. #define DA9055_IRQ_GPI0 3
  29. struct da9055_gpio {
  30. struct da9055 *da9055;
  31. struct gpio_chip gp;
  32. };
  33. static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
  34. {
  35. struct da9055_gpio *gpio = gpiochip_get_data(gc);
  36. int gpio_direction = 0;
  37. int ret;
  38. /* Get GPIO direction */
  39. ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
  40. if (ret < 0)
  41. return ret;
  42. gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
  43. gpio_direction >>= DA9055_PORT_SHIFT(offset);
  44. switch (gpio_direction) {
  45. case DA9055_INPUT:
  46. ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
  47. if (ret < 0)
  48. return ret;
  49. break;
  50. case DA9055_OUTPUT:
  51. ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
  52. if (ret < 0)
  53. return ret;
  54. }
  55. return ret & (1 << offset);
  56. }
  57. static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
  58. {
  59. struct da9055_gpio *gpio = gpiochip_get_data(gc);
  60. da9055_reg_update(gpio->da9055,
  61. DA9055_REG_GPIO_MODE0_2,
  62. 1 << offset,
  63. value << offset);
  64. }
  65. static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
  66. {
  67. struct da9055_gpio *gpio = gpiochip_get_data(gc);
  68. unsigned char reg_byte;
  69. reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
  70. << DA9055_PORT_SHIFT(offset);
  71. return da9055_reg_update(gpio->da9055, (offset >> 1) +
  72. DA9055_REG_GPIO0_1,
  73. DA9055_PORT_MASK <<
  74. DA9055_PORT_SHIFT(offset),
  75. reg_byte);
  76. }
  77. static int da9055_gpio_direction_output(struct gpio_chip *gc,
  78. unsigned offset, int value)
  79. {
  80. struct da9055_gpio *gpio = gpiochip_get_data(gc);
  81. unsigned char reg_byte;
  82. int ret;
  83. reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
  84. << DA9055_PORT_SHIFT(offset);
  85. ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
  86. DA9055_REG_GPIO0_1,
  87. DA9055_PORT_MASK <<
  88. DA9055_PORT_SHIFT(offset),
  89. reg_byte);
  90. if (ret < 0)
  91. return ret;
  92. da9055_gpio_set(gc, offset, value);
  93. return 0;
  94. }
  95. static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
  96. {
  97. struct da9055_gpio *gpio = gpiochip_get_data(gc);
  98. struct da9055 *da9055 = gpio->da9055;
  99. return regmap_irq_get_virq(da9055->irq_data,
  100. DA9055_IRQ_GPI0 + offset);
  101. }
  102. static const struct gpio_chip reference_gp = {
  103. .label = "da9055-gpio",
  104. .owner = THIS_MODULE,
  105. .get = da9055_gpio_get,
  106. .set = da9055_gpio_set,
  107. .direction_input = da9055_gpio_direction_input,
  108. .direction_output = da9055_gpio_direction_output,
  109. .to_irq = da9055_gpio_to_irq,
  110. .can_sleep = true,
  111. .ngpio = 3,
  112. .base = -1,
  113. };
  114. static int da9055_gpio_probe(struct platform_device *pdev)
  115. {
  116. struct da9055_gpio *gpio;
  117. struct da9055_pdata *pdata;
  118. int ret;
  119. gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
  120. if (!gpio)
  121. return -ENOMEM;
  122. gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
  123. pdata = dev_get_platdata(gpio->da9055->dev);
  124. gpio->gp = reference_gp;
  125. if (pdata && pdata->gpio_base)
  126. gpio->gp.base = pdata->gpio_base;
  127. ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
  128. if (ret < 0) {
  129. dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
  130. return ret;
  131. }
  132. platform_set_drvdata(pdev, gpio);
  133. return 0;
  134. }
  135. static struct platform_driver da9055_gpio_driver = {
  136. .probe = da9055_gpio_probe,
  137. .driver = {
  138. .name = "da9055-gpio",
  139. },
  140. };
  141. static int __init da9055_gpio_init(void)
  142. {
  143. return platform_driver_register(&da9055_gpio_driver);
  144. }
  145. subsys_initcall(da9055_gpio_init);
  146. static void __exit da9055_gpio_exit(void)
  147. {
  148. platform_driver_unregister(&da9055_gpio_driver);
  149. }
  150. module_exit(da9055_gpio_exit);
  151. MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
  152. MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
  153. MODULE_LICENSE("GPL");
  154. MODULE_ALIAS("platform:da9055-gpio");