pinctrl-intel-platform.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Intel PCH pinctrl/GPIO driver
  4. *
  5. * Copyright (C) 2021-2023 Intel Corporation
  6. * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  7. */
  8. #include <linux/mod_devicetable.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/pm.h>
  12. #include <linux/property.h>
  13. #include <linux/string_helpers.h>
  14. #include <linux/pinctrl/pinctrl.h>
  15. #include "pinctrl-intel.h"
  16. struct intel_platform_pins {
  17. struct pinctrl_pin_desc *pins;
  18. size_t npins;
  19. };
  20. static int intel_platform_pinctrl_prepare_pins(struct device *dev, size_t base,
  21. const char *name, u32 size,
  22. struct intel_platform_pins *pins)
  23. {
  24. struct pinctrl_pin_desc *descs;
  25. char **pin_names;
  26. unsigned int i;
  27. pin_names = devm_kasprintf_strarray(dev, name, size);
  28. if (IS_ERR(pin_names))
  29. return PTR_ERR(pin_names);
  30. descs = devm_krealloc_array(dev, pins->pins, base + size, sizeof(*descs), GFP_KERNEL);
  31. if (!descs)
  32. return -ENOMEM;
  33. for (i = 0; i < size; i++) {
  34. unsigned int pin_number = base + i;
  35. char *pin_name = pin_names[i];
  36. struct pinctrl_pin_desc *desc;
  37. /* Unify delimiter for pin name */
  38. strreplace(pin_name, '-', '_');
  39. desc = &descs[pin_number];
  40. desc->number = pin_number;
  41. desc->name = pin_name;
  42. }
  43. pins->pins = descs;
  44. pins->npins = base + size;
  45. return 0;
  46. }
  47. static int intel_platform_pinctrl_prepare_group(struct device *dev,
  48. struct fwnode_handle *child,
  49. struct intel_padgroup *gpp,
  50. struct intel_platform_pins *pins)
  51. {
  52. size_t base = pins->npins;
  53. const char *name;
  54. u32 size;
  55. int ret;
  56. ret = fwnode_property_read_string(child, "intc-gpio-group-name", &name);
  57. if (ret)
  58. return ret;
  59. ret = fwnode_property_read_u32(child, "intc-gpio-pad-count", &size);
  60. if (ret)
  61. return ret;
  62. ret = intel_platform_pinctrl_prepare_pins(dev, base, name, size, pins);
  63. if (ret)
  64. return ret;
  65. gpp->base = base;
  66. gpp->size = size;
  67. gpp->gpio_base = INTEL_GPIO_BASE_MATCH;
  68. return 0;
  69. }
  70. static int intel_platform_pinctrl_prepare_community(struct device *dev,
  71. struct intel_community *community,
  72. struct intel_platform_pins *pins)
  73. {
  74. struct intel_padgroup *gpps;
  75. unsigned int group;
  76. size_t ngpps;
  77. u32 offset;
  78. int ret;
  79. ret = device_property_read_u32(dev, "intc-gpio-pad-ownership-offset", &offset);
  80. if (ret)
  81. return ret;
  82. community->padown_offset = offset;
  83. ret = device_property_read_u32(dev, "intc-gpio-pad-configuration-lock-offset", &offset);
  84. if (ret)
  85. return ret;
  86. community->padcfglock_offset = offset;
  87. ret = device_property_read_u32(dev, "intc-gpio-host-software-pad-ownership-offset", &offset);
  88. if (ret)
  89. return ret;
  90. community->hostown_offset = offset;
  91. ret = device_property_read_u32(dev, "intc-gpio-gpi-interrupt-status-offset", &offset);
  92. if (ret)
  93. return ret;
  94. community->is_offset = offset;
  95. ret = device_property_read_u32(dev, "intc-gpio-gpi-interrupt-enable-offset", &offset);
  96. if (ret)
  97. return ret;
  98. community->ie_offset = offset;
  99. ngpps = device_get_child_node_count(dev);
  100. if (!ngpps)
  101. return -ENODEV;
  102. gpps = devm_kcalloc(dev, ngpps, sizeof(*gpps), GFP_KERNEL);
  103. if (!gpps)
  104. return -ENOMEM;
  105. group = 0;
  106. device_for_each_child_node_scoped(dev, child) {
  107. struct intel_padgroup *gpp = &gpps[group];
  108. gpp->reg_num = group;
  109. ret = intel_platform_pinctrl_prepare_group(dev, child, gpp, pins);
  110. if (ret)
  111. return ret;
  112. group++;
  113. }
  114. community->ngpps = ngpps;
  115. community->gpps = gpps;
  116. return 0;
  117. }
  118. static int intel_platform_pinctrl_prepare_soc_data(struct device *dev,
  119. struct intel_pinctrl_soc_data *data)
  120. {
  121. struct intel_platform_pins pins = {};
  122. struct intel_community *communities;
  123. size_t ncommunities;
  124. unsigned int i;
  125. int ret;
  126. /* Version 1.0 of the specification assumes only a single community per device node */
  127. ncommunities = 1;
  128. communities = devm_kcalloc(dev, ncommunities, sizeof(*communities), GFP_KERNEL);
  129. if (!communities)
  130. return -ENOMEM;
  131. for (i = 0; i < ncommunities; i++) {
  132. struct intel_community *community = &communities[i];
  133. community->barno = i;
  134. community->pin_base = pins.npins;
  135. ret = intel_platform_pinctrl_prepare_community(dev, community, &pins);
  136. if (ret)
  137. return ret;
  138. community->npins = pins.npins - community->pin_base;
  139. }
  140. data->ncommunities = ncommunities;
  141. data->communities = communities;
  142. data->npins = pins.npins;
  143. data->pins = pins.pins;
  144. return 0;
  145. }
  146. static int intel_platform_pinctrl_probe(struct platform_device *pdev)
  147. {
  148. struct intel_pinctrl_soc_data *data;
  149. struct device *dev = &pdev->dev;
  150. int ret;
  151. data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  152. if (!data)
  153. return -ENOMEM;
  154. ret = intel_platform_pinctrl_prepare_soc_data(dev, data);
  155. if (ret)
  156. return ret;
  157. return intel_pinctrl_probe(pdev, data);
  158. }
  159. static const struct acpi_device_id intel_platform_pinctrl_acpi_match[] = {
  160. { "INTC105F" },
  161. { }
  162. };
  163. MODULE_DEVICE_TABLE(acpi, intel_platform_pinctrl_acpi_match);
  164. static struct platform_driver intel_platform_pinctrl_driver = {
  165. .probe = intel_platform_pinctrl_probe,
  166. .driver = {
  167. .name = "intel-pinctrl",
  168. .acpi_match_table = intel_platform_pinctrl_acpi_match,
  169. .pm = pm_sleep_ptr(&intel_pinctrl_pm_ops),
  170. },
  171. };
  172. module_platform_driver(intel_platform_pinctrl_driver);
  173. MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
  174. MODULE_DESCRIPTION("Intel PCH pinctrl/GPIO driver");
  175. MODULE_LICENSE("GPL v2");
  176. MODULE_IMPORT_NS("PINCTRL_INTEL");