gpio-bd71815.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Support to GPOs on ROHM BD71815
  4. * Copyright 2021 ROHM Semiconductors.
  5. * Author: Matti Vaittinen <[email protected]>
  6. *
  7. * Copyright 2014 Embest Technology Co. Ltd. Inc.
  8. * Author: [email protected]
  9. */
  10. #include <linux/gpio/driver.h>
  11. #include <linux/init.h>
  12. #include <linux/irq.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. /* For the BD71815 register definitions */
  17. #include <linux/mfd/rohm-bd71815.h>
  18. struct bd71815_gpio {
  19. /* chip.parent points the MFD which provides DT node and regmap */
  20. struct gpio_chip chip;
  21. /* dev points to the platform device for devm and prints */
  22. struct device *dev;
  23. struct regmap *regmap;
  24. };
  25. static int bd71815gpo_get(struct gpio_chip *chip, unsigned int offset)
  26. {
  27. struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
  28. int ret, val;
  29. ret = regmap_read(bd71815->regmap, BD71815_REG_GPO, &val);
  30. if (ret)
  31. return ret;
  32. return (val >> offset) & 1;
  33. }
  34. static void bd71815gpo_set(struct gpio_chip *chip, unsigned int offset,
  35. int value)
  36. {
  37. struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
  38. int ret, bit;
  39. bit = BIT(offset);
  40. if (value)
  41. ret = regmap_set_bits(bd71815->regmap, BD71815_REG_GPO, bit);
  42. else
  43. ret = regmap_clear_bits(bd71815->regmap, BD71815_REG_GPO, bit);
  44. if (ret)
  45. dev_warn(bd71815->dev, "failed to toggle GPO\n");
  46. }
  47. static int bd71815_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
  48. unsigned long config)
  49. {
  50. struct bd71815_gpio *bdgpio = gpiochip_get_data(chip);
  51. switch (pinconf_to_config_param(config)) {
  52. case PIN_CONFIG_DRIVE_OPEN_DRAIN:
  53. return regmap_update_bits(bdgpio->regmap,
  54. BD71815_REG_GPO,
  55. BD71815_GPIO_DRIVE_MASK << offset,
  56. BD71815_GPIO_OPEN_DRAIN << offset);
  57. case PIN_CONFIG_DRIVE_PUSH_PULL:
  58. return regmap_update_bits(bdgpio->regmap,
  59. BD71815_REG_GPO,
  60. BD71815_GPIO_DRIVE_MASK << offset,
  61. BD71815_GPIO_CMOS << offset);
  62. default:
  63. break;
  64. }
  65. return -ENOTSUPP;
  66. }
  67. /* BD71815 GPIO is actually GPO */
  68. static int bd71815gpo_direction_get(struct gpio_chip *gc, unsigned int offset)
  69. {
  70. return GPIO_LINE_DIRECTION_OUT;
  71. }
  72. /* Template for GPIO chip */
  73. static const struct gpio_chip bd71815gpo_chip = {
  74. .label = "bd71815",
  75. .owner = THIS_MODULE,
  76. .get = bd71815gpo_get,
  77. .get_direction = bd71815gpo_direction_get,
  78. .set = bd71815gpo_set,
  79. .set_config = bd71815_gpio_set_config,
  80. .can_sleep = true,
  81. };
  82. #define BD71815_TWO_GPIOS GENMASK(1, 0)
  83. #define BD71815_ONE_GPIO BIT(0)
  84. /*
  85. * Sigh. The BD71815 and BD71817 were originally designed to support two GPO
  86. * pins. At some point it was noticed the second GPO pin which is the E5 pin
  87. * located at the center of IC is hard to use on PCB (due to the location). It
  88. * was decided to not promote this second GPO and the pin is marked as GND in
  89. * the datasheet. The functionality is still there though! I guess driving a GPO
  90. * connected to the ground is a bad idea. Thus we do not support it by default.
  91. * OTOH - the original driver written by colleagues at Embest did support
  92. * controlling this second GPO. It is thus possible this is used in some of the
  93. * products.
  94. *
  95. * This driver does not by default support configuring this second GPO
  96. * but allows using it by providing the DT property
  97. * "rohm,enable-hidden-gpo".
  98. */
  99. static int bd71815_init_valid_mask(struct gpio_chip *gc,
  100. unsigned long *valid_mask,
  101. unsigned int ngpios)
  102. {
  103. if (ngpios != 2)
  104. return 0;
  105. if (gc->parent && device_property_present(gc->parent,
  106. "rohm,enable-hidden-gpo"))
  107. *valid_mask = BD71815_TWO_GPIOS;
  108. else
  109. *valid_mask = BD71815_ONE_GPIO;
  110. return 0;
  111. }
  112. static int gpo_bd71815_probe(struct platform_device *pdev)
  113. {
  114. struct bd71815_gpio *g;
  115. struct device *parent, *dev;
  116. /*
  117. * Bind devm lifetime to this platform device => use dev for devm.
  118. * also the prints should originate from this device.
  119. */
  120. dev = &pdev->dev;
  121. /* The device-tree and regmap come from MFD => use parent for that */
  122. parent = dev->parent;
  123. g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
  124. if (!g)
  125. return -ENOMEM;
  126. g->chip = bd71815gpo_chip;
  127. /*
  128. * FIXME: As writing of this the sysfs interface for GPIO control does
  129. * not respect the valid_mask. Do not trust it but rather set the ngpios
  130. * to 1 if "rohm,enable-hidden-gpo" is not given.
  131. *
  132. * This check can be removed later if the sysfs export is fixed and
  133. * if the fix is backported.
  134. *
  135. * For now it is safest to just set the ngpios though.
  136. */
  137. if (device_property_present(parent, "rohm,enable-hidden-gpo"))
  138. g->chip.ngpio = 2;
  139. else
  140. g->chip.ngpio = 1;
  141. g->chip.init_valid_mask = bd71815_init_valid_mask;
  142. g->chip.base = -1;
  143. g->chip.parent = parent;
  144. g->regmap = dev_get_regmap(parent, NULL);
  145. g->dev = dev;
  146. return devm_gpiochip_add_data(dev, &g->chip, g);
  147. }
  148. static struct platform_driver gpo_bd71815_driver = {
  149. .driver = {
  150. .name = "bd71815-gpo",
  151. },
  152. .probe = gpo_bd71815_probe,
  153. };
  154. module_platform_driver(gpo_bd71815_driver);
  155. MODULE_ALIAS("platform:bd71815-gpo");
  156. MODULE_AUTHOR("Matti Vaittinen <[email protected]>");
  157. MODULE_AUTHOR("Peter Yang <[email protected]>");
  158. MODULE_DESCRIPTION("GPO interface for BD71815");
  159. MODULE_LICENSE("GPL");