brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 5447e1a Raw
258 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2017 Spreadtrum Communications Inc.4 */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/regulator/driver.h>11#include <linux/regulator/of_regulator.h>12 13/*14 * SC2731 regulator lock register15 */16#define SC2731_PWR_WR_PROT		0xf0c17#define SC2731_WR_UNLOCK_VALUE		0x6e7f18 19/*20 * SC2731 enable register21 */22#define SC2731_POWER_PD_SW		0xc2823#define SC2731_LDO_CAMA0_PD		0xcfc24#define SC2731_LDO_CAMA1_PD		0xd0425#define SC2731_LDO_CAMMOT_PD		0xd0c26#define SC2731_LDO_VLDO_PD		0xd6c27#define SC2731_LDO_EMMCCORE_PD		0xd2c28#define SC2731_LDO_SDCORE_PD		0xd7429#define SC2731_LDO_SDIO_PD		0xd7030#define SC2731_LDO_WIFIPA_PD		0xd4c31#define SC2731_LDO_USB33_PD		0xd5c32#define SC2731_LDO_CAMD0_PD		0xd7c33#define SC2731_LDO_CAMD1_PD		0xd8434#define SC2731_LDO_CON_PD		0xd8c35#define SC2731_LDO_CAMIO_PD		0xd9436#define SC2731_LDO_SRAM_PD		0xd7837 38/*39 * SC2731 enable mask40 */41#define SC2731_DCDC_CPU0_PD_MASK	BIT(4)42#define SC2731_DCDC_CPU1_PD_MASK	BIT(3)43#define SC2731_DCDC_RF_PD_MASK		BIT(11)44#define SC2731_LDO_CAMA0_PD_MASK	BIT(0)45#define SC2731_LDO_CAMA1_PD_MASK	BIT(0)46#define SC2731_LDO_CAMMOT_PD_MASK	BIT(0)47#define SC2731_LDO_VLDO_PD_MASK		BIT(0)48#define SC2731_LDO_EMMCCORE_PD_MASK	BIT(0)49#define SC2731_LDO_SDCORE_PD_MASK	BIT(0)50#define SC2731_LDO_SDIO_PD_MASK		BIT(0)51#define SC2731_LDO_WIFIPA_PD_MASK	BIT(0)52#define SC2731_LDO_USB33_PD_MASK	BIT(0)53#define SC2731_LDO_CAMD0_PD_MASK	BIT(0)54#define SC2731_LDO_CAMD1_PD_MASK	BIT(0)55#define SC2731_LDO_CON_PD_MASK		BIT(0)56#define SC2731_LDO_CAMIO_PD_MASK	BIT(0)57#define SC2731_LDO_SRAM_PD_MASK		BIT(0)58 59/*60 * SC2731 vsel register61 */62#define SC2731_DCDC_CPU0_VOL		0xc5463#define SC2731_DCDC_CPU1_VOL		0xc6464#define SC2731_DCDC_RF_VOL		0xcb865#define SC2731_LDO_CAMA0_VOL		0xd0066#define SC2731_LDO_CAMA1_VOL		0xd0867#define SC2731_LDO_CAMMOT_VOL		0xd1068#define SC2731_LDO_VLDO_VOL		0xd2869#define SC2731_LDO_EMMCCORE_VOL		0xd3070#define SC2731_LDO_SDCORE_VOL		0xd3871#define SC2731_LDO_SDIO_VOL		0xd4072#define SC2731_LDO_WIFIPA_VOL		0xd5073#define SC2731_LDO_USB33_VOL		0xd6074#define SC2731_LDO_CAMD0_VOL		0xd8075#define SC2731_LDO_CAMD1_VOL		0xd8876#define SC2731_LDO_CON_VOL		0xd9077#define SC2731_LDO_CAMIO_VOL		0xd9878#define SC2731_LDO_SRAM_VOL		0xdB079 80/*81 * SC2731 vsel register mask82 */83#define SC2731_DCDC_CPU0_VOL_MASK	GENMASK(8, 0)84#define SC2731_DCDC_CPU1_VOL_MASK	GENMASK(8, 0)85#define SC2731_DCDC_RF_VOL_MASK		GENMASK(8, 0)86#define SC2731_LDO_CAMA0_VOL_MASK	GENMASK(7, 0)87#define SC2731_LDO_CAMA1_VOL_MASK	GENMASK(7, 0)88#define SC2731_LDO_CAMMOT_VOL_MASK	GENMASK(7, 0)89#define SC2731_LDO_VLDO_VOL_MASK	GENMASK(7, 0)90#define SC2731_LDO_EMMCCORE_VOL_MASK	GENMASK(7, 0)91#define SC2731_LDO_SDCORE_VOL_MASK	GENMASK(7, 0)92#define SC2731_LDO_SDIO_VOL_MASK	GENMASK(7, 0)93#define SC2731_LDO_WIFIPA_VOL_MASK	GENMASK(7, 0)94#define SC2731_LDO_USB33_VOL_MASK	GENMASK(7, 0)95#define SC2731_LDO_CAMD0_VOL_MASK	GENMASK(6, 0)96#define SC2731_LDO_CAMD1_VOL_MASK	GENMASK(6, 0)97#define SC2731_LDO_CON_VOL_MASK		GENMASK(6, 0)98#define SC2731_LDO_CAMIO_VOL_MASK	GENMASK(6, 0)99#define SC2731_LDO_SRAM_VOL_MASK	GENMASK(6, 0)100 101enum sc2731_regulator_id {102	SC2731_BUCK_CPU0,103	SC2731_BUCK_CPU1,104	SC2731_BUCK_RF,105	SC2731_LDO_CAMA0,106	SC2731_LDO_CAMA1,107	SC2731_LDO_CAMMOT,108	SC2731_LDO_VLDO,109	SC2731_LDO_EMMCCORE,110	SC2731_LDO_SDCORE,111	SC2731_LDO_SDIO,112	SC2731_LDO_WIFIPA,113	SC2731_LDO_USB33,114	SC2731_LDO_CAMD0,115	SC2731_LDO_CAMD1,116	SC2731_LDO_CON,117	SC2731_LDO_CAMIO,118	SC2731_LDO_SRAM,119};120 121static const struct regulator_ops sc2731_regu_linear_ops = {122	.enable = regulator_enable_regmap,123	.disable = regulator_disable_regmap,124	.is_enabled = regulator_is_enabled_regmap,125	.list_voltage = regulator_list_voltage_linear,126	.get_voltage_sel = regulator_get_voltage_sel_regmap,127	.set_voltage_sel = regulator_set_voltage_sel_regmap,128};129 130#define SC2731_REGU_LINEAR(_id, en_reg, en_mask, vreg, vmask,	\131			  vstep, vmin, vmax) {			\132	.name			= #_id,				\133	.of_match		= of_match_ptr(#_id),		\134	.ops			= &sc2731_regu_linear_ops,	\135	.type			= REGULATOR_VOLTAGE,		\136	.id			= SC2731_##_id,			\137	.owner			= THIS_MODULE,			\138	.min_uV			= vmin,				\139	.n_voltages		= ((vmax) - (vmin)) / (vstep) + 1,	\140	.uV_step		= vstep,			\141	.enable_is_inverted	= true,				\142	.enable_val		= 0,				\143	.enable_reg		= en_reg,			\144	.enable_mask		= en_mask,			\145	.vsel_reg		= vreg,				\146	.vsel_mask		= vmask,			\147}148 149static const struct regulator_desc regulators[] = {150	SC2731_REGU_LINEAR(BUCK_CPU0, SC2731_POWER_PD_SW,151			   SC2731_DCDC_CPU0_PD_MASK, SC2731_DCDC_CPU0_VOL,152			   SC2731_DCDC_CPU0_VOL_MASK, 3125, 400000, 1996875),153	SC2731_REGU_LINEAR(BUCK_CPU1, SC2731_POWER_PD_SW,154			   SC2731_DCDC_CPU1_PD_MASK, SC2731_DCDC_CPU1_VOL,155			   SC2731_DCDC_CPU1_VOL_MASK, 3125, 400000, 1996875),156	SC2731_REGU_LINEAR(BUCK_RF, SC2731_POWER_PD_SW, SC2731_DCDC_RF_PD_MASK,157			   SC2731_DCDC_RF_VOL, SC2731_DCDC_RF_VOL_MASK,158			   3125, 600000, 2196875),159	SC2731_REGU_LINEAR(LDO_CAMA0, SC2731_LDO_CAMA0_PD,160			   SC2731_LDO_CAMA0_PD_MASK, SC2731_LDO_CAMA0_VOL,161			   SC2731_LDO_CAMA0_VOL_MASK, 10000, 1200000, 3750000),162	SC2731_REGU_LINEAR(LDO_CAMA1, SC2731_LDO_CAMA1_PD,163			   SC2731_LDO_CAMA1_PD_MASK, SC2731_LDO_CAMA1_VOL,164			   SC2731_LDO_CAMA1_VOL_MASK, 10000, 1200000, 3750000),165	SC2731_REGU_LINEAR(LDO_CAMMOT, SC2731_LDO_CAMMOT_PD,166			   SC2731_LDO_CAMMOT_PD_MASK, SC2731_LDO_CAMMOT_VOL,167			   SC2731_LDO_CAMMOT_VOL_MASK, 10000, 1200000, 3750000),168	SC2731_REGU_LINEAR(LDO_VLDO, SC2731_LDO_VLDO_PD,169			   SC2731_LDO_VLDO_PD_MASK, SC2731_LDO_VLDO_VOL,170			   SC2731_LDO_VLDO_VOL_MASK, 10000, 1200000, 3750000),171	SC2731_REGU_LINEAR(LDO_EMMCCORE, SC2731_LDO_EMMCCORE_PD,172			   SC2731_LDO_EMMCCORE_PD_MASK, SC2731_LDO_EMMCCORE_VOL,173			   SC2731_LDO_EMMCCORE_VOL_MASK, 10000, 1200000,174			   3750000),175	SC2731_REGU_LINEAR(LDO_SDCORE, SC2731_LDO_SDCORE_PD,176			   SC2731_LDO_SDCORE_PD_MASK, SC2731_LDO_SDCORE_VOL,177			   SC2731_LDO_SDCORE_VOL_MASK, 10000, 1200000, 3750000),178	SC2731_REGU_LINEAR(LDO_SDIO, SC2731_LDO_SDIO_PD,179			   SC2731_LDO_SDIO_PD_MASK, SC2731_LDO_SDIO_VOL,180			   SC2731_LDO_SDIO_VOL_MASK, 10000, 1200000, 3750000),181	SC2731_REGU_LINEAR(LDO_WIFIPA, SC2731_LDO_WIFIPA_PD,182			   SC2731_LDO_WIFIPA_PD_MASK, SC2731_LDO_WIFIPA_VOL,183			   SC2731_LDO_WIFIPA_VOL_MASK, 10000, 1200000, 3750000),184	SC2731_REGU_LINEAR(LDO_USB33, SC2731_LDO_USB33_PD,185			   SC2731_LDO_USB33_PD_MASK, SC2731_LDO_USB33_VOL,186			   SC2731_LDO_USB33_VOL_MASK, 10000, 1200000, 3750000),187	SC2731_REGU_LINEAR(LDO_CAMD0, SC2731_LDO_CAMD0_PD,188			   SC2731_LDO_CAMD0_PD_MASK, SC2731_LDO_CAMD0_VOL,189			   SC2731_LDO_CAMD0_VOL_MASK, 6250, 1000000, 1793750),190	SC2731_REGU_LINEAR(LDO_CAMD1, SC2731_LDO_CAMD1_PD,191			   SC2731_LDO_CAMD1_PD_MASK, SC2731_LDO_CAMD1_VOL,192			   SC2731_LDO_CAMD1_VOL_MASK, 6250, 1000000, 1793750),193	SC2731_REGU_LINEAR(LDO_CON, SC2731_LDO_CON_PD,194			   SC2731_LDO_CON_PD_MASK, SC2731_LDO_CON_VOL,195			   SC2731_LDO_CON_VOL_MASK, 6250, 1000000, 1793750),196	SC2731_REGU_LINEAR(LDO_CAMIO, SC2731_LDO_CAMIO_PD,197			   SC2731_LDO_CAMIO_PD_MASK, SC2731_LDO_CAMIO_VOL,198			   SC2731_LDO_CAMIO_VOL_MASK, 6250, 1000000, 1793750),199	SC2731_REGU_LINEAR(LDO_SRAM, SC2731_LDO_SRAM_PD,200			   SC2731_LDO_SRAM_PD_MASK, SC2731_LDO_SRAM_VOL,201			   SC2731_LDO_SRAM_VOL_MASK, 6250, 1000000, 1793750),202};203 204static int sc2731_regulator_unlock(struct regmap *regmap)205{206	return regmap_write(regmap, SC2731_PWR_WR_PROT,207			    SC2731_WR_UNLOCK_VALUE);208}209 210static int sc2731_regulator_probe(struct platform_device *pdev)211{212	int i, ret;213	struct regmap *regmap;214	struct regulator_config config = { };215	struct regulator_dev *rdev;216 217	regmap = dev_get_regmap(pdev->dev.parent, NULL);218	if (!regmap) {219		dev_err(&pdev->dev, "failed to get regmap.\n");220		return -ENODEV;221	}222 223	ret = sc2731_regulator_unlock(regmap);224	if (ret) {225		dev_err(&pdev->dev, "failed to release regulator lock\n");226		return ret;227	}228 229	config.dev = &pdev->dev;230	config.regmap = regmap;231 232	for (i = 0; i < ARRAY_SIZE(regulators); i++) {233		rdev = devm_regulator_register(&pdev->dev, &regulators[i],234					       &config);235		if (IS_ERR(rdev)) {236			dev_err(&pdev->dev, "failed to register regulator %s\n",237				regulators[i].name);238			return PTR_ERR(rdev);239		}240	}241 242	return 0;243}244 245static struct platform_driver sc2731_regulator_driver = {246	.driver = {247		.name = "sc27xx-regulator",248		.probe_type = PROBE_PREFER_ASYNCHRONOUS,249	},250	.probe = sc2731_regulator_probe,251};252 253module_platform_driver(sc2731_regulator_driver);254 255MODULE_AUTHOR("Chen Junhui <erick.chen@spreadtrum.com>");256MODULE_DESCRIPTION("Spreadtrum SC2731 regulator driver");257MODULE_LICENSE("GPL v2");258