wm8350-gpio.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * wm8350-core.c -- Device access for Wolfson WM8350
  4. *
  5. * Copyright 2007, 2008 Wolfson Microelectronics PLC.
  6. *
  7. * Author: Liam Girdwood
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/errno.h>
  12. #include <linux/mfd/wm8350/core.h>
  13. #include <linux/mfd/wm8350/gpio.h>
  14. #include <linux/mfd/wm8350/pmic.h>
  15. static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
  16. {
  17. int ret;
  18. wm8350_reg_unlock(wm8350);
  19. if (dir == WM8350_GPIO_DIR_OUT)
  20. ret = wm8350_clear_bits(wm8350,
  21. WM8350_GPIO_CONFIGURATION_I_O,
  22. 1 << gpio);
  23. else
  24. ret = wm8350_set_bits(wm8350,
  25. WM8350_GPIO_CONFIGURATION_I_O,
  26. 1 << gpio);
  27. wm8350_reg_lock(wm8350);
  28. return ret;
  29. }
  30. static int wm8350_gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
  31. {
  32. if (db == WM8350_GPIO_DEBOUNCE_ON)
  33. return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
  34. 1 << gpio);
  35. else
  36. return wm8350_clear_bits(wm8350,
  37. WM8350_GPIO_DEBOUNCE, 1 << gpio);
  38. }
  39. static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
  40. {
  41. u16 reg;
  42. wm8350_reg_unlock(wm8350);
  43. switch (gpio) {
  44. case 0:
  45. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  46. & ~WM8350_GP0_FN_MASK;
  47. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  48. reg | ((func & 0xf) << 0));
  49. break;
  50. case 1:
  51. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  52. & ~WM8350_GP1_FN_MASK;
  53. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  54. reg | ((func & 0xf) << 4));
  55. break;
  56. case 2:
  57. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  58. & ~WM8350_GP2_FN_MASK;
  59. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  60. reg | ((func & 0xf) << 8));
  61. break;
  62. case 3:
  63. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  64. & ~WM8350_GP3_FN_MASK;
  65. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  66. reg | ((func & 0xf) << 12));
  67. break;
  68. case 4:
  69. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  70. & ~WM8350_GP4_FN_MASK;
  71. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  72. reg | ((func & 0xf) << 0));
  73. break;
  74. case 5:
  75. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  76. & ~WM8350_GP5_FN_MASK;
  77. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  78. reg | ((func & 0xf) << 4));
  79. break;
  80. case 6:
  81. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  82. & ~WM8350_GP6_FN_MASK;
  83. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  84. reg | ((func & 0xf) << 8));
  85. break;
  86. case 7:
  87. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  88. & ~WM8350_GP7_FN_MASK;
  89. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  90. reg | ((func & 0xf) << 12));
  91. break;
  92. case 8:
  93. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
  94. & ~WM8350_GP8_FN_MASK;
  95. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
  96. reg | ((func & 0xf) << 0));
  97. break;
  98. case 9:
  99. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
  100. & ~WM8350_GP9_FN_MASK;
  101. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
  102. reg | ((func & 0xf) << 4));
  103. break;
  104. case 10:
  105. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
  106. & ~WM8350_GP10_FN_MASK;
  107. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
  108. reg | ((func & 0xf) << 8));
  109. break;
  110. case 11:
  111. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
  112. & ~WM8350_GP11_FN_MASK;
  113. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
  114. reg | ((func & 0xf) << 12));
  115. break;
  116. case 12:
  117. reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
  118. & ~WM8350_GP12_FN_MASK;
  119. wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
  120. reg | ((func & 0xf) << 0));
  121. break;
  122. default:
  123. wm8350_reg_lock(wm8350);
  124. return -EINVAL;
  125. }
  126. wm8350_reg_lock(wm8350);
  127. return 0;
  128. }
  129. static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
  130. {
  131. if (up)
  132. return wm8350_set_bits(wm8350,
  133. WM8350_GPIO_PIN_PULL_UP_CONTROL,
  134. 1 << gpio);
  135. else
  136. return wm8350_clear_bits(wm8350,
  137. WM8350_GPIO_PIN_PULL_UP_CONTROL,
  138. 1 << gpio);
  139. }
  140. static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
  141. {
  142. if (down)
  143. return wm8350_set_bits(wm8350,
  144. WM8350_GPIO_PULL_DOWN_CONTROL,
  145. 1 << gpio);
  146. else
  147. return wm8350_clear_bits(wm8350,
  148. WM8350_GPIO_PULL_DOWN_CONTROL,
  149. 1 << gpio);
  150. }
  151. static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
  152. {
  153. if (pol == WM8350_GPIO_ACTIVE_HIGH)
  154. return wm8350_set_bits(wm8350,
  155. WM8350_GPIO_PIN_POLARITY_TYPE,
  156. 1 << gpio);
  157. else
  158. return wm8350_clear_bits(wm8350,
  159. WM8350_GPIO_PIN_POLARITY_TYPE,
  160. 1 << gpio);
  161. }
  162. static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
  163. {
  164. if (invert == WM8350_GPIO_INVERT_ON)
  165. return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
  166. else
  167. return wm8350_clear_bits(wm8350,
  168. WM8350_GPIO_INT_MODE, 1 << gpio);
  169. }
  170. int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
  171. int pol, int pull, int invert, int debounce)
  172. {
  173. /* make sure we never pull up and down at the same time */
  174. if (pull == WM8350_GPIO_PULL_NONE) {
  175. if (gpio_set_pull_up(wm8350, gpio, 0))
  176. goto err;
  177. if (gpio_set_pull_down(wm8350, gpio, 0))
  178. goto err;
  179. } else if (pull == WM8350_GPIO_PULL_UP) {
  180. if (gpio_set_pull_down(wm8350, gpio, 0))
  181. goto err;
  182. if (gpio_set_pull_up(wm8350, gpio, 1))
  183. goto err;
  184. } else if (pull == WM8350_GPIO_PULL_DOWN) {
  185. if (gpio_set_pull_up(wm8350, gpio, 0))
  186. goto err;
  187. if (gpio_set_pull_down(wm8350, gpio, 1))
  188. goto err;
  189. }
  190. if (gpio_set_invert(wm8350, gpio, invert))
  191. goto err;
  192. if (gpio_set_polarity(wm8350, gpio, pol))
  193. goto err;
  194. if (wm8350_gpio_set_debounce(wm8350, gpio, debounce))
  195. goto err;
  196. if (gpio_set_dir(wm8350, gpio, dir))
  197. goto err;
  198. return gpio_set_func(wm8350, gpio, func);
  199. err:
  200. return -EIO;
  201. }
  202. EXPORT_SYMBOL_GPL(wm8350_gpio_config);