1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Texas Instruments' K3 Clas 0 Adaptive Voltage Scaling driver 4 * 5 * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/ 6 * Tero Kristo <t-kristo@ti.com> 7 * 8 */ 9 10#include <common.h> 11#include <dm.h> 12#include <errno.h> 13#include <asm/io.h> 14#include <i2c.h> 15#include <k3-avs.h> 16#include <dm/device_compat.h> 17#include <linux/bitops.h> 18#include <linux/delay.h> 19#include <power/regulator.h> 20 21#define AM6_VTM_DEVINFO(i) (priv->base + 0x100 + 0x20 * (i)) 22#define AM6_VTM_OPPVID_VD(i) (priv->base + 0x104 + 0x20 * (i)) 23 24#define AM6_VTM_AVS0_SUPPORTED BIT(12) 25 26#define AM6_VTM_OPP_SHIFT(opp) (8 * (opp)) 27#define AM6_VTM_OPP_MASK 0xff 28 29#define K3_VTM_DEVINFO_PWR0_OFFSET 0x4 30#define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK 0xf0 31#define K3_VTM_TMPSENS0_CTRL_OFFSET 0x300 32#define K3_VTM_TMPSENS_STAT_OFFSET 0x8 33#define K3_VTM_ANYMAXT_OUTRG_ALERT_EN 0x1 34#define K3_VTM_LOW_TEMP_OFFSET 0x10 35#define K3_VTM_MISC_CTRL2_OFFSET 0x10 36#define K3_VTM_MISC_CTRL1_OFFSET 0xc 37#define K3_VTM_TMPSENS_CTRL1_SOC BIT(5) 38#define K3_VTM_TMPSENS_CTRL_CLRZ BIT(6) 39#define K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN BIT(11) 40#define K3_VTM_ADC_COUNT_FOR_123C 0x2f8 41#define K3_VTM_ADC_COUNT_FOR_105C 0x288 42#define K3_VTM_ADC_WA_VALUE 0x2c 43#define K3_VTM_FUSE_MASK 0xc0000000 44 45#define VD_FLAG_INIT_DONE BIT(0) 46 47struct k3_avs_privdata { 48 void *base; 49 struct vd_config *vd_config; 50 struct udevice *dev; 51}; 52 53struct opp { 54 u32 freq; 55 u32 volt; 56}; 57 58struct vd_data { 59 int id; 60 u8 opp; 61 u8 flags; 62 int dev_id; 63 int clk_id; 64 struct opp opps[NUM_OPPS]; 65 struct udevice *supply; 66}; 67 68struct vd_config { 69 struct vd_data *vds; 70 u32 (*efuse_xlate)(struct k3_avs_privdata *priv, int idx, int opp); 71}; 72 73static struct k3_avs_privdata *k3_avs_priv; 74 75/** 76 * am6_efuse_voltage: read efuse voltage from VTM 77 * @priv: driver private data 78 * @idx: VD to read efuse for 79 * @opp: opp id to read 80 * 81 * Reads efuse value for the specified OPP, and converts the register 82 * value to a voltage. Returns the voltage in uV, or 0 if nominal voltage 83 * should be used. 84 * 85 * Efuse val to volt conversion logic: 86 * 87 * val > 171 volt increments in 20mV steps with base 171 => 1.66V 88 * val between 115 to 11 increments in 10mV steps with base 115 => 1.1V 89 * val between 15 to 115 increments in 5mV steps with base 15 => .6V 90 * val between 1 to 15 increments in 20mv steps with base 0 => .3V 91 * val 0 is invalid 92 */ 93static u32 am6_efuse_xlate(struct k3_avs_privdata *priv, int idx, int opp) 94{ 95 u32 val = readl(AM6_VTM_OPPVID_VD(idx)); 96 97 val >>= AM6_VTM_OPP_SHIFT(opp); 98 val &= AM6_VTM_OPP_MASK; 99 100 if (!val) 101 return 0; 102 103 if (val > 171) 104 return 1660000 + 20000 * (val - 171); 105 106 if (val > 115) 107 return 1100000 + 10000 * (val - 115); 108 109 if (val > 15) 110 return 600000 + 5000 * (val - 15); 111 112 return 300000 + 20000 * val; 113} 114 115static int k3_avs_program_voltage(struct k3_avs_privdata *priv, 116 struct vd_data *vd, 117 int opp_id) 118{ 119 u32 volt = vd->opps[opp_id].volt; 120 struct vd_data *vd2; 121 122 if (!vd->supply) 123 return -ENODEV; 124 125 vd->opp = opp_id; 126 vd->flags |= VD_FLAG_INIT_DONE; 127 128 /* Take care of ganged rails and pick the Max amongst them*/ 129 for (vd2 = priv->vd_config->vds; vd2->id >= 0; vd2++) { 130 if (vd == vd2) 131 continue; 132 133 if (vd2->supply != vd->supply) 134 continue; 135 136 if (vd2->opps[vd2->opp].volt > volt) 137 volt = vd2->opps[vd2->opp].volt; 138 139 vd2->flags |= VD_FLAG_INIT_DONE; 140 } 141 142 return regulator_set_value(vd->supply, volt); 143} 144 145static struct vd_data *get_vd(struct k3_avs_privdata *priv, int idx) 146{ 147 struct vd_data *vd; 148 149 for (vd = priv->vd_config->vds; vd->id >= 0 && vd->id != idx; vd++) 150 ; 151 152 if (vd->id < 0) 153 return NULL; 154 155 return vd; 156} 157 158/** 159 * k3_avs_set_opp: Sets the voltage for an arbitrary VD rail 160 * @dev: AVS device 161 * @vdd_id: voltage domain ID 162 * @opp_id: OPP ID 163 * 164 * Programs the desired OPP value for the defined voltage rail. This 165 * should be called from board files if reconfiguration is desired. 166 * Returns 0 on success, negative error value on failure. 167 */ 168int k3_avs_set_opp(struct udevice *dev, int vdd_id, int opp_id) 169{ 170 struct k3_avs_privdata *priv = dev_get_priv(dev); 171 struct vd_data *vd; 172 173 vd = get_vd(priv, vdd_id); 174 if (!vd) 175 return -EINVAL; 176 177 return k3_avs_program_voltage(priv, vd, opp_id); 178} 179 180static int match_opp(struct vd_data *vd, u32 freq) 181{ 182 struct opp *opp; 183 int opp_id; 184 185 for (opp_id = 0; opp_id < NUM_OPPS; opp_id++) { 186 opp = &vd->opps[opp_id]; 187 if (opp->freq == freq) 188 return opp_id; 189 } 190 191 printf("No matching OPP found for freq %d.\n", freq); 192 193 return -EINVAL; 194} 195 196/** 197 * k3_avs_notify_freq: Notify clock rate change towards AVS subsystem 198 * @dev_id: Device ID for the clock to be changed 199 * @clk_id: Clock ID for the clock to be changed 200 * @freq: New frequency for clock 201 * 202 * Checks if the provided clock is the MPU clock or not, if not, return 203 * immediately. If MPU clock is provided, maps the provided MPU frequency 204 * towards an MPU OPP, and programs the voltage to the regulator. Return 0 205 * on success, negative error value on failure. 206 */ 207int k3_avs_notify_freq(int dev_id, int clk_id, u32 freq) 208{ 209 int opp_id; 210 struct k3_avs_privdata *priv = k3_avs_priv; 211 struct vd_data *vd; 212 213 /* Driver may not be probed yet */ 214 if (!priv) 215 return -EINVAL; 216 217 for (vd = priv->vd_config->vds; vd->id >= 0; vd++) { 218 if (vd->dev_id != dev_id || vd->clk_id != clk_id) 219 continue; 220 221 opp_id = match_opp(vd, freq); 222 if (opp_id < 0) 223 return opp_id; 224 225 vd->opp = opp_id; 226 return k3_avs_program_voltage(priv, vd, opp_id); 227 } 228 229 return -EINVAL; 230} 231 232static int k3_avs_configure(struct udevice *dev, struct k3_avs_privdata *priv) 233{ 234 struct vd_config *conf; 235 int ret; 236 char pname[20]; 237 struct vd_data *vd; 238 239 conf = (void *)dev_get_driver_data(dev); 240 241 priv->vd_config = conf; 242 243 for (vd = conf->vds; vd->id >= 0; vd++) { 244 sprintf(pname, "vdd-supply-%d", vd->id); 245 ret = device_get_supply_regulator(dev, pname, &vd->supply); 246 if (ret) 247 dev_warn(dev, "supply not found for VD%d.\n", vd->id); 248 249 sprintf(pname, "ti,default-opp-%d", vd->id); 250 ret = dev_read_u32_default(dev, pname, -1); 251 if (ret != -1) 252 vd->opp = ret; 253 } 254 255 return 0; 256} 257 258/* k3_avs_program_tshut : Program thermal shutdown value for SOC 259 * set the values corresponding to thresholds to ~123C and 105C 260 * This is optional feature, Few times OS driver takes care of 261 * tshut programing. 262 */ 263 264static void k3_avs_program_tshut(struct k3_avs_privdata *priv) 265{ 266 int cnt, id, val; 267 int workaround_needed = 0; 268 u32 ctrl_offset; 269 void __iomem *cfg2_base; 270 void __iomem *fuse_base; 271 272 cfg2_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 1); 273 if (IS_ERR(cfg2_base)) { 274 dev_err(priv->dev, "cfg base is not defined\n"); 275 return; 276 } 277 278 /* 279 * Some of TI's J721E SoCs require a software trimming procedure 280 * for the temperature monitors to function properly. To determine 281 * if this particular SoC is NOT affected, both bits in the 282 * WKUP_SPARE_FUSE0[31:30] will be set (0xC0000000) indicating 283 * when software trimming should NOT be applied. 284 * 285 * https://www.ti.com/lit/er/sprz455c/sprz455c.pdf 286 * This routine checks if workaround_needed to be applied or not 287 * based upon workaround_needed, adjust fixed value of tshut high and low 288 */ 289 290 if (device_is_compatible(priv->dev, "ti,j721e-vtm")) { 291 fuse_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 2); 292 if (IS_ERR(fuse_base)) { 293 dev_err(priv->dev, "fuse-base is not defined for J721E Soc\n"); 294 return; 295 } 296 297 if (!((readl(fuse_base) & K3_VTM_FUSE_MASK) == K3_VTM_FUSE_MASK)) 298 workaround_needed = 1; 299 } 300 301 dev_dbg(priv->dev, "Work around %sneeded\n", workaround_needed ? "" : "not "); 302 303 /* Get the sensor count in the VTM */ 304 val = readl(priv->base + K3_VTM_DEVINFO_PWR0_OFFSET); 305 cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK; 306 cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK); 307 308 /* Program the thermal sensors */ 309 for (id = 0; id < cnt; id++) { 310 ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20; 311 312 val = readl(cfg2_base + ctrl_offset); 313 val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN | 314 K3_VTM_TMPSENS_CTRL1_SOC | 315 K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4)); 316 writel(val, cfg2_base + ctrl_offset); 317 } 318 319 /* 320 * Program TSHUT thresholds 321 * Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2 322 * Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN bit 323 * This is already taken care as per of init 324 * Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN bit 325 */ 326 327 /* Low thresholds for tshut*/ 328 val = (K3_VTM_ADC_COUNT_FOR_105C - workaround_needed * K3_VTM_ADC_WA_VALUE) 329 << K3_VTM_LOW_TEMP_OFFSET; 330 /* high thresholds */ 331 val |= K3_VTM_ADC_COUNT_FOR_123C - workaround_needed * K3_VTM_ADC_WA_VALUE; 332 333 writel(val, cfg2_base + K3_VTM_MISC_CTRL2_OFFSET); 334 /* ramp-up delay from Linux code */ 335 mdelay(100); 336 val = readl(cfg2_base + K3_VTM_MISC_CTRL1_OFFSET) | K3_VTM_ANYMAXT_OUTRG_ALERT_EN; 337 writel(val, cfg2_base + K3_VTM_MISC_CTRL1_OFFSET); 338} 339 340/** 341 * k3_avs_probe: parses VD info from VTM, and re-configures the OPP data 342 * 343 * Parses all VDs on a device calculating the AVS class-0 voltages for them, 344 * and updates the vd_data based on this. The vd_data itself shall be used 345 * to program the required OPPs later on. Returns 0 on success, negative 346 * error value on failure. 347 */ 348static int k3_avs_probe(struct udevice *dev) 349{ 350 int opp_id; 351 u32 volt; 352 struct opp *opp; 353 struct k3_avs_privdata *priv; 354 struct vd_data *vd; 355 int ret; 356 357 priv = dev_get_priv(dev); 358 priv->dev = dev; 359 360 k3_avs_priv = priv; 361 362 ret = k3_avs_configure(dev, priv); 363 if (ret) 364 return ret; 365 366 priv->base = dev_read_addr_ptr(dev); 367 if (!priv->base) 368 return -ENODEV; 369 370 for (vd = priv->vd_config->vds; vd->id >= 0; vd++) { 371 if (!(readl(AM6_VTM_DEVINFO(vd->id)) & 372 AM6_VTM_AVS0_SUPPORTED)) { 373 dev_warn(dev, "AVS-class 0 not supported for VD%d\n", 374 vd->id); 375 continue; 376 } 377 378 for (opp_id = 0; opp_id < NUM_OPPS; opp_id++) { 379 opp = &vd->opps[opp_id]; 380 381 if (!opp->freq) 382 continue; 383 384 volt = priv->vd_config->efuse_xlate(priv, vd->id, 385 opp_id); 386 if (volt) 387 opp->volt = volt; 388 } 389 } 390 391 for (vd = priv->vd_config->vds; vd->id >= 0; vd++) { 392 if (vd->flags & VD_FLAG_INIT_DONE) 393 continue; 394 395 k3_avs_program_voltage(priv, vd, vd->opp); 396 } 397 398 if (!device_is_compatible(priv->dev, "ti,am654-avs")) 399 k3_avs_program_tshut(priv); 400 401 return 0; 402} 403 404static struct vd_data am654_vd_data[] = { 405 { 406 .id = AM6_VDD_CORE, 407 .dev_id = 82, /* AM6_DEV_CBASS0 */ 408 .clk_id = 0, /* main sysclk0 */ 409 .opp = AM6_OPP_NOM, 410 .opps = { 411 [AM6_OPP_NOM] = { 412 .volt = 1000000, 413 .freq = 250000000, /* CBASS0 */ 414 }, 415 }, 416 }, 417 { 418 .id = AM6_VDD_MPU0, 419 .dev_id = 202, /* AM6_DEV_COMPUTE_CLUSTER_A53_0 */ 420 .clk_id = 0, /* ARM clock */ 421 .opp = AM6_OPP_NOM, 422 .opps = { 423 [AM6_OPP_NOM] = { 424 .volt = 1100000, 425 .freq = 800000000, 426 }, 427 [AM6_OPP_OD] = { 428 .volt = 1200000, 429 .freq = 1000000000, 430 }, 431 [AM6_OPP_TURBO] = { 432 .volt = 1240000, 433 .freq = 1100000000, 434 }, 435 }, 436 }, 437 { 438 .id = AM6_VDD_MPU1, 439 .opp = AM6_OPP_NOM, 440 .dev_id = 204, /* AM6_DEV_COMPUTE_CLUSTER_A53_2 */ 441 .clk_id = 0, /* ARM clock */ 442 .opps = { 443 [AM6_OPP_NOM] = { 444 .volt = 1100000, 445 .freq = 800000000, 446 }, 447 [AM6_OPP_OD] = { 448 .volt = 1200000, 449 .freq = 1000000000, 450 }, 451 [AM6_OPP_TURBO] = { 452 .volt = 1240000, 453 .freq = 1100000000, 454 }, 455 }, 456 }, 457 { .id = -1 }, 458}; 459 460static struct vd_data j721e_vd_data[] = { 461 { 462 .id = J721E_VDD_MPU, 463 .opp = AM6_OPP_NOM, 464 .dev_id = 202, /* J721E_DEV_A72SS0_CORE0 */ 465 .clk_id = 2, /* ARM clock */ 466 .opps = { 467 [AM6_OPP_NOM] = { 468 .volt = 880000, /* TBD in DM */ 469 .freq = 2000000000, 470 }, 471 }, 472 }, 473 { .id = -1 }, 474}; 475 476static struct vd_config j721e_vd_config = { 477 .efuse_xlate = am6_efuse_xlate, 478 .vds = j721e_vd_data, 479}; 480 481static struct vd_config am654_vd_config = { 482 .efuse_xlate = am6_efuse_xlate, 483 .vds = am654_vd_data, 484}; 485 486static const struct udevice_id k3_avs_ids[] = { 487 { .compatible = "ti,am654-avs", .data = (ulong)&am654_vd_config }, 488 { .compatible = "ti,j721e-avs", .data = (ulong)&j721e_vd_config }, 489 { .compatible = "ti,j721e-vtm", .data = (ulong)&j721e_vd_config }, 490 { .compatible = "ti,j7200-vtm", .data = (ulong)&j721e_vd_config }, 491 {} 492}; 493 494U_BOOT_DRIVER(k3_avs) = { 495 .name = "k3_avs", 496 .of_match = k3_avs_ids, 497 .id = UCLASS_MISC, 498 .probe = k3_avs_probe, 499 .priv_auto = sizeof(struct k3_avs_privdata), 500}; 501