847 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Voltage regulator support for AMS AS3722 PMIC4 *5 * Copyright (C) 2013 ams6 *7 * Author: Florian Lobmaier <florian.lobmaier@ams.com>8 * Author: Laxman Dewangan <ldewangan@nvidia.com>9 */10 11#include <linux/err.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/mfd/as3722.h>15#include <linux/of.h>16#include <linux/of_platform.h>17#include <linux/platform_device.h>18#include <linux/regulator/driver.h>19#include <linux/regulator/machine.h>20#include <linux/regulator/of_regulator.h>21#include <linux/slab.h>22 23/* Regulator IDs */24enum as3722_regulators_id {25 AS3722_REGULATOR_ID_SD0,26 AS3722_REGULATOR_ID_SD1,27 AS3722_REGULATOR_ID_SD2,28 AS3722_REGULATOR_ID_SD3,29 AS3722_REGULATOR_ID_SD4,30 AS3722_REGULATOR_ID_SD5,31 AS3722_REGULATOR_ID_SD6,32 AS3722_REGULATOR_ID_LDO0,33 AS3722_REGULATOR_ID_LDO1,34 AS3722_REGULATOR_ID_LDO2,35 AS3722_REGULATOR_ID_LDO3,36 AS3722_REGULATOR_ID_LDO4,37 AS3722_REGULATOR_ID_LDO5,38 AS3722_REGULATOR_ID_LDO6,39 AS3722_REGULATOR_ID_LDO7,40 AS3722_REGULATOR_ID_LDO9,41 AS3722_REGULATOR_ID_LDO10,42 AS3722_REGULATOR_ID_LDO11,43 AS3722_REGULATOR_ID_MAX,44};45 46struct as3722_register_mapping {47 u8 regulator_id;48 const char *name;49 const char *sname;50 u8 vsel_reg;51 u8 vsel_mask;52 int n_voltages;53 u32 enable_reg;54 u8 enable_mask;55 u32 control_reg;56 u8 mode_mask;57 u32 sleep_ctrl_reg;58 u8 sleep_ctrl_mask;59};60 61struct as3722_regulator_config_data {62 struct regulator_init_data *reg_init;63 bool enable_tracking;64 int ext_control;65};66 67struct as3722_regulators {68 struct device *dev;69 struct as3722 *as3722;70 struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];71 struct as3722_regulator_config_data72 reg_config_data[AS3722_REGULATOR_ID_MAX];73};74 75static const struct as3722_register_mapping as3722_reg_lookup[] = {76 {77 .regulator_id = AS3722_REGULATOR_ID_SD0,78 .name = "as3722-sd0",79 .vsel_reg = AS3722_SD0_VOLTAGE_REG,80 .vsel_mask = AS3722_SD_VSEL_MASK,81 .enable_reg = AS3722_SD_CONTROL_REG,82 .enable_mask = AS3722_SDn_CTRL(0),83 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,84 .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,85 .control_reg = AS3722_SD0_CONTROL_REG,86 .mode_mask = AS3722_SD0_MODE_FAST,87 },88 {89 .regulator_id = AS3722_REGULATOR_ID_SD1,90 .name = "as3722-sd1",91 .vsel_reg = AS3722_SD1_VOLTAGE_REG,92 .vsel_mask = AS3722_SD_VSEL_MASK,93 .enable_reg = AS3722_SD_CONTROL_REG,94 .enable_mask = AS3722_SDn_CTRL(1),95 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,96 .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,97 .control_reg = AS3722_SD1_CONTROL_REG,98 .mode_mask = AS3722_SD1_MODE_FAST,99 },100 {101 .regulator_id = AS3722_REGULATOR_ID_SD2,102 .name = "as3722-sd2",103 .sname = "vsup-sd2",104 .vsel_reg = AS3722_SD2_VOLTAGE_REG,105 .vsel_mask = AS3722_SD_VSEL_MASK,106 .enable_reg = AS3722_SD_CONTROL_REG,107 .enable_mask = AS3722_SDn_CTRL(2),108 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,109 .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,110 .control_reg = AS3722_SD23_CONTROL_REG,111 .mode_mask = AS3722_SD2_MODE_FAST,112 .n_voltages = AS3722_SD2_VSEL_MAX + 1,113 },114 {115 .regulator_id = AS3722_REGULATOR_ID_SD3,116 .name = "as3722-sd3",117 .sname = "vsup-sd3",118 .vsel_reg = AS3722_SD3_VOLTAGE_REG,119 .vsel_mask = AS3722_SD_VSEL_MASK,120 .enable_reg = AS3722_SD_CONTROL_REG,121 .enable_mask = AS3722_SDn_CTRL(3),122 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,123 .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,124 .control_reg = AS3722_SD23_CONTROL_REG,125 .mode_mask = AS3722_SD3_MODE_FAST,126 .n_voltages = AS3722_SD2_VSEL_MAX + 1,127 },128 {129 .regulator_id = AS3722_REGULATOR_ID_SD4,130 .name = "as3722-sd4",131 .sname = "vsup-sd4",132 .vsel_reg = AS3722_SD4_VOLTAGE_REG,133 .vsel_mask = AS3722_SD_VSEL_MASK,134 .enable_reg = AS3722_SD_CONTROL_REG,135 .enable_mask = AS3722_SDn_CTRL(4),136 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,137 .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,138 .control_reg = AS3722_SD4_CONTROL_REG,139 .mode_mask = AS3722_SD4_MODE_FAST,140 .n_voltages = AS3722_SD2_VSEL_MAX + 1,141 },142 {143 .regulator_id = AS3722_REGULATOR_ID_SD5,144 .name = "as3722-sd5",145 .sname = "vsup-sd5",146 .vsel_reg = AS3722_SD5_VOLTAGE_REG,147 .vsel_mask = AS3722_SD_VSEL_MASK,148 .enable_reg = AS3722_SD_CONTROL_REG,149 .enable_mask = AS3722_SDn_CTRL(5),150 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,151 .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,152 .control_reg = AS3722_SD5_CONTROL_REG,153 .mode_mask = AS3722_SD5_MODE_FAST,154 .n_voltages = AS3722_SD2_VSEL_MAX + 1,155 },156 {157 .regulator_id = AS3722_REGULATOR_ID_SD6,158 .name = "as3722-sd6",159 .vsel_reg = AS3722_SD6_VOLTAGE_REG,160 .vsel_mask = AS3722_SD_VSEL_MASK,161 .enable_reg = AS3722_SD_CONTROL_REG,162 .enable_mask = AS3722_SDn_CTRL(6),163 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,164 .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,165 .control_reg = AS3722_SD6_CONTROL_REG,166 .mode_mask = AS3722_SD6_MODE_FAST,167 },168 {169 .regulator_id = AS3722_REGULATOR_ID_LDO0,170 .name = "as3722-ldo0",171 .sname = "vin-ldo0",172 .vsel_reg = AS3722_LDO0_VOLTAGE_REG,173 .vsel_mask = AS3722_LDO0_VSEL_MASK,174 .enable_reg = AS3722_LDOCONTROL0_REG,175 .enable_mask = AS3722_LDO0_CTRL,176 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,177 .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,178 .n_voltages = AS3722_LDO0_NUM_VOLT,179 },180 {181 .regulator_id = AS3722_REGULATOR_ID_LDO1,182 .name = "as3722-ldo1",183 .sname = "vin-ldo1-6",184 .vsel_reg = AS3722_LDO1_VOLTAGE_REG,185 .vsel_mask = AS3722_LDO_VSEL_MASK,186 .enable_reg = AS3722_LDOCONTROL0_REG,187 .enable_mask = AS3722_LDO1_CTRL,188 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,189 .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,190 .n_voltages = AS3722_LDO_NUM_VOLT,191 },192 {193 .regulator_id = AS3722_REGULATOR_ID_LDO2,194 .name = "as3722-ldo2",195 .sname = "vin-ldo2-5-7",196 .vsel_reg = AS3722_LDO2_VOLTAGE_REG,197 .vsel_mask = AS3722_LDO_VSEL_MASK,198 .enable_reg = AS3722_LDOCONTROL0_REG,199 .enable_mask = AS3722_LDO2_CTRL,200 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,201 .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,202 .n_voltages = AS3722_LDO_NUM_VOLT,203 },204 {205 .regulator_id = AS3722_REGULATOR_ID_LDO3,206 .name = "as3722-ldo3",207 .sname = "vin-ldo3-4",208 .vsel_reg = AS3722_LDO3_VOLTAGE_REG,209 .vsel_mask = AS3722_LDO3_VSEL_MASK,210 .enable_reg = AS3722_LDOCONTROL0_REG,211 .enable_mask = AS3722_LDO3_CTRL,212 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,213 .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,214 .n_voltages = AS3722_LDO3_NUM_VOLT,215 },216 {217 .regulator_id = AS3722_REGULATOR_ID_LDO4,218 .name = "as3722-ldo4",219 .sname = "vin-ldo3-4",220 .vsel_reg = AS3722_LDO4_VOLTAGE_REG,221 .vsel_mask = AS3722_LDO_VSEL_MASK,222 .enable_reg = AS3722_LDOCONTROL0_REG,223 .enable_mask = AS3722_LDO4_CTRL,224 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,225 .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,226 .n_voltages = AS3722_LDO_NUM_VOLT,227 },228 {229 .regulator_id = AS3722_REGULATOR_ID_LDO5,230 .name = "as3722-ldo5",231 .sname = "vin-ldo2-5-7",232 .vsel_reg = AS3722_LDO5_VOLTAGE_REG,233 .vsel_mask = AS3722_LDO_VSEL_MASK,234 .enable_reg = AS3722_LDOCONTROL0_REG,235 .enable_mask = AS3722_LDO5_CTRL,236 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,237 .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,238 .n_voltages = AS3722_LDO_NUM_VOLT,239 },240 {241 .regulator_id = AS3722_REGULATOR_ID_LDO6,242 .name = "as3722-ldo6",243 .sname = "vin-ldo1-6",244 .vsel_reg = AS3722_LDO6_VOLTAGE_REG,245 .vsel_mask = AS3722_LDO_VSEL_MASK,246 .enable_reg = AS3722_LDOCONTROL0_REG,247 .enable_mask = AS3722_LDO6_CTRL,248 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,249 .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,250 .n_voltages = AS3722_LDO_NUM_VOLT,251 },252 {253 .regulator_id = AS3722_REGULATOR_ID_LDO7,254 .name = "as3722-ldo7",255 .sname = "vin-ldo2-5-7",256 .vsel_reg = AS3722_LDO7_VOLTAGE_REG,257 .vsel_mask = AS3722_LDO_VSEL_MASK,258 .enable_reg = AS3722_LDOCONTROL0_REG,259 .enable_mask = AS3722_LDO7_CTRL,260 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,261 .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,262 .n_voltages = AS3722_LDO_NUM_VOLT,263 },264 {265 .regulator_id = AS3722_REGULATOR_ID_LDO9,266 .name = "as3722-ldo9",267 .sname = "vin-ldo9-10",268 .vsel_reg = AS3722_LDO9_VOLTAGE_REG,269 .vsel_mask = AS3722_LDO_VSEL_MASK,270 .enable_reg = AS3722_LDOCONTROL1_REG,271 .enable_mask = AS3722_LDO9_CTRL,272 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,273 .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,274 .n_voltages = AS3722_LDO_NUM_VOLT,275 },276 {277 .regulator_id = AS3722_REGULATOR_ID_LDO10,278 .name = "as3722-ldo10",279 .sname = "vin-ldo9-10",280 .vsel_reg = AS3722_LDO10_VOLTAGE_REG,281 .vsel_mask = AS3722_LDO_VSEL_MASK,282 .enable_reg = AS3722_LDOCONTROL1_REG,283 .enable_mask = AS3722_LDO10_CTRL,284 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,285 .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,286 .n_voltages = AS3722_LDO_NUM_VOLT,287 },288 {289 .regulator_id = AS3722_REGULATOR_ID_LDO11,290 .name = "as3722-ldo11",291 .sname = "vin-ldo11",292 .vsel_reg = AS3722_LDO11_VOLTAGE_REG,293 .vsel_mask = AS3722_LDO_VSEL_MASK,294 .enable_reg = AS3722_LDOCONTROL1_REG,295 .enable_mask = AS3722_LDO11_CTRL,296 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,297 .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,298 .n_voltages = AS3722_LDO_NUM_VOLT,299 },300};301 302static const unsigned int as3722_ldo_current[] = { 150000, 300000 };303static const unsigned int as3722_sd016_current[] = {304 2500000, 3000000, 3500000305};306 307static const struct regulator_ops as3722_ldo0_ops = {308 .is_enabled = regulator_is_enabled_regmap,309 .enable = regulator_enable_regmap,310 .disable = regulator_disable_regmap,311 .list_voltage = regulator_list_voltage_linear,312 .get_voltage_sel = regulator_get_voltage_sel_regmap,313 .set_voltage_sel = regulator_set_voltage_sel_regmap,314 .get_current_limit = regulator_get_current_limit_regmap,315 .set_current_limit = regulator_set_current_limit_regmap,316};317 318static const struct regulator_ops as3722_ldo0_extcntrl_ops = {319 .list_voltage = regulator_list_voltage_linear,320 .get_voltage_sel = regulator_get_voltage_sel_regmap,321 .set_voltage_sel = regulator_set_voltage_sel_regmap,322 .get_current_limit = regulator_get_current_limit_regmap,323 .set_current_limit = regulator_set_current_limit_regmap,324};325 326static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,327 int id, u8 mode)328{329 struct as3722 *as3722 = as3722_reg->as3722;330 331 switch (mode) {332 case AS3722_LDO3_MODE_PMOS:333 case AS3722_LDO3_MODE_PMOS_TRACKING:334 case AS3722_LDO3_MODE_NMOS:335 case AS3722_LDO3_MODE_SWITCH:336 return as3722_update_bits(as3722,337 as3722_reg_lookup[id].vsel_reg,338 AS3722_LDO3_MODE_MASK, mode);339 340 default:341 return -EINVAL;342 }343}344 345static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)346{347 return 150000;348}349 350static const struct regulator_ops as3722_ldo3_ops = {351 .is_enabled = regulator_is_enabled_regmap,352 .enable = regulator_enable_regmap,353 .disable = regulator_disable_regmap,354 .list_voltage = regulator_list_voltage_linear,355 .get_voltage_sel = regulator_get_voltage_sel_regmap,356 .set_voltage_sel = regulator_set_voltage_sel_regmap,357 .get_current_limit = as3722_ldo3_get_current_limit,358};359 360static const struct regulator_ops as3722_ldo3_extcntrl_ops = {361 .list_voltage = regulator_list_voltage_linear,362 .get_voltage_sel = regulator_get_voltage_sel_regmap,363 .set_voltage_sel = regulator_set_voltage_sel_regmap,364 .get_current_limit = as3722_ldo3_get_current_limit,365};366 367static const struct regulator_ops as3722_ldo6_ops = {368 .is_enabled = regulator_is_enabled_regmap,369 .enable = regulator_enable_regmap,370 .disable = regulator_disable_regmap,371 .map_voltage = regulator_map_voltage_linear_range,372 .set_voltage_sel = regulator_set_voltage_sel_regmap,373 .get_voltage_sel = regulator_get_voltage_sel_regmap,374 .list_voltage = regulator_list_voltage_linear_range,375 .get_current_limit = regulator_get_current_limit_regmap,376 .set_current_limit = regulator_set_current_limit_regmap,377 .get_bypass = regulator_get_bypass_regmap,378 .set_bypass = regulator_set_bypass_regmap,379};380 381static const struct regulator_ops as3722_ldo6_extcntrl_ops = {382 .map_voltage = regulator_map_voltage_linear_range,383 .set_voltage_sel = regulator_set_voltage_sel_regmap,384 .get_voltage_sel = regulator_get_voltage_sel_regmap,385 .list_voltage = regulator_list_voltage_linear_range,386 .get_current_limit = regulator_get_current_limit_regmap,387 .set_current_limit = regulator_set_current_limit_regmap,388 .get_bypass = regulator_get_bypass_regmap,389 .set_bypass = regulator_set_bypass_regmap,390};391 392static const struct linear_range as3722_ldo_ranges[] = {393 REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),394 REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),395 REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),396};397 398static const struct regulator_ops as3722_ldo_ops = {399 .is_enabled = regulator_is_enabled_regmap,400 .enable = regulator_enable_regmap,401 .disable = regulator_disable_regmap,402 .map_voltage = regulator_map_voltage_linear_range,403 .set_voltage_sel = regulator_set_voltage_sel_regmap,404 .get_voltage_sel = regulator_get_voltage_sel_regmap,405 .list_voltage = regulator_list_voltage_linear_range,406 .get_current_limit = regulator_get_current_limit_regmap,407 .set_current_limit = regulator_set_current_limit_regmap,408};409 410static const struct regulator_ops as3722_ldo_extcntrl_ops = {411 .map_voltage = regulator_map_voltage_linear_range,412 .set_voltage_sel = regulator_set_voltage_sel_regmap,413 .get_voltage_sel = regulator_get_voltage_sel_regmap,414 .list_voltage = regulator_list_voltage_linear_range,415 .get_current_limit = regulator_get_current_limit_regmap,416 .set_current_limit = regulator_set_current_limit_regmap,417};418 419static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)420{421 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);422 struct as3722 *as3722 = as3722_regs->as3722;423 int id = rdev_get_id(rdev);424 u32 val;425 int ret;426 427 if (!as3722_reg_lookup[id].control_reg)428 return -ENOTSUPP;429 430 ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);431 if (ret < 0) {432 dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",433 as3722_reg_lookup[id].control_reg, ret);434 return ret;435 }436 437 if (val & as3722_reg_lookup[id].mode_mask)438 return REGULATOR_MODE_FAST;439 else440 return REGULATOR_MODE_NORMAL;441}442 443static int as3722_sd_set_mode(struct regulator_dev *rdev,444 unsigned int mode)445{446 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);447 struct as3722 *as3722 = as3722_regs->as3722;448 u8 id = rdev_get_id(rdev);449 u8 val = 0;450 int ret;451 452 if (!as3722_reg_lookup[id].control_reg)453 return -ERANGE;454 455 switch (mode) {456 case REGULATOR_MODE_FAST:457 val = as3722_reg_lookup[id].mode_mask;458 fallthrough;459 case REGULATOR_MODE_NORMAL:460 break;461 default:462 return -EINVAL;463 }464 465 ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,466 as3722_reg_lookup[id].mode_mask, val);467 if (ret < 0) {468 dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",469 as3722_reg_lookup[id].control_reg, ret);470 return ret;471 }472 return ret;473}474 475static bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs)476{477 int err;478 unsigned val;479 480 err = as3722_read(as3722_regs->as3722, AS3722_FUSE7_REG, &val);481 if (err < 0) {482 dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",483 AS3722_FUSE7_REG, err);484 return false;485 }486 if (val & AS3722_FUSE7_SD0_LOW_VOLTAGE)487 return true;488 return false;489}490 491static const struct linear_range as3722_sd2345_ranges[] = {492 REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),493 REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),494 REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),495 REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000),496};497 498static const struct regulator_ops as3722_sd016_ops = {499 .is_enabled = regulator_is_enabled_regmap,500 .enable = regulator_enable_regmap,501 .disable = regulator_disable_regmap,502 .list_voltage = regulator_list_voltage_linear,503 .map_voltage = regulator_map_voltage_linear,504 .get_voltage_sel = regulator_get_voltage_sel_regmap,505 .set_voltage_sel = regulator_set_voltage_sel_regmap,506 .get_current_limit = regulator_get_current_limit_regmap,507 .set_current_limit = regulator_set_current_limit_regmap,508 .get_mode = as3722_sd_get_mode,509 .set_mode = as3722_sd_set_mode,510};511 512static const struct regulator_ops as3722_sd016_extcntrl_ops = {513 .list_voltage = regulator_list_voltage_linear,514 .map_voltage = regulator_map_voltage_linear,515 .get_voltage_sel = regulator_get_voltage_sel_regmap,516 .set_voltage_sel = regulator_set_voltage_sel_regmap,517 .get_current_limit = regulator_get_current_limit_regmap,518 .set_current_limit = regulator_set_current_limit_regmap,519 .get_mode = as3722_sd_get_mode,520 .set_mode = as3722_sd_set_mode,521};522 523static const struct regulator_ops as3722_sd2345_ops = {524 .is_enabled = regulator_is_enabled_regmap,525 .enable = regulator_enable_regmap,526 .disable = regulator_disable_regmap,527 .list_voltage = regulator_list_voltage_linear_range,528 .map_voltage = regulator_map_voltage_linear_range,529 .set_voltage_sel = regulator_set_voltage_sel_regmap,530 .get_voltage_sel = regulator_get_voltage_sel_regmap,531 .get_mode = as3722_sd_get_mode,532 .set_mode = as3722_sd_set_mode,533};534 535static const struct regulator_ops as3722_sd2345_extcntrl_ops = {536 .list_voltage = regulator_list_voltage_linear_range,537 .map_voltage = regulator_map_voltage_linear_range,538 .set_voltage_sel = regulator_set_voltage_sel_regmap,539 .get_voltage_sel = regulator_get_voltage_sel_regmap,540 .get_mode = as3722_sd_get_mode,541 .set_mode = as3722_sd_set_mode,542};543 544static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,545 int ext_pwr_ctrl)546{547 int ret;548 unsigned int val;549 550 if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||551 (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))552 return -EINVAL;553 554 val = ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);555 ret = as3722_update_bits(as3722_regs->as3722,556 as3722_reg_lookup[id].sleep_ctrl_reg,557 as3722_reg_lookup[id].sleep_ctrl_mask, val);558 if (ret < 0)559 dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",560 as3722_reg_lookup[id].sleep_ctrl_reg, ret);561 return ret;562}563 564static struct of_regulator_match as3722_regulator_matches[] = {565 { .name = "sd0", },566 { .name = "sd1", },567 { .name = "sd2", },568 { .name = "sd3", },569 { .name = "sd4", },570 { .name = "sd5", },571 { .name = "sd6", },572 { .name = "ldo0", },573 { .name = "ldo1", },574 { .name = "ldo2", },575 { .name = "ldo3", },576 { .name = "ldo4", },577 { .name = "ldo5", },578 { .name = "ldo6", },579 { .name = "ldo7", },580 { .name = "ldo9", },581 { .name = "ldo10", },582 { .name = "ldo11", },583};584 585static int as3722_get_regulator_dt_data(struct platform_device *pdev,586 struct as3722_regulators *as3722_regs)587{588 struct device_node *np;589 struct as3722_regulator_config_data *reg_config;590 u32 prop;591 int id;592 int ret;593 594 np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");595 if (!np) {596 dev_err(&pdev->dev, "Device is not having regulators node\n");597 return -ENODEV;598 }599 pdev->dev.of_node = np;600 601 ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,602 ARRAY_SIZE(as3722_regulator_matches));603 of_node_put(np);604 if (ret < 0) {605 dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",606 ret);607 return ret;608 }609 610 for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {611 struct device_node *reg_node;612 613 reg_config = &as3722_regs->reg_config_data[id];614 reg_config->reg_init = as3722_regulator_matches[id].init_data;615 reg_node = as3722_regulator_matches[id].of_node;616 617 if (!reg_config->reg_init || !reg_node)618 continue;619 620 ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);621 if (!ret) {622 if (prop < 3)623 reg_config->ext_control = prop;624 else625 dev_warn(&pdev->dev,626 "ext-control have invalid option: %u\n",627 prop);628 }629 reg_config->enable_tracking =630 of_property_read_bool(reg_node, "ams,enable-tracking");631 }632 return 0;633}634 635static int as3722_regulator_probe(struct platform_device *pdev)636{637 struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);638 struct as3722_regulators *as3722_regs;639 struct as3722_regulator_config_data *reg_config;640 struct regulator_dev *rdev;641 struct regulator_config config = { };642 const struct regulator_ops *ops;643 int id;644 int ret;645 646 as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),647 GFP_KERNEL);648 if (!as3722_regs)649 return -ENOMEM;650 651 as3722_regs->dev = &pdev->dev;652 as3722_regs->as3722 = as3722;653 platform_set_drvdata(pdev, as3722_regs);654 655 ret = as3722_get_regulator_dt_data(pdev, as3722_regs);656 if (ret < 0)657 return ret;658 659 config.dev = &pdev->dev;660 config.driver_data = as3722_regs;661 config.regmap = as3722->regmap;662 663 for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {664 struct regulator_desc *desc;665 666 desc = &as3722_regs->desc[id];667 reg_config = &as3722_regs->reg_config_data[id];668 669 desc->name = as3722_reg_lookup[id].name;670 desc->supply_name = as3722_reg_lookup[id].sname;671 desc->id = as3722_reg_lookup[id].regulator_id;672 desc->n_voltages = as3722_reg_lookup[id].n_voltages;673 desc->type = REGULATOR_VOLTAGE;674 desc->owner = THIS_MODULE;675 desc->enable_reg = as3722_reg_lookup[id].enable_reg;676 desc->enable_mask = as3722_reg_lookup[id].enable_mask;677 desc->vsel_reg = as3722_reg_lookup[id].vsel_reg;678 desc->vsel_mask = as3722_reg_lookup[id].vsel_mask;679 switch (id) {680 case AS3722_REGULATOR_ID_LDO0:681 if (reg_config->ext_control)682 ops = &as3722_ldo0_extcntrl_ops;683 else684 ops = &as3722_ldo0_ops;685 desc->min_uV = 825000;686 desc->uV_step = 25000;687 desc->linear_min_sel = 1;688 desc->enable_time = 500;689 desc->curr_table = as3722_ldo_current;690 desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);691 desc->csel_reg = as3722_reg_lookup[id].vsel_reg;692 desc->csel_mask = AS3722_LDO_ILIMIT_MASK;693 break;694 case AS3722_REGULATOR_ID_LDO3:695 if (reg_config->ext_control)696 ops = &as3722_ldo3_extcntrl_ops;697 else698 ops = &as3722_ldo3_ops;699 desc->min_uV = 620000;700 desc->uV_step = 20000;701 desc->linear_min_sel = 1;702 desc->enable_time = 500;703 if (reg_config->enable_tracking) {704 ret = as3722_ldo3_set_tracking_mode(as3722_regs,705 id, AS3722_LDO3_MODE_PMOS_TRACKING);706 if (ret < 0) {707 dev_err(&pdev->dev,708 "LDO3 tracking failed: %d\n",709 ret);710 return ret;711 }712 }713 break;714 case AS3722_REGULATOR_ID_LDO6:715 if (reg_config->ext_control)716 ops = &as3722_ldo6_extcntrl_ops;717 else718 ops = &as3722_ldo6_ops;719 desc->enable_time = 500;720 desc->bypass_reg = AS3722_LDO6_VOLTAGE_REG;721 desc->bypass_mask = AS3722_LDO_VSEL_MASK;722 desc->bypass_val_on = AS3722_LDO6_VSEL_BYPASS;723 desc->bypass_val_off = AS3722_LDO6_VSEL_BYPASS;724 desc->linear_ranges = as3722_ldo_ranges;725 desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges);726 desc->curr_table = as3722_ldo_current;727 desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);728 desc->csel_reg = as3722_reg_lookup[id].vsel_reg;729 desc->csel_mask = AS3722_LDO_ILIMIT_MASK;730 break;731 case AS3722_REGULATOR_ID_SD0:732 case AS3722_REGULATOR_ID_SD1:733 case AS3722_REGULATOR_ID_SD6:734 if (reg_config->ext_control)735 ops = &as3722_sd016_extcntrl_ops;736 else737 ops = &as3722_sd016_ops;738 if (id == AS3722_REGULATOR_ID_SD0 &&739 as3722_sd0_is_low_voltage(as3722_regs)) {740 as3722_regs->desc[id].n_voltages =741 AS3722_SD0_VSEL_LOW_VOL_MAX + 1;742 as3722_regs->desc[id].min_uV = 410000;743 } else {744 as3722_regs->desc[id].n_voltages =745 AS3722_SD0_VSEL_MAX + 1;746 as3722_regs->desc[id].min_uV = 610000;747 }748 desc->uV_step = 10000;749 desc->linear_min_sel = 1;750 desc->enable_time = 600;751 desc->curr_table = as3722_sd016_current;752 desc->n_current_limits =753 ARRAY_SIZE(as3722_sd016_current);754 if (id == AS3722_REGULATOR_ID_SD0) {755 desc->csel_reg = AS3722_OVCURRENT_REG;756 desc->csel_mask =757 AS3722_OVCURRENT_SD0_TRIP_MASK;758 } else if (id == AS3722_REGULATOR_ID_SD1) {759 desc->csel_reg = AS3722_OVCURRENT_REG;760 desc->csel_mask =761 AS3722_OVCURRENT_SD1_TRIP_MASK;762 } else if (id == AS3722_REGULATOR_ID_SD6) {763 desc->csel_reg = AS3722_OVCURRENT_DEB_REG;764 desc->csel_mask =765 AS3722_OVCURRENT_SD6_TRIP_MASK;766 }767 break;768 case AS3722_REGULATOR_ID_SD2:769 case AS3722_REGULATOR_ID_SD3:770 case AS3722_REGULATOR_ID_SD4:771 case AS3722_REGULATOR_ID_SD5:772 if (reg_config->ext_control)773 ops = &as3722_sd2345_extcntrl_ops;774 else775 ops = &as3722_sd2345_ops;776 desc->linear_ranges = as3722_sd2345_ranges;777 desc->n_linear_ranges =778 ARRAY_SIZE(as3722_sd2345_ranges);779 break;780 default:781 if (reg_config->ext_control)782 ops = &as3722_ldo_extcntrl_ops;783 else784 ops = &as3722_ldo_ops;785 desc->enable_time = 500;786 desc->linear_ranges = as3722_ldo_ranges;787 desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges);788 desc->curr_table = as3722_ldo_current;789 desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);790 desc->csel_reg = as3722_reg_lookup[id].vsel_reg;791 desc->csel_mask = AS3722_LDO_ILIMIT_MASK;792 break;793 }794 desc->ops = ops;795 config.init_data = reg_config->reg_init;796 config.of_node = as3722_regulator_matches[id].of_node;797 rdev = devm_regulator_register(&pdev->dev, desc, &config);798 if (IS_ERR(rdev)) {799 ret = PTR_ERR(rdev);800 dev_err(&pdev->dev, "regulator %d register failed %d\n",801 id, ret);802 return ret;803 }804 805 if (reg_config->ext_control) {806 ret = regulator_enable_regmap(rdev);807 if (ret < 0) {808 dev_err(&pdev->dev,809 "Regulator %d enable failed: %d\n",810 id, ret);811 return ret;812 }813 ret = as3722_extreg_init(as3722_regs, id,814 reg_config->ext_control);815 if (ret < 0) {816 dev_err(&pdev->dev,817 "AS3722 ext control failed: %d", ret);818 return ret;819 }820 }821 }822 return 0;823}824 825static const struct of_device_id of_as3722_regulator_match[] = {826 { .compatible = "ams,as3722-regulator", },827 {},828};829MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);830 831static struct platform_driver as3722_regulator_driver = {832 .driver = {833 .name = "as3722-regulator",834 .probe_type = PROBE_PREFER_ASYNCHRONOUS,835 .of_match_table = of_as3722_regulator_match,836 },837 .probe = as3722_regulator_probe,838};839 840module_platform_driver(as3722_regulator_driver);841 842MODULE_ALIAS("platform:as3722-regulator");843MODULE_DESCRIPTION("AS3722 regulator driver");844MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");845MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");846MODULE_LICENSE("GPL");847