pinctrl-amdisp.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * AMD ISP Pinctrl Driver
  4. *
  5. * Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
  6. *
  7. */
  8. #include <linux/gpio/driver.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include "pinctrl-amdisp.h"
  12. #define DRV_NAME "amdisp-pinctrl"
  13. #define GPIO_CONTROL_PIN 4
  14. #define GPIO_OFFSET_0 0x0
  15. #define GPIO_OFFSET_1 0x4
  16. #define GPIO_OFFSET_2 0x50
  17. static const u32 gpio_offset[] = {
  18. GPIO_OFFSET_0,
  19. GPIO_OFFSET_1,
  20. GPIO_OFFSET_2
  21. };
  22. struct amdisp_pinctrl_data {
  23. const struct pinctrl_pin_desc *pins;
  24. unsigned int npins;
  25. const struct amdisp_function *functions;
  26. unsigned int nfunctions;
  27. const struct amdisp_pingroup *groups;
  28. unsigned int ngroups;
  29. };
  30. static const struct amdisp_pinctrl_data amdisp_pinctrl_data = {
  31. .pins = amdisp_pins,
  32. .npins = ARRAY_SIZE(amdisp_pins),
  33. .functions = amdisp_functions,
  34. .nfunctions = ARRAY_SIZE(amdisp_functions),
  35. .groups = amdisp_groups,
  36. .ngroups = ARRAY_SIZE(amdisp_groups),
  37. };
  38. struct amdisp_pinctrl {
  39. struct device *dev;
  40. struct pinctrl_dev *pctrl;
  41. struct pinctrl_desc desc;
  42. struct pinctrl_gpio_range gpio_range;
  43. struct gpio_chip gc;
  44. const struct amdisp_pinctrl_data *data;
  45. void __iomem *gpiobase;
  46. raw_spinlock_t lock;
  47. };
  48. static int amdisp_get_groups_count(struct pinctrl_dev *pctldev)
  49. {
  50. struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
  51. return pctrl->data->ngroups;
  52. }
  53. static const char *amdisp_get_group_name(struct pinctrl_dev *pctldev,
  54. unsigned int group)
  55. {
  56. struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
  57. return pctrl->data->groups[group].name;
  58. }
  59. static int amdisp_get_group_pins(struct pinctrl_dev *pctldev,
  60. unsigned int group,
  61. const unsigned int **pins,
  62. unsigned int *num_pins)
  63. {
  64. struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
  65. *pins = pctrl->data->groups[group].pins;
  66. *num_pins = pctrl->data->groups[group].npins;
  67. return 0;
  68. }
  69. static const struct pinctrl_ops amdisp_pinctrl_ops = {
  70. .get_groups_count = amdisp_get_groups_count,
  71. .get_group_name = amdisp_get_group_name,
  72. .get_group_pins = amdisp_get_group_pins,
  73. };
  74. static int amdisp_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
  75. {
  76. /* amdisp gpio only has output mode */
  77. return GPIO_LINE_DIRECTION_OUT;
  78. }
  79. static int amdisp_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
  80. {
  81. return -EOPNOTSUPP;
  82. }
  83. static int amdisp_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
  84. int value)
  85. {
  86. /* Nothing to do, amdisp gpio only has output mode */
  87. return 0;
  88. }
  89. static int amdisp_gpio_get(struct gpio_chip *gc, unsigned int gpio)
  90. {
  91. unsigned long flags;
  92. u32 pin_reg;
  93. struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
  94. raw_spin_lock_irqsave(&pctrl->lock, flags);
  95. pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
  96. raw_spin_unlock_irqrestore(&pctrl->lock, flags);
  97. return !!(pin_reg & BIT(GPIO_CONTROL_PIN));
  98. }
  99. static int amdisp_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
  100. {
  101. unsigned long flags;
  102. u32 pin_reg;
  103. struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
  104. raw_spin_lock_irqsave(&pctrl->lock, flags);
  105. pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
  106. if (value)
  107. pin_reg |= BIT(GPIO_CONTROL_PIN);
  108. else
  109. pin_reg &= ~BIT(GPIO_CONTROL_PIN);
  110. writel(pin_reg, pctrl->gpiobase + gpio_offset[gpio]);
  111. raw_spin_unlock_irqrestore(&pctrl->lock, flags);
  112. return 0;
  113. }
  114. static int amdisp_gpiochip_add(struct platform_device *pdev,
  115. struct amdisp_pinctrl *pctrl)
  116. {
  117. struct gpio_chip *gc = &pctrl->gc;
  118. struct pinctrl_gpio_range *grange = &pctrl->gpio_range;
  119. int ret;
  120. gc->label = dev_name(pctrl->dev);
  121. gc->parent = &pdev->dev;
  122. gc->names = amdisp_range_pins_name;
  123. gc->request = gpiochip_generic_request;
  124. gc->free = gpiochip_generic_free;
  125. gc->get_direction = amdisp_gpio_get_direction;
  126. gc->direction_input = amdisp_gpio_direction_input;
  127. gc->direction_output = amdisp_gpio_direction_output;
  128. gc->get = amdisp_gpio_get;
  129. gc->set = amdisp_gpio_set;
  130. gc->base = -1;
  131. gc->ngpio = ARRAY_SIZE(amdisp_range_pins);
  132. grange->id = 0;
  133. grange->pin_base = 0;
  134. grange->base = 0;
  135. grange->pins = amdisp_range_pins;
  136. grange->npins = ARRAY_SIZE(amdisp_range_pins);
  137. grange->name = gc->label;
  138. grange->gc = gc;
  139. ret = devm_gpiochip_add_data(&pdev->dev, gc, pctrl);
  140. if (ret)
  141. return ret;
  142. pinctrl_add_gpio_range(pctrl->pctrl, grange);
  143. return 0;
  144. }
  145. static int amdisp_pinctrl_probe(struct platform_device *pdev)
  146. {
  147. struct amdisp_pinctrl *pctrl;
  148. struct resource *res;
  149. int ret;
  150. pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
  151. if (!pctrl)
  152. return -ENOMEM;
  153. pdev->dev.init_name = DRV_NAME;
  154. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  155. if (!res)
  156. return -EINVAL;
  157. pctrl->gpiobase = devm_ioremap_resource(&pdev->dev, res);
  158. if (IS_ERR(pctrl->gpiobase))
  159. return PTR_ERR(pctrl->gpiobase);
  160. platform_set_drvdata(pdev, pctrl);
  161. pctrl->dev = &pdev->dev;
  162. pctrl->data = &amdisp_pinctrl_data;
  163. pctrl->desc.owner = THIS_MODULE;
  164. pctrl->desc.pctlops = &amdisp_pinctrl_ops;
  165. pctrl->desc.pmxops = NULL;
  166. pctrl->desc.name = dev_name(&pdev->dev);
  167. pctrl->desc.pins = pctrl->data->pins;
  168. pctrl->desc.npins = pctrl->data->npins;
  169. ret = devm_pinctrl_register_and_init(&pdev->dev, &pctrl->desc,
  170. pctrl, &pctrl->pctrl);
  171. if (ret)
  172. return ret;
  173. ret = pinctrl_enable(pctrl->pctrl);
  174. if (ret)
  175. return ret;
  176. ret = amdisp_gpiochip_add(pdev, pctrl);
  177. if (ret)
  178. return ret;
  179. return 0;
  180. }
  181. static struct platform_driver amdisp_pinctrl_driver = {
  182. .driver = {
  183. .name = DRV_NAME,
  184. },
  185. .probe = amdisp_pinctrl_probe,
  186. };
  187. module_platform_driver(amdisp_pinctrl_driver);
  188. MODULE_AUTHOR("Benjamin Chan <benjamin.chan@amd.com>");
  189. MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>");
  190. MODULE_DESCRIPTION("AMDISP pinctrl driver");
  191. MODULE_LICENSE("GPL v2");
  192. MODULE_ALIAS("platform:" DRV_NAME);