brintos

brintos / linux-shallow public Read only

0
0
Text · 27.0 KiB · 9876cc0 Raw
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