1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 MediaTek Inc. 4 * Copyright (c) 2024 Collabora Ltd. 5 * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 6 */ 7 8 #include <linux/arm-smccc.h> 9 #include <linux/bitfield.h> 10 #include <linux/iopoll.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_platform.h> 14 #include <linux/platform_device.h> 15 #include <linux/soc/mediatek/dvfsrc.h> 16 #include <linux/soc/mediatek/mtk_sip_svc.h> 17 18 /* DVFSRC_LEVEL */ 19 #define DVFSRC_V1_LEVEL_TARGET_LEVEL GENMASK(15, 0) 20 #define DVFSRC_TGT_LEVEL_IDLE 0x00 21 #define DVFSRC_V1_LEVEL_CURRENT_LEVEL GENMASK(31, 16) 22 23 /* DVFSRC_SW_REQ, DVFSRC_SW_REQ2 */ 24 #define DVFSRC_V1_SW_REQ2_DRAM_LEVEL GENMASK(1, 0) 25 #define DVFSRC_V1_SW_REQ2_VCORE_LEVEL GENMASK(3, 2) 26 27 #define DVFSRC_V2_SW_REQ_DRAM_LEVEL GENMASK(3, 0) 28 #define DVFSRC_V2_SW_REQ_VCORE_LEVEL GENMASK(6, 4) 29 30 /* DVFSRC_VCORE */ 31 #define DVFSRC_V2_VCORE_REQ_VSCP_LEVEL GENMASK(14, 12) 32 33 #define DVFSRC_POLL_TIMEOUT_US 1000 34 #define STARTUP_TIME_US 1 35 36 #define MTK_SIP_DVFSRC_INIT 0x0 37 #define MTK_SIP_DVFSRC_START 0x1 38 39 struct dvfsrc_bw_constraints { 40 u16 max_dram_nom_bw; 41 u16 max_dram_peak_bw; 42 u16 max_dram_hrt_bw; 43 }; 44 45 struct dvfsrc_opp { 46 u32 vcore_opp; 47 u32 dram_opp; 48 }; 49 50 struct dvfsrc_opp_desc { 51 const struct dvfsrc_opp *opps; 52 u32 num_opp; 53 }; 54 55 struct dvfsrc_soc_data; 56 struct mtk_dvfsrc { 57 struct device *dev; 58 struct platform_device *icc; 59 struct platform_device *regulator; 60 const struct dvfsrc_soc_data *dvd; 61 const struct dvfsrc_opp_desc *curr_opps; 62 void __iomem *regs; 63 int dram_type; 64 }; 65 66 struct dvfsrc_soc_data { 67 const int *regs; 68 const struct dvfsrc_opp_desc *opps_desc; 69 u32 (*get_target_level)(struct mtk_dvfsrc *dvfsrc); 70 u32 (*get_current_level)(struct mtk_dvfsrc *dvfsrc); 71 u32 (*get_vcore_level)(struct mtk_dvfsrc *dvfsrc); 72 u32 (*get_vscp_level)(struct mtk_dvfsrc *dvfsrc); 73 void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); 74 void (*set_dram_peak_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); 75 void (*set_dram_hrt_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); 76 void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); 77 void (*set_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level); 78 void (*set_vscp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); 79 int (*wait_for_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); 80 int (*wait_for_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level); 81 const struct dvfsrc_bw_constraints *bw_constraints; 82 }; 83 84 static u32 dvfsrc_readl(struct mtk_dvfsrc *dvfs, u32 offset) 85 { 86 return readl(dvfs->regs + dvfs->dvd->regs[offset]); 87 } 88 89 static void dvfsrc_writel(struct mtk_dvfsrc *dvfs, u32 offset, u32 val) 90 { 91 writel(val, dvfs->regs + dvfs->dvd->regs[offset]); 92 } 93 94 enum dvfsrc_regs { 95 DVFSRC_SW_REQ, 96 DVFSRC_SW_REQ2, 97 DVFSRC_LEVEL, 98 DVFSRC_TARGET_LEVEL, 99 DVFSRC_SW_BW, 100 DVFSRC_SW_PEAK_BW, 101 DVFSRC_SW_HRT_BW, 102 DVFSRC_VCORE, 103 DVFSRC_REGS_MAX, 104 }; 105 106 static const int dvfsrc_mt8183_regs[] = { 107 [DVFSRC_SW_REQ] = 0x4, 108 [DVFSRC_SW_REQ2] = 0x8, 109 [DVFSRC_LEVEL] = 0xDC, 110 [DVFSRC_SW_BW] = 0x160, 111 }; 112 113 static const int dvfsrc_mt8195_regs[] = { 114 [DVFSRC_SW_REQ] = 0xc, 115 [DVFSRC_VCORE] = 0x6c, 116 [DVFSRC_SW_PEAK_BW] = 0x278, 117 [DVFSRC_SW_BW] = 0x26c, 118 [DVFSRC_SW_HRT_BW] = 0x290, 119 [DVFSRC_LEVEL] = 0xd44, 120 [DVFSRC_TARGET_LEVEL] = 0xd48, 121 }; 122 123 static const struct dvfsrc_opp *dvfsrc_get_current_opp(struct mtk_dvfsrc *dvfsrc) 124 { 125 u32 level = dvfsrc->dvd->get_current_level(dvfsrc); 126 127 return &dvfsrc->curr_opps->opps[level]; 128 } 129 130 static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc) 131 { 132 if (!dvfsrc->dvd->get_target_level) 133 return true; 134 135 return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_TGT_LEVEL_IDLE; 136 } 137 138 static int dvfsrc_wait_for_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) 139 { 140 const struct dvfsrc_opp *curr; 141 142 return readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, 143 curr->vcore_opp >= level, STARTUP_TIME_US, 144 DVFSRC_POLL_TIMEOUT_US); 145 } 146 147 static int dvfsrc_wait_for_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) 148 { 149 const struct dvfsrc_opp *target, *curr; 150 int ret; 151 152 target = &dvfsrc->curr_opps->opps[level]; 153 ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, 154 curr->dram_opp >= target->dram_opp && 155 curr->vcore_opp >= target->vcore_opp, 156 STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); 157 if (ret < 0) { 158 dev_warn(dvfsrc->dev, 159 "timeout! target OPP: %u, dram: %d, vcore: %d\n", level, 160 curr->dram_opp, curr->vcore_opp); 161 return ret; 162 } 163 164 return 0; 165 } 166 167 static int dvfsrc_wait_for_opp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) 168 { 169 const struct dvfsrc_opp *target, *curr; 170 int ret; 171 172 target = &dvfsrc->curr_opps->opps[level]; 173 ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, 174 curr->dram_opp >= target->dram_opp && 175 curr->vcore_opp >= target->vcore_opp, 176 STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); 177 if (ret < 0) { 178 dev_warn(dvfsrc->dev, 179 "timeout! target OPP: %u, dram: %d\n", level, curr->dram_opp); 180 return ret; 181 } 182 183 return 0; 184 } 185 186 static u32 dvfsrc_get_target_level_v1(struct mtk_dvfsrc *dvfsrc) 187 { 188 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); 189 190 return FIELD_GET(DVFSRC_V1_LEVEL_TARGET_LEVEL, val); 191 } 192 193 static u32 dvfsrc_get_current_level_v1(struct mtk_dvfsrc *dvfsrc) 194 { 195 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); 196 u32 current_level = FIELD_GET(DVFSRC_V1_LEVEL_CURRENT_LEVEL, val); 197 198 return ffs(current_level) - 1; 199 } 200 201 static u32 dvfsrc_get_target_level_v2(struct mtk_dvfsrc *dvfsrc) 202 { 203 return dvfsrc_readl(dvfsrc, DVFSRC_TARGET_LEVEL); 204 } 205 206 static u32 dvfsrc_get_current_level_v2(struct mtk_dvfsrc *dvfsrc) 207 { 208 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); 209 u32 level = ffs(val); 210 211 /* Valid levels */ 212 if (level < dvfsrc->curr_opps->num_opp) 213 return dvfsrc->curr_opps->num_opp - level; 214 215 /* Zero for level 0 or invalid level */ 216 return 0; 217 } 218 219 static u32 dvfsrc_get_vcore_level_v1(struct mtk_dvfsrc *dvfsrc) 220 { 221 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2); 222 223 return FIELD_GET(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, val); 224 } 225 226 static void dvfsrc_set_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) 227 { 228 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2); 229 230 val &= ~DVFSRC_V1_SW_REQ2_VCORE_LEVEL; 231 val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, level); 232 233 dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ2, val); 234 } 235 236 static u32 dvfsrc_get_vcore_level_v2(struct mtk_dvfsrc *dvfsrc) 237 { 238 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ); 239 240 return FIELD_GET(DVFSRC_V2_SW_REQ_VCORE_LEVEL, val); 241 } 242 243 static void dvfsrc_set_vcore_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) 244 { 245 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ); 246 247 val &= ~DVFSRC_V2_SW_REQ_VCORE_LEVEL; 248 val |= FIELD_PREP(DVFSRC_V2_SW_REQ_VCORE_LEVEL, level); 249 250 dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); 251 } 252 253 static u32 dvfsrc_get_vscp_level_v2(struct mtk_dvfsrc *dvfsrc) 254 { 255 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE); 256 257 return FIELD_GET(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, val); 258 } 259 260 static void dvfsrc_set_vscp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) 261 { 262 u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE); 263 264 val &= ~DVFSRC_V2_VCORE_REQ_VSCP_LEVEL; 265 val |= FIELD_PREP(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, level); 266 267 dvfsrc_writel(dvfsrc, DVFSRC_VCORE, val); 268 } 269 270 static void __dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u32 reg, 271 u16 max_bw, u16 min_bw, u64 bw) 272 { 273 u32 new_bw = (u32)div_u64(bw, 100 * 1000); 274 275 /* If bw constraints (in mbps) are defined make sure to respect them */ 276 if (max_bw) 277 new_bw = min(new_bw, max_bw); 278 if (min_bw && new_bw > 0) 279 new_bw = max(new_bw, min_bw); 280 281 dvfsrc_writel(dvfsrc, reg, new_bw); 282 } 283 284 static void dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) 285 { 286 u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_nom_bw; 287 288 __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_BW, max_bw, 0, bw); 289 }; 290 291 static void dvfsrc_set_dram_peak_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) 292 { 293 u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_peak_bw; 294 295 __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_PEAK_BW, max_bw, 0, bw); 296 } 297 298 static void dvfsrc_set_dram_hrt_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) 299 { 300 u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_hrt_bw; 301 302 __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_HRT_BW, max_bw, 0, bw); 303 } 304 305 static void dvfsrc_set_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) 306 { 307 const struct dvfsrc_opp *opp = &dvfsrc->curr_opps->opps[level]; 308 u32 val; 309 310 /* Translate Pstate to DVFSRC level and set it to DVFSRC HW */ 311 val = FIELD_PREP(DVFSRC_V1_SW_REQ2_DRAM_LEVEL, opp->dram_opp); 312 val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, opp->vcore_opp); 313 314 dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n", opp->vcore_opp, opp->dram_opp); 315 dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); 316 } 317 318 int mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data) 319 { 320 struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev); 321 bool state; 322 int ret; 323 324 dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data); 325 326 switch (cmd) { 327 case MTK_DVFSRC_CMD_BW: 328 dvfsrc->dvd->set_dram_bw(dvfsrc, data); 329 return 0; 330 case MTK_DVFSRC_CMD_HRT_BW: 331 if (dvfsrc->dvd->set_dram_hrt_bw) 332 dvfsrc->dvd->set_dram_hrt_bw(dvfsrc, data); 333 return 0; 334 case MTK_DVFSRC_CMD_PEAK_BW: 335 if (dvfsrc->dvd->set_dram_peak_bw) 336 dvfsrc->dvd->set_dram_peak_bw(dvfsrc, data); 337 return 0; 338 case MTK_DVFSRC_CMD_OPP: 339 if (!dvfsrc->dvd->set_opp_level) 340 return 0; 341 342 dvfsrc->dvd->set_opp_level(dvfsrc, data); 343 break; 344 case MTK_DVFSRC_CMD_VCORE_LEVEL: 345 dvfsrc->dvd->set_vcore_level(dvfsrc, data); 346 break; 347 case MTK_DVFSRC_CMD_VSCP_LEVEL: 348 if (!dvfsrc->dvd->set_vscp_level) 349 return 0; 350 351 dvfsrc->dvd->set_vscp_level(dvfsrc, data); 352 break; 353 default: 354 dev_err(dvfsrc->dev, "unknown command: %d\n", cmd); 355 return -EOPNOTSUPP; 356 } 357 358 /* DVFSRC needs at least 2T(~196ns) to handle a request */ 359 udelay(STARTUP_TIME_US); 360 361 ret = readx_poll_timeout_atomic(dvfsrc_is_idle, dvfsrc, state, state, 362 STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); 363 if (ret < 0) { 364 dev_warn(dvfsrc->dev, 365 "%d: idle timeout, data: %llu, last: %d -> %d\n", cmd, data, 366 dvfsrc->dvd->get_current_level(dvfsrc), 367 dvfsrc->dvd->get_target_level(dvfsrc)); 368 return ret; 369 } 370 371 if (cmd == MTK_DVFSRC_CMD_OPP) 372 ret = dvfsrc->dvd->wait_for_opp_level(dvfsrc, data); 373 else 374 ret = dvfsrc->dvd->wait_for_vcore_level(dvfsrc, data); 375 376 if (ret < 0) { 377 dev_warn(dvfsrc->dev, 378 "%d: wait timeout, data: %llu, last: %d -> %d\n", 379 cmd, data, 380 dvfsrc->dvd->get_current_level(dvfsrc), 381 dvfsrc->dvd->get_target_level(dvfsrc)); 382 return ret; 383 } 384 385 return 0; 386 } 387 EXPORT_SYMBOL(mtk_dvfsrc_send_request); 388 389 int mtk_dvfsrc_query_info(const struct device *dev, u32 cmd, int *data) 390 { 391 struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev); 392 393 switch (cmd) { 394 case MTK_DVFSRC_CMD_VCORE_LEVEL: 395 *data = dvfsrc->dvd->get_vcore_level(dvfsrc); 396 break; 397 case MTK_DVFSRC_CMD_VSCP_LEVEL: 398 *data = dvfsrc->dvd->get_vscp_level(dvfsrc); 399 break; 400 default: 401 return -EOPNOTSUPP; 402 } 403 404 return 0; 405 } 406 EXPORT_SYMBOL(mtk_dvfsrc_query_info); 407 408 static int mtk_dvfsrc_probe(struct platform_device *pdev) 409 { 410 struct arm_smccc_res ares; 411 struct mtk_dvfsrc *dvfsrc; 412 int ret; 413 414 dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL); 415 if (!dvfsrc) 416 return -ENOMEM; 417 418 dvfsrc->dvd = of_device_get_match_data(&pdev->dev); 419 dvfsrc->dev = &pdev->dev; 420 421 dvfsrc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 422 if (IS_ERR(dvfsrc->regs)) 423 return PTR_ERR(dvfsrc->regs); 424 425 arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_INIT, 426 0, 0, 0, 0, 0, 0, &ares); 427 if (ares.a0) 428 return dev_err_probe(&pdev->dev, -EINVAL, "DVFSRC init failed: %lu\n", ares.a0); 429 430 dvfsrc->dram_type = ares.a1; 431 dev_dbg(&pdev->dev, "DRAM Type: %d\n", dvfsrc->dram_type); 432 433 dvfsrc->curr_opps = &dvfsrc->dvd->opps_desc[dvfsrc->dram_type]; 434 platform_set_drvdata(pdev, dvfsrc); 435 436 ret = devm_of_platform_populate(&pdev->dev); 437 if (ret) 438 return dev_err_probe(&pdev->dev, ret, "Failed to populate child devices\n"); 439 440 /* Everything is set up - make it run! */ 441 arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_START, 442 0, 0, 0, 0, 0, 0, &ares); 443 if (ares.a0) 444 return dev_err_probe(&pdev->dev, -EINVAL, "Cannot start DVFSRC: %lu\n", ares.a0); 445 446 return 0; 447 } 448 449 static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = { 450 { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 2 }, 451 }; 452 453 static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = { 454 { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 }, 455 }; 456 457 static const struct dvfsrc_opp_desc dvfsrc_opp_mt8183_desc[] = { 458 [0] = { 459 .opps = dvfsrc_opp_mt8183_lp4, 460 .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4), 461 }, 462 [1] = { 463 .opps = dvfsrc_opp_mt8183_lp3, 464 .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3), 465 }, 466 [2] = { 467 .opps = dvfsrc_opp_mt8183_lp3, 468 .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3), 469 } 470 }; 471 472 static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8183 = { 0, 0, 0 }; 473 474 static const struct dvfsrc_soc_data mt8183_data = { 475 .opps_desc = dvfsrc_opp_mt8183_desc, 476 .regs = dvfsrc_mt8183_regs, 477 .get_target_level = dvfsrc_get_target_level_v1, 478 .get_current_level = dvfsrc_get_current_level_v1, 479 .get_vcore_level = dvfsrc_get_vcore_level_v1, 480 .set_dram_bw = dvfsrc_set_dram_bw_v1, 481 .set_opp_level = dvfsrc_set_opp_level_v1, 482 .set_vcore_level = dvfsrc_set_vcore_level_v1, 483 .wait_for_opp_level = dvfsrc_wait_for_opp_level_v1, 484 .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, 485 .bw_constraints = &dvfsrc_bw_constr_mt8183, 486 }; 487 488 static const struct dvfsrc_opp dvfsrc_opp_mt8195_lp4[] = { 489 { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, 490 { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, 491 { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, 492 { 1, 3 }, { 2, 3 }, { 3, 3 }, { 1, 4 }, 493 { 2, 4 }, { 3, 4 }, { 2, 5 }, { 3, 5 }, 494 { 3, 6 }, 495 }; 496 497 static const struct dvfsrc_opp_desc dvfsrc_opp_mt8195_desc[] = { 498 [0] = { 499 .opps = dvfsrc_opp_mt8195_lp4, 500 .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8195_lp4), 501 } 502 }; 503 504 static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8195 = { 505 .max_dram_nom_bw = 255, 506 .max_dram_peak_bw = 255, 507 .max_dram_hrt_bw = 1023, 508 }; 509 510 static const struct dvfsrc_soc_data mt8195_data = { 511 .opps_desc = dvfsrc_opp_mt8195_desc, 512 .regs = dvfsrc_mt8195_regs, 513 .get_target_level = dvfsrc_get_target_level_v2, 514 .get_current_level = dvfsrc_get_current_level_v2, 515 .get_vcore_level = dvfsrc_get_vcore_level_v2, 516 .get_vscp_level = dvfsrc_get_vscp_level_v2, 517 .set_dram_bw = dvfsrc_set_dram_bw_v1, 518 .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1, 519 .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1, 520 .set_vcore_level = dvfsrc_set_vcore_level_v2, 521 .set_vscp_level = dvfsrc_set_vscp_level_v2, 522 .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2, 523 .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, 524 .bw_constraints = &dvfsrc_bw_constr_mt8195, 525 }; 526 527 static const struct of_device_id mtk_dvfsrc_of_match[] = { 528 { .compatible = "mediatek,mt8183-dvfsrc", .data = &mt8183_data }, 529 { .compatible = "mediatek,mt8195-dvfsrc", .data = &mt8195_data }, 530 { /* sentinel */ } 531 }; 532 533 static struct platform_driver mtk_dvfsrc_driver = { 534 .probe = mtk_dvfsrc_probe, 535 .driver = { 536 .name = "mtk-dvfsrc", 537 .of_match_table = mtk_dvfsrc_of_match, 538 }, 539 }; 540 module_platform_driver(mtk_dvfsrc_driver); 541 542 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); 543 MODULE_AUTHOR("Dawei Chien <dawei.chien@mediatek.com>"); 544 MODULE_LICENSE("GPL"); 545 MODULE_DESCRIPTION("MediaTek DVFSRC driver"); 546