gpio-da9052.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * GPIO Driver for Dialog DA9052 PMICs.
  4. *
  5. * Copyright(c) 2011 Dialog Semiconductor Ltd.
  6. *
  7. * Author: David Dajun Chen <dchen@diasemi.com>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/fs.h>
  11. #include <linux/uaccess.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/gpio/driver.h>
  14. #include <linux/syscalls.h>
  15. #include <linux/seq_file.h>
  16. #include <linux/mfd/da9052/da9052.h>
  17. #include <linux/mfd/da9052/reg.h>
  18. #include <linux/mfd/da9052/pdata.h>
  19. #define DA9052_INPUT 1
  20. #define DA9052_OUTPUT_OPENDRAIN 2
  21. #define DA9052_OUTPUT_PUSHPULL 3
  22. #define DA9052_SUPPLY_VDD_IO1 0
  23. #define DA9052_DEBOUNCING_OFF 0
  24. #define DA9052_DEBOUNCING_ON 1
  25. #define DA9052_OUTPUT_LOWLEVEL 0
  26. #define DA9052_ACTIVE_LOW 0
  27. #define DA9052_ACTIVE_HIGH 1
  28. #define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8
  29. #define DA9052_GPIO_SHIFT_COUNT(no) (no%8)
  30. #define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
  31. #define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
  32. #define DA9052_GPIO_NIBBLE_SHIFT 4
  33. #define DA9052_IRQ_GPI0 16
  34. #define DA9052_GPIO_ODD_SHIFT 7
  35. #define DA9052_GPIO_EVEN_SHIFT 3
  36. struct da9052_gpio {
  37. struct da9052 *da9052;
  38. struct gpio_chip gp;
  39. };
  40. static unsigned char da9052_gpio_port_odd(unsigned offset)
  41. {
  42. return offset % 2;
  43. }
  44. static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
  45. {
  46. struct da9052_gpio *gpio = gpiochip_get_data(gc);
  47. int da9052_port_direction = 0;
  48. int ret;
  49. ret = da9052_reg_read(gpio->da9052,
  50. DA9052_GPIO_0_1_REG + (offset >> 1));
  51. if (ret < 0)
  52. return ret;
  53. if (da9052_gpio_port_odd(offset)) {
  54. da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
  55. da9052_port_direction >>= 4;
  56. } else {
  57. da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
  58. }
  59. switch (da9052_port_direction) {
  60. case DA9052_INPUT:
  61. if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
  62. ret = da9052_reg_read(gpio->da9052,
  63. DA9052_STATUS_C_REG);
  64. else
  65. ret = da9052_reg_read(gpio->da9052,
  66. DA9052_STATUS_D_REG);
  67. if (ret < 0)
  68. return ret;
  69. return !!(ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)));
  70. case DA9052_OUTPUT_PUSHPULL:
  71. if (da9052_gpio_port_odd(offset))
  72. return !!(ret & DA9052_GPIO_ODD_PORT_MODE);
  73. else
  74. return !!(ret & DA9052_GPIO_EVEN_PORT_MODE);
  75. default:
  76. return -EINVAL;
  77. }
  78. }
  79. static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
  80. {
  81. struct da9052_gpio *gpio = gpiochip_get_data(gc);
  82. int ret;
  83. if (da9052_gpio_port_odd(offset)) {
  84. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  85. DA9052_GPIO_0_1_REG,
  86. DA9052_GPIO_ODD_PORT_MODE,
  87. value << DA9052_GPIO_ODD_SHIFT);
  88. if (ret != 0)
  89. dev_err(gpio->da9052->dev,
  90. "Failed to updated gpio odd reg,%d",
  91. ret);
  92. } else {
  93. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  94. DA9052_GPIO_0_1_REG,
  95. DA9052_GPIO_EVEN_PORT_MODE,
  96. value << DA9052_GPIO_EVEN_SHIFT);
  97. if (ret != 0)
  98. dev_err(gpio->da9052->dev,
  99. "Failed to updated gpio even reg,%d",
  100. ret);
  101. }
  102. }
  103. static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
  104. {
  105. struct da9052_gpio *gpio = gpiochip_get_data(gc);
  106. unsigned char register_value;
  107. int ret;
  108. /* Format: function - 2 bits type - 1 bit mode - 1 bit */
  109. register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
  110. DA9052_DEBOUNCING_ON << 3;
  111. if (da9052_gpio_port_odd(offset))
  112. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  113. DA9052_GPIO_0_1_REG,
  114. DA9052_GPIO_MASK_UPPER_NIBBLE,
  115. (register_value <<
  116. DA9052_GPIO_NIBBLE_SHIFT));
  117. else
  118. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  119. DA9052_GPIO_0_1_REG,
  120. DA9052_GPIO_MASK_LOWER_NIBBLE,
  121. register_value);
  122. return ret;
  123. }
  124. static int da9052_gpio_direction_output(struct gpio_chip *gc,
  125. unsigned offset, int value)
  126. {
  127. struct da9052_gpio *gpio = gpiochip_get_data(gc);
  128. unsigned char register_value;
  129. int ret;
  130. /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
  131. register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
  132. value << 3;
  133. if (da9052_gpio_port_odd(offset))
  134. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  135. DA9052_GPIO_0_1_REG,
  136. DA9052_GPIO_MASK_UPPER_NIBBLE,
  137. (register_value <<
  138. DA9052_GPIO_NIBBLE_SHIFT));
  139. else
  140. ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
  141. DA9052_GPIO_0_1_REG,
  142. DA9052_GPIO_MASK_LOWER_NIBBLE,
  143. register_value);
  144. return ret;
  145. }
  146. static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
  147. {
  148. struct da9052_gpio *gpio = gpiochip_get_data(gc);
  149. struct da9052 *da9052 = gpio->da9052;
  150. int irq;
  151. irq = regmap_irq_get_virq(da9052->irq_data, DA9052_IRQ_GPI0 + offset);
  152. return irq;
  153. }
  154. static const struct gpio_chip reference_gp = {
  155. .label = "da9052-gpio",
  156. .owner = THIS_MODULE,
  157. .get = da9052_gpio_get,
  158. .set = da9052_gpio_set,
  159. .direction_input = da9052_gpio_direction_input,
  160. .direction_output = da9052_gpio_direction_output,
  161. .to_irq = da9052_gpio_to_irq,
  162. .can_sleep = true,
  163. .ngpio = 16,
  164. .base = -1,
  165. };
  166. static int da9052_gpio_probe(struct platform_device *pdev)
  167. {
  168. struct da9052_gpio *gpio;
  169. struct da9052_pdata *pdata;
  170. int ret;
  171. gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
  172. if (!gpio)
  173. return -ENOMEM;
  174. gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
  175. pdata = dev_get_platdata(gpio->da9052->dev);
  176. gpio->gp = reference_gp;
  177. if (pdata && pdata->gpio_base)
  178. gpio->gp.base = pdata->gpio_base;
  179. ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
  180. if (ret < 0) {
  181. dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
  182. return ret;
  183. }
  184. platform_set_drvdata(pdev, gpio);
  185. return 0;
  186. }
  187. static struct platform_driver da9052_gpio_driver = {
  188. .probe = da9052_gpio_probe,
  189. .driver = {
  190. .name = "da9052-gpio",
  191. },
  192. };
  193. module_platform_driver(da9052_gpio_driver);
  194. MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
  195. MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
  196. MODULE_LICENSE("GPL");
  197. MODULE_ALIAS("platform:da9052-gpio");