brintos

brintos / linux-shallow public Read only

0
0
Text · 12.6 KiB · b43da84 Raw
423 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Copyright (c) 2016 MediaTek Inc.4// Author: Chen Zhong <chen.zhong@mediatek.com>5 6#include <linux/module.h>7#include <linux/of.h>8#include <linux/platform_device.h>9#include <linux/regmap.h>10#include <linux/mfd/mt6397/core.h>11#include <linux/mfd/mt6323/registers.h>12#include <linux/regulator/driver.h>13#include <linux/regulator/machine.h>14#include <linux/regulator/mt6323-regulator.h>15#include <linux/regulator/of_regulator.h>16 17#define MT6323_LDO_MODE_NORMAL	018#define MT6323_LDO_MODE_LP	119 20/*21 * MT6323 regulators' information22 *23 * @desc: standard fields of regulator description.24 * @qi: Mask for query enable signal status of regulators25 * @vselon_reg: Register sections for hardware control mode of bucks26 * @vselctrl_reg: Register for controlling the buck control mode.27 * @vselctrl_mask: Mask for query buck's voltage control mode.28 */29struct mt6323_regulator_info {30	struct regulator_desc desc;31	u32 qi;32	u32 vselon_reg;33	u32 vselctrl_reg;34	u32 vselctrl_mask;35	u32 modeset_reg;36	u32 modeset_mask;37};38 39#define MT6323_BUCK(match, vreg, min, max, step, volt_ranges, enreg,	\40		vosel, vosel_mask, voselon, vosel_ctrl)			\41[MT6323_ID_##vreg] = {							\42	.desc = {							\43		.name = #vreg,						\44		.of_match = of_match_ptr(match),			\45		.ops = &mt6323_volt_range_ops,				\46		.type = REGULATOR_VOLTAGE,				\47		.id = MT6323_ID_##vreg,					\48		.owner = THIS_MODULE,					\49		.n_voltages = (max - min)/step + 1,			\50		.linear_ranges = volt_ranges,				\51		.n_linear_ranges = ARRAY_SIZE(volt_ranges),		\52		.vsel_reg = vosel,					\53		.vsel_mask = vosel_mask,				\54		.enable_reg = enreg,					\55		.enable_mask = BIT(0),					\56	},								\57	.qi = BIT(13),							\58	.vselon_reg = voselon,						\59	.vselctrl_reg = vosel_ctrl,					\60	.vselctrl_mask = BIT(1),					\61}62 63#define MT6323_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,	\64		vosel_mask, _modeset_reg, _modeset_mask)		\65[MT6323_ID_##vreg] = {							\66	.desc = {							\67		.name = #vreg,						\68		.of_match = of_match_ptr(match),			\69		.ops = &mt6323_volt_table_ops,				\70		.type = REGULATOR_VOLTAGE,				\71		.id = MT6323_ID_##vreg,					\72		.owner = THIS_MODULE,					\73		.n_voltages = ARRAY_SIZE(ldo_volt_table),		\74		.volt_table = ldo_volt_table,				\75		.vsel_reg = vosel,					\76		.vsel_mask = vosel_mask,				\77		.enable_reg = enreg,					\78		.enable_mask = BIT(enbit),				\79	},								\80	.qi = BIT(15),							\81	.modeset_reg = _modeset_reg,					\82	.modeset_mask = _modeset_mask,					\83}84 85#define MT6323_REG_FIXED(match, vreg, enreg, enbit, volt,		\86		_modeset_reg, _modeset_mask)				\87[MT6323_ID_##vreg] = {							\88	.desc = {							\89		.name = #vreg,						\90		.of_match = of_match_ptr(match),			\91		.ops = &mt6323_volt_fixed_ops,				\92		.type = REGULATOR_VOLTAGE,				\93		.id = MT6323_ID_##vreg,					\94		.owner = THIS_MODULE,					\95		.n_voltages = 1,					\96		.enable_reg = enreg,					\97		.enable_mask = BIT(enbit),				\98		.min_uV = volt,						\99	},								\100	.qi = BIT(15),							\101	.modeset_reg = _modeset_reg,					\102	.modeset_mask = _modeset_mask,					\103}104 105static const struct linear_range buck_volt_range1[] = {106	REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),107};108 109static const struct linear_range buck_volt_range2[] = {110	REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),111};112 113static const struct linear_range buck_volt_range3[] = {114	REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),115};116 117static const unsigned int ldo_volt_table1[] = {118	3300000, 3400000, 3500000, 3600000,119};120 121static const unsigned int ldo_volt_table2[] = {122	1500000, 1800000, 2500000, 2800000,123};124 125static const unsigned int ldo_volt_table3[] = {126	1800000, 3300000,127};128 129static const unsigned int ldo_volt_table4[] = {130	3000000, 3300000,131};132 133static const unsigned int ldo_volt_table5[] = {134	1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,135};136 137static const unsigned int ldo_volt_table6[] = {138	1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,139};140 141static const unsigned int ldo_volt_table7[] = {142	1200000, 1300000, 1500000, 1800000,143};144 145static const unsigned int ldo_volt_table8[] = {146	1800000, 3000000,147};148 149static const unsigned int ldo_volt_table9[] = {150	1200000, 1350000, 1500000, 1800000,151};152 153static const unsigned int ldo_volt_table10[] = {154	1200000, 1300000, 1500000, 1800000,155};156 157static int mt6323_get_status(struct regulator_dev *rdev)158{159	int ret;160	u32 regval;161	struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);162 163	ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);164	if (ret != 0) {165		dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);166		return ret;167	}168 169	return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;170}171 172static int mt6323_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)173{174	int ret, val = 0;175	struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);176 177	if (!info->modeset_mask) {178		dev_err(&rdev->dev, "regulator %s doesn't support set_mode\n",179			info->desc.name);180		return -EINVAL;181	}182 183	switch (mode) {184	case REGULATOR_MODE_STANDBY:185		val = MT6323_LDO_MODE_LP;186		break;187	case REGULATOR_MODE_NORMAL:188		val = MT6323_LDO_MODE_NORMAL;189		break;190	default:191		return -EINVAL;192	}193 194	val <<= ffs(info->modeset_mask) - 1;195 196	ret = regmap_update_bits(rdev->regmap, info->modeset_reg,197				  info->modeset_mask, val);198 199	return ret;200}201 202static unsigned int mt6323_ldo_get_mode(struct regulator_dev *rdev)203{204	unsigned int val;205	unsigned int mode;206	int ret;207	struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);208 209	if (!info->modeset_mask) {210		dev_err(&rdev->dev, "regulator %s doesn't support get_mode\n",211			info->desc.name);212		return -EINVAL;213	}214 215	ret = regmap_read(rdev->regmap, info->modeset_reg, &val);216	if (ret < 0)217		return ret;218 219	val &= info->modeset_mask;220	val >>= ffs(info->modeset_mask) - 1;221 222	if (val & 0x1)223		mode = REGULATOR_MODE_STANDBY;224	else225		mode = REGULATOR_MODE_NORMAL;226 227	return mode;228}229 230static const struct regulator_ops mt6323_volt_range_ops = {231	.list_voltage = regulator_list_voltage_linear_range,232	.map_voltage = regulator_map_voltage_linear_range,233	.set_voltage_sel = regulator_set_voltage_sel_regmap,234	.get_voltage_sel = regulator_get_voltage_sel_regmap,235	.set_voltage_time_sel = regulator_set_voltage_time_sel,236	.enable = regulator_enable_regmap,237	.disable = regulator_disable_regmap,238	.is_enabled = regulator_is_enabled_regmap,239	.get_status = mt6323_get_status,240};241 242static const struct regulator_ops mt6323_volt_table_ops = {243	.list_voltage = regulator_list_voltage_table,244	.map_voltage = regulator_map_voltage_iterate,245	.set_voltage_sel = regulator_set_voltage_sel_regmap,246	.get_voltage_sel = regulator_get_voltage_sel_regmap,247	.set_voltage_time_sel = regulator_set_voltage_time_sel,248	.enable = regulator_enable_regmap,249	.disable = regulator_disable_regmap,250	.is_enabled = regulator_is_enabled_regmap,251	.get_status = mt6323_get_status,252	.set_mode = mt6323_ldo_set_mode,253	.get_mode = mt6323_ldo_get_mode,254};255 256static const struct regulator_ops mt6323_volt_fixed_ops = {257	.list_voltage = regulator_list_voltage_linear,258	.enable = regulator_enable_regmap,259	.disable = regulator_disable_regmap,260	.is_enabled = regulator_is_enabled_regmap,261	.get_status = mt6323_get_status,262	.set_mode = mt6323_ldo_set_mode,263	.get_mode = mt6323_ldo_get_mode,264};265 266/* The array is indexed by id(MT6323_ID_XXX) */267static struct mt6323_regulator_info mt6323_regulators[] = {268	MT6323_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,269		buck_volt_range1, MT6323_VPROC_CON7, MT6323_VPROC_CON9, 0x7f,270		MT6323_VPROC_CON10, MT6323_VPROC_CON5),271	MT6323_BUCK("buck_vsys", VSYS, 1400000, 2987500, 12500,272		buck_volt_range2, MT6323_VSYS_CON7, MT6323_VSYS_CON9, 0x7f,273		MT6323_VSYS_CON10, MT6323_VSYS_CON5),274	MT6323_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,275		buck_volt_range3, MT6323_VPA_CON7, MT6323_VPA_CON9,276		0x3f, MT6323_VPA_CON10, MT6323_VPA_CON5),277	MT6323_REG_FIXED("ldo_vtcxo", VTCXO, MT6323_ANALDO_CON1, 10, 2800000,278		MT6323_ANALDO_CON1, 0x2),279	MT6323_REG_FIXED("ldo_vcn28", VCN28, MT6323_ANALDO_CON19, 12, 2800000,280		MT6323_ANALDO_CON20, 0x2),281	MT6323_LDO("ldo_vcn33_bt", VCN33_BT, ldo_volt_table1,282		MT6323_ANALDO_CON16, 7, MT6323_ANALDO_CON16, 0xC,283		MT6323_ANALDO_CON21, 0x2),284	MT6323_LDO("ldo_vcn33_wifi", VCN33_WIFI, ldo_volt_table1,285		MT6323_ANALDO_CON17, 12, MT6323_ANALDO_CON16, 0xC,286		MT6323_ANALDO_CON21, 0x2),287	MT6323_REG_FIXED("ldo_va", VA, MT6323_ANALDO_CON2, 14, 2800000,288		MT6323_ANALDO_CON2, 0x2),289	MT6323_LDO("ldo_vcama", VCAMA, ldo_volt_table2,290		MT6323_ANALDO_CON4, 15, MT6323_ANALDO_CON10, 0x60, -1, 0),291	MT6323_REG_FIXED("ldo_vio28", VIO28, MT6323_DIGLDO_CON0, 14, 2800000,292		MT6323_DIGLDO_CON0, 0x2),293	MT6323_REG_FIXED("ldo_vusb", VUSB, MT6323_DIGLDO_CON2, 14, 3300000,294		MT6323_DIGLDO_CON2, 0x2),295	MT6323_LDO("ldo_vmc", VMC, ldo_volt_table3,296		MT6323_DIGLDO_CON3, 12, MT6323_DIGLDO_CON24, 0x10,297		MT6323_DIGLDO_CON3, 0x2),298	MT6323_LDO("ldo_vmch", VMCH, ldo_volt_table4,299		MT6323_DIGLDO_CON5, 14, MT6323_DIGLDO_CON26, 0x80,300		MT6323_DIGLDO_CON5, 0x2),301	MT6323_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table4,302		MT6323_DIGLDO_CON6, 14, MT6323_DIGLDO_CON27, 0x80,303		MT6323_DIGLDO_CON6, 0x2),304	MT6323_LDO("ldo_vgp1", VGP1, ldo_volt_table5,305		MT6323_DIGLDO_CON7, 15, MT6323_DIGLDO_CON28, 0xE0,306		MT6323_DIGLDO_CON7, 0x2),307	MT6323_LDO("ldo_vgp2", VGP2, ldo_volt_table6,308		MT6323_DIGLDO_CON8, 15, MT6323_DIGLDO_CON29, 0xE0,309		MT6323_DIGLDO_CON8, 0x2),310	MT6323_LDO("ldo_vgp3", VGP3, ldo_volt_table7,311		MT6323_DIGLDO_CON9, 15, MT6323_DIGLDO_CON30, 0x60,312		MT6323_DIGLDO_CON9, 0x2),313	MT6323_REG_FIXED("ldo_vcn18", VCN18, MT6323_DIGLDO_CON11, 14, 1800000,314		MT6323_DIGLDO_CON11, 0x2),315	MT6323_LDO("ldo_vsim1", VSIM1, ldo_volt_table8,316		MT6323_DIGLDO_CON13, 15, MT6323_DIGLDO_CON34, 0x20,317		MT6323_DIGLDO_CON13, 0x2),318	MT6323_LDO("ldo_vsim2", VSIM2, ldo_volt_table8,319		MT6323_DIGLDO_CON14, 15, MT6323_DIGLDO_CON35, 0x20,320		MT6323_DIGLDO_CON14, 0x2),321	MT6323_REG_FIXED("ldo_vrtc", VRTC, MT6323_DIGLDO_CON15, 8, 2800000,322		-1, 0),323	MT6323_LDO("ldo_vcamaf", VCAMAF, ldo_volt_table5,324		MT6323_DIGLDO_CON31, 15, MT6323_DIGLDO_CON32, 0xE0,325		MT6323_DIGLDO_CON31, 0x2),326	MT6323_LDO("ldo_vibr", VIBR, ldo_volt_table5,327		MT6323_DIGLDO_CON39, 15, MT6323_DIGLDO_CON40, 0xE0,328		MT6323_DIGLDO_CON39, 0x2),329	MT6323_REG_FIXED("ldo_vrf18", VRF18, MT6323_DIGLDO_CON45, 15, 1825000,330		MT6323_DIGLDO_CON45, 0x2),331	MT6323_LDO("ldo_vm", VM, ldo_volt_table9,332		MT6323_DIGLDO_CON47, 14, MT6323_DIGLDO_CON48, 0x30,333		MT6323_DIGLDO_CON47, 0x2),334	MT6323_REG_FIXED("ldo_vio18", VIO18, MT6323_DIGLDO_CON49, 14, 1800000,335		MT6323_DIGLDO_CON49, 0x2),336	MT6323_LDO("ldo_vcamd", VCAMD, ldo_volt_table10,337		MT6323_DIGLDO_CON51, 14, MT6323_DIGLDO_CON52, 0x60,338		MT6323_DIGLDO_CON51, 0x2),339	MT6323_REG_FIXED("ldo_vcamio", VCAMIO, MT6323_DIGLDO_CON53, 14, 1800000,340		MT6323_DIGLDO_CON53, 0x2),341};342 343static int mt6323_set_buck_vosel_reg(struct platform_device *pdev)344{345	struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);346	int i;347	u32 regval;348 349	for (i = 0; i < MT6323_MAX_REGULATOR; i++) {350		if (mt6323_regulators[i].vselctrl_reg) {351			if (regmap_read(mt6323->regmap,352				mt6323_regulators[i].vselctrl_reg,353				&regval) < 0) {354				dev_err(&pdev->dev,355					"Failed to read buck ctrl\n");356				return -EIO;357			}358 359			if (regval & mt6323_regulators[i].vselctrl_mask) {360				mt6323_regulators[i].desc.vsel_reg =361				mt6323_regulators[i].vselon_reg;362			}363		}364	}365 366	return 0;367}368 369static int mt6323_regulator_probe(struct platform_device *pdev)370{371	struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);372	struct regulator_config config = {};373	struct regulator_dev *rdev;374	int i;375	u32 reg_value;376 377	/* Query buck controller to select activated voltage register part */378	if (mt6323_set_buck_vosel_reg(pdev))379		return -EIO;380 381	/* Read PMIC chip revision to update constraints and voltage table */382	if (regmap_read(mt6323->regmap, MT6323_CID, &reg_value) < 0) {383		dev_err(&pdev->dev, "Failed to read Chip ID\n");384		return -EIO;385	}386	dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);387 388	for (i = 0; i < MT6323_MAX_REGULATOR; i++) {389		config.dev = &pdev->dev;390		config.driver_data = &mt6323_regulators[i];391		config.regmap = mt6323->regmap;392		rdev = devm_regulator_register(&pdev->dev,393				&mt6323_regulators[i].desc, &config);394		if (IS_ERR(rdev)) {395			dev_err(&pdev->dev, "failed to register %s\n",396				mt6323_regulators[i].desc.name);397			return PTR_ERR(rdev);398		}399	}400	return 0;401}402 403static const struct platform_device_id mt6323_platform_ids[] = {404	{"mt6323-regulator", 0},405	{ /* sentinel */ },406};407MODULE_DEVICE_TABLE(platform, mt6323_platform_ids);408 409static struct platform_driver mt6323_regulator_driver = {410	.driver = {411		.name = "mt6323-regulator",412		.probe_type = PROBE_PREFER_ASYNCHRONOUS,413	},414	.probe = mt6323_regulator_probe,415	.id_table = mt6323_platform_ids,416};417 418module_platform_driver(mt6323_regulator_driver);419 420MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");421MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6323 PMIC");422MODULE_LICENSE("GPL v2");423