anatop-regulator.c (9744B)
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. 4 5#include <linux/slab.h> 6#include <linux/device.h> 7#include <linux/module.h> 8#include <linux/mfd/syscon.h> 9#include <linux/err.h> 10#include <linux/io.h> 11#include <linux/platform_device.h> 12#include <linux/of.h> 13#include <linux/of_address.h> 14#include <linux/regmap.h> 15#include <linux/regulator/driver.h> 16#include <linux/regulator/of_regulator.h> 17#include <linux/regulator/machine.h> 18 19#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ 20#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ 21 22#define LDO_POWER_GATE 0x00 23#define LDO_FET_FULL_ON 0x1f 24 25struct anatop_regulator { 26 u32 delay_reg; 27 int delay_bit_shift; 28 int delay_bit_width; 29 struct regulator_desc rdesc; 30 bool bypass; 31 int sel; 32}; 33 34static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg, 35 unsigned int old_sel, 36 unsigned int new_sel) 37{ 38 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 39 u32 val; 40 int ret = 0; 41 42 /* check whether need to care about LDO ramp up speed */ 43 if (anatop_reg->delay_bit_width && new_sel > old_sel) { 44 /* 45 * the delay for LDO ramp up time is 46 * based on the register setting, we need 47 * to calculate how many steps LDO need to 48 * ramp up, and how much delay needed. (us) 49 */ 50 regmap_read(reg->regmap, anatop_reg->delay_reg, &val); 51 val = (val >> anatop_reg->delay_bit_shift) & 52 ((1 << anatop_reg->delay_bit_width) - 1); 53 ret = (new_sel - old_sel) * (LDO_RAMP_UP_UNIT_IN_CYCLES << 54 val) / LDO_RAMP_UP_FREQ_IN_MHZ + 1; 55 } 56 57 return ret; 58} 59 60static int anatop_regmap_enable(struct regulator_dev *reg) 61{ 62 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 63 int sel; 64 65 sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel; 66 return regulator_set_voltage_sel_regmap(reg, sel); 67} 68 69static int anatop_regmap_disable(struct regulator_dev *reg) 70{ 71 return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE); 72} 73 74static int anatop_regmap_is_enabled(struct regulator_dev *reg) 75{ 76 return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE; 77} 78 79static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg, 80 unsigned selector) 81{ 82 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 83 int ret; 84 85 if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) { 86 anatop_reg->sel = selector; 87 return 0; 88 } 89 90 ret = regulator_set_voltage_sel_regmap(reg, selector); 91 if (!ret) 92 anatop_reg->sel = selector; 93 return ret; 94} 95 96static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg) 97{ 98 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 99 100 if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) 101 return anatop_reg->sel; 102 103 return regulator_get_voltage_sel_regmap(reg); 104} 105 106static int anatop_regmap_get_bypass(struct regulator_dev *reg, bool *enable) 107{ 108 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 109 int sel; 110 111 sel = regulator_get_voltage_sel_regmap(reg); 112 if (sel == LDO_FET_FULL_ON) 113 WARN_ON(!anatop_reg->bypass); 114 else if (sel != LDO_POWER_GATE) 115 WARN_ON(anatop_reg->bypass); 116 117 *enable = anatop_reg->bypass; 118 return 0; 119} 120 121static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable) 122{ 123 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 124 int sel; 125 126 if (enable == anatop_reg->bypass) 127 return 0; 128 129 sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel; 130 anatop_reg->bypass = enable; 131 132 return regulator_set_voltage_sel_regmap(reg, sel); 133} 134 135static struct regulator_ops anatop_rops = { 136 .set_voltage_sel = regulator_set_voltage_sel_regmap, 137 .get_voltage_sel = regulator_get_voltage_sel_regmap, 138 .list_voltage = regulator_list_voltage_linear, 139 .map_voltage = regulator_map_voltage_linear, 140}; 141 142static const struct regulator_ops anatop_core_rops = { 143 .enable = anatop_regmap_enable, 144 .disable = anatop_regmap_disable, 145 .is_enabled = anatop_regmap_is_enabled, 146 .set_voltage_sel = anatop_regmap_core_set_voltage_sel, 147 .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel, 148 .get_voltage_sel = anatop_regmap_core_get_voltage_sel, 149 .list_voltage = regulator_list_voltage_linear, 150 .map_voltage = regulator_map_voltage_linear, 151 .get_bypass = anatop_regmap_get_bypass, 152 .set_bypass = anatop_regmap_set_bypass, 153}; 154 155static int anatop_regulator_probe(struct platform_device *pdev) 156{ 157 struct device *dev = &pdev->dev; 158 struct device_node *np = dev->of_node; 159 struct device_node *anatop_np; 160 struct regulator_desc *rdesc; 161 struct regulator_dev *rdev; 162 struct anatop_regulator *sreg; 163 struct regulator_init_data *initdata; 164 struct regulator_config config = { }; 165 struct regmap *regmap; 166 u32 control_reg; 167 u32 vol_bit_shift; 168 u32 vol_bit_width; 169 u32 min_bit_val; 170 u32 min_voltage; 171 u32 max_voltage; 172 int ret = 0; 173 u32 val; 174 175 sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); 176 if (!sreg) 177 return -ENOMEM; 178 179 rdesc = &sreg->rdesc; 180 rdesc->type = REGULATOR_VOLTAGE; 181 rdesc->owner = THIS_MODULE; 182 183 of_property_read_string(np, "regulator-name", &rdesc->name); 184 if (!rdesc->name) { 185 dev_err(dev, "failed to get a regulator-name\n"); 186 return -EINVAL; 187 } 188 189 initdata = of_get_regulator_init_data(dev, np, rdesc); 190 if (!initdata) 191 return -ENOMEM; 192 193 initdata->supply_regulator = "vin"; 194 195 anatop_np = of_get_parent(np); 196 if (!anatop_np) 197 return -ENODEV; 198 regmap = syscon_node_to_regmap(anatop_np); 199 of_node_put(anatop_np); 200 if (IS_ERR(regmap)) 201 return PTR_ERR(regmap); 202 203 ret = of_property_read_u32(np, "anatop-reg-offset", &control_reg); 204 if (ret) { 205 dev_err(dev, "no anatop-reg-offset property set\n"); 206 return ret; 207 } 208 ret = of_property_read_u32(np, "anatop-vol-bit-width", &vol_bit_width); 209 if (ret) { 210 dev_err(dev, "no anatop-vol-bit-width property set\n"); 211 return ret; 212 } 213 ret = of_property_read_u32(np, "anatop-vol-bit-shift", &vol_bit_shift); 214 if (ret) { 215 dev_err(dev, "no anatop-vol-bit-shift property set\n"); 216 return ret; 217 } 218 ret = of_property_read_u32(np, "anatop-min-bit-val", &min_bit_val); 219 if (ret) { 220 dev_err(dev, "no anatop-min-bit-val property set\n"); 221 return ret; 222 } 223 ret = of_property_read_u32(np, "anatop-min-voltage", &min_voltage); 224 if (ret) { 225 dev_err(dev, "no anatop-min-voltage property set\n"); 226 return ret; 227 } 228 ret = of_property_read_u32(np, "anatop-max-voltage", &max_voltage); 229 if (ret) { 230 dev_err(dev, "no anatop-max-voltage property set\n"); 231 return ret; 232 } 233 234 /* read LDO ramp up setting, only for core reg */ 235 of_property_read_u32(np, "anatop-delay-reg-offset", 236 &sreg->delay_reg); 237 of_property_read_u32(np, "anatop-delay-bit-width", 238 &sreg->delay_bit_width); 239 of_property_read_u32(np, "anatop-delay-bit-shift", 240 &sreg->delay_bit_shift); 241 242 rdesc->n_voltages = (max_voltage - min_voltage) / 25000 + 1 243 + min_bit_val; 244 rdesc->min_uV = min_voltage; 245 rdesc->uV_step = 25000; 246 rdesc->linear_min_sel = min_bit_val; 247 rdesc->vsel_reg = control_reg; 248 rdesc->vsel_mask = ((1 << vol_bit_width) - 1) << vol_bit_shift; 249 rdesc->min_dropout_uV = 125000; 250 251 config.dev = &pdev->dev; 252 config.init_data = initdata; 253 config.driver_data = sreg; 254 config.of_node = pdev->dev.of_node; 255 config.regmap = regmap; 256 257 /* Only core regulators have the ramp up delay configuration. */ 258 if (control_reg && sreg->delay_bit_width) { 259 rdesc->ops = &anatop_core_rops; 260 261 ret = regmap_read(config.regmap, rdesc->vsel_reg, &val); 262 if (ret) { 263 dev_err(dev, "failed to read initial state\n"); 264 return ret; 265 } 266 267 sreg->sel = (val & rdesc->vsel_mask) >> vol_bit_shift; 268 if (sreg->sel == LDO_FET_FULL_ON) { 269 sreg->sel = 0; 270 sreg->bypass = true; 271 } 272 273 /* 274 * In case vddpu was disabled by the bootloader, we need to set 275 * a sane default until imx6-cpufreq was probed and changes the 276 * voltage to the correct value. In this case we set 1.25V. 277 */ 278 if (!sreg->sel && !strcmp(rdesc->name, "vddpu")) 279 sreg->sel = 22; 280 281 /* set the default voltage of the pcie phy to be 1.100v */ 282 if (!sreg->sel && !strcmp(rdesc->name, "vddpcie")) 283 sreg->sel = 0x10; 284 285 if (!sreg->bypass && !sreg->sel) { 286 dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n"); 287 return -EINVAL; 288 } 289 } else { 290 u32 enable_bit; 291 292 rdesc->ops = &anatop_rops; 293 294 if (!of_property_read_u32(np, "anatop-enable-bit", 295 &enable_bit)) { 296 anatop_rops.enable = regulator_enable_regmap; 297 anatop_rops.disable = regulator_disable_regmap; 298 anatop_rops.is_enabled = regulator_is_enabled_regmap; 299 300 rdesc->enable_reg = control_reg; 301 rdesc->enable_mask = BIT(enable_bit); 302 } 303 } 304 305 /* register regulator */ 306 rdev = devm_regulator_register(dev, rdesc, &config); 307 if (IS_ERR(rdev)) { 308 ret = PTR_ERR(rdev); 309 if (ret == -EPROBE_DEFER) 310 dev_dbg(dev, "failed to register %s, deferring...\n", 311 rdesc->name); 312 else 313 dev_err(dev, "failed to register %s\n", rdesc->name); 314 return ret; 315 } 316 317 platform_set_drvdata(pdev, rdev); 318 319 return 0; 320} 321 322static const struct of_device_id of_anatop_regulator_match_tbl[] = { 323 { .compatible = "fsl,anatop-regulator", }, 324 { /* end */ } 325}; 326MODULE_DEVICE_TABLE(of, of_anatop_regulator_match_tbl); 327 328static struct platform_driver anatop_regulator_driver = { 329 .driver = { 330 .name = "anatop_regulator", 331 .of_match_table = of_anatop_regulator_match_tbl, 332 }, 333 .probe = anatop_regulator_probe, 334}; 335 336static int __init anatop_regulator_init(void) 337{ 338 return platform_driver_register(&anatop_regulator_driver); 339} 340postcore_initcall(anatop_regulator_init); 341 342static void __exit anatop_regulator_exit(void) 343{ 344 platform_driver_unregister(&anatop_regulator_driver); 345} 346module_exit(anatop_regulator_exit); 347 348MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>"); 349MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>"); 350MODULE_DESCRIPTION("ANATOP Regulator driver"); 351MODULE_LICENSE("GPL v2"); 352MODULE_ALIAS("platform:anatop_regulator");