902 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2024 ROHM Semiconductors3// bd96801-regulator.c ROHM BD96801 regulator driver4 5/*6 * This version of the "BD86801 scalable PMIC"'s driver supports only very7 * basic set of the PMIC features. Most notably, there is no support for8 * the ERRB interrupt and the configurations which should be done when the9 * PMIC is in STBY mode.10 *11 * Supporting the ERRB interrupt would require dropping the regmap-IRQ12 * usage or working around (or accepting a presense of) a naming conflict13 * in debugFS IRQs.14 *15 * Being able to reliably do the configurations like changing the16 * regulator safety limits (like limits for the over/under -voltages, over17 * current, thermal protection) would require the configuring driver to be18 * synchronized with entity causing the PMIC state transitions. Eg, one19 * should be able to ensure the PMIC is in STBY state when the20 * configurations are applied to the hardware. How and when the PMIC state21 * transitions are to be done is likely to be very system specific, as will22 * be the need to configure these safety limits. Hence it's not simple to23 * come up with a generic solution.24 *25 * Users who require the ERRB handling and STBY state configurations can26 * have a look at the original RFC:27 * https://lore.kernel.org/all/cover.1712920132.git.mazziesaccount@gmail.com/28 * which implements a workaround to debugFS naming conflict and some of29 * the safety limit configurations - but leaves the state change handling30 * and synchronization to be implemented.31 *32 * It would be great to hear (and receive a patch!) if you implement the33 * STBY configuration support or a proper fix to the debugFS naming34 * conflict in your downstream driver ;)35 */36 37#include <linux/cleanup.h>38#include <linux/delay.h>39#include <linux/err.h>40#include <linux/interrupt.h>41#include <linux/kernel.h>42#include <linux/linear_range.h>43#include <linux/mfd/rohm-generic.h>44#include <linux/mfd/rohm-bd96801.h>45#include <linux/module.h>46#include <linux/of.h>47#include <linux/platform_device.h>48#include <linux/regmap.h>49#include <linux/regulator/coupler.h>50#include <linux/regulator/driver.h>51#include <linux/regulator/machine.h>52#include <linux/regulator/of_regulator.h>53#include <linux/slab.h>54#include <linux/timer.h>55 56enum {57 BD96801_BUCK1,58 BD96801_BUCK2,59 BD96801_BUCK3,60 BD96801_BUCK4,61 BD96801_LDO5,62 BD96801_LDO6,63 BD96801_LDO7,64 BD96801_REGULATOR_AMOUNT,65};66 67enum {68 BD96801_PROT_OVP,69 BD96801_PROT_UVP,70 BD96801_PROT_OCP,71 BD96801_PROT_TEMP,72 BD96801_NUM_PROT,73};74 75#define BD96801_ALWAYS_ON_REG 0x3c76#define BD96801_REG_ENABLE 0x0b77#define BD96801_BUCK1_EN_MASK BIT(0)78#define BD96801_BUCK2_EN_MASK BIT(1)79#define BD96801_BUCK3_EN_MASK BIT(2)80#define BD96801_BUCK4_EN_MASK BIT(3)81#define BD96801_LDO5_EN_MASK BIT(4)82#define BD96801_LDO6_EN_MASK BIT(5)83#define BD96801_LDO7_EN_MASK BIT(6)84 85#define BD96801_BUCK1_VSEL_REG 0x2886#define BD96801_BUCK2_VSEL_REG 0x2987#define BD96801_BUCK3_VSEL_REG 0x2a88#define BD96801_BUCK4_VSEL_REG 0x2b89#define BD96801_LDO5_VSEL_REG 0x2590#define BD96801_LDO6_VSEL_REG 0x2691#define BD96801_LDO7_VSEL_REG 0x2792#define BD96801_BUCK_VSEL_MASK 0x1F93#define BD96801_LDO_VSEL_MASK 0xff94 95#define BD96801_MASK_RAMP_DELAY 0xc096#define BD96801_INT_VOUT_BASE_REG 0x2197#define BD96801_BUCK_INT_VOUT_MASK 0xff98 99#define BD96801_BUCK_VOLTS 256100#define BD96801_LDO_VOLTS 256101 102#define BD96801_OVP_MASK 0x03103#define BD96801_MASK_BUCK1_OVP_SHIFT 0x00104#define BD96801_MASK_BUCK2_OVP_SHIFT 0x02105#define BD96801_MASK_BUCK3_OVP_SHIFT 0x04106#define BD96801_MASK_BUCK4_OVP_SHIFT 0x06107#define BD96801_MASK_LDO5_OVP_SHIFT 0x00108#define BD96801_MASK_LDO6_OVP_SHIFT 0x02109#define BD96801_MASK_LDO7_OVP_SHIFT 0x04110 111#define BD96801_PROT_LIMIT_OCP_MIN 0x00112#define BD96801_PROT_LIMIT_LOW 0x01113#define BD96801_PROT_LIMIT_MID 0x02114#define BD96801_PROT_LIMIT_HI 0x03115 116#define BD96801_REG_BUCK1_OCP 0x32117#define BD96801_REG_BUCK2_OCP 0x32118#define BD96801_REG_BUCK3_OCP 0x33119#define BD96801_REG_BUCK4_OCP 0x33120 121#define BD96801_MASK_BUCK1_OCP_SHIFT 0x00122#define BD96801_MASK_BUCK2_OCP_SHIFT 0x04123#define BD96801_MASK_BUCK3_OCP_SHIFT 0x00124#define BD96801_MASK_BUCK4_OCP_SHIFT 0x04125 126#define BD96801_REG_LDO5_OCP 0x34127#define BD96801_REG_LDO6_OCP 0x34128#define BD96801_REG_LDO7_OCP 0x34129 130#define BD96801_MASK_LDO5_OCP_SHIFT 0x00131#define BD96801_MASK_LDO6_OCP_SHIFT 0x02132#define BD96801_MASK_LDO7_OCP_SHIFT 0x04133 134#define BD96801_MASK_SHD_INTB BIT(7)135#define BD96801_INTB_FATAL BIT(7)136 137#define BD96801_NUM_REGULATORS 7138#define BD96801_NUM_LDOS 4139 140/*141 * Ramp rates for bucks are controlled by bits [7:6] as follows:142 * 00 => 1 mV/uS143 * 01 => 5 mV/uS144 * 10 => 10 mV/uS145 * 11 => 20 mV/uS146 */147static const unsigned int buck_ramp_table[] = { 1000, 5000, 10000, 20000 };148 149/*150 * This is a voltage range that get's appended to selected151 * bd96801_buck_init_volts value. The range from 0x0 to 0xF is actually152 * bd96801_buck_init_volts + 0 ... bd96801_buck_init_volts + 150mV153 * and the range from 0x10 to 0x1f is bd96801_buck_init_volts - 150mV ...154 * bd96801_buck_init_volts - 0. But as the members of linear_range155 * are all unsigned I will apply offset of -150 mV to value in156 * linear_range - which should increase these ranges with157 * 150 mV getting all the values to >= 0.158 */159static const struct linear_range bd96801_tune_volts[] = {160 REGULATOR_LINEAR_RANGE(150000, 0x00, 0xF, 10000),161 REGULATOR_LINEAR_RANGE(0, 0x10, 0x1F, 10000),162};163 164static const struct linear_range bd96801_buck_init_volts[] = {165 REGULATOR_LINEAR_RANGE(500000 - 150000, 0x00, 0xc8, 5000),166 REGULATOR_LINEAR_RANGE(1550000 - 150000, 0xc9, 0xec, 50000),167 REGULATOR_LINEAR_RANGE(3300000 - 150000, 0xed, 0xff, 0),168};169 170static const struct linear_range bd96801_ldo_int_volts[] = {171 REGULATOR_LINEAR_RANGE(300000, 0x00, 0x78, 25000),172 REGULATOR_LINEAR_RANGE(3300000, 0x79, 0xff, 0),173};174 175#define BD96801_LDO_SD_VOLT_MASK 0x1176#define BD96801_LDO_MODE_MASK 0x6177#define BD96801_LDO_MODE_INT 0x0178#define BD96801_LDO_MODE_SD 0x2179#define BD96801_LDO_MODE_DDR 0x4180 181static int ldo_ddr_volt_table[] = {500000, 300000};182static int ldo_sd_volt_table[] = {3300000, 1800000};183 184/* Constant IRQ initialization data (templates) */185struct bd96801_irqinfo {186 int type;187 struct regulator_irq_desc irq_desc;188 int err_cfg;189 int wrn_cfg;190 const char *irq_name;191};192 193#define BD96801_IRQINFO(_type, _name, _irqoff_ms, _irqname) \194{ \195 .type = (_type), \196 .err_cfg = -1, \197 .wrn_cfg = -1, \198 .irq_name = (_irqname), \199 .irq_desc = { \200 .name = (_name), \201 .irq_off_ms = (_irqoff_ms), \202 .map_event = regulator_irq_map_event_simple, \203 }, \204}205 206static const struct bd96801_irqinfo buck1_irqinfo[] = {207 BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-h", 500,208 "bd96801-buck1-overcurr-h"),209 BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-l", 500,210 "bd96801-buck1-overcurr-l"),211 BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-n", 500,212 "bd96801-buck1-overcurr-n"),213 BD96801_IRQINFO(BD96801_PROT_OVP, "buck1-over-voltage", 500,214 "bd96801-buck1-overvolt"),215 BD96801_IRQINFO(BD96801_PROT_UVP, "buck1-under-voltage", 500,216 "bd96801-buck1-undervolt"),217 BD96801_IRQINFO(BD96801_PROT_TEMP, "buck1-over-temp", 500,218 "bd96801-buck1-thermal")219};220 221static const struct bd96801_irqinfo buck2_irqinfo[] = {222 BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-h", 500,223 "bd96801-buck2-overcurr-h"),224 BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-l", 500,225 "bd96801-buck2-overcurr-l"),226 BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-n", 500,227 "bd96801-buck2-overcurr-n"),228 BD96801_IRQINFO(BD96801_PROT_OVP, "buck2-over-voltage", 500,229 "bd96801-buck2-overvolt"),230 BD96801_IRQINFO(BD96801_PROT_UVP, "buck2-under-voltage", 500,231 "bd96801-buck2-undervolt"),232 BD96801_IRQINFO(BD96801_PROT_TEMP, "buck2-over-temp", 500,233 "bd96801-buck2-thermal")234};235 236static const struct bd96801_irqinfo buck3_irqinfo[] = {237 BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-h", 500,238 "bd96801-buck3-overcurr-h"),239 BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-l", 500,240 "bd96801-buck3-overcurr-l"),241 BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-n", 500,242 "bd96801-buck3-overcurr-n"),243 BD96801_IRQINFO(BD96801_PROT_OVP, "buck3-over-voltage", 500,244 "bd96801-buck3-overvolt"),245 BD96801_IRQINFO(BD96801_PROT_UVP, "buck3-under-voltage", 500,246 "bd96801-buck3-undervolt"),247 BD96801_IRQINFO(BD96801_PROT_TEMP, "buck3-over-temp", 500,248 "bd96801-buck3-thermal")249};250 251static const struct bd96801_irqinfo buck4_irqinfo[] = {252 BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-h", 500,253 "bd96801-buck4-overcurr-h"),254 BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-l", 500,255 "bd96801-buck4-overcurr-l"),256 BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-n", 500,257 "bd96801-buck4-overcurr-n"),258 BD96801_IRQINFO(BD96801_PROT_OVP, "buck4-over-voltage", 500,259 "bd96801-buck4-overvolt"),260 BD96801_IRQINFO(BD96801_PROT_UVP, "buck4-under-voltage", 500,261 "bd96801-buck4-undervolt"),262 BD96801_IRQINFO(BD96801_PROT_TEMP, "buck4-over-temp", 500,263 "bd96801-buck4-thermal")264};265 266static const struct bd96801_irqinfo ldo5_irqinfo[] = {267 BD96801_IRQINFO(BD96801_PROT_OCP, "ldo5-overcurr", 500,268 "bd96801-ldo5-overcurr"),269 BD96801_IRQINFO(BD96801_PROT_OVP, "ldo5-over-voltage", 500,270 "bd96801-ldo5-overvolt"),271 BD96801_IRQINFO(BD96801_PROT_UVP, "ldo5-under-voltage", 500,272 "bd96801-ldo5-undervolt"),273};274 275static const struct bd96801_irqinfo ldo6_irqinfo[] = {276 BD96801_IRQINFO(BD96801_PROT_OCP, "ldo6-overcurr", 500,277 "bd96801-ldo6-overcurr"),278 BD96801_IRQINFO(BD96801_PROT_OVP, "ldo6-over-voltage", 500,279 "bd96801-ldo6-overvolt"),280 BD96801_IRQINFO(BD96801_PROT_UVP, "ldo6-under-voltage", 500,281 "bd96801-ldo6-undervolt"),282};283 284static const struct bd96801_irqinfo ldo7_irqinfo[] = {285 BD96801_IRQINFO(BD96801_PROT_OCP, "ldo7-overcurr", 500,286 "bd96801-ldo7-overcurr"),287 BD96801_IRQINFO(BD96801_PROT_OVP, "ldo7-over-voltage", 500,288 "bd96801-ldo7-overvolt"),289 BD96801_IRQINFO(BD96801_PROT_UVP, "ldo7-under-voltage", 500,290 "bd96801-ldo7-undervolt"),291};292 293struct bd96801_irq_desc {294 struct bd96801_irqinfo *irqinfo;295 int num_irqs;296};297 298struct bd96801_regulator_data {299 struct regulator_desc desc;300 const struct linear_range *init_ranges;301 int num_ranges;302 struct bd96801_irq_desc irq_desc;303 int initial_voltage;304 int ldo_vol_lvl;305 int ldo_errs;306};307 308struct bd96801_pmic_data {309 struct bd96801_regulator_data regulator_data[BD96801_NUM_REGULATORS];310 struct regmap *regmap;311 int fatal_ind;312};313 314static int ldo_map_notif(int irq, struct regulator_irq_data *rid,315 unsigned long *dev_mask)316{317 int i;318 319 for (i = 0; i < rid->num_states; i++) {320 struct bd96801_regulator_data *rdata;321 struct regulator_dev *rdev;322 323 rdev = rid->states[i].rdev;324 rdata = container_of(rdev->desc, struct bd96801_regulator_data,325 desc);326 rid->states[i].notifs = regulator_err2notif(rdata->ldo_errs);327 rid->states[i].errors = rdata->ldo_errs;328 *dev_mask |= BIT(i);329 }330 return 0;331}332 333static int bd96801_list_voltage_lr(struct regulator_dev *rdev,334 unsigned int selector)335{336 int voltage;337 struct bd96801_regulator_data *data;338 339 data = container_of(rdev->desc, struct bd96801_regulator_data, desc);340 341 /*342 * The BD096801 has voltage setting in two registers. One giving the343 * "initial voltage" (can be changed only when regulator is disabled.344 * This driver caches the value and sets it only at startup. The other345 * register is voltage tuning value which applies -150 mV ... +150 mV346 * offset to the voltage.347 *348 * Note that the cached initial voltage stored in regulator data is349 * 'scaled down' by the 150 mV so that all of our tuning values are350 * >= 0. This is done because the linear_ranges uses unsigned values.351 *352 * As a result, we increase the tuning voltage which we get based on353 * the selector by the stored initial_voltage.354 */355 voltage = regulator_list_voltage_linear_range(rdev, selector);356 if (voltage < 0)357 return voltage;358 359 return voltage + data->initial_voltage;360}361 362 363static const struct regulator_ops bd96801_ldo_table_ops = {364 .is_enabled = regulator_is_enabled_regmap,365 .list_voltage = regulator_list_voltage_table,366 .get_voltage_sel = regulator_get_voltage_sel_regmap,367};368 369static const struct regulator_ops bd96801_buck_ops = {370 .is_enabled = regulator_is_enabled_regmap,371 .list_voltage = bd96801_list_voltage_lr,372 .set_voltage_sel = regulator_set_voltage_sel_regmap,373 .get_voltage_sel = regulator_get_voltage_sel_regmap,374 .set_voltage_time_sel = regulator_set_voltage_time_sel,375 .set_ramp_delay = regulator_set_ramp_delay_regmap,376};377 378static const struct regulator_ops bd96801_ldo_ops = {379 .is_enabled = regulator_is_enabled_regmap,380 .list_voltage = regulator_list_voltage_linear_range,381 .get_voltage_sel = regulator_get_voltage_sel_regmap,382};383 384static int buck_get_initial_voltage(struct regmap *regmap, struct device *dev,385 struct bd96801_regulator_data *data)386{387 int ret = 0, sel, initial_uv;388 int reg = BD96801_INT_VOUT_BASE_REG + data->desc.id;389 390 if (data->num_ranges) {391 ret = regmap_read(regmap, reg, &sel);392 sel &= BD96801_BUCK_INT_VOUT_MASK;393 394 ret = linear_range_get_value_array(data->init_ranges,395 data->num_ranges, sel,396 &initial_uv);397 if (ret)398 return ret;399 400 data->initial_voltage = initial_uv;401 dev_dbg(dev, "Tune-scaled initial voltage %u\n",402 data->initial_voltage);403 }404 405 return 0;406}407 408static int get_ldo_initial_voltage(struct regmap *regmap,409 struct device *dev,410 struct bd96801_regulator_data *data)411{412 int ret;413 int cfgreg;414 415 ret = regmap_read(regmap, data->ldo_vol_lvl, &cfgreg);416 if (ret)417 return ret;418 419 switch (cfgreg & BD96801_LDO_MODE_MASK) {420 case BD96801_LDO_MODE_DDR:421 data->desc.volt_table = ldo_ddr_volt_table;422 data->desc.n_voltages = ARRAY_SIZE(ldo_ddr_volt_table);423 break;424 case BD96801_LDO_MODE_SD:425 data->desc.volt_table = ldo_sd_volt_table;426 data->desc.n_voltages = ARRAY_SIZE(ldo_sd_volt_table);427 break;428 default:429 dev_info(dev, "Leaving LDO to normal mode");430 return 0;431 }432 433 /* SD or DDR mode => override default ops */434 data->desc.ops = &bd96801_ldo_table_ops,435 data->desc.vsel_mask = 1;436 data->desc.vsel_reg = data->ldo_vol_lvl;437 438 return 0;439}440 441static int get_initial_voltage(struct device *dev, struct regmap *regmap,442 struct bd96801_regulator_data *data)443{444 /* BUCK */445 if (data->desc.id <= BD96801_BUCK4)446 return buck_get_initial_voltage(regmap, dev, data);447 448 /* LDO */449 return get_ldo_initial_voltage(regmap, dev, data);450}451 452static int bd96801_walk_regulator_dt(struct device *dev, struct regmap *regmap,453 struct bd96801_regulator_data *data,454 int num)455{456 int i, ret;457 458 struct device_node *nproot __free(device_node) =459 of_get_child_by_name(dev->parent->of_node, "regulators");460 if (!nproot) {461 dev_err(dev, "failed to find regulators node\n");462 return -ENODEV;463 }464 for_each_child_of_node_scoped(nproot, np) {465 for (i = 0; i < num; i++) {466 if (!of_node_name_eq(np, data[i].desc.of_match))467 continue;468 /*469 * If STBY configs are supported, we must pass node470 * here to extract the initial voltages from the DT.471 * Thus we do the initial voltage getting in this472 * loop.473 */474 ret = get_initial_voltage(dev, regmap, &data[i]);475 if (ret) {476 dev_err(dev,477 "Initializing voltages for %s failed\n",478 data[i].desc.name);479 return ret;480 }481 482 if (of_property_read_bool(np, "rohm,keep-on-stby")) {483 ret = regmap_set_bits(regmap,484 BD96801_ALWAYS_ON_REG,485 1 << data[i].desc.id);486 if (ret) {487 dev_err(dev,488 "failed to set %s on-at-stby\n",489 data[i].desc.name);490 return ret;491 }492 }493 }494 }495 496 return 0;497}498 499/*500 * Template for regulator data. Probe will allocate dynamic / driver instance501 * struct so we should be on a safe side even if there were multiple PMICs to502 * control. Note that there is a plan to allow multiple PMICs to be used so503 * systems can scale better. I am however still slightly unsure how the504 * multi-PMIC case will be handled. I don't know if the processor will have I2C505 * acces to all of the PMICs or only the first one. I'd guess there will be506 * access provided to all PMICs for voltage scaling - but the errors will only507 * be informed via the master PMIC. Eg, we should prepare to support multiple508 * driver instances - either with or without the IRQs... Well, let's first509 * just support the simple and clear single-PMIC setup and ponder the multi PMIC510 * case later. What we can easly do for preparing is to not use static global511 * data for regulators though.512 */513static const struct bd96801_pmic_data bd96801_data = {514 .regulator_data = {515 {516 .desc = {517 .name = "buck1",518 .of_match = of_match_ptr("buck1"),519 .regulators_node = of_match_ptr("regulators"),520 .id = BD96801_BUCK1,521 .ops = &bd96801_buck_ops,522 .type = REGULATOR_VOLTAGE,523 .linear_ranges = bd96801_tune_volts,524 .n_linear_ranges = ARRAY_SIZE(bd96801_tune_volts),525 .n_voltages = BD96801_BUCK_VOLTS,526 .enable_reg = BD96801_REG_ENABLE,527 .enable_mask = BD96801_BUCK1_EN_MASK,528 .enable_is_inverted = true,529 .vsel_reg = BD96801_BUCK1_VSEL_REG,530 .vsel_mask = BD96801_BUCK_VSEL_MASK,531 .ramp_reg = BD96801_BUCK1_VSEL_REG,532 .ramp_mask = BD96801_MASK_RAMP_DELAY,533 .ramp_delay_table = &buck_ramp_table[0],534 .n_ramp_values = ARRAY_SIZE(buck_ramp_table),535 .owner = THIS_MODULE,536 },537 .init_ranges = bd96801_buck_init_volts,538 .num_ranges = ARRAY_SIZE(bd96801_buck_init_volts),539 .irq_desc = {540 .irqinfo = (struct bd96801_irqinfo *)&buck1_irqinfo[0],541 .num_irqs = ARRAY_SIZE(buck1_irqinfo),542 },543 }, {544 .desc = {545 .name = "buck2",546 .of_match = of_match_ptr("buck2"),547 .regulators_node = of_match_ptr("regulators"),548 .id = BD96801_BUCK2,549 .ops = &bd96801_buck_ops,550 .type = REGULATOR_VOLTAGE,551 .linear_ranges = bd96801_tune_volts,552 .n_linear_ranges = ARRAY_SIZE(bd96801_tune_volts),553 .n_voltages = BD96801_BUCK_VOLTS,554 .enable_reg = BD96801_REG_ENABLE,555 .enable_mask = BD96801_BUCK2_EN_MASK,556 .enable_is_inverted = true,557 .vsel_reg = BD96801_BUCK2_VSEL_REG,558 .vsel_mask = BD96801_BUCK_VSEL_MASK,559 .ramp_reg = BD96801_BUCK2_VSEL_REG,560 .ramp_mask = BD96801_MASK_RAMP_DELAY,561 .ramp_delay_table = &buck_ramp_table[0],562 .n_ramp_values = ARRAY_SIZE(buck_ramp_table),563 .owner = THIS_MODULE,564 },565 .irq_desc = {566 .irqinfo = (struct bd96801_irqinfo *)&buck2_irqinfo[0],567 .num_irqs = ARRAY_SIZE(buck2_irqinfo),568 },569 .init_ranges = bd96801_buck_init_volts,570 .num_ranges = ARRAY_SIZE(bd96801_buck_init_volts),571 }, {572 .desc = {573 .name = "buck3",574 .of_match = of_match_ptr("buck3"),575 .regulators_node = of_match_ptr("regulators"),576 .id = BD96801_BUCK3,577 .ops = &bd96801_buck_ops,578 .type = REGULATOR_VOLTAGE,579 .linear_ranges = bd96801_tune_volts,580 .n_linear_ranges = ARRAY_SIZE(bd96801_tune_volts),581 .n_voltages = BD96801_BUCK_VOLTS,582 .enable_reg = BD96801_REG_ENABLE,583 .enable_mask = BD96801_BUCK3_EN_MASK,584 .enable_is_inverted = true,585 .vsel_reg = BD96801_BUCK3_VSEL_REG,586 .vsel_mask = BD96801_BUCK_VSEL_MASK,587 .ramp_reg = BD96801_BUCK3_VSEL_REG,588 .ramp_mask = BD96801_MASK_RAMP_DELAY,589 .ramp_delay_table = &buck_ramp_table[0],590 .n_ramp_values = ARRAY_SIZE(buck_ramp_table),591 .owner = THIS_MODULE,592 },593 .irq_desc = {594 .irqinfo = (struct bd96801_irqinfo *)&buck3_irqinfo[0],595 .num_irqs = ARRAY_SIZE(buck3_irqinfo),596 },597 .init_ranges = bd96801_buck_init_volts,598 .num_ranges = ARRAY_SIZE(bd96801_buck_init_volts),599 }, {600 .desc = {601 .name = "buck4",602 .of_match = of_match_ptr("buck4"),603 .regulators_node = of_match_ptr("regulators"),604 .id = BD96801_BUCK4,605 .ops = &bd96801_buck_ops,606 .type = REGULATOR_VOLTAGE,607 .linear_ranges = bd96801_tune_volts,608 .n_linear_ranges = ARRAY_SIZE(bd96801_tune_volts),609 .n_voltages = BD96801_BUCK_VOLTS,610 .enable_reg = BD96801_REG_ENABLE,611 .enable_mask = BD96801_BUCK4_EN_MASK,612 .enable_is_inverted = true,613 .vsel_reg = BD96801_BUCK4_VSEL_REG,614 .vsel_mask = BD96801_BUCK_VSEL_MASK,615 .ramp_reg = BD96801_BUCK4_VSEL_REG,616 .ramp_mask = BD96801_MASK_RAMP_DELAY,617 .ramp_delay_table = &buck_ramp_table[0],618 .n_ramp_values = ARRAY_SIZE(buck_ramp_table),619 .owner = THIS_MODULE,620 },621 .irq_desc = {622 .irqinfo = (struct bd96801_irqinfo *)&buck4_irqinfo[0],623 .num_irqs = ARRAY_SIZE(buck4_irqinfo),624 },625 .init_ranges = bd96801_buck_init_volts,626 .num_ranges = ARRAY_SIZE(bd96801_buck_init_volts),627 }, {628 .desc = {629 .name = "ldo5",630 .of_match = of_match_ptr("ldo5"),631 .regulators_node = of_match_ptr("regulators"),632 .id = BD96801_LDO5,633 .ops = &bd96801_ldo_ops,634 .type = REGULATOR_VOLTAGE,635 .linear_ranges = bd96801_ldo_int_volts,636 .n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),637 .n_voltages = BD96801_LDO_VOLTS,638 .enable_reg = BD96801_REG_ENABLE,639 .enable_mask = BD96801_LDO5_EN_MASK,640 .enable_is_inverted = true,641 .vsel_reg = BD96801_LDO5_VSEL_REG,642 .vsel_mask = BD96801_LDO_VSEL_MASK,643 .owner = THIS_MODULE,644 },645 .irq_desc = {646 .irqinfo = (struct bd96801_irqinfo *)&ldo5_irqinfo[0],647 .num_irqs = ARRAY_SIZE(ldo5_irqinfo),648 },649 .ldo_vol_lvl = BD96801_LDO5_VOL_LVL_REG,650 }, {651 .desc = {652 .name = "ldo6",653 .of_match = of_match_ptr("ldo6"),654 .regulators_node = of_match_ptr("regulators"),655 .id = BD96801_LDO6,656 .ops = &bd96801_ldo_ops,657 .type = REGULATOR_VOLTAGE,658 .linear_ranges = bd96801_ldo_int_volts,659 .n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),660 .n_voltages = BD96801_LDO_VOLTS,661 .enable_reg = BD96801_REG_ENABLE,662 .enable_mask = BD96801_LDO6_EN_MASK,663 .enable_is_inverted = true,664 .vsel_reg = BD96801_LDO6_VSEL_REG,665 .vsel_mask = BD96801_LDO_VSEL_MASK,666 .owner = THIS_MODULE,667 },668 .irq_desc = {669 .irqinfo = (struct bd96801_irqinfo *)&ldo6_irqinfo[0],670 .num_irqs = ARRAY_SIZE(ldo6_irqinfo),671 },672 .ldo_vol_lvl = BD96801_LDO6_VOL_LVL_REG,673 }, {674 .desc = {675 .name = "ldo7",676 .of_match = of_match_ptr("ldo7"),677 .regulators_node = of_match_ptr("regulators"),678 .id = BD96801_LDO7,679 .ops = &bd96801_ldo_ops,680 .type = REGULATOR_VOLTAGE,681 .linear_ranges = bd96801_ldo_int_volts,682 .n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),683 .n_voltages = BD96801_LDO_VOLTS,684 .enable_reg = BD96801_REG_ENABLE,685 .enable_mask = BD96801_LDO7_EN_MASK,686 .enable_is_inverted = true,687 .vsel_reg = BD96801_LDO7_VSEL_REG,688 .vsel_mask = BD96801_LDO_VSEL_MASK,689 .owner = THIS_MODULE,690 },691 .irq_desc = {692 .irqinfo = (struct bd96801_irqinfo *)&ldo7_irqinfo[0],693 .num_irqs = ARRAY_SIZE(ldo7_irqinfo),694 },695 .ldo_vol_lvl = BD96801_LDO7_VOL_LVL_REG,696 },697 },698};699 700static int initialize_pmic_data(struct device *dev,701 struct bd96801_pmic_data *pdata)702{703 int r, i;704 705 /*706 * Allocate and initialize IRQ data for all of the regulators. We707 * wish to modify IRQ information independently for each driver708 * instance.709 */710 for (r = 0; r < BD96801_NUM_REGULATORS; r++) {711 const struct bd96801_irqinfo *template;712 struct bd96801_irqinfo *new;713 int num_infos;714 715 template = pdata->regulator_data[r].irq_desc.irqinfo;716 num_infos = pdata->regulator_data[r].irq_desc.num_irqs;717 718 new = devm_kcalloc(dev, num_infos, sizeof(*new), GFP_KERNEL);719 if (!new)720 return -ENOMEM;721 722 pdata->regulator_data[r].irq_desc.irqinfo = new;723 724 for (i = 0; i < num_infos; i++)725 new[i] = template[i];726 }727 728 return 0;729}730 731static int bd96801_rdev_intb_irqs(struct platform_device *pdev,732 struct bd96801_pmic_data *pdata,733 struct bd96801_irqinfo *iinfo,734 struct regulator_dev *rdev)735{736 struct regulator_dev *rdev_arr[1];737 void *retp;738 int err = 0;739 int irq;740 int err_flags[] = {741 [BD96801_PROT_OVP] = REGULATOR_ERROR_REGULATION_OUT,742 [BD96801_PROT_UVP] = REGULATOR_ERROR_UNDER_VOLTAGE,743 [BD96801_PROT_OCP] = REGULATOR_ERROR_OVER_CURRENT,744 [BD96801_PROT_TEMP] = REGULATOR_ERROR_OVER_TEMP,745 746 };747 int wrn_flags[] = {748 [BD96801_PROT_OVP] = REGULATOR_ERROR_OVER_VOLTAGE_WARN,749 [BD96801_PROT_UVP] = REGULATOR_ERROR_UNDER_VOLTAGE_WARN,750 [BD96801_PROT_OCP] = REGULATOR_ERROR_OVER_CURRENT_WARN,751 [BD96801_PROT_TEMP] = REGULATOR_ERROR_OVER_TEMP_WARN,752 };753 754 /*755 * Don't install IRQ handler if both error and warning756 * notifications are explicitly disabled757 */758 if (!iinfo->err_cfg && !iinfo->wrn_cfg)759 return 0;760 761 if (WARN_ON(iinfo->type >= BD96801_NUM_PROT))762 return -EINVAL;763 764 if (iinfo->err_cfg)765 err = err_flags[iinfo->type];766 else if (iinfo->wrn_cfg)767 err = wrn_flags[iinfo->type];768 769 iinfo->irq_desc.data = pdata;770 irq = platform_get_irq_byname(pdev, iinfo->irq_name);771 if (irq < 0)772 return irq;773 /* Find notifications for this IRQ (WARN/ERR) */774 775 rdev_arr[0] = rdev;776 retp = devm_regulator_irq_helper(&pdev->dev,777 &iinfo->irq_desc, irq,778 0, err, NULL, rdev_arr,779 1);780 if (IS_ERR(retp))781 return PTR_ERR(retp);782 783 return 0;784}785 786 787 788static int bd96801_probe(struct platform_device *pdev)789{790 struct regulator_dev *ldo_errs_rdev_arr[BD96801_NUM_LDOS];791 struct bd96801_regulator_data *rdesc;792 struct regulator_config config = {};793 int ldo_errs_arr[BD96801_NUM_LDOS];794 struct bd96801_pmic_data *pdata;795 int temp_notif_ldos = 0;796 struct device *parent;797 int i, ret;798 void *retp;799 800 parent = pdev->dev.parent;801 802 pdata = devm_kmemdup(&pdev->dev, &bd96801_data, sizeof(bd96801_data),803 GFP_KERNEL);804 if (!pdata)805 return -ENOMEM;806 807 if (initialize_pmic_data(&pdev->dev, pdata))808 return -ENOMEM;809 810 pdata->regmap = dev_get_regmap(parent, NULL);811 if (!pdata->regmap) {812 dev_err(&pdev->dev, "No register map found\n");813 return -ENODEV;814 }815 816 rdesc = &pdata->regulator_data[0];817 818 config.driver_data = pdata;819 config.regmap = pdata->regmap;820 config.dev = parent;821 822 ret = bd96801_walk_regulator_dt(&pdev->dev, pdata->regmap, rdesc,823 BD96801_NUM_REGULATORS);824 if (ret)825 return ret;826 827 for (i = 0; i < ARRAY_SIZE(pdata->regulator_data); i++) {828 struct regulator_dev *rdev;829 struct bd96801_irq_desc *idesc = &rdesc[i].irq_desc;830 int j;831 832 rdev = devm_regulator_register(&pdev->dev,833 &rdesc[i].desc, &config);834 if (IS_ERR(rdev)) {835 dev_err(&pdev->dev,836 "failed to register %s regulator\n",837 rdesc[i].desc.name);838 return PTR_ERR(rdev);839 }840 /*841 * LDOs don't have own temperature monitoring. If temperature842 * notification was requested for this LDO from DT then we will843 * add the regulator to be notified if central IC temperature844 * exceeds threshold.845 */846 if (rdesc[i].ldo_errs) {847 ldo_errs_rdev_arr[temp_notif_ldos] = rdev;848 ldo_errs_arr[temp_notif_ldos] = rdesc[i].ldo_errs;849 temp_notif_ldos++;850 }851 852 /* Register INTB handlers for configured protections */853 for (j = 0; j < idesc->num_irqs; j++) {854 ret = bd96801_rdev_intb_irqs(pdev, pdata,855 &idesc->irqinfo[j], rdev);856 if (ret)857 return ret;858 }859 }860 if (temp_notif_ldos) {861 int irq;862 struct regulator_irq_desc tw_desc = {863 .name = "bd96801-core-thermal",864 .irq_off_ms = 500,865 .map_event = ldo_map_notif,866 };867 868 irq = platform_get_irq_byname(pdev, "bd96801-core-thermal");869 if (irq < 0)870 return irq;871 872 retp = devm_regulator_irq_helper(&pdev->dev, &tw_desc, irq, 0,873 0, &ldo_errs_arr[0],874 &ldo_errs_rdev_arr[0],875 temp_notif_ldos);876 if (IS_ERR(retp))877 return PTR_ERR(retp);878 }879 880 return 0;881}882 883static const struct platform_device_id bd96801_pmic_id[] = {884 { "bd96801-regulator", },885 { }886};887MODULE_DEVICE_TABLE(platform, bd96801_pmic_id);888 889static struct platform_driver bd96801_regulator = {890 .driver = {891 .name = "bd96801-pmic"892 },893 .probe = bd96801_probe,894 .id_table = bd96801_pmic_id,895};896 897module_platform_driver(bd96801_regulator);898 899MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");900MODULE_DESCRIPTION("BD96801 voltage regulator driver");901MODULE_LICENSE("GPL");902