rpmpd.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
  3. #include <linux/err.h>
  4. #include <linux/init.h>
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/mutex.h>
  8. #include <linux/pm_domain.h>
  9. #include <linux/of.h>
  10. #include <linux/of_device.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/pm_opp.h>
  13. #include <linux/soc/qcom/smd-rpm.h>
  14. #include <dt-bindings/power/qcom-rpmpd.h>
  15. #define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
  16. /* Resource types:
  17. * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
  18. #define RPMPD_SMPA 0x61706d73
  19. #define RPMPD_LDOA 0x616f646c
  20. #define RPMPD_SMPB 0x62706d73
  21. #define RPMPD_LDOB 0x626f646c
  22. #define RPMPD_RWCX 0x78637772
  23. #define RPMPD_RWMX 0x786d7772
  24. #define RPMPD_RWLC 0x636c7772
  25. #define RPMPD_RWLM 0x6d6c7772
  26. #define RPMPD_RWSC 0x63737772
  27. #define RPMPD_RWSM 0x6d737772
  28. #define RPMPD_RWGX 0x78677772
  29. /* Operation Keys */
  30. #define KEY_CORNER 0x6e726f63 /* corn */
  31. #define KEY_ENABLE 0x6e657773 /* swen */
  32. #define KEY_FLOOR_CORNER 0x636676 /* vfc */
  33. #define KEY_FLOOR_LEVEL 0x6c6676 /* vfl */
  34. #define KEY_LEVEL 0x6c766c76 /* vlvl */
  35. #define MAX_CORNER_RPMPD_STATE 6
  36. #define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key, \
  37. r_id) \
  38. static struct rpmpd _platform##_##_active; \
  39. static struct rpmpd _platform##_##_name = { \
  40. .pd = { .name = #_name, }, \
  41. .peer = &_platform##_##_active, \
  42. .res_type = RPMPD_##r_type, \
  43. .res_id = r_id, \
  44. .key = KEY_##r_key, \
  45. }; \
  46. static struct rpmpd _platform##_##_active = { \
  47. .pd = { .name = #_active, }, \
  48. .peer = &_platform##_##_name, \
  49. .active_only = true, \
  50. .res_type = RPMPD_##r_type, \
  51. .res_id = r_id, \
  52. .key = KEY_##r_key, \
  53. }
  54. #define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id) \
  55. static struct rpmpd _platform##_##_name = { \
  56. .pd = { .name = #_name, }, \
  57. .res_type = RPMPD_##r_type, \
  58. .res_id = r_id, \
  59. .key = KEY_CORNER, \
  60. }
  61. #define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id) \
  62. static struct rpmpd _platform##_##_name = { \
  63. .pd = { .name = #_name, }, \
  64. .res_type = RPMPD_##r_type, \
  65. .res_id = r_id, \
  66. .key = KEY_LEVEL, \
  67. }
  68. #define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id) \
  69. static struct rpmpd _platform##_##_name = { \
  70. .pd = { .name = #_name, }, \
  71. .res_type = RPMPD_##r_type, \
  72. .res_id = r_id, \
  73. .key = KEY_FLOOR_CORNER, \
  74. }
  75. #define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id) \
  76. static struct rpmpd _platform##_##_name = { \
  77. .pd = { .name = #_name, }, \
  78. .res_type = RPMPD_##r_type, \
  79. .res_id = r_id, \
  80. .key = KEY_FLOOR_LEVEL, \
  81. }
  82. struct rpmpd_req {
  83. __le32 key;
  84. __le32 nbytes;
  85. __le32 value;
  86. };
  87. struct rpmpd {
  88. struct generic_pm_domain pd;
  89. struct rpmpd *peer;
  90. const bool active_only;
  91. unsigned int corner;
  92. bool enabled;
  93. const int res_type;
  94. const int res_id;
  95. struct qcom_smd_rpm *rpm;
  96. unsigned int max_state;
  97. __le32 key;
  98. };
  99. struct rpmpd_desc {
  100. struct rpmpd **rpmpds;
  101. size_t num_pds;
  102. unsigned int max_state;
  103. };
  104. static DEFINE_MUTEX(rpmpd_lock);
  105. /* mdm9607 RPM Power Domains */
  106. DEFINE_RPMPD_PAIR(mdm9607, vddcx, vddcx_ao, SMPA, LEVEL, 3);
  107. DEFINE_RPMPD_VFL(mdm9607, vddcx_vfl, SMPA, 3);
  108. DEFINE_RPMPD_PAIR(mdm9607, vddmx, vddmx_ao, LDOA, LEVEL, 12);
  109. DEFINE_RPMPD_VFL(mdm9607, vddmx_vfl, LDOA, 12);
  110. static struct rpmpd *mdm9607_rpmpds[] = {
  111. [MDM9607_VDDCX] = &mdm9607_vddcx,
  112. [MDM9607_VDDCX_AO] = &mdm9607_vddcx_ao,
  113. [MDM9607_VDDCX_VFL] = &mdm9607_vddcx_vfl,
  114. [MDM9607_VDDMX] = &mdm9607_vddmx,
  115. [MDM9607_VDDMX_AO] = &mdm9607_vddmx_ao,
  116. [MDM9607_VDDMX_VFL] = &mdm9607_vddmx_vfl,
  117. };
  118. static const struct rpmpd_desc mdm9607_desc = {
  119. .rpmpds = mdm9607_rpmpds,
  120. .num_pds = ARRAY_SIZE(mdm9607_rpmpds),
  121. .max_state = RPM_SMD_LEVEL_TURBO,
  122. };
  123. /* msm8226 RPM Power Domains */
  124. DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1);
  125. DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1);
  126. static struct rpmpd *msm8226_rpmpds[] = {
  127. [MSM8226_VDDCX] = &msm8226_vddcx,
  128. [MSM8226_VDDCX_AO] = &msm8226_vddcx_ao,
  129. [MSM8226_VDDCX_VFC] = &msm8226_vddcx_vfc,
  130. };
  131. static const struct rpmpd_desc msm8226_desc = {
  132. .rpmpds = msm8226_rpmpds,
  133. .num_pds = ARRAY_SIZE(msm8226_rpmpds),
  134. .max_state = MAX_CORNER_RPMPD_STATE,
  135. };
  136. /* msm8939 RPM Power Domains */
  137. DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1);
  138. DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1);
  139. DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2);
  140. DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2);
  141. DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3);
  142. static struct rpmpd *msm8939_rpmpds[] = {
  143. [MSM8939_VDDMDCX] = &msm8939_vddmd,
  144. [MSM8939_VDDMDCX_AO] = &msm8939_vddmd_ao,
  145. [MSM8939_VDDMDCX_VFC] = &msm8939_vddmd_vfc,
  146. [MSM8939_VDDCX] = &msm8939_vddcx,
  147. [MSM8939_VDDCX_AO] = &msm8939_vddcx_ao,
  148. [MSM8939_VDDCX_VFC] = &msm8939_vddcx_vfc,
  149. [MSM8939_VDDMX] = &msm8939_vddmx,
  150. [MSM8939_VDDMX_AO] = &msm8939_vddmx_ao,
  151. };
  152. static const struct rpmpd_desc msm8939_desc = {
  153. .rpmpds = msm8939_rpmpds,
  154. .num_pds = ARRAY_SIZE(msm8939_rpmpds),
  155. .max_state = MAX_CORNER_RPMPD_STATE,
  156. };
  157. /* msm8916 RPM Power Domains */
  158. DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
  159. DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
  160. DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
  161. static struct rpmpd *msm8916_rpmpds[] = {
  162. [MSM8916_VDDCX] = &msm8916_vddcx,
  163. [MSM8916_VDDCX_AO] = &msm8916_vddcx_ao,
  164. [MSM8916_VDDCX_VFC] = &msm8916_vddcx_vfc,
  165. [MSM8916_VDDMX] = &msm8916_vddmx,
  166. [MSM8916_VDDMX_AO] = &msm8916_vddmx_ao,
  167. };
  168. static const struct rpmpd_desc msm8916_desc = {
  169. .rpmpds = msm8916_rpmpds,
  170. .num_pds = ARRAY_SIZE(msm8916_rpmpds),
  171. .max_state = MAX_CORNER_RPMPD_STATE,
  172. };
  173. /* msm8953 RPM Power Domains */
  174. DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1);
  175. DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2);
  176. DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7);
  177. DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2);
  178. static struct rpmpd *msm8953_rpmpds[] = {
  179. [MSM8953_VDDMD] = &msm8953_vddmd,
  180. [MSM8953_VDDMD_AO] = &msm8953_vddmd_ao,
  181. [MSM8953_VDDCX] = &msm8953_vddcx,
  182. [MSM8953_VDDCX_AO] = &msm8953_vddcx_ao,
  183. [MSM8953_VDDCX_VFL] = &msm8953_vddcx_vfl,
  184. [MSM8953_VDDMX] = &msm8953_vddmx,
  185. [MSM8953_VDDMX_AO] = &msm8953_vddmx_ao,
  186. };
  187. static const struct rpmpd_desc msm8953_desc = {
  188. .rpmpds = msm8953_rpmpds,
  189. .num_pds = ARRAY_SIZE(msm8953_rpmpds),
  190. .max_state = RPM_SMD_LEVEL_TURBO,
  191. };
  192. /* msm8976 RPM Power Domains */
  193. DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
  194. DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
  195. DEFINE_RPMPD_VFL(msm8976, vddcx_vfl, RWSC, 2);
  196. DEFINE_RPMPD_VFL(msm8976, vddmx_vfl, RWSM, 6);
  197. static struct rpmpd *msm8976_rpmpds[] = {
  198. [MSM8976_VDDCX] = &msm8976_vddcx,
  199. [MSM8976_VDDCX_AO] = &msm8976_vddcx_ao,
  200. [MSM8976_VDDCX_VFL] = &msm8976_vddcx_vfl,
  201. [MSM8976_VDDMX] = &msm8976_vddmx,
  202. [MSM8976_VDDMX_AO] = &msm8976_vddmx_ao,
  203. [MSM8976_VDDMX_VFL] = &msm8976_vddmx_vfl,
  204. };
  205. static const struct rpmpd_desc msm8976_desc = {
  206. .rpmpds = msm8976_rpmpds,
  207. .num_pds = ARRAY_SIZE(msm8976_rpmpds),
  208. .max_state = RPM_SMD_LEVEL_TURBO_HIGH,
  209. };
  210. /* msm8994 RPM Power domains */
  211. DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1);
  212. DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2);
  213. /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
  214. DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2);
  215. DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1);
  216. DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2);
  217. static struct rpmpd *msm8994_rpmpds[] = {
  218. [MSM8994_VDDCX] = &msm8994_vddcx,
  219. [MSM8994_VDDCX_AO] = &msm8994_vddcx_ao,
  220. [MSM8994_VDDCX_VFC] = &msm8994_vddcx_vfc,
  221. [MSM8994_VDDMX] = &msm8994_vddmx,
  222. [MSM8994_VDDMX_AO] = &msm8994_vddmx_ao,
  223. [MSM8994_VDDGFX] = &msm8994_vddgfx,
  224. [MSM8994_VDDGFX_VFC] = &msm8994_vddgfx_vfc,
  225. };
  226. static const struct rpmpd_desc msm8994_desc = {
  227. .rpmpds = msm8994_rpmpds,
  228. .num_pds = ARRAY_SIZE(msm8994_rpmpds),
  229. .max_state = MAX_CORNER_RPMPD_STATE,
  230. };
  231. /* msm8996 RPM Power domains */
  232. DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1);
  233. DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2);
  234. DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26);
  235. DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1);
  236. DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26);
  237. static struct rpmpd *msm8996_rpmpds[] = {
  238. [MSM8996_VDDCX] = &msm8996_vddcx,
  239. [MSM8996_VDDCX_AO] = &msm8996_vddcx_ao,
  240. [MSM8996_VDDCX_VFC] = &msm8996_vddcx_vfc,
  241. [MSM8996_VDDMX] = &msm8996_vddmx,
  242. [MSM8996_VDDMX_AO] = &msm8996_vddmx_ao,
  243. [MSM8996_VDDSSCX] = &msm8996_vddsscx,
  244. [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
  245. };
  246. static const struct rpmpd_desc msm8996_desc = {
  247. .rpmpds = msm8996_rpmpds,
  248. .num_pds = ARRAY_SIZE(msm8996_rpmpds),
  249. .max_state = MAX_CORNER_RPMPD_STATE,
  250. };
  251. /* msm8998 RPM Power domains */
  252. DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0);
  253. DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0);
  254. DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0);
  255. DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0);
  256. DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0);
  257. DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0);
  258. DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0);
  259. DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0);
  260. static struct rpmpd *msm8998_rpmpds[] = {
  261. [MSM8998_VDDCX] = &msm8998_vddcx,
  262. [MSM8998_VDDCX_AO] = &msm8998_vddcx_ao,
  263. [MSM8998_VDDCX_VFL] = &msm8998_vddcx_vfl,
  264. [MSM8998_VDDMX] = &msm8998_vddmx,
  265. [MSM8998_VDDMX_AO] = &msm8998_vddmx_ao,
  266. [MSM8998_VDDMX_VFL] = &msm8998_vddmx_vfl,
  267. [MSM8998_SSCCX] = &msm8998_vdd_ssccx,
  268. [MSM8998_SSCCX_VFL] = &msm8998_vdd_ssccx_vfl,
  269. [MSM8998_SSCMX] = &msm8998_vdd_sscmx,
  270. [MSM8998_SSCMX_VFL] = &msm8998_vdd_sscmx_vfl,
  271. };
  272. static const struct rpmpd_desc msm8998_desc = {
  273. .rpmpds = msm8998_rpmpds,
  274. .num_pds = ARRAY_SIZE(msm8998_rpmpds),
  275. .max_state = RPM_SMD_LEVEL_BINNING,
  276. };
  277. /* qcs404 RPM Power domains */
  278. DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0);
  279. DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0);
  280. DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0);
  281. DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0);
  282. DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0);
  283. DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0);
  284. static struct rpmpd *qcs404_rpmpds[] = {
  285. [QCS404_VDDMX] = &qcs404_vddmx,
  286. [QCS404_VDDMX_AO] = &qcs404_vddmx_ao,
  287. [QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl,
  288. [QCS404_LPICX] = &qcs404_vdd_lpicx,
  289. [QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl,
  290. [QCS404_LPIMX] = &qcs404_vdd_lpimx,
  291. [QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl,
  292. };
  293. static const struct rpmpd_desc qcs404_desc = {
  294. .rpmpds = qcs404_rpmpds,
  295. .num_pds = ARRAY_SIZE(qcs404_rpmpds),
  296. .max_state = RPM_SMD_LEVEL_BINNING,
  297. };
  298. /* sdm660 RPM Power domains */
  299. DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0);
  300. DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0);
  301. DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0);
  302. DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0);
  303. DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0);
  304. DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0);
  305. DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0);
  306. DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0);
  307. static struct rpmpd *sdm660_rpmpds[] = {
  308. [SDM660_VDDCX] = &sdm660_vddcx,
  309. [SDM660_VDDCX_AO] = &sdm660_vddcx_ao,
  310. [SDM660_VDDCX_VFL] = &sdm660_vddcx_vfl,
  311. [SDM660_VDDMX] = &sdm660_vddmx,
  312. [SDM660_VDDMX_AO] = &sdm660_vddmx_ao,
  313. [SDM660_VDDMX_VFL] = &sdm660_vddmx_vfl,
  314. [SDM660_SSCCX] = &sdm660_vdd_ssccx,
  315. [SDM660_SSCCX_VFL] = &sdm660_vdd_ssccx_vfl,
  316. [SDM660_SSCMX] = &sdm660_vdd_sscmx,
  317. [SDM660_SSCMX_VFL] = &sdm660_vdd_sscmx_vfl,
  318. };
  319. static const struct rpmpd_desc sdm660_desc = {
  320. .rpmpds = sdm660_rpmpds,
  321. .num_pds = ARRAY_SIZE(sdm660_rpmpds),
  322. .max_state = RPM_SMD_LEVEL_TURBO,
  323. };
  324. /* sm4250/6115 RPM Power domains */
  325. DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
  326. DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
  327. DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
  328. DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
  329. DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
  330. DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
  331. static struct rpmpd *sm6115_rpmpds[] = {
  332. [SM6115_VDDCX] = &sm6115_vddcx,
  333. [SM6115_VDDCX_AO] = &sm6115_vddcx_ao,
  334. [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl,
  335. [SM6115_VDDMX] = &sm6115_vddmx,
  336. [SM6115_VDDMX_AO] = &sm6115_vddmx_ao,
  337. [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl,
  338. [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
  339. [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
  340. };
  341. static const struct rpmpd_desc sm6115_desc = {
  342. .rpmpds = sm6115_rpmpds,
  343. .num_pds = ARRAY_SIZE(sm6115_rpmpds),
  344. .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
  345. };
  346. /* sm6125 RPM Power domains */
  347. DEFINE_RPMPD_PAIR(sm6125, vddcx, vddcx_ao, RWCX, LEVEL, 0);
  348. DEFINE_RPMPD_VFL(sm6125, vddcx_vfl, RWCX, 0);
  349. DEFINE_RPMPD_PAIR(sm6125, vddmx, vddmx_ao, RWMX, LEVEL, 0);
  350. DEFINE_RPMPD_VFL(sm6125, vddmx_vfl, RWMX, 0);
  351. static struct rpmpd *sm6125_rpmpds[] = {
  352. [SM6125_VDDCX] = &sm6125_vddcx,
  353. [SM6125_VDDCX_AO] = &sm6125_vddcx_ao,
  354. [SM6125_VDDCX_VFL] = &sm6125_vddcx_vfl,
  355. [SM6125_VDDMX] = &sm6125_vddmx,
  356. [SM6125_VDDMX_AO] = &sm6125_vddmx_ao,
  357. [SM6125_VDDMX_VFL] = &sm6125_vddmx_vfl,
  358. };
  359. static const struct rpmpd_desc sm6125_desc = {
  360. .rpmpds = sm6125_rpmpds,
  361. .num_pds = ARRAY_SIZE(sm6125_rpmpds),
  362. .max_state = RPM_SMD_LEVEL_BINNING,
  363. };
  364. DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0);
  365. static struct rpmpd *sm6375_rpmpds[] = {
  366. [SM6375_VDDCX] = &sm6125_vddcx,
  367. [SM6375_VDDCX_AO] = &sm6125_vddcx_ao,
  368. [SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl,
  369. [SM6375_VDDMX] = &sm6125_vddmx,
  370. [SM6375_VDDMX_AO] = &sm6125_vddmx_ao,
  371. [SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl,
  372. [SM6375_VDDGX] = &sm6375_vddgx,
  373. [SM6375_VDDGX_AO] = &sm6375_vddgx_ao,
  374. [SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
  375. [SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
  376. };
  377. static const struct rpmpd_desc sm6375_desc = {
  378. .rpmpds = sm6375_rpmpds,
  379. .num_pds = ARRAY_SIZE(sm6375_rpmpds),
  380. .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
  381. };
  382. static struct rpmpd *qcm2290_rpmpds[] = {
  383. [QCM2290_VDDCX] = &sm6115_vddcx,
  384. [QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
  385. [QCM2290_VDDCX_VFL] = &sm6115_vddcx_vfl,
  386. [QCM2290_VDDMX] = &sm6115_vddmx,
  387. [QCM2290_VDDMX_AO] = &sm6115_vddmx_ao,
  388. [QCM2290_VDDMX_VFL] = &sm6115_vddmx_vfl,
  389. [QCM2290_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
  390. [QCM2290_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
  391. };
  392. static const struct rpmpd_desc qcm2290_desc = {
  393. .rpmpds = qcm2290_rpmpds,
  394. .num_pds = ARRAY_SIZE(qcm2290_rpmpds),
  395. .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
  396. };
  397. static const struct of_device_id rpmpd_match_table[] = {
  398. { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
  399. { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
  400. { .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
  401. { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
  402. { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
  403. { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
  404. { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
  405. { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
  406. { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
  407. { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
  408. { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
  409. { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
  410. { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
  411. { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
  412. { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
  413. { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
  414. { }
  415. };
  416. MODULE_DEVICE_TABLE(of, rpmpd_match_table);
  417. static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
  418. {
  419. struct rpmpd_req req = {
  420. .key = KEY_ENABLE,
  421. .nbytes = cpu_to_le32(sizeof(u32)),
  422. .value = cpu_to_le32(enable),
  423. };
  424. return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
  425. pd->res_type, pd->res_id, &req, sizeof(req));
  426. }
  427. static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
  428. {
  429. struct rpmpd_req req = {
  430. .key = pd->key,
  431. .nbytes = cpu_to_le32(sizeof(u32)),
  432. .value = cpu_to_le32(corner),
  433. };
  434. return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
  435. &req, sizeof(req));
  436. };
  437. static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
  438. unsigned int *active, unsigned int *sleep)
  439. {
  440. *active = corner;
  441. if (pd->active_only)
  442. *sleep = 0;
  443. else
  444. *sleep = *active;
  445. }
  446. static int rpmpd_aggregate_corner(struct rpmpd *pd)
  447. {
  448. int ret;
  449. struct rpmpd *peer = pd->peer;
  450. unsigned int active_corner, sleep_corner;
  451. unsigned int this_active_corner = 0, this_sleep_corner = 0;
  452. unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
  453. to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
  454. if (peer && peer->enabled)
  455. to_active_sleep(peer, peer->corner, &peer_active_corner,
  456. &peer_sleep_corner);
  457. active_corner = max(this_active_corner, peer_active_corner);
  458. ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
  459. if (ret)
  460. return ret;
  461. sleep_corner = max(this_sleep_corner, peer_sleep_corner);
  462. return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
  463. }
  464. static int rpmpd_power_on(struct generic_pm_domain *domain)
  465. {
  466. int ret;
  467. struct rpmpd *pd = domain_to_rpmpd(domain);
  468. mutex_lock(&rpmpd_lock);
  469. ret = rpmpd_send_enable(pd, true);
  470. if (ret)
  471. goto out;
  472. pd->enabled = true;
  473. if (pd->corner)
  474. ret = rpmpd_aggregate_corner(pd);
  475. out:
  476. mutex_unlock(&rpmpd_lock);
  477. return ret;
  478. }
  479. static int rpmpd_power_off(struct generic_pm_domain *domain)
  480. {
  481. int ret;
  482. struct rpmpd *pd = domain_to_rpmpd(domain);
  483. mutex_lock(&rpmpd_lock);
  484. ret = rpmpd_send_enable(pd, false);
  485. if (!ret)
  486. pd->enabled = false;
  487. mutex_unlock(&rpmpd_lock);
  488. return ret;
  489. }
  490. static int rpmpd_set_performance(struct generic_pm_domain *domain,
  491. unsigned int state)
  492. {
  493. int ret = 0;
  494. struct rpmpd *pd = domain_to_rpmpd(domain);
  495. if (state > pd->max_state)
  496. state = pd->max_state;
  497. mutex_lock(&rpmpd_lock);
  498. pd->corner = state;
  499. /* Always send updates for vfc and vfl */
  500. if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
  501. pd->key != KEY_FLOOR_LEVEL)
  502. goto out;
  503. ret = rpmpd_aggregate_corner(pd);
  504. out:
  505. mutex_unlock(&rpmpd_lock);
  506. return ret;
  507. }
  508. static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
  509. struct dev_pm_opp *opp)
  510. {
  511. return dev_pm_opp_get_level(opp);
  512. }
  513. static int rpmpd_probe(struct platform_device *pdev)
  514. {
  515. int i;
  516. size_t num;
  517. struct genpd_onecell_data *data;
  518. struct qcom_smd_rpm *rpm;
  519. struct rpmpd **rpmpds;
  520. const struct rpmpd_desc *desc;
  521. rpm = dev_get_drvdata(pdev->dev.parent);
  522. if (!rpm) {
  523. dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
  524. return -ENODEV;
  525. }
  526. desc = of_device_get_match_data(&pdev->dev);
  527. if (!desc)
  528. return -EINVAL;
  529. rpmpds = desc->rpmpds;
  530. num = desc->num_pds;
  531. data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  532. if (!data)
  533. return -ENOMEM;
  534. data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
  535. GFP_KERNEL);
  536. if (!data->domains)
  537. return -ENOMEM;
  538. data->num_domains = num;
  539. for (i = 0; i < num; i++) {
  540. if (!rpmpds[i]) {
  541. dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
  542. i);
  543. continue;
  544. }
  545. rpmpds[i]->rpm = rpm;
  546. rpmpds[i]->max_state = desc->max_state;
  547. rpmpds[i]->pd.power_off = rpmpd_power_off;
  548. rpmpds[i]->pd.power_on = rpmpd_power_on;
  549. rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
  550. rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
  551. pm_genpd_init(&rpmpds[i]->pd, NULL, true);
  552. data->domains[i] = &rpmpds[i]->pd;
  553. }
  554. return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
  555. }
  556. static struct platform_driver rpmpd_driver = {
  557. .driver = {
  558. .name = "qcom-rpmpd",
  559. .of_match_table = rpmpd_match_table,
  560. .suppress_bind_attrs = true,
  561. },
  562. .probe = rpmpd_probe,
  563. };
  564. static int __init rpmpd_init(void)
  565. {
  566. return platform_driver_register(&rpmpd_driver);
  567. }
  568. core_initcall(rpmpd_init);
  569. MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
  570. MODULE_LICENSE("GPL v2");