brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · 1d8211f Raw
218 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Device driver for regulators in Hi655x IC4//5// Copyright (c) 2016 HiSilicon Ltd.6//7// Authors:8// Chen Feng <puck.chen@hisilicon.com>9// Fei  Wang <w.f@huawei.com>10 11#include <linux/bitops.h>12#include <linux/device.h>13#include <linux/err.h>14#include <linux/module.h>15#include <linux/io.h>16#include <linux/of.h>17#include <linux/platform_device.h>18#include <linux/regmap.h>19#include <linux/regulator/driver.h>20#include <linux/regulator/machine.h>21#include <linux/regulator/of_regulator.h>22#include <linux/mfd/hi655x-pmic.h>23 24struct hi655x_regulator {25	unsigned int disable_reg;26	unsigned int status_reg;27	struct regulator_desc rdesc;28};29 30/* LDO7 & LDO10 */31static const unsigned int ldo7_voltages[] = {32	1800000, 1850000, 2850000, 2900000,33	3000000, 3100000, 3200000, 3300000,34};35 36static const unsigned int ldo19_voltages[] = {37	1800000, 1850000, 1900000, 1750000,38	2800000, 2850000, 2900000, 3000000,39};40 41static const unsigned int ldo22_voltages[] = {42	 900000, 1000000, 1050000, 1100000,43	1150000, 1175000, 1185000, 1200000,44};45 46enum hi655x_regulator_id {47	HI655X_LDO0,48	HI655X_LDO1,49	HI655X_LDO2,50	HI655X_LDO3,51	HI655X_LDO4,52	HI655X_LDO5,53	HI655X_LDO6,54	HI655X_LDO7,55	HI655X_LDO8,56	HI655X_LDO9,57	HI655X_LDO10,58	HI655X_LDO11,59	HI655X_LDO12,60	HI655X_LDO13,61	HI655X_LDO14,62	HI655X_LDO15,63	HI655X_LDO16,64	HI655X_LDO17,65	HI655X_LDO18,66	HI655X_LDO19,67	HI655X_LDO20,68	HI655X_LDO21,69	HI655X_LDO22,70};71 72static int hi655x_is_enabled(struct regulator_dev *rdev)73{74	unsigned int value = 0;75	const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);76 77	regmap_read(rdev->regmap, regulator->status_reg, &value);78	return (value & rdev->desc->enable_mask);79}80 81static int hi655x_disable(struct regulator_dev *rdev)82{83	const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);84 85	return regmap_write(rdev->regmap, regulator->disable_reg,86			    rdev->desc->enable_mask);87}88 89static const struct regulator_ops hi655x_regulator_ops = {90	.enable = regulator_enable_regmap,91	.disable = hi655x_disable,92	.is_enabled = hi655x_is_enabled,93	.list_voltage = regulator_list_voltage_table,94	.get_voltage_sel = regulator_get_voltage_sel_regmap,95	.set_voltage_sel = regulator_set_voltage_sel_regmap,96};97 98static const struct regulator_ops hi655x_ldo_linear_ops = {99	.enable = regulator_enable_regmap,100	.disable = hi655x_disable,101	.is_enabled = hi655x_is_enabled,102	.list_voltage = regulator_list_voltage_linear,103	.get_voltage_sel = regulator_get_voltage_sel_regmap,104	.set_voltage_sel = regulator_set_voltage_sel_regmap,105};106 107#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg,                 \108		   sreg, cmask, vtable) {                        \109	.rdesc = {                                               \110		.name            = #_ID,                         \111		.of_match        = of_match_ptr(#_ID),           \112		.ops             = &hi655x_regulator_ops,        \113		.regulators_node = of_match_ptr("regulators"),   \114		.type            = REGULATOR_VOLTAGE,            \115		.id              = HI655X_##_ID,                 \116		.owner           = THIS_MODULE,                  \117		.n_voltages      = ARRAY_SIZE(vtable),           \118		.volt_table      = vtable,                       \119		.vsel_reg        = HI655X_BUS_ADDR(vreg),        \120		.vsel_mask       = vmask,                        \121		.enable_reg      = HI655X_BUS_ADDR(ereg),        \122		.enable_mask     = BIT(cmask),                   \123	},                                                       \124	.disable_reg = HI655X_BUS_ADDR(dreg),                    \125	.status_reg = HI655X_BUS_ADDR(sreg),                     \126}127 128#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg,          \129			  sreg, cmask, minv, nvolt, vstep) {     \130	.rdesc = {                                               \131		.name            = #_ID,                         \132		.of_match        = of_match_ptr(#_ID),           \133		.ops             = &hi655x_ldo_linear_ops,       \134		.regulators_node = of_match_ptr("regulators"),   \135		.type            = REGULATOR_VOLTAGE,            \136		.id              = HI655X_##_ID,                 \137		.owner           = THIS_MODULE,                  \138		.min_uV          = minv,                         \139		.n_voltages      = nvolt,                        \140		.uV_step         = vstep,                        \141		.vsel_reg        = HI655X_BUS_ADDR(vreg),        \142		.vsel_mask       = vmask,                        \143		.enable_reg      = HI655X_BUS_ADDR(ereg),        \144		.enable_mask     = BIT(cmask),                   \145	},                                                       \146	.disable_reg = HI655X_BUS_ADDR(dreg),                    \147	.status_reg = HI655X_BUS_ADDR(sreg),                     \148}149 150static const struct hi655x_regulator regulators[] = {151	HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,152			  2500000, 8, 100000),153	HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),154	HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),155	HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,156			  1600000, 8, 50000),157	HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,158			  2500000, 8, 100000),159	HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,160			  1600000, 8, 50000),161	HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,162			  2500000, 8, 100000),163	HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),164	HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,165			  1650000, 8, 50000),166	HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),167};168 169static int hi655x_regulator_probe(struct platform_device *pdev)170{171	unsigned int i;172	struct hi655x_pmic *pmic;173	struct regulator_config config = { };174	struct regulator_dev *rdev;175 176	pmic = dev_get_drvdata(pdev->dev.parent);177	if (!pmic) {178		dev_err(&pdev->dev, "no pmic in the regulator parent node\n");179		return -ENODEV;180	}181 182	config.dev = pdev->dev.parent;183	config.regmap = pmic->regmap;184	for (i = 0; i < ARRAY_SIZE(regulators); i++) {185		config.driver_data = (void *) &regulators[i];186 187		rdev = devm_regulator_register(&pdev->dev,188					       &regulators[i].rdesc,189					       &config);190		if (IS_ERR(rdev)) {191			dev_err(&pdev->dev, "failed to register regulator %s\n",192				regulators[i].rdesc.name);193			return PTR_ERR(rdev);194		}195	}196	return 0;197}198 199static const struct platform_device_id hi655x_regulator_table[] = {200	{ .name = "hi655x-regulator" },201	{},202};203MODULE_DEVICE_TABLE(platform, hi655x_regulator_table);204 205static struct platform_driver hi655x_regulator_driver = {206	.id_table = hi655x_regulator_table,207	.driver = {208		.name	= "hi655x-regulator",209		.probe_type = PROBE_PREFER_ASYNCHRONOUS,210	},211	.probe	= hi655x_regulator_probe,212};213module_platform_driver(hi655x_regulator_driver);214 215MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");216MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");217MODULE_LICENSE("GPL v2");218