ti-opp-supply.c (12012B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ 4 * Nishanth Menon <nm@ti.com> 5 * Dave Gerlach <d-gerlach@ti.com> 6 * 7 * TI OPP supply driver that provides override into the regulator control 8 * for generic opp core to handle devices with ABB regulator and/or 9 * SmartReflex Class0. 10 */ 11#include <linux/clk.h> 12#include <linux/cpufreq.h> 13#include <linux/device.h> 14#include <linux/io.h> 15#include <linux/module.h> 16#include <linux/notifier.h> 17#include <linux/of_device.h> 18#include <linux/of.h> 19#include <linux/platform_device.h> 20#include <linux/pm_opp.h> 21#include <linux/regulator/consumer.h> 22#include <linux/slab.h> 23 24/** 25 * struct ti_opp_supply_optimum_voltage_table - optimized voltage table 26 * @reference_uv: reference voltage (usually Nominal voltage) 27 * @optimized_uv: Optimized voltage from efuse 28 */ 29struct ti_opp_supply_optimum_voltage_table { 30 unsigned int reference_uv; 31 unsigned int optimized_uv; 32}; 33 34/** 35 * struct ti_opp_supply_data - OMAP specific opp supply data 36 * @vdd_table: Optimized voltage mapping table 37 * @num_vdd_table: number of entries in vdd_table 38 * @vdd_absolute_max_voltage_uv: absolute maximum voltage in UV for the supply 39 */ 40struct ti_opp_supply_data { 41 struct ti_opp_supply_optimum_voltage_table *vdd_table; 42 u32 num_vdd_table; 43 u32 vdd_absolute_max_voltage_uv; 44}; 45 46static struct ti_opp_supply_data opp_data; 47 48/** 49 * struct ti_opp_supply_of_data - device tree match data 50 * @flags: specific type of opp supply 51 * @efuse_voltage_mask: mask required for efuse register representing voltage 52 * @efuse_voltage_uv: Are the efuse entries in micro-volts? if not, assume 53 * milli-volts. 54 */ 55struct ti_opp_supply_of_data { 56#define OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE BIT(1) 57#define OPPDM_HAS_NO_ABB BIT(2) 58 const u8 flags; 59 const u32 efuse_voltage_mask; 60 const bool efuse_voltage_uv; 61}; 62 63/** 64 * _store_optimized_voltages() - store optimized voltages 65 * @dev: ti opp supply device for which we need to store info 66 * @data: data specific to the device 67 * 68 * Picks up efuse based optimized voltages for VDD unique per device and 69 * stores it in internal data structure for use during transition requests. 70 * 71 * Return: If successful, 0, else appropriate error value. 72 */ 73static int _store_optimized_voltages(struct device *dev, 74 struct ti_opp_supply_data *data) 75{ 76 void __iomem *base; 77 struct property *prop; 78 struct resource *res; 79 const __be32 *val; 80 int proplen, i; 81 int ret = 0; 82 struct ti_opp_supply_optimum_voltage_table *table; 83 const struct ti_opp_supply_of_data *of_data = dev_get_drvdata(dev); 84 85 /* pick up Efuse based voltages */ 86 res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 0); 87 if (!res) { 88 dev_err(dev, "Unable to get IO resource\n"); 89 ret = -ENODEV; 90 goto out_map; 91 } 92 93 base = ioremap(res->start, resource_size(res)); 94 if (!base) { 95 dev_err(dev, "Unable to map Efuse registers\n"); 96 ret = -ENOMEM; 97 goto out_map; 98 } 99 100 /* Fetch efuse-settings. */ 101 prop = of_find_property(dev->of_node, "ti,efuse-settings", NULL); 102 if (!prop) { 103 dev_err(dev, "No 'ti,efuse-settings' property found\n"); 104 ret = -EINVAL; 105 goto out; 106 } 107 108 proplen = prop->length / sizeof(int); 109 data->num_vdd_table = proplen / 2; 110 /* Verify for corrupted OPP entries in dt */ 111 if (data->num_vdd_table * 2 * sizeof(int) != prop->length) { 112 dev_err(dev, "Invalid 'ti,efuse-settings'\n"); 113 ret = -EINVAL; 114 goto out; 115 } 116 117 ret = of_property_read_u32(dev->of_node, "ti,absolute-max-voltage-uv", 118 &data->vdd_absolute_max_voltage_uv); 119 if (ret) { 120 dev_err(dev, "ti,absolute-max-voltage-uv is missing\n"); 121 ret = -EINVAL; 122 goto out; 123 } 124 125 table = kcalloc(data->num_vdd_table, sizeof(*data->vdd_table), 126 GFP_KERNEL); 127 if (!table) { 128 ret = -ENOMEM; 129 goto out; 130 } 131 data->vdd_table = table; 132 133 val = prop->value; 134 for (i = 0; i < data->num_vdd_table; i++, table++) { 135 u32 efuse_offset; 136 u32 tmp; 137 138 table->reference_uv = be32_to_cpup(val++); 139 efuse_offset = be32_to_cpup(val++); 140 141 tmp = readl(base + efuse_offset); 142 tmp &= of_data->efuse_voltage_mask; 143 tmp >>= __ffs(of_data->efuse_voltage_mask); 144 145 table->optimized_uv = of_data->efuse_voltage_uv ? tmp : 146 tmp * 1000; 147 148 dev_dbg(dev, "[%d] efuse=0x%08x volt_table=%d vset=%d\n", 149 i, efuse_offset, table->reference_uv, 150 table->optimized_uv); 151 152 /* 153 * Some older samples might not have optimized efuse 154 * Use reference voltage for those - just add debug message 155 * for them. 156 */ 157 if (!table->optimized_uv) { 158 dev_dbg(dev, "[%d] efuse=0x%08x volt_table=%d:vset0\n", 159 i, efuse_offset, table->reference_uv); 160 table->optimized_uv = table->reference_uv; 161 } 162 } 163out: 164 iounmap(base); 165out_map: 166 return ret; 167} 168 169/** 170 * _free_optimized_voltages() - free resources for optvoltages 171 * @dev: device for which we need to free info 172 * @data: data specific to the device 173 */ 174static void _free_optimized_voltages(struct device *dev, 175 struct ti_opp_supply_data *data) 176{ 177 kfree(data->vdd_table); 178 data->vdd_table = NULL; 179 data->num_vdd_table = 0; 180} 181 182/** 183 * _get_optimal_vdd_voltage() - Finds optimal voltage for the supply 184 * @dev: device for which we need to find info 185 * @data: data specific to the device 186 * @reference_uv: reference voltage (OPP voltage) for which we need value 187 * 188 * Return: if a match is found, return optimized voltage, else return 189 * reference_uv, also return reference_uv if no optimization is needed. 190 */ 191static int _get_optimal_vdd_voltage(struct device *dev, 192 struct ti_opp_supply_data *data, 193 int reference_uv) 194{ 195 int i; 196 struct ti_opp_supply_optimum_voltage_table *table; 197 198 if (!data->num_vdd_table) 199 return reference_uv; 200 201 table = data->vdd_table; 202 if (!table) 203 return -EINVAL; 204 205 /* Find a exact match - this list is usually very small */ 206 for (i = 0; i < data->num_vdd_table; i++, table++) 207 if (table->reference_uv == reference_uv) 208 return table->optimized_uv; 209 210 /* IF things are screwed up, we'd make a mess on console.. ratelimit */ 211 dev_err_ratelimited(dev, "%s: Failed optimized voltage match for %d\n", 212 __func__, reference_uv); 213 return reference_uv; 214} 215 216static int _opp_set_voltage(struct device *dev, 217 struct dev_pm_opp_supply *supply, 218 int new_target_uv, struct regulator *reg, 219 char *reg_name) 220{ 221 int ret; 222 unsigned long vdd_uv, uv_max; 223 224 if (new_target_uv) 225 vdd_uv = new_target_uv; 226 else 227 vdd_uv = supply->u_volt; 228 229 /* 230 * If we do have an absolute max voltage specified, then we should 231 * use that voltage instead to allow for cases where the voltage rails 232 * are ganged (example if we set the max for an opp as 1.12v, and 233 * the absolute max is 1.5v, for another rail to get 1.25v, it cannot 234 * be achieved if the regulator is constrainted to max of 1.12v, even 235 * if it can function at 1.25v 236 */ 237 if (opp_data.vdd_absolute_max_voltage_uv) 238 uv_max = opp_data.vdd_absolute_max_voltage_uv; 239 else 240 uv_max = supply->u_volt_max; 241 242 if (vdd_uv > uv_max || 243 vdd_uv < supply->u_volt_min || 244 supply->u_volt_min > uv_max) { 245 dev_warn(dev, 246 "Invalid range voltages [Min:%lu target:%lu Max:%lu]\n", 247 supply->u_volt_min, vdd_uv, uv_max); 248 return -EINVAL; 249 } 250 251 dev_dbg(dev, "%s scaling to %luuV[min %luuV max %luuV]\n", reg_name, 252 vdd_uv, supply->u_volt_min, 253 uv_max); 254 255 ret = regulator_set_voltage_triplet(reg, 256 supply->u_volt_min, 257 vdd_uv, 258 uv_max); 259 if (ret) { 260 dev_err(dev, "%s failed for %luuV[min %luuV max %luuV]\n", 261 reg_name, vdd_uv, supply->u_volt_min, 262 uv_max); 263 return ret; 264 } 265 266 return 0; 267} 268 269/** 270 * ti_opp_supply_set_opp() - do the opp supply transition 271 * @data: information on regulators and new and old opps provided by 272 * opp core to use in transition 273 * 274 * Return: If successful, 0, else appropriate error value. 275 */ 276static int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data) 277{ 278 struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0]; 279 struct dev_pm_opp_supply *old_supply_vbb = &data->old_opp.supplies[1]; 280 struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0]; 281 struct dev_pm_opp_supply *new_supply_vbb = &data->new_opp.supplies[1]; 282 struct device *dev = data->dev; 283 unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate; 284 struct clk *clk = data->clk; 285 struct regulator *vdd_reg = data->regulators[0]; 286 struct regulator *vbb_reg = data->regulators[1]; 287 int vdd_uv; 288 int ret; 289 290 vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data, 291 new_supply_vdd->u_volt); 292 293 if (new_supply_vdd->u_volt_min < vdd_uv) 294 new_supply_vdd->u_volt_min = vdd_uv; 295 296 /* Scaling up? Scale voltage before frequency */ 297 if (freq > old_freq) { 298 ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg, 299 "vdd"); 300 if (ret) 301 goto restore_voltage; 302 303 ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb"); 304 if (ret) 305 goto restore_voltage; 306 } 307 308 /* Change frequency */ 309 dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", 310 __func__, old_freq, freq); 311 312 ret = clk_set_rate(clk, freq); 313 if (ret) { 314 dev_err(dev, "%s: failed to set clock rate: %d\n", __func__, 315 ret); 316 goto restore_voltage; 317 } 318 319 /* Scaling down? Scale voltage after frequency */ 320 if (freq < old_freq) { 321 ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb"); 322 if (ret) 323 goto restore_freq; 324 325 ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg, 326 "vdd"); 327 if (ret) 328 goto restore_freq; 329 } 330 331 return 0; 332 333restore_freq: 334 ret = clk_set_rate(clk, old_freq); 335 if (ret) 336 dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", 337 __func__, old_freq); 338restore_voltage: 339 /* This shouldn't harm even if the voltages weren't updated earlier */ 340 if (old_supply_vdd->u_volt) { 341 ret = _opp_set_voltage(dev, old_supply_vbb, 0, vbb_reg, "vbb"); 342 if (ret) 343 return ret; 344 345 ret = _opp_set_voltage(dev, old_supply_vdd, 0, vdd_reg, 346 "vdd"); 347 if (ret) 348 return ret; 349 } 350 351 return ret; 352} 353 354static const struct ti_opp_supply_of_data omap_generic_of_data = { 355}; 356 357static const struct ti_opp_supply_of_data omap_omap5_of_data = { 358 .flags = OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE, 359 .efuse_voltage_mask = 0xFFF, 360 .efuse_voltage_uv = false, 361}; 362 363static const struct ti_opp_supply_of_data omap_omap5core_of_data = { 364 .flags = OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE | OPPDM_HAS_NO_ABB, 365 .efuse_voltage_mask = 0xFFF, 366 .efuse_voltage_uv = false, 367}; 368 369static const struct of_device_id ti_opp_supply_of_match[] = { 370 {.compatible = "ti,omap-opp-supply", .data = &omap_generic_of_data}, 371 {.compatible = "ti,omap5-opp-supply", .data = &omap_omap5_of_data}, 372 {.compatible = "ti,omap5-core-opp-supply", 373 .data = &omap_omap5core_of_data}, 374 {}, 375}; 376MODULE_DEVICE_TABLE(of, ti_opp_supply_of_match); 377 378static int ti_opp_supply_probe(struct platform_device *pdev) 379{ 380 struct device *dev = &pdev->dev; 381 struct device *cpu_dev = get_cpu_device(0); 382 const struct of_device_id *match; 383 const struct ti_opp_supply_of_data *of_data; 384 int ret = 0; 385 386 match = of_match_device(ti_opp_supply_of_match, dev); 387 if (!match) { 388 /* We do not expect this to happen */ 389 dev_err(dev, "%s: Unable to match device\n", __func__); 390 return -ENODEV; 391 } 392 if (!match->data) { 393 /* Again, unlikely.. but mistakes do happen */ 394 dev_err(dev, "%s: Bad data in match\n", __func__); 395 return -EINVAL; 396 } 397 of_data = match->data; 398 399 dev_set_drvdata(dev, (void *)of_data); 400 401 /* If we need optimized voltage */ 402 if (of_data->flags & OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE) { 403 ret = _store_optimized_voltages(dev, &opp_data); 404 if (ret) 405 return ret; 406 } 407 408 ret = PTR_ERR_OR_ZERO(dev_pm_opp_register_set_opp_helper(cpu_dev, 409 ti_opp_supply_set_opp)); 410 if (ret) 411 _free_optimized_voltages(dev, &opp_data); 412 413 return ret; 414} 415 416static struct platform_driver ti_opp_supply_driver = { 417 .probe = ti_opp_supply_probe, 418 .driver = { 419 .name = "ti_opp_supply", 420 .of_match_table = of_match_ptr(ti_opp_supply_of_match), 421 }, 422}; 423module_platform_driver(ti_opp_supply_driver); 424 425MODULE_DESCRIPTION("Texas Instruments OMAP OPP Supply driver"); 426MODULE_AUTHOR("Texas Instruments Inc."); 427MODULE_LICENSE("GPL v2");