gpio-madera.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * GPIO support for Cirrus Logic Madera codecs
  4. *
  5. * Copyright (C) 2015-2018 Cirrus Logic
  6. */
  7. #include <linux/gpio/driver.h>
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/mfd/madera/core.h>
  12. #include <linux/mfd/madera/pdata.h>
  13. #include <linux/mfd/madera/registers.h>
  14. struct madera_gpio {
  15. struct madera *madera;
  16. /* storage space for the gpio_chip we're using */
  17. struct gpio_chip gpio_chip;
  18. };
  19. static int madera_gpio_get_direction(struct gpio_chip *chip,
  20. unsigned int offset)
  21. {
  22. struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
  23. struct madera *madera = madera_gpio->madera;
  24. unsigned int reg_offset = 2 * offset;
  25. unsigned int val;
  26. int ret;
  27. ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset,
  28. &val);
  29. if (ret < 0)
  30. return ret;
  31. if (val & MADERA_GP1_DIR_MASK)
  32. return GPIO_LINE_DIRECTION_IN;
  33. return GPIO_LINE_DIRECTION_OUT;
  34. }
  35. static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
  36. {
  37. struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
  38. struct madera *madera = madera_gpio->madera;
  39. unsigned int reg_offset = 2 * offset;
  40. return regmap_update_bits(madera->regmap,
  41. MADERA_GPIO1_CTRL_2 + reg_offset,
  42. MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
  43. }
  44. static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
  45. {
  46. struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
  47. struct madera *madera = madera_gpio->madera;
  48. unsigned int reg_offset = 2 * offset;
  49. unsigned int val;
  50. int ret;
  51. ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset,
  52. &val);
  53. if (ret < 0)
  54. return ret;
  55. return !!(val & MADERA_GP1_LVL_MASK);
  56. }
  57. static int madera_gpio_direction_out(struct gpio_chip *chip,
  58. unsigned int offset, int value)
  59. {
  60. struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
  61. struct madera *madera = madera_gpio->madera;
  62. unsigned int reg_offset = 2 * offset;
  63. unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
  64. int ret;
  65. ret = regmap_update_bits(madera->regmap,
  66. MADERA_GPIO1_CTRL_2 + reg_offset,
  67. MADERA_GP1_DIR_MASK, 0);
  68. if (ret < 0)
  69. return ret;
  70. return regmap_update_bits(madera->regmap,
  71. MADERA_GPIO1_CTRL_1 + reg_offset,
  72. MADERA_GP1_LVL_MASK, reg_val);
  73. }
  74. static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
  75. int value)
  76. {
  77. struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
  78. struct madera *madera = madera_gpio->madera;
  79. unsigned int reg_offset = 2 * offset;
  80. unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
  81. int ret;
  82. ret = regmap_update_bits(madera->regmap,
  83. MADERA_GPIO1_CTRL_1 + reg_offset,
  84. MADERA_GP1_LVL_MASK, reg_val);
  85. /* set() doesn't return an error so log a warning */
  86. if (ret)
  87. dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
  88. MADERA_GPIO1_CTRL_1 + reg_offset, ret);
  89. }
  90. static const struct gpio_chip madera_gpio_chip = {
  91. .label = "madera",
  92. .owner = THIS_MODULE,
  93. .request = gpiochip_generic_request,
  94. .free = gpiochip_generic_free,
  95. .get_direction = madera_gpio_get_direction,
  96. .direction_input = madera_gpio_direction_in,
  97. .get = madera_gpio_get,
  98. .direction_output = madera_gpio_direction_out,
  99. .set = madera_gpio_set,
  100. .set_config = gpiochip_generic_config,
  101. .can_sleep = true,
  102. };
  103. static int madera_gpio_probe(struct platform_device *pdev)
  104. {
  105. struct madera *madera = dev_get_drvdata(pdev->dev.parent);
  106. struct madera_pdata *pdata = &madera->pdata;
  107. struct madera_gpio *madera_gpio;
  108. int ret;
  109. madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
  110. GFP_KERNEL);
  111. if (!madera_gpio)
  112. return -ENOMEM;
  113. madera_gpio->madera = madera;
  114. /* Construct suitable gpio_chip from the template in madera_gpio_chip */
  115. madera_gpio->gpio_chip = madera_gpio_chip;
  116. madera_gpio->gpio_chip.parent = pdev->dev.parent;
  117. switch (madera->type) {
  118. case CS47L15:
  119. madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS;
  120. break;
  121. case CS47L35:
  122. madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
  123. break;
  124. case CS47L85:
  125. case WM1840:
  126. madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
  127. break;
  128. case CS47L90:
  129. case CS47L91:
  130. madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
  131. break;
  132. case CS42L92:
  133. case CS47L92:
  134. case CS47L93:
  135. madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS;
  136. break;
  137. default:
  138. dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
  139. return -EINVAL;
  140. }
  141. /* We want to be usable on systems that don't use devicetree or acpi */
  142. if (pdata->gpio_base)
  143. madera_gpio->gpio_chip.base = pdata->gpio_base;
  144. else
  145. madera_gpio->gpio_chip.base = -1;
  146. ret = devm_gpiochip_add_data(&pdev->dev,
  147. &madera_gpio->gpio_chip,
  148. madera_gpio);
  149. if (ret < 0) {
  150. dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret);
  151. return ret;
  152. }
  153. /*
  154. * This is part of a composite MFD device which can only be used with
  155. * the corresponding pinctrl driver. On all supported silicon the GPIO
  156. * to pinctrl mapping is fixed in the silicon, so we register it
  157. * explicitly instead of requiring a redundant gpio-ranges in the
  158. * devicetree.
  159. * In any case we also want to work on systems that don't use devicetree
  160. * or acpi.
  161. */
  162. ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl",
  163. 0, 0, madera_gpio->gpio_chip.ngpio);
  164. if (ret) {
  165. dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret);
  166. return ret;
  167. }
  168. return 0;
  169. }
  170. static struct platform_driver madera_gpio_driver = {
  171. .driver = {
  172. .name = "madera-gpio",
  173. },
  174. .probe = madera_gpio_probe,
  175. };
  176. module_platform_driver(madera_gpio_driver);
  177. MODULE_SOFTDEP("pre: pinctrl-madera");
  178. MODULE_DESCRIPTION("GPIO interface for Madera codecs");
  179. MODULE_AUTHOR("Nariman Poushin <[email protected]>");
  180. MODULE_AUTHOR("Richard Fitzgerald <[email protected]>");
  181. MODULE_LICENSE("GPL v2");
  182. MODULE_ALIAS("platform:madera-gpio");