cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hi6421-regulator.c (18387B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Device driver for regulators in Hi6421 IC
      4//
      5// Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
      6//              http://www.hisilicon.com
      7// Copyright (c) <2013-2014> Linaro Ltd.
      8//              https://www.linaro.org
      9//
     10// Author: Guodong Xu <guodong.xu@linaro.org>
     11
     12#include <linux/slab.h>
     13#include <linux/device.h>
     14#include <linux/module.h>
     15#include <linux/err.h>
     16#include <linux/platform_device.h>
     17#include <linux/of.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/hi6421-pmic.h>
     23
     24/*
     25 * struct hi6421_regulator_pdata - Hi6421 regulator data of platform device
     26 * @lock: mutex to serialize regulator enable
     27 */
     28struct hi6421_regulator_pdata {
     29	struct mutex lock;
     30};
     31
     32/*
     33 * struct hi6421_regulator_info - hi6421 regulator information
     34 * @desc: regulator description
     35 * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
     36 * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
     37 */
     38struct hi6421_regulator_info {
     39	struct regulator_desc	desc;
     40	u8		mode_mask;
     41	u32		eco_microamp;
     42};
     43
     44/* HI6421 regulators */
     45enum hi6421_regulator_id {
     46	HI6421_LDO0,
     47	HI6421_LDO1,
     48	HI6421_LDO2,
     49	HI6421_LDO3,
     50	HI6421_LDO4,
     51	HI6421_LDO5,
     52	HI6421_LDO6,
     53	HI6421_LDO7,
     54	HI6421_LDO8,
     55	HI6421_LDO9,
     56	HI6421_LDO10,
     57	HI6421_LDO11,
     58	HI6421_LDO12,
     59	HI6421_LDO13,
     60	HI6421_LDO14,
     61	HI6421_LDO15,
     62	HI6421_LDO16,
     63	HI6421_LDO17,
     64	HI6421_LDO18,
     65	HI6421_LDO19,
     66	HI6421_LDO20,
     67	HI6421_LDOAUDIO,
     68	HI6421_BUCK0,
     69	HI6421_BUCK1,
     70	HI6421_BUCK2,
     71	HI6421_BUCK3,
     72	HI6421_BUCK4,
     73	HI6421_BUCK5,
     74	HI6421_NUM_REGULATORS,
     75};
     76
     77/* LDO 0, 4~7, 9~14, 16~20 have same voltage table. */
     78static const unsigned int ldo_0_voltages[] = {
     79	1500000, 1800000, 2400000, 2500000,
     80	2600000, 2700000, 2850000, 3000000,
     81};
     82
     83/* LDO 8, 15 have same voltage table. */
     84static const unsigned int ldo_8_voltages[] = {
     85	1500000, 1800000, 2400000, 2600000,
     86	2700000, 2850000, 3000000, 3300000,
     87};
     88
     89/* Ranges are sorted in ascending order. */
     90static const struct linear_range ldo_audio_volt_range[] = {
     91	REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000),
     92	REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000),
     93};
     94
     95static const unsigned int buck_3_voltages[] = {
     96	 950000, 1050000, 1100000, 1117000,
     97	1134000, 1150000, 1167000, 1200000,
     98};
     99
    100static const unsigned int buck_4_voltages[] = {
    101	1150000, 1200000, 1250000, 1350000,
    102	1700000, 1800000, 1900000, 2000000,
    103};
    104
    105static const unsigned int buck_5_voltages[] = {
    106	1150000, 1200000, 1250000, 1350000,
    107	1600000, 1700000, 1800000, 1900000,
    108};
    109
    110static const struct regulator_ops hi6421_ldo_ops;
    111static const struct regulator_ops hi6421_ldo_linear_ops;
    112static const struct regulator_ops hi6421_ldo_linear_range_ops;
    113static const struct regulator_ops hi6421_buck012_ops;
    114static const struct regulator_ops hi6421_buck345_ops;
    115
    116#define HI6421_LDO_ENABLE_TIME (350)
    117/*
    118 * _id - LDO id name string
    119 * _match - of match name string
    120 * v_table - voltage table
    121 * vreg - voltage select register
    122 * vmask - voltage select mask
    123 * ereg - enable register
    124 * emask - enable mask
    125 * odelay - off/on delay time in uS
    126 * ecomask - eco mode mask
    127 * ecoamp - eco mode load uppler limit in uA
    128 */
    129#define HI6421_LDO(_id, _match, v_table, vreg, vmask, ereg, emask,	\
    130		   odelay, ecomask, ecoamp)				\
    131	[HI6421_##_id] = {						\
    132		.desc = {						\
    133			.name		= #_id,				\
    134			.of_match        = of_match_ptr(#_match),	\
    135			.regulators_node = of_match_ptr("regulators"),	\
    136			.ops		= &hi6421_ldo_ops,		\
    137			.type		= REGULATOR_VOLTAGE,		\
    138			.id		= HI6421_##_id,			\
    139			.owner		= THIS_MODULE,			\
    140			.n_voltages	= ARRAY_SIZE(v_table),		\
    141			.volt_table	= v_table,			\
    142			.vsel_reg	= HI6421_REG_TO_BUS_ADDR(vreg),	\
    143			.vsel_mask	= vmask,			\
    144			.enable_reg	= HI6421_REG_TO_BUS_ADDR(ereg),	\
    145			.enable_mask	= emask,			\
    146			.enable_time	= HI6421_LDO_ENABLE_TIME,	\
    147			.off_on_delay	= odelay,			\
    148		},							\
    149		.mode_mask		= ecomask,			\
    150		.eco_microamp		= ecoamp,			\
    151	}
    152
    153/* HI6421 LDO1~3 are linear voltage regulators at fixed uV_step
    154 *
    155 * _id - LDO id name string
    156 * _match - of match name string
    157 * _min_uV - minimum voltage supported in uV
    158 * n_volt - number of votages available
    159 * vstep - voltage increase in each linear step in uV
    160 * vreg - voltage select register
    161 * vmask - voltage select mask
    162 * ereg - enable register
    163 * emask - enable mask
    164 * odelay - off/on delay time in uS
    165 * ecomask - eco mode mask
    166 * ecoamp - eco mode load uppler limit in uA
    167 */
    168#define HI6421_LDO_LINEAR(_id, _match, _min_uV, n_volt, vstep, vreg, vmask,\
    169			  ereg, emask, odelay, ecomask, ecoamp)		\
    170	[HI6421_##_id] = {						\
    171		.desc = {						\
    172			.name		= #_id,				\
    173			.of_match        = of_match_ptr(#_match),	\
    174			.regulators_node = of_match_ptr("regulators"),	\
    175			.ops		= &hi6421_ldo_linear_ops,	\
    176			.type		= REGULATOR_VOLTAGE,		\
    177			.id		= HI6421_##_id,			\
    178			.owner		= THIS_MODULE,			\
    179			.min_uV		= _min_uV,			\
    180			.n_voltages	= n_volt,			\
    181			.uV_step	= vstep,			\
    182			.vsel_reg	= HI6421_REG_TO_BUS_ADDR(vreg),	\
    183			.vsel_mask	= vmask,			\
    184			.enable_reg	= HI6421_REG_TO_BUS_ADDR(ereg),	\
    185			.enable_mask	= emask,			\
    186			.enable_time	= HI6421_LDO_ENABLE_TIME,	\
    187			.off_on_delay	= odelay,			\
    188		},							\
    189		.mode_mask		= ecomask,			\
    190		.eco_microamp		= ecoamp,			\
    191	}
    192
    193/* HI6421 LDOAUDIO is a linear voltage regulator with two 4-step ranges
    194 *
    195 * _id - LDO id name string
    196 * _match - of match name string
    197 * n_volt - number of votages available
    198 * volt_ranges - array of linear_range
    199 * vstep - voltage increase in each linear step in uV
    200 * vreg - voltage select register
    201 * vmask - voltage select mask
    202 * ereg - enable register
    203 * emask - enable mask
    204 * odelay - off/on delay time in uS
    205 * ecomask - eco mode mask
    206 * ecoamp - eco mode load uppler limit in uA
    207 */
    208#define HI6421_LDO_LINEAR_RANGE(_id, _match, n_volt, volt_ranges, vreg, vmask,\
    209				ereg, emask, odelay, ecomask, ecoamp)	\
    210	[HI6421_##_id] = {						\
    211		.desc = {						\
    212			.name		= #_id,				\
    213			.of_match        = of_match_ptr(#_match),	\
    214			.regulators_node = of_match_ptr("regulators"),	\
    215			.ops		= &hi6421_ldo_linear_range_ops,	\
    216			.type		= REGULATOR_VOLTAGE,		\
    217			.id		= HI6421_##_id,			\
    218			.owner		= THIS_MODULE,			\
    219			.n_voltages	= n_volt,			\
    220			.linear_ranges	= volt_ranges,			\
    221			.n_linear_ranges = ARRAY_SIZE(volt_ranges),	\
    222			.vsel_reg	= HI6421_REG_TO_BUS_ADDR(vreg),	\
    223			.vsel_mask	= vmask,			\
    224			.enable_reg	= HI6421_REG_TO_BUS_ADDR(ereg),	\
    225			.enable_mask	= emask,			\
    226			.enable_time	= HI6421_LDO_ENABLE_TIME,	\
    227			.off_on_delay	= odelay,			\
    228		},							\
    229		.mode_mask		= ecomask,			\
    230		.eco_microamp		= ecoamp,			\
    231	}
    232
    233/* HI6421 BUCK0/1/2 are linear voltage regulators at fixed uV_step
    234 *
    235 * _id - BUCK0/1/2 id name string
    236 * _match - of match name string
    237 * vreg - voltage select register
    238 * vmask - voltage select mask
    239 * ereg - enable register
    240 * emask - enable mask
    241 * sleepmask - mask of sleep mode
    242 * etime - enable time
    243 * odelay - off/on delay time in uS
    244 */
    245#define HI6421_BUCK012(_id, _match, vreg, vmask, ereg, emask, sleepmask,\
    246			etime, odelay)					\
    247	[HI6421_##_id] = {						\
    248		.desc = {						\
    249			.name		= #_id,				\
    250			.of_match        = of_match_ptr(#_match),	\
    251			.regulators_node = of_match_ptr("regulators"),	\
    252			.ops		= &hi6421_buck012_ops,		\
    253			.type		= REGULATOR_VOLTAGE,		\
    254			.id		= HI6421_##_id,			\
    255			.owner		= THIS_MODULE,			\
    256			.min_uV		= 700000,			\
    257			.n_voltages	= 128,				\
    258			.uV_step	= 7086,				\
    259			.vsel_reg	= HI6421_REG_TO_BUS_ADDR(vreg),	\
    260			.vsel_mask	= vmask,			\
    261			.enable_reg	= HI6421_REG_TO_BUS_ADDR(ereg),	\
    262			.enable_mask	= emask,			\
    263			.enable_time	= etime,			\
    264			.off_on_delay	= odelay,			\
    265		},							\
    266		.mode_mask		= sleepmask,			\
    267	}
    268
    269/* HI6421 BUCK3/4/5 share similar configurations as LDOs, with exception
    270 *  that it supports SLEEP mode, so has different .ops.
    271 *
    272 * _id - LDO id name string
    273 * _match - of match name string
    274 * v_table - voltage table
    275 * vreg - voltage select register
    276 * vmask - voltage select mask
    277 * ereg - enable register
    278 * emask - enable mask
    279 * odelay - off/on delay time in uS
    280 * sleepmask - mask of sleep mode
    281 */
    282#define HI6421_BUCK345(_id, _match, v_table, vreg, vmask, ereg, emask,	\
    283			odelay, sleepmask)				\
    284	[HI6421_##_id] = {						\
    285		.desc = {						\
    286			.name		= #_id,				\
    287			.of_match        = of_match_ptr(#_match),	\
    288			.regulators_node = of_match_ptr("regulators"),	\
    289			.ops		= &hi6421_buck345_ops,		\
    290			.type		= REGULATOR_VOLTAGE,		\
    291			.id		= HI6421_##_id,			\
    292			.owner		= THIS_MODULE,			\
    293			.n_voltages	= ARRAY_SIZE(v_table),		\
    294			.volt_table	= v_table,			\
    295			.vsel_reg	= HI6421_REG_TO_BUS_ADDR(vreg),	\
    296			.vsel_mask	= vmask,			\
    297			.enable_reg	= HI6421_REG_TO_BUS_ADDR(ereg),	\
    298			.enable_mask	= emask,			\
    299			.enable_time	= HI6421_LDO_ENABLE_TIME,	\
    300			.off_on_delay	= odelay,			\
    301		},							\
    302		.mode_mask		= sleepmask,			\
    303	}
    304
    305/* HI6421 regulator information */
    306static struct hi6421_regulator_info
    307		hi6421_regulator_info[HI6421_NUM_REGULATORS] = {
    308	HI6421_LDO(LDO0, hi6421_vout0, ldo_0_voltages, 0x20, 0x07, 0x20, 0x10,
    309		   10000, 0x20, 8000),
    310	HI6421_LDO_LINEAR(LDO1, hi6421_vout1, 1700000, 4, 100000, 0x21, 0x03,
    311			  0x21, 0x10, 10000, 0x20, 5000),
    312	HI6421_LDO_LINEAR(LDO2, hi6421_vout2, 1050000, 8, 50000, 0x22, 0x07,
    313			  0x22, 0x10, 20000, 0x20, 8000),
    314	HI6421_LDO_LINEAR(LDO3, hi6421_vout3, 1050000, 8, 50000, 0x23, 0x07,
    315			  0x23, 0x10, 20000, 0x20, 8000),
    316	HI6421_LDO(LDO4, hi6421_vout4, ldo_0_voltages, 0x24, 0x07, 0x24, 0x10,
    317		   20000, 0x20, 8000),
    318	HI6421_LDO(LDO5, hi6421_vout5, ldo_0_voltages, 0x25, 0x07, 0x25, 0x10,
    319		   20000, 0x20, 8000),
    320	HI6421_LDO(LDO6, hi6421_vout6, ldo_0_voltages, 0x26, 0x07, 0x26, 0x10,
    321		   20000, 0x20, 8000),
    322	HI6421_LDO(LDO7, hi6421_vout7, ldo_0_voltages, 0x27, 0x07, 0x27, 0x10,
    323		   20000, 0x20, 5000),
    324	HI6421_LDO(LDO8, hi6421_vout8, ldo_8_voltages, 0x28, 0x07, 0x28, 0x10,
    325		   20000, 0x20, 8000),
    326	HI6421_LDO(LDO9, hi6421_vout9, ldo_0_voltages, 0x29, 0x07, 0x29, 0x10,
    327		   40000, 0x20, 8000),
    328	HI6421_LDO(LDO10, hi6421_vout10, ldo_0_voltages, 0x2a, 0x07, 0x2a, 0x10,
    329		   40000, 0x20, 8000),
    330	HI6421_LDO(LDO11, hi6421_vout11, ldo_0_voltages, 0x2b, 0x07, 0x2b, 0x10,
    331		   40000, 0x20, 8000),
    332	HI6421_LDO(LDO12, hi6421_vout12, ldo_0_voltages, 0x2c, 0x07, 0x2c, 0x10,
    333		   40000, 0x20, 8000),
    334	HI6421_LDO(LDO13, hi6421_vout13, ldo_0_voltages, 0x2d, 0x07, 0x2d, 0x10,
    335		   40000, 0x20, 8000),
    336	HI6421_LDO(LDO14, hi6421_vout14, ldo_0_voltages, 0x2e, 0x07, 0x2e, 0x10,
    337		   40000, 0x20, 8000),
    338	HI6421_LDO(LDO15, hi6421_vout15, ldo_8_voltages, 0x2f, 0x07, 0x2f, 0x10,
    339		   40000, 0x20, 8000),
    340	HI6421_LDO(LDO16, hi6421_vout16, ldo_0_voltages, 0x30, 0x07, 0x30, 0x10,
    341		   40000, 0x20, 8000),
    342	HI6421_LDO(LDO17, hi6421_vout17, ldo_0_voltages, 0x31, 0x07, 0x31, 0x10,
    343		   40000, 0x20, 8000),
    344	HI6421_LDO(LDO18, hi6421_vout18, ldo_0_voltages, 0x32, 0x07, 0x32, 0x10,
    345		   40000, 0x20, 8000),
    346	HI6421_LDO(LDO19, hi6421_vout19, ldo_0_voltages, 0x33, 0x07, 0x33, 0x10,
    347		   40000, 0x20, 8000),
    348	HI6421_LDO(LDO20, hi6421_vout20, ldo_0_voltages, 0x34, 0x07, 0x34, 0x10,
    349		   40000, 0x20, 8000),
    350	HI6421_LDO_LINEAR_RANGE(LDOAUDIO, hi6421_vout_audio, 8,
    351				ldo_audio_volt_range, 0x36, 0x70, 0x36, 0x01,
    352				40000, 0x02, 5000),
    353	HI6421_BUCK012(BUCK0, hi6421_buck0, 0x0d, 0x7f, 0x0c, 0x01, 0x10, 400,
    354		       20000),
    355	HI6421_BUCK012(BUCK1, hi6421_buck1, 0x0f, 0x7f, 0x0e, 0x01, 0x10, 400,
    356		       20000),
    357	HI6421_BUCK012(BUCK2, hi6421_buck2, 0x11, 0x7f, 0x10, 0x01, 0x10, 350,
    358		       100),
    359	HI6421_BUCK345(BUCK3, hi6421_buck3, buck_3_voltages, 0x13, 0x07, 0x12,
    360		       0x01, 20000, 0x10),
    361	HI6421_BUCK345(BUCK4, hi6421_buck4, buck_4_voltages, 0x15, 0x07, 0x14,
    362		       0x01, 20000, 0x10),
    363	HI6421_BUCK345(BUCK5, hi6421_buck5, buck_5_voltages, 0x17, 0x07, 0x16,
    364		       0x01, 20000, 0x10),
    365};
    366
    367static int hi6421_regulator_enable(struct regulator_dev *rdev)
    368{
    369	struct hi6421_regulator_pdata *pdata = rdev_get_drvdata(rdev);
    370
    371	/* hi6421 spec requires regulator enablement must be serialized:
    372	 *  - Because when BUCK, LDO switching from off to on, it will have
    373	 *    a huge instantaneous current; so you can not turn on two or
    374	 *    more LDO or BUCKs simultaneously, or it may burn the chip.
    375	 */
    376	mutex_lock(&pdata->lock);
    377
    378	/* call regulator regmap helper */
    379	regulator_enable_regmap(rdev);
    380
    381	mutex_unlock(&pdata->lock);
    382	return 0;
    383}
    384
    385static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev)
    386{
    387	struct hi6421_regulator_info *info;
    388	unsigned int reg_val;
    389
    390	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
    391	regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
    392	if (reg_val & info->mode_mask)
    393		return REGULATOR_MODE_IDLE;
    394
    395	return REGULATOR_MODE_NORMAL;
    396}
    397
    398static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev)
    399{
    400	struct hi6421_regulator_info *info;
    401	unsigned int reg_val;
    402
    403	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
    404	regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
    405	if (reg_val & info->mode_mask)
    406		return REGULATOR_MODE_STANDBY;
    407
    408	return REGULATOR_MODE_NORMAL;
    409}
    410
    411static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev,
    412						unsigned int mode)
    413{
    414	struct hi6421_regulator_info *info;
    415	unsigned int new_mode;
    416
    417	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
    418	switch (mode) {
    419	case REGULATOR_MODE_NORMAL:
    420		new_mode = 0;
    421		break;
    422	case REGULATOR_MODE_IDLE:
    423		new_mode = info->mode_mask;
    424		break;
    425	default:
    426		return -EINVAL;
    427	}
    428
    429	/* set mode */
    430	regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
    431			   info->mode_mask, new_mode);
    432
    433	return 0;
    434}
    435
    436static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
    437						unsigned int mode)
    438{
    439	struct hi6421_regulator_info *info;
    440	unsigned int new_mode;
    441
    442	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
    443	switch (mode) {
    444	case REGULATOR_MODE_NORMAL:
    445		new_mode = 0;
    446		break;
    447	case REGULATOR_MODE_STANDBY:
    448		new_mode = info->mode_mask;
    449		break;
    450	default:
    451		return -EINVAL;
    452	}
    453
    454	/* set mode */
    455	regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
    456			   info->mode_mask, new_mode);
    457
    458	return 0;
    459}
    460
    461static unsigned int
    462hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
    463			int input_uV, int output_uV, int load_uA)
    464{
    465	struct hi6421_regulator_info *info;
    466
    467	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
    468
    469	if (load_uA > info->eco_microamp)
    470		return REGULATOR_MODE_NORMAL;
    471
    472	return REGULATOR_MODE_IDLE;
    473}
    474
    475static const struct regulator_ops hi6421_ldo_ops = {
    476	.is_enabled = regulator_is_enabled_regmap,
    477	.enable = hi6421_regulator_enable,
    478	.disable = regulator_disable_regmap,
    479	.list_voltage = regulator_list_voltage_table,
    480	.map_voltage = regulator_map_voltage_ascend,
    481	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    482	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    483	.get_mode = hi6421_regulator_ldo_get_mode,
    484	.set_mode = hi6421_regulator_ldo_set_mode,
    485	.get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
    486};
    487
    488static const struct regulator_ops hi6421_ldo_linear_ops = {
    489	.is_enabled = regulator_is_enabled_regmap,
    490	.enable = hi6421_regulator_enable,
    491	.disable = regulator_disable_regmap,
    492	.list_voltage = regulator_list_voltage_linear,
    493	.map_voltage = regulator_map_voltage_linear,
    494	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    495	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    496	.get_mode = hi6421_regulator_ldo_get_mode,
    497	.set_mode = hi6421_regulator_ldo_set_mode,
    498	.get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
    499};
    500
    501static const struct regulator_ops hi6421_ldo_linear_range_ops = {
    502	.is_enabled = regulator_is_enabled_regmap,
    503	.enable = hi6421_regulator_enable,
    504	.disable = regulator_disable_regmap,
    505	.list_voltage = regulator_list_voltage_linear_range,
    506	.map_voltage = regulator_map_voltage_linear_range,
    507	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    508	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    509	.get_mode = hi6421_regulator_ldo_get_mode,
    510	.set_mode = hi6421_regulator_ldo_set_mode,
    511	.get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
    512};
    513
    514static const struct regulator_ops hi6421_buck012_ops = {
    515	.is_enabled = regulator_is_enabled_regmap,
    516	.enable = hi6421_regulator_enable,
    517	.disable = regulator_disable_regmap,
    518	.list_voltage = regulator_list_voltage_linear,
    519	.map_voltage = regulator_map_voltage_linear,
    520	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    521	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    522	.get_mode = hi6421_regulator_buck_get_mode,
    523	.set_mode = hi6421_regulator_buck_set_mode,
    524};
    525
    526static const struct regulator_ops hi6421_buck345_ops = {
    527	.is_enabled = regulator_is_enabled_regmap,
    528	.enable = hi6421_regulator_enable,
    529	.disable = regulator_disable_regmap,
    530	.list_voltage = regulator_list_voltage_table,
    531	.map_voltage = regulator_map_voltage_ascend,
    532	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    533	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    534	.get_mode = hi6421_regulator_buck_get_mode,
    535	.set_mode = hi6421_regulator_buck_set_mode,
    536};
    537
    538static int hi6421_regulator_probe(struct platform_device *pdev)
    539{
    540	struct hi6421_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
    541	struct hi6421_regulator_pdata *pdata;
    542	struct hi6421_regulator_info *info;
    543	struct regulator_config config = { };
    544	struct regulator_dev *rdev;
    545	int i;
    546
    547	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
    548	if (!pdata)
    549		return -ENOMEM;
    550	mutex_init(&pdata->lock);
    551
    552	for (i = 0; i < ARRAY_SIZE(hi6421_regulator_info); i++) {
    553		/* assign per-regulator data */
    554		info = &hi6421_regulator_info[i];
    555
    556		config.dev = pdev->dev.parent;
    557		config.driver_data = pdata;
    558		config.regmap = pmic->regmap;
    559
    560		rdev = devm_regulator_register(&pdev->dev, &info->desc,
    561					       &config);
    562		if (IS_ERR(rdev)) {
    563			dev_err(&pdev->dev, "failed to register regulator %s\n",
    564				info->desc.name);
    565			return PTR_ERR(rdev);
    566		}
    567	}
    568
    569	return 0;
    570}
    571
    572static const struct platform_device_id hi6421_regulator_table[] = {
    573	{ .name = "hi6421-regulator" },
    574	{},
    575};
    576MODULE_DEVICE_TABLE(platform, hi6421_regulator_table);
    577
    578static struct platform_driver hi6421_regulator_driver = {
    579	.id_table = hi6421_regulator_table,
    580	.driver = {
    581		.name	= "hi6421-regulator",
    582	},
    583	.probe	= hi6421_regulator_probe,
    584};
    585module_platform_driver(hi6421_regulator_driver);
    586
    587MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>");
    588MODULE_DESCRIPTION("Hi6421 regulator driver");
    589MODULE_LICENSE("GPL v2");