gpio-madera.c 5.7 KB

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