raspberrypi-power.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
  3. *
  4. * Authors:
  5. * Alexander Aring <aar@pengutronix.de>
  6. * Eric Anholt <eric@anholt.net>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/pm_domain.h>
  12. #include <dt-bindings/power/raspberrypi-power.h>
  13. #include <soc/bcm2835/raspberrypi-firmware.h>
  14. /*
  15. * Firmware indices for the old power domains interface. Only a few
  16. * of them were actually implemented.
  17. */
  18. #define RPI_OLD_POWER_DOMAIN_USB 3
  19. #define RPI_OLD_POWER_DOMAIN_V3D 10
  20. struct rpi_power_domain {
  21. u32 domain;
  22. bool enabled;
  23. bool old_interface;
  24. struct generic_pm_domain base;
  25. struct rpi_firmware *fw;
  26. };
  27. struct rpi_power_domains {
  28. bool has_new_interface;
  29. struct genpd_onecell_data xlate;
  30. struct rpi_firmware *fw;
  31. struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT];
  32. };
  33. /*
  34. * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and
  35. * RPI_FIRMWARE_SET_DOMAIN_STATE
  36. */
  37. struct rpi_power_domain_packet {
  38. u32 domain;
  39. u32 on;
  40. };
  41. /*
  42. * Asks the firmware to enable or disable power on a specific power
  43. * domain.
  44. */
  45. static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on)
  46. {
  47. struct rpi_power_domain_packet packet;
  48. packet.domain = rpi_domain->domain;
  49. packet.on = on;
  50. return rpi_firmware_property(rpi_domain->fw,
  51. rpi_domain->old_interface ?
  52. RPI_FIRMWARE_SET_POWER_STATE :
  53. RPI_FIRMWARE_SET_DOMAIN_STATE,
  54. &packet, sizeof(packet));
  55. }
  56. static int rpi_domain_off(struct generic_pm_domain *domain)
  57. {
  58. struct rpi_power_domain *rpi_domain =
  59. container_of(domain, struct rpi_power_domain, base);
  60. return rpi_firmware_set_power(rpi_domain, false);
  61. }
  62. static int rpi_domain_on(struct generic_pm_domain *domain)
  63. {
  64. struct rpi_power_domain *rpi_domain =
  65. container_of(domain, struct rpi_power_domain, base);
  66. return rpi_firmware_set_power(rpi_domain, true);
  67. }
  68. static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains,
  69. int xlate_index, const char *name)
  70. {
  71. struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
  72. dom->fw = rpi_domains->fw;
  73. dom->base.name = name;
  74. dom->base.power_on = rpi_domain_on;
  75. dom->base.power_off = rpi_domain_off;
  76. /*
  77. * Treat all power domains as off at boot.
  78. *
  79. * The firmware itself may be keeping some domains on, but
  80. * from Linux's perspective all we control is the refcounts
  81. * that we give to the firmware, and we can't ask the firmware
  82. * to turn off something that we haven't ourselves turned on.
  83. */
  84. pm_genpd_init(&dom->base, NULL, true);
  85. rpi_domains->xlate.domains[xlate_index] = &dom->base;
  86. }
  87. static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains,
  88. int xlate_index, const char *name)
  89. {
  90. struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
  91. if (!rpi_domains->has_new_interface)
  92. return;
  93. /* The DT binding index is the firmware's domain index minus one. */
  94. dom->domain = xlate_index + 1;
  95. rpi_common_init_power_domain(rpi_domains, xlate_index, name);
  96. }
  97. static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains,
  98. int xlate_index, int domain,
  99. const char *name)
  100. {
  101. struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
  102. dom->old_interface = true;
  103. dom->domain = domain;
  104. rpi_common_init_power_domain(rpi_domains, xlate_index, name);
  105. }
  106. /*
  107. * Detects whether the firmware supports the new power domains interface.
  108. *
  109. * The firmware doesn't actually return an error on an unknown tag,
  110. * and just skips over it, so we do the detection by putting an
  111. * unexpected value in the return field and checking if it was
  112. * unchanged.
  113. */
  114. static bool
  115. rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
  116. {
  117. struct rpi_power_domain_packet packet;
  118. int ret;
  119. packet.domain = RPI_POWER_DOMAIN_ARM;
  120. packet.on = ~0;
  121. ret = rpi_firmware_property(rpi_domains->fw,
  122. RPI_FIRMWARE_GET_DOMAIN_STATE,
  123. &packet, sizeof(packet));
  124. return ret == 0 && packet.on != ~0;
  125. }
  126. static int rpi_power_probe(struct platform_device *pdev)
  127. {
  128. struct device_node *fw_np;
  129. struct device *dev = &pdev->dev;
  130. struct rpi_power_domains *rpi_domains;
  131. rpi_domains = devm_kzalloc(dev, sizeof(*rpi_domains), GFP_KERNEL);
  132. if (!rpi_domains)
  133. return -ENOMEM;
  134. rpi_domains->xlate.domains =
  135. devm_kcalloc(dev,
  136. RPI_POWER_DOMAIN_COUNT,
  137. sizeof(*rpi_domains->xlate.domains),
  138. GFP_KERNEL);
  139. if (!rpi_domains->xlate.domains)
  140. return -ENOMEM;
  141. rpi_domains->xlate.num_domains = RPI_POWER_DOMAIN_COUNT;
  142. fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
  143. if (!fw_np) {
  144. dev_err(&pdev->dev, "no firmware node\n");
  145. return -ENODEV;
  146. }
  147. rpi_domains->fw = rpi_firmware_get(fw_np);
  148. of_node_put(fw_np);
  149. if (!rpi_domains->fw)
  150. return -EPROBE_DEFER;
  151. rpi_domains->has_new_interface =
  152. rpi_has_new_domain_support(rpi_domains);
  153. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0");
  154. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1");
  155. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2");
  156. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER,
  157. "VIDEO_SCALER");
  158. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1");
  159. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI");
  160. /*
  161. * Use the old firmware interface for USB power, so that we
  162. * can turn it on even if the firmware hasn't been updated.
  163. */
  164. rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB,
  165. RPI_OLD_POWER_DOMAIN_USB, "USB");
  166. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC");
  167. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG");
  168. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264");
  169. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D");
  170. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP");
  171. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0");
  172. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1");
  173. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX");
  174. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2");
  175. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI");
  176. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0");
  177. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1");
  178. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER,
  179. "TRANSPOSER");
  180. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX");
  181. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP");
  182. rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM");
  183. of_genpd_add_provider_onecell(dev->of_node, &rpi_domains->xlate);
  184. platform_set_drvdata(pdev, rpi_domains);
  185. return 0;
  186. }
  187. static const struct of_device_id rpi_power_of_match[] = {
  188. { .compatible = "raspberrypi,bcm2835-power", },
  189. {},
  190. };
  191. MODULE_DEVICE_TABLE(of, rpi_power_of_match);
  192. static struct platform_driver rpi_power_driver = {
  193. .driver = {
  194. .name = "raspberrypi-power",
  195. .of_match_table = rpi_power_of_match,
  196. },
  197. .probe = rpi_power_probe,
  198. };
  199. builtin_platform_driver(rpi_power_driver);
  200. MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
  201. MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
  202. MODULE_DESCRIPTION("Raspberry Pi power domain driver");
  203. MODULE_LICENSE("GPL v2");