Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

soc: mediatek: mtk-dvfsrc: Add support for DVFSRCv4 and MT8196

Add support for the DVFSRC Version 4 by adding new functions for
vcore/dram levels (in v4, called gears instead), and for readout
of pre-programmed dvfsrc_opp entries, corresponding to each gear.

In the probe function, for v4, the curr_opps is initialized from
the get_hw_opps() function instead of platform data.

In order to make use of the new DVFSRCv4 code, also add support
for the MediaTek MT8196 SoC.

Co-developed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>

+247 -1
+247 -1
drivers/soc/mediatek/mtk-dvfsrc.c
··· 15 15 #include <linux/soc/mediatek/dvfsrc.h> 16 16 #include <linux/soc/mediatek/mtk_sip_svc.h> 17 17 18 + /* DVFSRC_BASIC_CONTROL */ 19 + #define DVFSRC_V4_BASIC_CTRL_OPP_COUNT GENMASK(26, 20) 20 + 18 21 /* DVFSRC_LEVEL */ 19 22 #define DVFSRC_V1_LEVEL_TARGET_LEVEL GENMASK(15, 0) 20 23 #define DVFSRC_TGT_LEVEL_IDLE 0x00 21 24 #define DVFSRC_V1_LEVEL_CURRENT_LEVEL GENMASK(31, 16) 25 + 26 + #define DVFSRC_V4_LEVEL_TARGET_LEVEL GENMASK(15, 8) 27 + #define DVFSRC_V4_LEVEL_TARGET_PRESENT BIT(16) 22 28 23 29 /* DVFSRC_SW_REQ, DVFSRC_SW_REQ2 */ 24 30 #define DVFSRC_V1_SW_REQ2_DRAM_LEVEL GENMASK(1, 0) ··· 33 27 #define DVFSRC_V2_SW_REQ_DRAM_LEVEL GENMASK(3, 0) 34 28 #define DVFSRC_V2_SW_REQ_VCORE_LEVEL GENMASK(6, 4) 35 29 30 + #define DVFSRC_V4_SW_REQ_EMI_LEVEL GENMASK(3, 0) 31 + #define DVFSRC_V4_SW_REQ_DRAM_LEVEL GENMASK(15, 12) 32 + 36 33 /* DVFSRC_VCORE */ 37 34 #define DVFSRC_V2_VCORE_REQ_VSCP_LEVEL GENMASK(14, 12) 35 + 36 + /* DVFSRC_TARGET_GEAR */ 37 + #define DVFSRC_V4_GEAR_TARGET_DRAM GENMASK(7, 0) 38 + #define DVFSRC_V4_GEAR_TARGET_VCORE GENMASK(15, 8) 39 + 40 + /* DVFSRC_GEAR_INFO */ 41 + #define DVFSRC_V4_GEAR_INFO_REG_WIDTH 0x4 42 + #define DVFSRC_V4_GEAR_INFO_REG_LEVELS 64 43 + #define DVFSRC_V4_GEAR_INFO_VCORE GENMASK(3, 0) 44 + #define DVFSRC_V4_GEAR_INFO_EMI GENMASK(7, 4) 45 + #define DVFSRC_V4_GEAR_INFO_DRAM GENMASK(15, 12) 38 46 39 47 #define DVFSRC_POLL_TIMEOUT_US 1000 40 48 #define STARTUP_TIME_US 1 ··· 72 52 struct dvfsrc_opp { 73 53 u32 vcore_opp; 74 54 u32 dram_opp; 55 + u32 emi_opp; 75 56 }; 76 57 77 58 struct dvfsrc_opp_desc { ··· 93 72 94 73 struct dvfsrc_soc_data { 95 74 const int *regs; 75 + const u8 *bw_units; 96 76 const bool has_emi_ddr; 97 77 const struct dvfsrc_opp_desc *opps_desc; 98 78 u32 (*calc_dram_bw)(struct mtk_dvfsrc *dvfsrc, int type, u64 bw); ··· 101 79 u32 (*get_current_level)(struct mtk_dvfsrc *dvfsrc); 102 80 u32 (*get_vcore_level)(struct mtk_dvfsrc *dvfsrc); 103 81 u32 (*get_vscp_level)(struct mtk_dvfsrc *dvfsrc); 82 + u32 (*get_opp_count)(struct mtk_dvfsrc *dvfsrc); 83 + int (*get_hw_opps)(struct mtk_dvfsrc *dvfsrc); 104 84 void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); 105 85 void (*set_dram_peak_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); 106 86 void (*set_dram_hrt_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); ··· 125 101 } 126 102 127 103 enum dvfsrc_regs { 104 + DVFSRC_BASIC_CONTROL, 128 105 DVFSRC_SW_REQ, 129 106 DVFSRC_SW_REQ2, 130 107 DVFSRC_LEVEL, ··· 135 110 DVFSRC_SW_HRT_BW, 136 111 DVFSRC_SW_EMI_BW, 137 112 DVFSRC_VCORE, 113 + DVFSRC_TARGET_GEAR, 114 + DVFSRC_GEAR_INFO_L, 115 + DVFSRC_GEAR_INFO_H, 138 116 DVFSRC_REGS_MAX, 139 117 }; 140 118 ··· 158 130 [DVFSRC_TARGET_LEVEL] = 0xd48, 159 131 }; 160 132 133 + static const int dvfsrc_mt8196_regs[] = { 134 + [DVFSRC_BASIC_CONTROL] = 0x0, 135 + [DVFSRC_SW_REQ] = 0x18, 136 + [DVFSRC_VCORE] = 0x80, 137 + [DVFSRC_GEAR_INFO_L] = 0xfc, 138 + [DVFSRC_SW_BW] = 0x1e8, 139 + [DVFSRC_SW_PEAK_BW] = 0x1f4, 140 + [DVFSRC_SW_HRT_BW] = 0x20c, 141 + [DVFSRC_LEVEL] = 0x5f0, 142 + [DVFSRC_TARGET_LEVEL] = 0x5f0, 143 + [DVFSRC_SW_REQ2] = 0x604, 144 + [DVFSRC_SW_EMI_BW] = 0x60c, 145 + [DVFSRC_TARGET_GEAR] = 0x6ac, 146 + [DVFSRC_GEAR_INFO_H] = 0x6b0, 147 + }; 148 + 161 149 static const struct dvfsrc_opp *dvfsrc_get_current_opp(struct mtk_dvfsrc *dvfsrc) 162 150 { 163 151 u32 level = dvfsrc->dvd->get_current_level(dvfsrc); 164 152 165 153 return &dvfsrc->curr_opps->opps[level]; 154 + } 155 + 156 + static u32 dvfsrc_get_current_target_vcore_gear(struct mtk_dvfsrc *dvfsrc) 157 + { 158 + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_TARGET_GEAR); 159 + 160 + return FIELD_GET(DVFSRC_V4_GEAR_TARGET_VCORE, val); 161 + } 162 + 163 + static u32 dvfsrc_get_current_target_dram_gear(struct mtk_dvfsrc *dvfsrc) 164 + { 165 + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_TARGET_GEAR); 166 + 167 + return FIELD_GET(DVFSRC_V4_GEAR_TARGET_DRAM, val); 166 168 } 167 169 168 170 static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc) ··· 251 193 return 0; 252 194 } 253 195 196 + static int dvfsrc_wait_for_vcore_level_v4(struct mtk_dvfsrc *dvfsrc, u32 level) 197 + { 198 + u32 val; 199 + 200 + return readx_poll_timeout_atomic(dvfsrc_get_current_target_vcore_gear, 201 + dvfsrc, val, val >= level, 202 + STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); 203 + } 204 + 205 + static int dvfsrc_wait_for_opp_level_v4(struct mtk_dvfsrc *dvfsrc, u32 level) 206 + { 207 + u32 val; 208 + 209 + return readx_poll_timeout_atomic(dvfsrc_get_current_target_dram_gear, 210 + dvfsrc, val, val >= level, 211 + STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); 212 + } 213 + 254 214 static u32 dvfsrc_get_target_level_v1(struct mtk_dvfsrc *dvfsrc) 255 215 { 256 216 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); ··· 293 217 { 294 218 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); 295 219 u32 level = ffs(val); 220 + 221 + /* Valid levels */ 222 + if (level < dvfsrc->curr_opps->num_opp) 223 + return dvfsrc->curr_opps->num_opp - level; 224 + 225 + /* Zero for level 0 or invalid level */ 226 + return 0; 227 + } 228 + 229 + static u32 dvfsrc_get_target_level_v4(struct mtk_dvfsrc *dvfsrc) 230 + { 231 + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_TARGET_LEVEL); 232 + 233 + if (val & DVFSRC_V4_LEVEL_TARGET_PRESENT) 234 + return FIELD_GET(DVFSRC_V4_LEVEL_TARGET_LEVEL, val) + 1; 235 + return 0; 236 + } 237 + 238 + static u32 dvfsrc_get_current_level_v4(struct mtk_dvfsrc *dvfsrc) 239 + { 240 + u32 level = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL) + 1; 296 241 297 242 /* Valid levels */ 298 243 if (level < dvfsrc->curr_opps->num_opp) ··· 374 277 dvfsrc_writel(dvfsrc, DVFSRC_VCORE, val); 375 278 } 376 279 280 + static u32 dvfsrc_get_opp_count_v4(struct mtk_dvfsrc *dvfsrc) 281 + { 282 + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_BASIC_CONTROL); 283 + 284 + return FIELD_GET(DVFSRC_V4_BASIC_CTRL_OPP_COUNT, val) + 1; 285 + } 286 + 377 287 static u32 dvfsrc_calc_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, int type, u64 bw) 378 288 { 379 289 return (u32)div_u64(bw, 100 * 1000); 290 + } 291 + 292 + static u32 dvfsrc_calc_dram_bw_v4(struct mtk_dvfsrc *dvfsrc, int type, u64 bw) 293 + { 294 + u8 bw_unit = dvfsrc->dvd->bw_units[type]; 295 + u64 bw_mbps; 296 + 297 + if (type < DVFSRC_BW_AVG || type >= DVFSRC_BW_MAX) 298 + return 0; 299 + 300 + bw_mbps = div_u64(bw, 1000); 301 + return (u32)div_u64((bw_mbps + bw_unit - 1), bw_unit); 380 302 } 381 303 382 304 static void __dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u32 reg, ··· 446 330 val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, opp->vcore_opp); 447 331 448 332 dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n", opp->vcore_opp, opp->dram_opp); 333 + dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); 334 + } 335 + 336 + static u32 dvfsrc_get_opp_gear(struct mtk_dvfsrc *dvfsrc, u8 level) 337 + { 338 + u32 reg_ofst, val; 339 + u8 idx; 340 + 341 + /* Calculate register offset and index for requested gear */ 342 + if (level < DVFSRC_V4_GEAR_INFO_REG_LEVELS) { 343 + reg_ofst = dvfsrc->dvd->regs[DVFSRC_GEAR_INFO_L]; 344 + idx = level; 345 + } else { 346 + reg_ofst = dvfsrc->dvd->regs[DVFSRC_GEAR_INFO_H]; 347 + idx = level - DVFSRC_V4_GEAR_INFO_REG_LEVELS; 348 + } 349 + reg_ofst += DVFSRC_V4_GEAR_INFO_REG_WIDTH * (level / 2); 350 + 351 + /* Read the corresponding gear register */ 352 + val = readl(dvfsrc->regs + reg_ofst); 353 + 354 + /* Each register contains two sets of data, 16 bits per gear */ 355 + val >>= 16 * (idx % 2); 356 + 357 + return val; 358 + } 359 + 360 + static int dvfsrc_get_hw_opps_v4(struct mtk_dvfsrc *dvfsrc) 361 + { 362 + struct dvfsrc_opp *dvfsrc_opps; 363 + struct dvfsrc_opp_desc *desc; 364 + u32 num_opps, gear_info; 365 + u8 num_vcore, num_dram; 366 + u8 num_emi; 367 + int i; 368 + 369 + num_opps = dvfsrc_get_opp_count_v4(dvfsrc); 370 + if (num_opps == 0) { 371 + dev_err(dvfsrc->dev, "No OPPs programmed in DVFSRC MCU.\n"); 372 + return -EINVAL; 373 + } 374 + 375 + /* 376 + * The first 16 bits set in the gear info table says how many OPPs 377 + * and how many vcore, dram and emi table entries are available. 378 + */ 379 + gear_info = dvfsrc_readl(dvfsrc, DVFSRC_GEAR_INFO_L); 380 + if (gear_info == 0) { 381 + dev_err(dvfsrc->dev, "No gear info in DVFSRC MCU.\n"); 382 + return -EINVAL; 383 + } 384 + 385 + num_vcore = FIELD_GET(DVFSRC_V4_GEAR_INFO_VCORE, gear_info) + 1; 386 + num_dram = FIELD_GET(DVFSRC_V4_GEAR_INFO_DRAM, gear_info) + 1; 387 + num_emi = FIELD_GET(DVFSRC_V4_GEAR_INFO_EMI, gear_info) + 1; 388 + dev_info(dvfsrc->dev, 389 + "Discovered %u gears and %u vcore, %u dram, %u emi table entries.\n", 390 + num_opps, num_vcore, num_dram, num_emi); 391 + 392 + /* Allocate everything now as anything else after that cannot fail */ 393 + desc = devm_kzalloc(dvfsrc->dev, sizeof(*desc), GFP_KERNEL); 394 + if (!desc) 395 + return -ENOMEM; 396 + 397 + dvfsrc_opps = devm_kcalloc(dvfsrc->dev, num_opps + 1, 398 + sizeof(*dvfsrc_opps), GFP_KERNEL); 399 + if (!dvfsrc_opps) 400 + return -ENOMEM; 401 + 402 + /* Read the OPP table gear indices */ 403 + for (i = 0; i <= num_opps; i++) { 404 + gear_info = dvfsrc_get_opp_gear(dvfsrc, num_opps - i); 405 + dvfsrc_opps[i].vcore_opp = FIELD_GET(DVFSRC_V4_GEAR_INFO_VCORE, gear_info); 406 + dvfsrc_opps[i].dram_opp = FIELD_GET(DVFSRC_V4_GEAR_INFO_DRAM, gear_info); 407 + dvfsrc_opps[i].emi_opp = FIELD_GET(DVFSRC_V4_GEAR_INFO_EMI, gear_info); 408 + }; 409 + desc->num_opp = num_opps + 1; 410 + desc->opps = dvfsrc_opps; 411 + 412 + /* Assign to main structure now that everything is done! */ 413 + dvfsrc->curr_opps = desc; 414 + 415 + return 0; 416 + } 417 + 418 + static void dvfsrc_set_dram_level_v4(struct mtk_dvfsrc *dvfsrc, u32 level) 419 + { 420 + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ); 421 + 422 + val &= ~DVFSRC_V4_SW_REQ_DRAM_LEVEL; 423 + val |= FIELD_PREP(DVFSRC_V4_SW_REQ_DRAM_LEVEL, level); 424 + 425 + dev_dbg(dvfsrc->dev, "%s level=%u\n", __func__, level); 426 + 449 427 dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); 450 428 } 451 429 ··· 658 448 dvfsrc->dram_type = ares.a1; 659 449 dev_dbg(&pdev->dev, "DRAM Type: %d\n", dvfsrc->dram_type); 660 450 661 - dvfsrc->curr_opps = &dvfsrc->dvd->opps_desc[dvfsrc->dram_type]; 451 + /* Newer versions of the DVFSRC MCU have pre-programmed gear tables */ 452 + if (dvfsrc->dvd->get_hw_opps) { 453 + ret = dvfsrc->dvd->get_hw_opps(dvfsrc); 454 + if (ret) 455 + return ret; 456 + } else { 457 + dvfsrc->curr_opps = &dvfsrc->dvd->opps_desc[dvfsrc->dram_type]; 458 + } 662 459 platform_set_drvdata(pdev, dvfsrc); 663 460 664 461 ret = devm_of_platform_populate(&pdev->dev); ··· 793 576 .bw_constraints = &dvfsrc_bw_constr_v2, 794 577 }; 795 578 579 + static const u8 mt8196_bw_units[] = { 580 + [DVFSRC_BW_AVG] = 64, 581 + [DVFSRC_BW_PEAK] = 64, 582 + [DVFSRC_BW_HRT] = 30, 583 + }; 584 + 585 + static const struct dvfsrc_soc_data mt8196_data = { 586 + .regs = dvfsrc_mt8196_regs, 587 + .bw_units = mt8196_bw_units, 588 + .has_emi_ddr = true, 589 + .get_target_level = dvfsrc_get_target_level_v4, 590 + .get_current_level = dvfsrc_get_current_level_v4, 591 + .get_vcore_level = dvfsrc_get_vcore_level_v2, 592 + .get_vscp_level = dvfsrc_get_vscp_level_v2, 593 + .get_opp_count = dvfsrc_get_opp_count_v4, 594 + .get_hw_opps = dvfsrc_get_hw_opps_v4, 595 + .calc_dram_bw = dvfsrc_calc_dram_bw_v4, 596 + .set_dram_bw = dvfsrc_set_dram_bw_v1, 597 + .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1, 598 + .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1, 599 + .set_opp_level = dvfsrc_set_dram_level_v4, 600 + .set_vcore_level = dvfsrc_set_vcore_level_v2, 601 + .set_vscp_level = dvfsrc_set_vscp_level_v2, 602 + .wait_for_opp_level = dvfsrc_wait_for_opp_level_v4, 603 + .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v4, 604 + .bw_constraints = &dvfsrc_bw_constr_v1, 605 + }; 606 + 796 607 static const struct of_device_id mtk_dvfsrc_of_match[] = { 797 608 { .compatible = "mediatek,mt6893-dvfsrc", .data = &mt6893_data }, 798 609 { .compatible = "mediatek,mt8183-dvfsrc", .data = &mt8183_data }, 799 610 { .compatible = "mediatek,mt8195-dvfsrc", .data = &mt8195_data }, 611 + { .compatible = "mediatek,mt8196-dvfsrc", .data = &mt8196_data }, 800 612 { /* sentinel */ } 801 613 }; 802 614