gpio-tps68470.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * GPIO driver for TPS68470 PMIC
  3. *
  4. * Copyright (C) 2017 Intel Corporation
  5. *
  6. * Authors:
  7. * Antti Laakso <antti.laakso@intel.com>
  8. * Tianshu Qiu <tian.shu.qiu@intel.com>
  9. * Jian Xu Zheng <jian.xu.zheng@intel.com>
  10. * Yuning Pu <yuning.pu@intel.com>
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation version 2.
  15. *
  16. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  17. * kind, whether express or implied; without even the implied warranty
  18. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. */
  21. #include <linux/gpio/driver.h>
  22. #include <linux/mfd/tps68470.h>
  23. #include <linux/module.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/regmap.h>
  26. #define TPS68470_N_LOGIC_OUTPUT 3
  27. #define TPS68470_N_REGULAR_GPIO 7
  28. #define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO)
  29. struct tps68470_gpio_data {
  30. struct regmap *tps68470_regmap;
  31. struct gpio_chip gc;
  32. };
  33. static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
  34. {
  35. struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  36. struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  37. unsigned int reg = TPS68470_REG_GPDO;
  38. int val, ret;
  39. if (offset >= TPS68470_N_REGULAR_GPIO) {
  40. offset -= TPS68470_N_REGULAR_GPIO;
  41. reg = TPS68470_REG_SGPO;
  42. }
  43. ret = regmap_read(regmap, reg, &val);
  44. if (ret) {
  45. dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
  46. TPS68470_REG_SGPO);
  47. return ret;
  48. }
  49. return !!(val & BIT(offset));
  50. }
  51. /* Return 0 if output, 1 if input */
  52. static int tps68470_gpio_get_direction(struct gpio_chip *gc,
  53. unsigned int offset)
  54. {
  55. struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  56. struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  57. int val, ret;
  58. /* rest are always outputs */
  59. if (offset >= TPS68470_N_REGULAR_GPIO)
  60. return 0;
  61. ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val);
  62. if (ret) {
  63. dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
  64. TPS68470_GPIO_CTL_REG_A(offset));
  65. return ret;
  66. }
  67. val &= TPS68470_GPIO_MODE_MASK;
  68. return val >= TPS68470_GPIO_MODE_OUT_CMOS ? 0 : 1;
  69. }
  70. static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
  71. int value)
  72. {
  73. struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  74. struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  75. unsigned int reg = TPS68470_REG_GPDO;
  76. if (offset >= TPS68470_N_REGULAR_GPIO) {
  77. reg = TPS68470_REG_SGPO;
  78. offset -= TPS68470_N_REGULAR_GPIO;
  79. }
  80. regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0);
  81. }
  82. static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
  83. int value)
  84. {
  85. struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  86. struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  87. /* rest are always outputs */
  88. if (offset >= TPS68470_N_REGULAR_GPIO)
  89. return 0;
  90. /* Set the initial value */
  91. tps68470_gpio_set(gc, offset, value);
  92. return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
  93. TPS68470_GPIO_MODE_MASK,
  94. TPS68470_GPIO_MODE_OUT_CMOS);
  95. }
  96. static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
  97. {
  98. struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  99. struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  100. /* rest are always outputs */
  101. if (offset >= TPS68470_N_REGULAR_GPIO)
  102. return -EINVAL;
  103. return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
  104. TPS68470_GPIO_MODE_MASK, 0x00);
  105. }
  106. static const char *tps68470_names[TPS68470_N_GPIO] = {
  107. "gpio.0", "gpio.1", "gpio.2", "gpio.3",
  108. "gpio.4", "gpio.5", "gpio.6",
  109. "s_enable", "s_idle", "s_resetn",
  110. };
  111. static int tps68470_gpio_probe(struct platform_device *pdev)
  112. {
  113. struct tps68470_gpio_data *tps68470_gpio;
  114. int ret;
  115. tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
  116. GFP_KERNEL);
  117. if (!tps68470_gpio)
  118. return -ENOMEM;
  119. tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
  120. tps68470_gpio->gc.label = "tps68470-gpio";
  121. tps68470_gpio->gc.owner = THIS_MODULE;
  122. tps68470_gpio->gc.direction_input = tps68470_gpio_input;
  123. tps68470_gpio->gc.direction_output = tps68470_gpio_output;
  124. tps68470_gpio->gc.get = tps68470_gpio_get;
  125. tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;
  126. tps68470_gpio->gc.set = tps68470_gpio_set;
  127. tps68470_gpio->gc.can_sleep = true;
  128. tps68470_gpio->gc.names = tps68470_names;
  129. tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
  130. tps68470_gpio->gc.base = -1;
  131. tps68470_gpio->gc.parent = &pdev->dev;
  132. ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc,
  133. tps68470_gpio);
  134. if (ret < 0) {
  135. dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret);
  136. return ret;
  137. }
  138. platform_set_drvdata(pdev, tps68470_gpio);
  139. return ret;
  140. }
  141. static struct platform_driver tps68470_gpio_driver = {
  142. .driver = {
  143. .name = "tps68470-gpio",
  144. },
  145. .probe = tps68470_gpio_probe,
  146. };
  147. builtin_platform_driver(tps68470_gpio_driver)