brintos

brintos / linux-shallow public Read only

0
0
Text · 25.4 KiB · da378bf Raw
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