Blame view
drivers/regulator/tps51632-regulator.c
10.2 KB
0c5706743 regulator: tps516... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * tps51632-regulator.c -- TI TPS51632 * * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless * Controller with serial VID control and DVFS. * * Copyright (c) 2012, NVIDIA Corporation. * * Author: Laxman Dewangan <ldewangan@nvidia.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2. * * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, * whether express or implied; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ #include <linux/err.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> |
c51ce403d regulator: tps516... |
31 32 |
#include <linux/of.h> #include <linux/of_device.h> |
0c5706743 regulator: tps516... |
33 34 35 36 |
#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> |
c51ce403d regulator: tps516... |
37 |
#include <linux/regulator/of_regulator.h> |
0c5706743 regulator: tps516... |
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#include <linux/regulator/tps51632-regulator.h> #include <linux/slab.h> /* Register definitions */ #define TPS51632_VOLTAGE_SELECT_REG 0x0 #define TPS51632_VOLTAGE_BASE_REG 0x1 #define TPS51632_OFFSET_REG 0x2 #define TPS51632_IMON_REG 0x3 #define TPS51632_VMAX_REG 0x4 #define TPS51632_DVFS_CONTROL_REG 0x5 #define TPS51632_POWER_STATE_REG 0x6 #define TPS51632_SLEW_REGS 0x7 #define TPS51632_FAULT_REG 0x14 #define TPS51632_MAX_REG 0x15 #define TPS51632_VOUT_MASK 0x7F #define TPS51632_VOUT_OFFSET_MASK 0x1F #define TPS51632_VMAX_MASK 0x7F #define TPS51632_VMAX_LOCK 0x80 /* TPS51632_DVFS_CONTROL_REG */ #define TPS51632_DVFS_PWMEN 0x1 #define TPS51632_DVFS_STEP_20 0x2 #define TPS51632_DVFS_VMAX_PG 0x4 #define TPS51632_DVFS_PWMRST 0x8 #define TPS51632_DVFS_OCA_EN 0x10 #define TPS51632_DVFS_FCCM 0x20 /* TPS51632_POWER_STATE_REG */ #define TPS51632_POWER_STATE_MASK 0x03 #define TPS51632_POWER_STATE_MULTI_PHASE_CCM 0x0 #define TPS51632_POWER_STATE_SINGLE_PHASE_CCM 0x1 #define TPS51632_POWER_STATE_SINGLE_PHASE_DCM 0x2 |
9d9339d3a regulator: tps516... |
72 73 74 75 |
#define TPS51632_MIN_VOLTAGE 500000 #define TPS51632_MAX_VOLTAGE 1520000 #define TPS51632_VOLTAGE_STEP_10mV 10000 #define TPS51632_VOLTAGE_STEP_20mV 20000 |
0c5706743 regulator: tps516... |
76 77 78 79 |
#define TPS51632_MAX_VSEL 0x7F #define TPS51632_MIN_VSEL 0x19 #define TPS51632_DEFAULT_RAMP_DELAY 6000 #define TPS51632_VOLT_VSEL(uV) \ |
9d9339d3a regulator: tps516... |
80 81 |
(DIV_ROUND_UP(uV - TPS51632_MIN_VOLTAGE, \ TPS51632_VOLTAGE_STEP_10mV) + \ |
0c5706743 regulator: tps516... |
82 83 84 85 86 87 88 89 |
TPS51632_MIN_VSEL) /* TPS51632 chip information */ struct tps51632_chip { struct device *dev; struct regulator_desc desc; struct regulator_dev *rdev; struct regmap *regmap; |
0c5706743 regulator: tps516... |
90 |
}; |
0c5706743 regulator: tps516... |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { struct tps51632_chip *tps = rdev_get_drvdata(rdev); int bit = ramp_delay/6000; int ret; if (bit) bit--; ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit)); if (ret < 0) dev_err(tps->dev, "SLEW reg write failed, err %d ", ret); return ret; } static struct regulator_ops tps51632_dcdc_ops = { |
d94d9aca5 regulator: tps516... |
108 109 |
.get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, |
0c5706743 regulator: tps516... |
110 111 112 113 |
.list_voltage = regulator_list_voltage_linear, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_ramp_delay = tps51632_dcdc_set_ramp_delay, }; |
a5023574d regulator: remove... |
114 |
static int tps51632_init_dcdc(struct tps51632_chip *tps, |
0c5706743 regulator: tps516... |
115 116 117 118 119 120 121 122 123 124 |
struct tps51632_regulator_platform_data *pdata) { int ret; uint8_t control = 0; int vsel; if (!pdata->enable_pwm_dvfs) goto skip_pwm_config; control |= TPS51632_DVFS_PWMEN; |
0c5706743 regulator: tps516... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV); ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel); if (ret < 0) { dev_err(tps->dev, "BASE reg write failed, err %d ", ret); return ret; } if (pdata->dvfs_step_20mV) control |= TPS51632_DVFS_STEP_20; if (pdata->max_voltage_uV) { unsigned int vmax; /** * TPS51632 hw behavior: VMAX register can be write only * once as it get locked after first write. The lock get * reset only when device is power-reset. * Write register only when lock bit is not enabled. */ ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax); if (ret < 0) { dev_err(tps->dev, "VMAX read failed, err %d ", ret); return ret; } if (!(vmax & TPS51632_VMAX_LOCK)) { vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV); ret = regmap_write(tps->regmap, TPS51632_VMAX_REG, vsel); if (ret < 0) { dev_err(tps->dev, "VMAX write failed, err %d ", ret); return ret; } } } skip_pwm_config: ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control); if (ret < 0) dev_err(tps->dev, "DVFS reg write failed, err %d ", ret); return ret; } |
faa3b2d57 regulator: tps516... |
170 |
static bool is_volatile_reg(struct device *dev, unsigned int reg) |
0c5706743 regulator: tps516... |
171 |
{ |
faa3b2d57 regulator: tps516... |
172 173 174 175 176 177 |
switch (reg) { case TPS51632_OFFSET_REG: case TPS51632_FAULT_REG: case TPS51632_IMON_REG: return true; default: |
0c5706743 regulator: tps516... |
178 |
return false; |
faa3b2d57 regulator: tps516... |
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
} } static bool is_read_reg(struct device *dev, unsigned int reg) { switch (reg) { case 0x08 ... 0x0F: return false; default: return true; } } static bool is_write_reg(struct device *dev, unsigned int reg) { switch (reg) { case TPS51632_VOLTAGE_SELECT_REG: case TPS51632_VOLTAGE_BASE_REG: case TPS51632_VMAX_REG: case TPS51632_DVFS_CONTROL_REG: case TPS51632_POWER_STATE_REG: case TPS51632_SLEW_REGS: return true; default: return false; } |
0c5706743 regulator: tps516... |
205 206 207 208 209 |
} static const struct regmap_config tps51632_regmap_config = { .reg_bits = 8, .val_bits = 8, |
faa3b2d57 regulator: tps516... |
210 211 212 |
.writeable_reg = is_write_reg, .readable_reg = is_read_reg, .volatile_reg = is_volatile_reg, |
0c5706743 regulator: tps516... |
213 214 215 |
.max_register = TPS51632_MAX_REG - 1, .cache_type = REGCACHE_RBTREE, }; |
c51ce403d regulator: tps516... |
216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
#if defined(CONFIG_OF) static const struct of_device_id tps51632_of_match[] = { { .compatible = "ti,tps51632",}, {}, }; MODULE_DEVICE_TABLE(of, tps51632_of_match); static struct tps51632_regulator_platform_data * of_get_tps51632_platform_data(struct device *dev) { struct tps51632_regulator_platform_data *pdata; struct device_node *np = dev->of_node; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
ef4bcf88e regulator: tps516... |
230 |
if (!pdata) |
c51ce403d regulator: tps516... |
231 |
return NULL; |
c51ce403d regulator: tps516... |
232 233 234 235 236 237 238 239 240 241 242 243 244 |
pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); if (!pdata->reg_init_data) { dev_err(dev, "Not able to get OF regulator init data "); return NULL; } pdata->enable_pwm_dvfs = of_property_read_bool(np, "ti,enable-pwm-dvfs"); pdata->dvfs_step_20mV = of_property_read_bool(np, "ti,dvfs-step-20mV"); pdata->base_voltage_uV = pdata->reg_init_data->constraints.min_uV ? : |
9d9339d3a regulator: tps516... |
245 |
TPS51632_MIN_VOLTAGE; |
c51ce403d regulator: tps516... |
246 |
pdata->max_voltage_uV = pdata->reg_init_data->constraints.max_uV ? : |
9d9339d3a regulator: tps516... |
247 |
TPS51632_MAX_VOLTAGE; |
c51ce403d regulator: tps516... |
248 249 250 251 252 253 254 255 256 |
return pdata; } #else static struct tps51632_regulator_platform_data * of_get_tps51632_platform_data(struct device *dev) { return NULL; } #endif |
a5023574d regulator: remove... |
257 |
static int tps51632_probe(struct i2c_client *client, |
0c5706743 regulator: tps516... |
258 259 260 261 262 263 264 |
const struct i2c_device_id *id) { struct tps51632_regulator_platform_data *pdata; struct regulator_dev *rdev; struct tps51632_chip *tps; int ret; struct regulator_config config = { }; |
c51ce403d regulator: tps516... |
265 266 267 268 269 270 271 272 273 274 |
if (client->dev.of_node) { const struct of_device_id *match; match = of_match_device(of_match_ptr(tps51632_of_match), &client->dev); if (!match) { dev_err(&client->dev, "Error: No device match found "); return -ENODEV; } } |
dff91d0b7 regulator: use de... |
275 |
pdata = dev_get_platdata(&client->dev); |
c51ce403d regulator: tps516... |
276 277 |
if (!pdata && client->dev.of_node) pdata = of_get_tps51632_platform_data(&client->dev); |
0c5706743 regulator: tps516... |
278 279 280 281 282 |
if (!pdata) { dev_err(&client->dev, "No Platform data "); return -EINVAL; } |
dbc705183 regulator: tps516... |
283 |
if (pdata->enable_pwm_dvfs) { |
9d9339d3a regulator: tps516... |
284 285 |
if ((pdata->base_voltage_uV < TPS51632_MIN_VOLTAGE) || (pdata->base_voltage_uV > TPS51632_MAX_VOLTAGE)) { |
dbc705183 regulator: tps516... |
286 287 288 289 290 291 |
dev_err(&client->dev, "Invalid base_voltage_uV setting "); return -EINVAL; } if ((pdata->max_voltage_uV) && |
9d9339d3a regulator: tps516... |
292 293 |
((pdata->max_voltage_uV < TPS51632_MIN_VOLTAGE) || (pdata->max_voltage_uV > TPS51632_MAX_VOLTAGE))) { |
dbc705183 regulator: tps516... |
294 295 296 297 298 |
dev_err(&client->dev, "Invalid max_voltage_uV setting "); return -EINVAL; } } |
0c5706743 regulator: tps516... |
299 |
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); |
ef4bcf88e regulator: tps516... |
300 |
if (!tps) |
0c5706743 regulator: tps516... |
301 |
return -ENOMEM; |
0c5706743 regulator: tps516... |
302 303 |
tps->dev = &client->dev; |
6930db1e9 regulator: tps516... |
304 |
tps->desc.name = client->name; |
0c5706743 regulator: tps516... |
305 306 |
tps->desc.id = 0; tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; |
9d9339d3a regulator: tps516... |
307 308 |
tps->desc.min_uV = TPS51632_MIN_VOLTAGE; tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV; |
bd0ec7c1e regulator: tps516... |
309 310 |
tps->desc.linear_min_sel = TPS51632_MIN_VSEL; tps->desc.n_voltages = TPS51632_MAX_VSEL + 1; |
0c5706743 regulator: tps516... |
311 312 313 |
tps->desc.ops = &tps51632_dcdc_ops; tps->desc.type = REGULATOR_VOLTAGE; tps->desc.owner = THIS_MODULE; |
d94d9aca5 regulator: tps516... |
314 315 316 317 318 |
if (pdata->enable_pwm_dvfs) tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG; else tps->desc.vsel_reg = TPS51632_VOLTAGE_SELECT_REG; tps->desc.vsel_mask = TPS51632_VOUT_MASK; |
0c5706743 regulator: tps516... |
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); dev_err(&client->dev, "regmap init failed, err %d ", ret); return ret; } i2c_set_clientdata(client, tps); ret = tps51632_init_dcdc(tps, pdata); if (ret < 0) { dev_err(tps->dev, "Init failed, err = %d ", ret); return ret; } /* Register the regulators */ config.dev = &client->dev; config.init_data = pdata->reg_init_data; config.driver_data = tps; config.regmap = tps->regmap; config.of_node = client->dev.of_node; |
1084081dc regulator: tps516... |
341 |
rdev = devm_regulator_register(&client->dev, &tps->desc, &config); |
0c5706743 regulator: tps516... |
342 343 344 345 346 347 348 349 350 |
if (IS_ERR(rdev)) { dev_err(tps->dev, "regulator register failed "); return PTR_ERR(rdev); } tps->rdev = rdev; return 0; } |
0c5706743 regulator: tps516... |
351 352 353 354 355 356 357 358 359 360 361 |
static const struct i2c_device_id tps51632_id[] = { {.name = "tps51632",}, {}, }; MODULE_DEVICE_TABLE(i2c, tps51632_id); static struct i2c_driver tps51632_i2c_driver = { .driver = { .name = "tps51632", .owner = THIS_MODULE, |
c51ce403d regulator: tps516... |
362 |
.of_match_table = of_match_ptr(tps51632_of_match), |
0c5706743 regulator: tps516... |
363 364 |
}, .probe = tps51632_probe, |
0c5706743 regulator: tps516... |
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
.id_table = tps51632_id, }; static int __init tps51632_init(void) { return i2c_add_driver(&tps51632_i2c_driver); } subsys_initcall(tps51632_init); static void __exit tps51632_cleanup(void) { i2c_del_driver(&tps51632_i2c_driver); } module_exit(tps51632_cleanup); MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); MODULE_DESCRIPTION("TPS51632 voltage regulator driver"); MODULE_LICENSE("GPL v2"); |