1 /* 2 * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <lib/mmio.h> 9 #include <platform_def.h> 10 11 #include <mt_spm_hwreq.h> 12 #include <mt_spm_reg.h> 13 14 static uint32_t spm_hwcg_index2res(uint32_t idx) 15 { 16 uint32_t res; 17 18 if (idx >= HWCG_MAX) 19 return 0; 20 21 switch (idx) { 22 case HWCG_DDREN: 23 res = (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI); 24 break; 25 case HWCG_VRF18: 26 res = MT_SPM_SYSPLL; 27 break; 28 case HWCG_INFRA: 29 res = MT_SPM_INFRA; 30 break; 31 case HWCG_PMIC: 32 res = MT_SPM_PMIC; 33 break; 34 case HWCG_F26M: 35 res = MT_SPM_26M; 36 break; 37 case HWCG_VCORE: 38 res = MT_SPM_VCORE; 39 break; 40 default: 41 res = 0; 42 } 43 return res; 44 } 45 46 static uint32_t spm_hwcg_ctrl_get(struct spm_hwcg_info *info, 47 enum spm_hwcg_setting type) 48 { 49 uint32_t reg = 0; 50 51 if (!info) 52 return 0; 53 54 switch (type) { 55 case HWCG_PWR: 56 reg = info->pwr; 57 break; 58 case HWCG_PWR_MSB: 59 reg = info->pwr_msb; 60 break; 61 default: 62 reg = info->module_busy; 63 break; 64 } 65 return reg; 66 } 67 68 static void __spm_hwcg_ctrl(struct spm_hwcg_info *info, 69 enum spm_hwcg_setting type, 70 uint32_t is_set, uint32_t val) 71 { 72 uint32_t reg; 73 74 reg = spm_hwcg_ctrl_get(info, type); 75 76 if (!reg) 77 return; 78 79 if (is_set) 80 mmio_setbits_32(reg, val); 81 else 82 mmio_clrbits_32(reg, val); 83 } 84 85 void spm_hwcg_ctrl(uint32_t res, enum spm_hwcg_setting type, 86 uint32_t is_set, uint32_t val) 87 { 88 struct spm_hwcg_info info; 89 90 if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) 91 DECLARE_HWCG_REG(DDREN, info); 92 else if (res & MT_SPM_SYSPLL) 93 DECLARE_HWCG_REG(VRF18, info); 94 else if (res & MT_SPM_INFRA) 95 DECLARE_HWCG_REG(INFRA, info); 96 else if (res & MT_SPM_PMIC) 97 DECLARE_HWCG_REG(PMIC, info); 98 else if (res & MT_SPM_26M) 99 DECLARE_HWCG_REG(F26M, info); 100 else if (res & MT_SPM_VCORE) 101 DECLARE_HWCG_REG(VCORE, info); 102 else 103 HWCG_INFO_INIT(info); 104 105 if (info.pwr) 106 __spm_hwcg_ctrl(&info, type, is_set, val); 107 } 108 109 void spm_hwcg_ctrl_by_index(uint32_t idx, enum spm_hwcg_setting type, 110 uint32_t is_set, uint32_t val) 111 { 112 uint32_t res = spm_hwcg_index2res(idx); 113 114 if (res) 115 spm_hwcg_ctrl(res, type, is_set, val); 116 } 117 118 static uint32_t spm_hwcg_mask_get(uint32_t res, enum spm_hwcg_setting type) 119 { 120 struct spm_hwcg_info info; 121 uint32_t raw_val = 0, reg = 0; 122 123 if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) 124 DECLARE_HWCG_REG(DDREN, info); 125 else if (res & MT_SPM_SYSPLL) 126 DECLARE_HWCG_REG(VRF18, info); 127 else if (res & MT_SPM_INFRA) 128 DECLARE_HWCG_REG(INFRA, info); 129 else if (res & MT_SPM_PMIC) 130 DECLARE_HWCG_REG(PMIC, info); 131 else if (res & MT_SPM_26M) 132 DECLARE_HWCG_REG(F26M, info); 133 else if (res & MT_SPM_VCORE) 134 DECLARE_HWCG_REG(VCORE, info); 135 else 136 HWCG_INFO_INIT(info); 137 138 if (!info.pwr) 139 return 0; 140 141 reg = spm_hwcg_ctrl_get(&info, type); 142 143 if (!reg) 144 return 0; 145 146 raw_val = ~mmio_read_32(reg); 147 148 return raw_val; 149 } 150 151 static uint32_t spm_hwcg_get_default(uint32_t res, enum spm_hwcg_setting type) 152 { 153 struct spm_hwcg_info info; 154 155 if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) 156 DECLARE_HWCG_DEFAULT(DDREN, info); 157 else if (res & MT_SPM_SYSPLL) 158 DECLARE_HWCG_DEFAULT(VRF18, info); 159 else if (res & MT_SPM_INFRA) 160 DECLARE_HWCG_DEFAULT(INFRA, info); 161 else if (res & MT_SPM_PMIC) 162 DECLARE_HWCG_DEFAULT(PMIC, info); 163 else if (res & MT_SPM_26M) 164 DECLARE_HWCG_DEFAULT(F26M, info); 165 else if (res & MT_SPM_VCORE) 166 DECLARE_HWCG_DEFAULT(VCORE, info); 167 else 168 HWCG_INFO_INIT(info); 169 170 if (!info.pwr) 171 return 0; 172 173 return spm_hwcg_ctrl_get(&info, type); 174 } 175 176 uint32_t spm_hwcg_get_status(uint32_t idx, enum spm_hwcg_setting type) 177 { 178 uint32_t val = 0; 179 180 switch (type) { 181 case HWCG_PWR: 182 val = mmio_read_32(PWR_STATUS); 183 break; 184 case HWCG_PWR_MSB: 185 val = mmio_read_32(PWR_STATUS_MSB); 186 break; 187 default: 188 break; 189 } 190 return val; 191 } 192 193 int spm_hwcg_get_setting(uint32_t res, enum spm_hwcg_sta_type sta_type, 194 enum spm_hwcg_setting type, 195 struct spm_hwcg_sta *sta) 196 { 197 int ret = 0; 198 199 if (!sta) 200 return -1; 201 202 switch (sta_type) { 203 case HWCG_STA_DEFAULT_MASK: 204 sta->sta = spm_hwcg_get_default(res, type); 205 break; 206 case HWCG_STA_MASK: 207 sta->sta = spm_hwcg_mask_get(res, type); 208 break; 209 default: 210 ret = -1; 211 MT_SPM_HW_CG_STA_INIT(sta); 212 break; 213 } 214 return ret; 215 } 216 217 int spm_hwcg_get_setting_by_index(uint32_t idx, 218 enum spm_hwcg_sta_type sta_type, 219 enum spm_hwcg_setting type, 220 struct spm_hwcg_sta *sta) 221 { 222 uint32_t res = spm_hwcg_index2res(idx); 223 224 return spm_hwcg_get_setting(res, sta_type, type, sta); 225 } 226 227 static void spm_infra_swcg_init(void) 228 { 229 mmio_write_32(INFRA_SW_CG_MASK, ~INFRA_SW_CG_MB); 230 } 231 232 static void spm_hwcg_init(void) 233 { 234 /* HW CG for ddren, apsrc, emi resource req */ 235 mmio_write_32(REG_PWR_STATUS_DDREN_REQ_MASK, 236 ~SPM_HWCG_DDREN_PWR_MB); 237 mmio_write_32(REG_PWR_STATUS_MSB_DDREN_REQ_MASK, 238 ~SPM_HWCG_DDREN_PWR_MSB_MB); 239 mmio_write_32(REG_MODULE_BUSY_DDREN_REQ_MASK, 240 ~SPM_HWCG_DDREN_MODULE_BUSY_MB); 241 242 /* HW CG for vrf18 resource req */ 243 mmio_write_32(REG_PWR_STATUS_VRF18_REQ_MASK, 244 ~SPM_HWCG_VRF18_PWR_MB); 245 mmio_write_32(REG_PWR_STATUS_MSB_VRF18_REQ_MASK, 246 ~SPM_HWCG_VRF18_PWR_MSB_MB); 247 mmio_write_32(REG_MODULE_BUSY_VRF18_REQ_MASK, 248 ~SPM_HWCG_VRF18_MODULE_BUSY_MB); 249 250 /* HW CG for infra resource req */ 251 mmio_write_32(REG_PWR_STATUS_INFRA_REQ_MASK, 252 ~SPM_HWCG_INFRA_PWR_MB); 253 mmio_write_32(REG_PWR_STATUS_MSB_INFRA_REQ_MASK, 254 ~SPM_HWCG_INFRA_PWR_MSB_MB); 255 mmio_write_32(REG_MODULE_BUSY_INFRA_REQ_MASK, 256 ~SPM_HWCG_INFRA_MODULE_BUSY_MB); 257 258 /* HW CG for pmic resource req */ 259 mmio_write_32(REG_PWR_STATUS_PMIC_REQ_MASK, 260 ~SPM_HWCG_PMIC_PWR_MB); 261 mmio_write_32(REG_PWR_STATUS_MSB_PMIC_REQ_MASK, 262 ~SPM_HWCG_PMIC_PWR_MSB_MB); 263 mmio_write_32(REG_MODULE_BUSY_PMIC_REQ_MASK, 264 ~SPM_HWCG_PMIC_MODULE_BUSY_MB); 265 266 /* HW CG for f26m resource req */ 267 mmio_write_32(REG_PWR_STATUS_F26M_REQ_MASK, 268 ~SPM_HWCG_F26M_PWR_MB); 269 mmio_write_32(REG_PWR_STATUS_MSB_F26M_REQ_MASK, 270 ~SPM_HWCG_F26M_PWR_MSB_MB); 271 mmio_write_32(REG_MODULE_BUSY_F26M_REQ_MASK, 272 ~SPM_HWCG_F26M_MODULE_BUSY_MB); 273 274 /* HW CG for vcore resource req */ 275 mmio_write_32(REG_PWR_STATUS_VCORE_REQ_MASK, 276 ~SPM_HWCG_VCORE_PWR_MB); 277 mmio_write_32(REG_PWR_STATUS_MSB_VCORE_REQ_MASK, 278 ~SPM_HWCG_VCORE_PWR_MSB_MB); 279 mmio_write_32(REG_MODULE_BUSY_VCORE_REQ_MASK, 280 ~SPM_HWCG_VCORE_MODULE_BUSY_MB); 281 } 282 283 #define PERI_CG(ofs) (PERICFG_AO_BASE + 0x10 + (0x4 * (ofs))) 284 #define PERI_REQ_DEFAULT_MB (BIT(PERI_REQ_EN_FLASHIF) | \ 285 BIT(PERI_REQ_EN_AP_DMA) | \ 286 BIT(PERI_REQ_EN_UART1) | \ 287 BIT(PERI_REQ_EN_UART2) | \ 288 BIT(PERI_REQ_EN_UART4) | \ 289 BIT(PERI_REQ_EN_UART5) | \ 290 BIT(PERI_REQ_EN_PWM) | \ 291 BIT(PERI_REQ_EN_SPI0) | \ 292 BIT(PERI_REQ_EN_SPI0_INCR16) | \ 293 BIT(PERI_REQ_EN_SPI1) | \ 294 BIT(PERI_REQ_EN_SPI2) | \ 295 BIT(PERI_REQ_EN_SPI3) | \ 296 BIT(PERI_REQ_EN_SPI4) | \ 297 BIT(PERI_REQ_EN_SPI5) | \ 298 BIT(PERI_REQ_EN_SPI6) | \ 299 BIT(PERI_REQ_EN_SPI7) | \ 300 BIT(PERI_REQ_EN_IMP_IIC)) 301 302 /* For MSDC reqesut WA: PERI_REQ_EN_RSV_FOR_MSDC */ 303 #define PERI_REQ_APSRC_MB (PERI_REQ_DEFAULT_MB | \ 304 BIT(PERI_REQ_EN_RSV_FOR_MSDC)) 305 306 #define PERI_REQ_DDREN_MB (PERI_REQ_DEFAULT_MB | \ 307 BIT(PERI_REQ_EN_USB) | \ 308 BIT(PERI_REQ_EN_UFS0) | \ 309 BIT(PERI_REQ_EN_PEXTP1) | \ 310 BIT(PERI_REQ_EN_PEXTP0) | \ 311 BIT(PERI_REQ_EN_PERI_BUS_TRAFFIC)) 312 #define PERI_REQ_EMI_MB (PERI_REQ_DEFAULT_MB) 313 #define PERI_REQ_INFRA_MB (PERI_REQ_DEFAULT_MB) 314 #define PERI_REQ_SYSPLL_MB (PERI_REQ_DEFAULT_MB) 315 #define PERI_REQ_F26M_MB (PERI_REQ_DEFAULT_MB) 316 317 uint32_t spm_peri_req_get_status(uint32_t idx, enum spm_peri_req_status type) 318 { 319 uint32_t val = 0, reg = 0; 320 struct spm_peri_req_info info; 321 322 switch (type) { 323 case PERI_RES_REQ_EN: 324 325 switch (idx) { 326 case PERI_REQ_DDREN: 327 DECLARE_PERI_REQ_STA_REG(PERI_REQ_DDREN, info); 328 329 break; 330 case PERI_REQ_EMI: 331 DECLARE_PERI_REQ_STA_REG(PERI_REQ_EMI, info); 332 333 break; 334 case PERI_REQ_APSRC: 335 DECLARE_PERI_REQ_STA_REG(PERI_REQ_APSRC, info); 336 337 break; 338 case PERI_REQ_SYSPLL: 339 DECLARE_PERI_REQ_STA_REG(PERI_REQ_SYSPLL, info); 340 341 break; 342 case PERI_REQ_INFRA: 343 DECLARE_PERI_REQ_STA_REG(PERI_REQ_INFRA, info); 344 345 break; 346 case PERI_REQ_F26M: 347 DECLARE_PERI_REQ_STA_REG(PERI_REQ_F26M, info); 348 349 break; 350 default: 351 PERI_REQ_STA_INFO_INIT(info); 352 break; 353 } 354 355 if (!info.req_sta) 356 return 0; 357 358 reg = info.req_sta; 359 val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); 360 361 break; 362 default: 363 break; 364 } 365 return val; 366 } 367 368 int spm_peri_req_name(uint32_t idex, char *name, size_t sz) 369 { 370 int ret = 0; 371 372 if (!name) 373 return -1; 374 375 switch (idex) { 376 case PERI_REQ_DDREN: 377 ret = snprintf(name, sz - 1, "ddren"); 378 break; 379 case PERI_REQ_EMI: 380 ret = snprintf(name, sz - 1, "emi"); 381 break; 382 case PERI_REQ_APSRC: 383 ret = snprintf(name, sz - 1, "apsrc"); 384 break; 385 case PERI_REQ_SYSPLL: 386 ret = snprintf(name, sz - 1, "syspll"); 387 break; 388 case PERI_REQ_INFRA: 389 ret = snprintf(name, sz - 1, "infra"); 390 break; 391 case PERI_REQ_F26M: 392 ret = snprintf(name, sz - 1, "26m_pmic_vcore"); 393 break; 394 default: 395 ret = -1; 396 break; 397 } 398 399 if (ret < 0) 400 ret = -1; 401 402 name[sz-1] = '\0'; 403 404 return ret; 405 } 406 407 uint32_t spm_peri_req_get_status_raw(enum spm_peri_req_status_raw type, 408 uint32_t idx, 409 char *name, size_t sz) 410 { 411 return 0; 412 } 413 414 static uint32_t spm_peri_req_get_default(uint32_t res) 415 { 416 struct spm_peri_req_info info; 417 418 if (res & MT_SPM_DRAM_S1) 419 DECLARE_PERI_REQ_DEFAULT(DDREN, info); 420 else if (res & MT_SPM_EMI) 421 DECLARE_PERI_REQ_DEFAULT(EMI, info); 422 else if (res & MT_SPM_DRAM_S0) 423 DECLARE_PERI_REQ_DEFAULT(APSRC, info); 424 else if (res & MT_SPM_SYSPLL) 425 DECLARE_PERI_REQ_DEFAULT(SYSPLL, info); 426 else if (res & MT_SPM_INFRA) 427 DECLARE_PERI_REQ_DEFAULT(INFRA, info); 428 else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) 429 DECLARE_PERI_REQ_DEFAULT(F26M, info); 430 else 431 PERI_REQ_EN_INFO_INIT(info); 432 433 return info.req_en; 434 } 435 436 static uint32_t spm_peri_req_mask_get(uint32_t res) 437 { 438 struct spm_peri_req_info info; 439 uint32_t raw_val = 0, reg = 0; 440 441 if (res & MT_SPM_DRAM_S1) 442 DECLARE_PERI_REQ_EN_REG(PERI_REQ_DDREN, info); 443 else if (res & MT_SPM_EMI) 444 DECLARE_PERI_REQ_EN_REG(PERI_REQ_EMI, info); 445 else if (res & MT_SPM_DRAM_S0) 446 DECLARE_PERI_REQ_EN_REG(PERI_REQ_APSRC, info); 447 else if (res & MT_SPM_SYSPLL) 448 DECLARE_PERI_REQ_EN_REG(PERI_REQ_SYSPLL, info); 449 else if (res & MT_SPM_INFRA) 450 DECLARE_PERI_REQ_EN_REG(PERI_REQ_INFRA, info); 451 else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) 452 DECLARE_PERI_REQ_EN_REG(PERI_REQ_F26M, info); 453 else 454 PERI_REQ_EN_INFO_INIT(info); 455 456 if (!info.req_en) 457 return 0; 458 459 reg = info.req_en; 460 461 raw_val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); 462 463 return raw_val; 464 } 465 466 int spm_peri_req_get_setting(uint32_t res, 467 enum spm_peri_req_sta_type sta_type, 468 struct spm_peri_req_sta *sta) 469 { 470 int ret = 0; 471 472 if (!sta) 473 return -1; 474 475 switch (sta_type) { 476 case PERI_REQ_STA_DEFAULT_MASK: 477 sta->sta = spm_peri_req_get_default(res); 478 break; 479 case PERI_REQ_STA_MASK: 480 sta->sta = spm_peri_req_mask_get(res); 481 break; 482 default: 483 ret = -1; 484 MT_SPM_HW_CG_STA_INIT(sta); 485 break; 486 } 487 return ret; 488 } 489 490 static uint32_t spm_peri_req_index2res(uint32_t idx) 491 { 492 uint32_t res; 493 494 if (idx >= PERI_REQ_MAX) 495 return 0; 496 497 switch (idx) { 498 case PERI_REQ_DDREN: 499 res = MT_SPM_DRAM_S1; 500 break; 501 case PERI_REQ_EMI: 502 res = MT_SPM_EMI; 503 break; 504 case PERI_REQ_APSRC: 505 res = MT_SPM_DRAM_S0; 506 break; 507 case PERI_REQ_SYSPLL: 508 res = MT_SPM_SYSPLL; 509 break; 510 case PERI_REQ_INFRA: 511 res = MT_SPM_INFRA; 512 break; 513 case PERI_REQ_F26M: 514 res = (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE); 515 break; 516 default: 517 res = 0; 518 } 519 return res; 520 521 } 522 523 int spm_peri_req_get_setting_by_index(uint32_t idx, 524 enum spm_peri_req_sta_type sta_type, 525 struct spm_peri_req_sta *sta) 526 { 527 uint32_t res = spm_peri_req_index2res(idx); 528 529 return spm_peri_req_get_setting(res, sta_type, sta); 530 } 531 532 static void __spm_peri_req_ctrl(struct spm_peri_req_info *info, 533 uint32_t is_set, uint32_t val) 534 { 535 uint32_t raw_val, reg; 536 537 reg = info->req_en; 538 539 if (!reg) 540 return; 541 542 raw_val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); 543 544 if (is_set) 545 raw_val |= val; 546 else 547 raw_val &= ~val; 548 549 mmio_write_32(reg, raw_val); 550 } 551 552 void spm_peri_req_ctrl(uint32_t res, 553 uint32_t is_set, uint32_t val) 554 { 555 struct spm_peri_req_info info; 556 557 if (res & MT_SPM_DRAM_S1) 558 DECLARE_PERI_REQ_EN_REG(PERI_REQ_DDREN, info); 559 else if (res & MT_SPM_EMI) 560 DECLARE_PERI_REQ_EN_REG(PERI_REQ_EMI, info); 561 else if (res & MT_SPM_DRAM_S0) 562 DECLARE_PERI_REQ_EN_REG(PERI_REQ_APSRC, info); 563 else if (res & MT_SPM_SYSPLL) 564 DECLARE_PERI_REQ_EN_REG(PERI_REQ_SYSPLL, info); 565 else if (res & MT_SPM_INFRA) 566 DECLARE_PERI_REQ_EN_REG(PERI_REQ_INFRA, info); 567 else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) 568 DECLARE_PERI_REQ_EN_REG(PERI_REQ_F26M, info); 569 else 570 PERI_REQ_EN_INFO_INIT(info); 571 572 if (info.req_en) 573 __spm_peri_req_ctrl(&info, is_set, val); 574 } 575 576 void spm_peri_req_ctrl_by_index(uint32_t idx, 577 uint32_t is_set, uint32_t val) 578 { 579 uint32_t res = spm_peri_req_index2res(idx); 580 581 if (res) 582 spm_peri_req_ctrl(res, is_set, val); 583 } 584 585 static void spm_peri_req_init(void) 586 { 587 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_DDREN), PERI_REQ_DDREN_MB); 588 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_EMI), PERI_REQ_EMI_MB); 589 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_APSRC), PERI_REQ_APSRC_MB); 590 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_INFRA), PERI_REQ_INFRA_MB); 591 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_SYSPLL), PERI_REQ_SYSPLL_MB); 592 mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_F26M), PERI_REQ_F26M_MB); 593 } 594 595 void spm_hwreq_init(void) 596 { 597 spm_infra_swcg_init(); 598 spm_hwcg_init(); 599 spm_peri_req_init(); 600 } 601