adreno_gen7_rpmh.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/types.h>
  7. #include <soc/qcom/cmd-db.h>
  8. #include <soc/qcom/tcs.h>
  9. #include "adreno.h"
  10. #include "adreno_gen7.h"
  11. #include "kgsl_bus.h"
  12. #include "kgsl_device.h"
  13. struct rpmh_arc_vals {
  14. u32 num;
  15. const u16 *val;
  16. };
  17. struct bcm {
  18. const char *name;
  19. u32 buswidth;
  20. u32 channels;
  21. u32 unit;
  22. u16 width;
  23. u8 vcd;
  24. bool fixed;
  25. };
  26. struct bcm_data {
  27. __le32 unit;
  28. __le16 width;
  29. u8 vcd;
  30. u8 reserved;
  31. };
  32. struct rpmh_bw_votes {
  33. u32 wait_bitmask;
  34. u32 num_cmds;
  35. u32 *addrs;
  36. u32 num_levels;
  37. u32 **cmds;
  38. };
  39. #define ARC_VOTE_SET(pri, sec, vlvl) \
  40. (FIELD_PREP(GENMASK(31, 16), vlvl) | \
  41. FIELD_PREP(GENMASK(15, 8), sec) | \
  42. FIELD_PREP(GENMASK(7, 0), pri))
  43. static int rpmh_arc_cmds(struct rpmh_arc_vals *arc, const char *res_id)
  44. {
  45. size_t len = 0;
  46. arc->val = cmd_db_read_aux_data(res_id, &len);
  47. /*
  48. * cmd_db_read_aux_data() gives us a zero-padded table of
  49. * size len that contains the arc values. To determine the
  50. * number of arc values, we loop through the table and count
  51. * them until we get to the end of the buffer or hit the
  52. * zero padding.
  53. */
  54. for (arc->num = 1; arc->num < (len >> 1); arc->num++) {
  55. if (arc->val[arc->num - 1] != 0 && arc->val[arc->num] == 0)
  56. break;
  57. }
  58. return 0;
  59. }
  60. static int setup_volt_dependency_tbl(u32 *votes,
  61. struct rpmh_arc_vals *pri_rail, struct rpmh_arc_vals *sec_rail,
  62. u16 *vlvl, unsigned int num_entries)
  63. {
  64. int i, j, k;
  65. uint16_t cur_vlvl;
  66. bool found_match;
  67. /* i tracks current KGSL GPU frequency table entry
  68. * j tracks secondary rail voltage table entry
  69. * k tracks primary rail voltage table entry
  70. */
  71. for (i = 0; i < num_entries; i++) {
  72. found_match = false;
  73. /* Look for a primary rail voltage that matches a VLVL level */
  74. for (k = 0; k < pri_rail->num; k++) {
  75. if (pri_rail->val[k] >= vlvl[i]) {
  76. cur_vlvl = pri_rail->val[k];
  77. found_match = true;
  78. break;
  79. }
  80. }
  81. /* If we did not find a matching VLVL level then abort */
  82. if (!found_match)
  83. return -EINVAL;
  84. /*
  85. * Look for a secondary rail index whose VLVL value
  86. * is greater than or equal to the VLVL value of the
  87. * corresponding index of the primary rail
  88. */
  89. for (j = 0; j < sec_rail->num; j++) {
  90. if (sec_rail->val[j] >= cur_vlvl ||
  91. j + 1 == sec_rail->num)
  92. break;
  93. }
  94. if (j == sec_rail->num)
  95. j = 0;
  96. votes[i] = ARC_VOTE_SET(k, j, cur_vlvl);
  97. }
  98. return 0;
  99. }
  100. /* Generate a set of bandwidth votes for the list of BCMs */
  101. static void tcs_cmd_data(struct bcm *bcms, int count,
  102. u32 ab, u32 ib, u32 *data, u32 perfmode_vote, bool set_perfmode)
  103. {
  104. int i;
  105. for (i = 0; i < count; i++) {
  106. bool valid = true;
  107. bool commit = false;
  108. u64 avg, peak, x, y;
  109. if (i == count - 1 || bcms[i].vcd != bcms[i + 1].vcd)
  110. commit = true;
  111. if (bcms[i].fixed) {
  112. if (!ab && !ib)
  113. data[i] = BCM_TCS_CMD(commit, false, 0x0, 0x0);
  114. else
  115. data[i] = BCM_TCS_CMD(commit, true, 0x0,
  116. set_perfmode ? perfmode_vote : 0x0);
  117. continue;
  118. }
  119. /* Multiple the bandwidth by the width of the connection */
  120. avg = ((u64) ab) * bcms[i].width;
  121. /* And then divide by the total width */
  122. do_div(avg, bcms[i].buswidth);
  123. peak = ((u64) ib) * bcms[i].width;
  124. do_div(peak, bcms[i].buswidth);
  125. /* Input bandwidth value is in KBps */
  126. x = avg * 1000ULL;
  127. do_div(x, bcms[i].unit);
  128. /* Input bandwidth value is in KBps */
  129. y = peak * 1000ULL;
  130. do_div(y, bcms[i].unit);
  131. /*
  132. * If a bandwidth value was specified but the calculation ends
  133. * rounding down to zero, set a minimum level
  134. */
  135. if (ab && x == 0)
  136. x = 1;
  137. if (ib && y == 0)
  138. y = 1;
  139. x = min_t(u64, x, BCM_TCS_CMD_VOTE_MASK);
  140. y = min_t(u64, y, BCM_TCS_CMD_VOTE_MASK);
  141. if (!x && !y)
  142. valid = false;
  143. data[i] = BCM_TCS_CMD(commit, valid, x, y);
  144. }
  145. }
  146. static void free_rpmh_bw_votes(struct rpmh_bw_votes *votes)
  147. {
  148. int i;
  149. if (!votes)
  150. return;
  151. for (i = 0; votes->cmds && i < votes->num_levels; i++)
  152. kfree(votes->cmds[i]);
  153. kfree(votes->cmds);
  154. kfree(votes->addrs);
  155. kfree(votes);
  156. }
  157. /* Build the votes table from the specified bandwidth levels */
  158. static struct rpmh_bw_votes *build_rpmh_bw_votes(struct bcm *bcms,
  159. int bcm_count, u32 *levels, int levels_count, u32 perfmode_vote, u32 perfmode_lvl)
  160. {
  161. struct rpmh_bw_votes *votes;
  162. bool set_perfmode;
  163. int i;
  164. votes = kzalloc(sizeof(*votes), GFP_KERNEL);
  165. if (!votes)
  166. return ERR_PTR(-ENOMEM);
  167. votes->addrs = kcalloc(bcm_count, sizeof(*votes->cmds), GFP_KERNEL);
  168. if (!votes->addrs) {
  169. free_rpmh_bw_votes(votes);
  170. return ERR_PTR(-ENOMEM);
  171. }
  172. votes->cmds = kcalloc(levels_count, sizeof(*votes->cmds), GFP_KERNEL);
  173. if (!votes->cmds) {
  174. free_rpmh_bw_votes(votes);
  175. return ERR_PTR(-ENOMEM);
  176. }
  177. votes->num_cmds = bcm_count;
  178. votes->num_levels = levels_count;
  179. /* Get the cmd-db information for each BCM */
  180. for (i = 0; i < bcm_count; i++) {
  181. size_t l;
  182. const struct bcm_data *data;
  183. data = cmd_db_read_aux_data(bcms[i].name, &l);
  184. votes->addrs[i] = cmd_db_read_addr(bcms[i].name);
  185. bcms[i].unit = le32_to_cpu(data->unit);
  186. bcms[i].width = le16_to_cpu(data->width);
  187. bcms[i].vcd = data->vcd;
  188. }
  189. for (i = 0; i < bcm_count; i++) {
  190. if (i == (bcm_count - 1) || bcms[i].vcd != bcms[i + 1].vcd)
  191. votes->wait_bitmask |= (1 << i);
  192. }
  193. for (i = 0; i < levels_count; i++) {
  194. votes->cmds[i] = kcalloc(bcm_count, sizeof(u32), GFP_KERNEL);
  195. if (!votes->cmds[i]) {
  196. free_rpmh_bw_votes(votes);
  197. return ERR_PTR(-ENOMEM);
  198. }
  199. set_perfmode = (i >= perfmode_lvl) ? true : false;
  200. tcs_cmd_data(bcms, bcm_count, levels[i], levels[i], votes->cmds[i],
  201. perfmode_vote, set_perfmode);
  202. }
  203. return votes;
  204. }
  205. /*
  206. * setup_gmu_arc_votes - Build the gmu voting table
  207. * @gmu: Pointer to gmu device
  208. * @pri_rail: Pointer to primary power rail vlvl table
  209. * @sec_rail: Pointer to second/dependent power rail vlvl table
  210. *
  211. * This function initializes the cx votes for all gmu frequencies
  212. * for gmu dcvs
  213. */
  214. static int setup_cx_arc_votes(struct gen7_gmu_device *gmu,
  215. struct rpmh_arc_vals *pri_rail, struct rpmh_arc_vals *sec_rail)
  216. {
  217. /* Hardcoded values of GMU CX voltage levels */
  218. u16 gmu_cx_vlvl[MAX_CX_LEVELS];
  219. u32 cx_votes[MAX_CX_LEVELS];
  220. struct gen7_dcvs_table *table = &gmu->dcvs_table;
  221. u32 *freqs = gmu->freqs;
  222. u32 *vlvls = gmu->vlvls;
  223. int ret, i;
  224. gmu_cx_vlvl[0] = 0;
  225. gmu_cx_vlvl[1] = vlvls[0];
  226. gmu_cx_vlvl[2] = vlvls[1];
  227. table->gmu_level_num = 3;
  228. table->cx_votes[0].freq = 0;
  229. table->cx_votes[1].freq = freqs[0] / 1000;
  230. table->cx_votes[2].freq = freqs[1] / 1000;
  231. ret = setup_volt_dependency_tbl(cx_votes, pri_rail,
  232. sec_rail, gmu_cx_vlvl, table->gmu_level_num);
  233. if (!ret) {
  234. for (i = 0; i < table->gmu_level_num; i++)
  235. table->cx_votes[i].vote = cx_votes[i];
  236. }
  237. return ret;
  238. }
  239. static int to_cx_hlvl(struct rpmh_arc_vals *cx_rail, u32 vlvl, u32 *hlvl)
  240. {
  241. u32 i;
  242. /*
  243. * This means that the Gx level doesn't have a dependency on Cx level.
  244. * Return the same value to disable cx voting at GMU.
  245. */
  246. if (vlvl == 0xffffffff) {
  247. *hlvl = vlvl;
  248. return 0;
  249. }
  250. for (i = 0; i < cx_rail->num; i++) {
  251. if (cx_rail->val[i] >= vlvl) {
  252. *hlvl = i;
  253. return 0;
  254. }
  255. }
  256. return -EINVAL;
  257. }
  258. /*
  259. * setup_gx_arc_votes - Build the gpu dcvs voting table
  260. * @hfi: Pointer to hfi device
  261. * @pri_rail: Pointer to primary power rail vlvl table
  262. * @sec_rail: Pointer to second/dependent power rail vlvl table
  263. *
  264. * This function initializes the gx votes for all gpu frequencies
  265. * for gpu dcvs
  266. */
  267. static int setup_gx_arc_votes(struct adreno_device *adreno_dev,
  268. struct rpmh_arc_vals *pri_rail, struct rpmh_arc_vals *sec_rail,
  269. struct rpmh_arc_vals *cx_rail)
  270. {
  271. struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
  272. struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev);
  273. struct kgsl_pwrctrl *pwr = &device->pwrctrl;
  274. struct gen7_dcvs_table *table = &gmu->dcvs_table;
  275. u32 index;
  276. u16 vlvl_tbl[MAX_GX_LEVELS];
  277. u32 gx_votes[MAX_GX_LEVELS];
  278. int ret, i;
  279. if (pwr->num_pwrlevels + 1 > ARRAY_SIZE(vlvl_tbl)) {
  280. dev_err(device->dev,
  281. "Defined more GPU DCVS levels than RPMh can support\n");
  282. return -ERANGE;
  283. }
  284. /* Add the zero powerlevel for the perf table */
  285. table->gpu_level_num = pwr->num_pwrlevels + 1;
  286. memset(vlvl_tbl, 0, sizeof(vlvl_tbl));
  287. table->gx_votes[0].freq = 0;
  288. table->gx_votes[0].cx_vote = 0;
  289. /* Disable cx vote in gmu dcvs table if it is not supported in DT */
  290. if (pwr->pwrlevels[0].cx_level == 0xffffffff)
  291. table->gx_votes[0].cx_vote = 0xffffffff;
  292. /* GMU power levels are in ascending order */
  293. for (index = 1, i = pwr->num_pwrlevels - 1; i >= 0; i--, index++) {
  294. u32 cx_vlvl = pwr->pwrlevels[i].cx_level;
  295. vlvl_tbl[index] = pwr->pwrlevels[i].voltage_level;
  296. table->gx_votes[index].freq = pwr->pwrlevels[i].gpu_freq / 1000;
  297. ret = to_cx_hlvl(cx_rail, cx_vlvl,
  298. &table->gx_votes[index].cx_vote);
  299. if (ret) {
  300. dev_err(device->dev, "Unsupported cx corner: %u\n",
  301. cx_vlvl);
  302. return ret;
  303. }
  304. }
  305. ret = setup_volt_dependency_tbl(gx_votes, pri_rail,
  306. sec_rail, vlvl_tbl, table->gpu_level_num);
  307. if (!ret) {
  308. for (i = 0; i < table->gpu_level_num; i++)
  309. table->gx_votes[i].vote = gx_votes[i];
  310. }
  311. return ret;
  312. }
  313. static int build_dcvs_table(struct adreno_device *adreno_dev)
  314. {
  315. struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev);
  316. struct rpmh_arc_vals gx_arc, cx_arc, mx_arc;
  317. int ret;
  318. ret = rpmh_arc_cmds(&gx_arc, "gfx.lvl");
  319. if (ret)
  320. return ret;
  321. ret = rpmh_arc_cmds(&cx_arc, "cx.lvl");
  322. if (ret)
  323. return ret;
  324. ret = rpmh_arc_cmds(&mx_arc, "mx.lvl");
  325. if (ret)
  326. return ret;
  327. ret = setup_cx_arc_votes(gmu, &cx_arc, &mx_arc);
  328. if (ret)
  329. return ret;
  330. return setup_gx_arc_votes(adreno_dev, &gx_arc, &mx_arc, &cx_arc);
  331. }
  332. /*
  333. * List of Bus Control Modules (BCMs) that need to be configured for the GPU
  334. * to access DDR. For each bus level we will generate a vote each BC
  335. */
  336. static struct bcm gen7_ddr_bcms[] = {
  337. { .name = "SH0", .buswidth = 16 },
  338. { .name = "MC0", .buswidth = 4 },
  339. { .name = "ACV", .fixed = true },
  340. };
  341. /* Same as above, but for the CNOC BCMs */
  342. static struct bcm gen7_cnoc_bcms[] = {
  343. { .name = "CN0", .buswidth = 4 },
  344. };
  345. static void build_bw_table_cmd(struct hfi_bwtable_cmd *cmd,
  346. struct rpmh_bw_votes *ddr, struct rpmh_bw_votes *cnoc)
  347. {
  348. u32 i, j;
  349. cmd->bw_level_num = ddr->num_levels;
  350. cmd->ddr_cmds_num = ddr->num_cmds;
  351. cmd->ddr_wait_bitmask = ddr->wait_bitmask;
  352. for (i = 0; i < ddr->num_cmds; i++)
  353. cmd->ddr_cmd_addrs[i] = ddr->addrs[i];
  354. for (i = 0; i < ddr->num_levels; i++)
  355. for (j = 0; j < ddr->num_cmds; j++)
  356. cmd->ddr_cmd_data[i][j] = (u32) ddr->cmds[i][j];
  357. if (!cnoc)
  358. return;
  359. cmd->cnoc_cmds_num = cnoc->num_cmds;
  360. cmd->cnoc_wait_bitmask = cnoc->wait_bitmask;
  361. for (i = 0; i < cnoc->num_cmds; i++)
  362. cmd->cnoc_cmd_addrs[i] = cnoc->addrs[i];
  363. for (i = 0; i < cnoc->num_levels; i++)
  364. for (j = 0; j < cnoc->num_cmds; j++)
  365. cmd->cnoc_cmd_data[i][j] = (u32) cnoc->cmds[i][j];
  366. }
  367. static int build_bw_table(struct adreno_device *adreno_dev)
  368. {
  369. struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev);
  370. const struct adreno_gen7_core *gen7_core = to_gen7_core(adreno_dev);
  371. struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
  372. struct kgsl_pwrctrl *pwr = &device->pwrctrl;
  373. struct rpmh_bw_votes *ddr, *cnoc = NULL;
  374. u32 perfmode_vote = gen7_core->acv_perfmode_vote;
  375. u32 perfmode_lvl = perfmode_vote ? kgsl_pwrctrl_get_acv_perfmode_lvl(device,
  376. gen7_core->acv_perfmode_ddr_freq) : 1;
  377. u32 *cnoc_table;
  378. u32 count;
  379. int ret;
  380. /* If perfmode vote is not defined, use default value as 0x8 */
  381. if (!perfmode_vote)
  382. perfmode_vote = BIT(3);
  383. ddr = build_rpmh_bw_votes(gen7_ddr_bcms, ARRAY_SIZE(gen7_ddr_bcms),
  384. pwr->ddr_table, pwr->ddr_table_count, perfmode_vote, perfmode_lvl);
  385. if (IS_ERR(ddr))
  386. return PTR_ERR(ddr);
  387. cnoc_table = kgsl_bus_get_table(device->pdev, "qcom,bus-table-cnoc",
  388. &count);
  389. if (count > 0)
  390. cnoc = build_rpmh_bw_votes(gen7_cnoc_bcms,
  391. ARRAY_SIZE(gen7_cnoc_bcms), cnoc_table, count, 0, 0);
  392. kfree(cnoc_table);
  393. if (IS_ERR(cnoc)) {
  394. free_rpmh_bw_votes(ddr);
  395. return PTR_ERR(cnoc);
  396. }
  397. ret = CMD_MSG_HDR(gmu->hfi.bw_table, H2F_MSG_BW_VOTE_TBL);
  398. if (ret)
  399. return ret;
  400. build_bw_table_cmd(&gmu->hfi.bw_table, ddr, cnoc);
  401. free_rpmh_bw_votes(ddr);
  402. free_rpmh_bw_votes(cnoc);
  403. return 0;
  404. }
  405. int gen7_build_rpmh_tables(struct adreno_device *adreno_dev)
  406. {
  407. int ret;
  408. ret = build_dcvs_table(adreno_dev);
  409. if (ret) {
  410. dev_err(adreno_dev->dev.dev, "Failed to build dcvs table\n");
  411. return ret;
  412. }
  413. ret = build_bw_table(adreno_dev);
  414. if (ret)
  415. dev_err(adreno_dev->dev.dev, "Failed to build bw table\n");
  416. return ret;
  417. }