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

pf8x00-regulator.c (17182B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2017 NXP
      4 * Copyright (C) 2019 Boundary Devices
      5 * Copyright (C) 2020 Amarula Solutions(India)
      6 */
      7
      8#include <linux/delay.h>
      9#include <linux/err.h>
     10#include <linux/gpio/consumer.h>
     11#include <linux/i2c.h>
     12#include <linux/module.h>
     13#include <linux/regmap.h>
     14#include <linux/regulator/driver.h>
     15#include <linux/regulator/machine.h>
     16
     17/* registers */
     18#define PF8X00_DEVICEID			0x00
     19#define PF8X00_REVID			0x01
     20#define PF8X00_EMREV			0x02
     21#define PF8X00_PROGID			0x03
     22#define PF8X00_IMS_INT			0x04
     23#define PF8X00_IMS_THERM		0x07
     24#define PF8X00_SW_MODE_INT		0x0a
     25#define PF8X00_SW_MODE_MASK		0x0b
     26#define PF8X00_IMS_SW_ILIM		0x12
     27#define PF8X00_IMS_LDO_ILIM		0x15
     28#define PF8X00_IMS_SW_UV		0x18
     29#define PF8X00_IMS_SW_OV		0x1b
     30#define PF8X00_IMS_LDO_UV		0x1e
     31#define PF8X00_IMS_LDO_OV		0x21
     32#define PF8X00_IMS_PWRON		0x24
     33#define PF8X00_SYS_INT			0x27
     34#define PF8X00_HARD_FAULT		0x29
     35#define PF8X00_FSOB_FLAGS		0x2a
     36#define PF8X00_FSOB_SELECT		0x2b
     37#define PF8X00_ABIST_OV1		0x2c
     38#define PF8X00_ABIST_OV2		0x2d
     39#define PF8X00_ABIST_UV1		0x2e
     40#define PF8X00_ABIST_UV2		0x2f
     41#define PF8X00_TEST_FLAGS		0x30
     42#define PF8X00_ABIST_RUN		0x31
     43#define PF8X00_RANDOM_GEN		0x33
     44#define PF8X00_RANDOM_CHK		0x34
     45#define PF8X00_VMONEN1			0x35
     46#define PF8X00_VMONEN2			0x36
     47#define PF8X00_CTRL1			0x37
     48#define PF8X00_CTRL2			0x38
     49#define PF8X00_CTRL3			0x39
     50#define PF8X00_PWRUP_CTRL		0x3a
     51#define PF8X00_RESETBMCU		0x3c
     52#define PF8X00_PGOOD			0x3d
     53#define PF8X00_PWRDN_DLY1		0x3e
     54#define PF8X00_PWRDN_DLY2		0x3f
     55#define PF8X00_FREQ_CTRL		0x40
     56#define PF8X00_COINCELL_CTRL		0x41
     57#define PF8X00_PWRON			0x42
     58#define PF8X00_WD_CONFIG		0x43
     59#define PF8X00_WD_CLEAR			0x44
     60#define PF8X00_WD_EXPIRE		0x45
     61#define PF8X00_WD_COUNTER		0x46
     62#define PF8X00_FAULT_COUNTER		0x47
     63#define PF8X00_FSAFE_COUNTER		0x48
     64#define PF8X00_FAULT_TIMER		0x49
     65#define PF8X00_AMUX			0x4a
     66#define PF8X00_SW1_CONFIG1		0x4d
     67#define PF8X00_LDO1_CONFIG1		0x85
     68#define PF8X00_VSNVS_CONFIG1		0x9d
     69#define PF8X00_PAGE_SELECT		0x9f
     70
     71/* regulators */
     72enum pf8x00_regulators {
     73	PF8X00_LDO1,
     74	PF8X00_LDO2,
     75	PF8X00_LDO3,
     76	PF8X00_LDO4,
     77	PF8X00_BUCK1,
     78	PF8X00_BUCK2,
     79	PF8X00_BUCK3,
     80	PF8X00_BUCK4,
     81	PF8X00_BUCK5,
     82	PF8X00_BUCK6,
     83	PF8X00_BUCK7,
     84	PF8X00_VSNVS,
     85
     86	PF8X00_MAX_REGULATORS,
     87};
     88
     89enum pf8x00_buck_states {
     90	SW_CONFIG1,
     91	SW_CONFIG2,
     92	SW_PWRUP,
     93	SW_MODE1,
     94	SW_RUN_VOLT,
     95	SW_STBY_VOLT,
     96};
     97#define PF8X00_SW_BASE(i)		(8 * (i - PF8X00_BUCK1) + PF8X00_SW1_CONFIG1)
     98
     99enum pf8x00_ldo_states {
    100	LDO_CONFIG1,
    101	LDO_CONFIG2,
    102	LDO_PWRUP,
    103	LDO_RUN_VOLT,
    104	LDO_STBY_VOLT,
    105};
    106#define PF8X00_LDO_BASE(i)		(6 * (i - PF8X00_LDO1) + PF8X00_LDO1_CONFIG1)
    107
    108enum swxilim_bits {
    109	SWXILIM_2100_MA,
    110	SWXILIM_2600_MA,
    111	SWXILIM_3000_MA,
    112	SWXILIM_4500_MA,
    113};
    114#define PF8X00_SWXILIM_SHIFT		3
    115#define PF8X00_SWXILIM_MASK		GENMASK(4, 3)
    116#define PF8X00_SWXPHASE_MASK		GENMASK(2, 0)
    117#define PF8X00_SWXPHASE_SHIFT		7
    118
    119enum pf8x00_devid {
    120	PF8100			= 0x0,
    121	PF8121A			= BIT(1),
    122	PF8200			= BIT(3),
    123};
    124#define PF8X00_FAM			BIT(6)
    125#define PF8X00_DEVICE_FAM_MASK		GENMASK(7, 4)
    126#define PF8X00_DEVICE_ID_MASK		GENMASK(3, 0)
    127
    128struct pf8x00_regulator_data {
    129	struct regulator_desc desc;
    130	unsigned int suspend_enable_reg;
    131	unsigned int suspend_enable_mask;
    132	unsigned int suspend_voltage_reg;
    133	unsigned int suspend_voltage_cache;
    134};
    135
    136struct pf8x00_chip {
    137	struct regmap *regmap;
    138	struct device *dev;
    139};
    140
    141static const struct regmap_config pf8x00_regmap_config = {
    142	.reg_bits = 8,
    143	.val_bits = 8,
    144	.max_register = PF8X00_PAGE_SELECT,
    145	.cache_type = REGCACHE_RBTREE,
    146};
    147
    148/* VLDOx output: 1.5V to 5.0V */
    149static const int pf8x00_ldo_voltages[] = {
    150	1500000, 1600000, 1800000, 1850000, 2150000, 2500000, 2800000, 3000000,
    151	3100000, 3150000, 3200000, 3300000, 3350000, 1650000, 1700000, 5000000,
    152};
    153
    154/* Output: 2.1A to 4.5A */
    155static const unsigned int pf8x00_sw_current_table[] = {
    156	2100000, 2600000, 3000000, 4500000,
    157};
    158
    159/* Output: 0.4V to 1.8V */
    160#define PF8XOO_SW1_6_VOLTAGE_NUM 0xB2
    161static const struct linear_range pf8x00_sw1_to_6_voltages[] = {
    162	REGULATOR_LINEAR_RANGE(400000, 0x00, 0xB0, 6250),
    163	REGULATOR_LINEAR_RANGE(1800000, 0xB1, 0xB1, 0),
    164};
    165
    166/* Output: 1.0V to 4.1V */
    167static const int pf8x00_sw7_voltages[] = {
    168	1000000, 1100000, 1200000, 1250000, 1300000, 1350000, 1500000, 1600000,
    169	1800000, 1850000, 2000000, 2100000, 2150000, 2250000, 2300000, 2400000,
    170	2500000, 2800000, 3150000, 3200000, 3250000, 3300000, 3350000, 3400000,
    171	3500000, 3800000, 4000000, 4100000, 4100000, 4100000, 4100000, 4100000,
    172};
    173
    174/* Output: 1.8V, 3.0V, or 3.3V */
    175static const int pf8x00_vsnvs_voltages[] = {
    176	0, 1800000, 3000000, 3300000,
    177};
    178
    179static void swxilim_select(struct pf8x00_chip *chip, int id, int ilim)
    180{
    181	u8 ilim_sel;
    182	u8 reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
    183
    184	switch (ilim) {
    185	case 2100:
    186		ilim_sel = SWXILIM_2100_MA;
    187		break;
    188	case 2600:
    189		ilim_sel = SWXILIM_2600_MA;
    190		break;
    191	case 3000:
    192		ilim_sel = SWXILIM_3000_MA;
    193		break;
    194	case 4500:
    195		ilim_sel = SWXILIM_4500_MA;
    196		break;
    197	default:
    198		ilim_sel = SWXILIM_2100_MA;
    199		break;
    200	}
    201
    202	regmap_update_bits(chip->regmap, reg,
    203					PF8X00_SWXILIM_MASK,
    204					ilim_sel << PF8X00_SWXILIM_SHIFT);
    205}
    206
    207static void handle_ilim_property(struct device_node *np,
    208			      const struct regulator_desc *desc,
    209			      struct regulator_config *config)
    210{
    211	struct pf8x00_chip *chip = config->driver_data;
    212	int ret;
    213	int val;
    214
    215	if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
    216		ret = of_property_read_u32(np, "nxp,ilim-ma", &val);
    217		if (ret) {
    218			dev_dbg(chip->dev, "unspecified ilim for BUCK%d, use value stored in OTP\n",
    219				desc->id - PF8X00_LDO4);
    220			return;
    221		}
    222
    223		dev_warn(chip->dev, "nxp,ilim-ma is deprecated, please use regulator-max-microamp\n");
    224		swxilim_select(chip, desc->id, val);
    225
    226	} else
    227		dev_warn(chip->dev, "nxp,ilim-ma used with incorrect regulator (%d)\n", desc->id);
    228}
    229
    230static void handle_shift_property(struct device_node *np,
    231			      const struct regulator_desc *desc,
    232			      struct regulator_config *config)
    233{
    234	unsigned char id = desc->id - PF8X00_LDO4;
    235	unsigned char reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
    236	struct pf8x00_chip *chip = config->driver_data;
    237
    238	int phase;
    239	int val;
    240	int ret;
    241	if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
    242		ret = of_property_read_u32(np, "nxp,phase-shift", &val);
    243		if (ret) {
    244			dev_dbg(chip->dev,
    245				"unspecified phase-shift for BUCK%d, using OTP configuration\n",
    246				id);
    247			return;
    248		}
    249
    250		if (val < 0 || val > 315 || val % 45 != 0) {
    251			dev_warn(config->dev,
    252				"invalid phase_shift %d for BUCK%d, using OTP configuration\n",
    253				val, id);
    254			return;
    255		}
    256
    257		phase = val / 45;
    258
    259		if (phase >= 1)
    260			phase -= 1;
    261		else
    262			phase = PF8X00_SWXPHASE_SHIFT;
    263
    264		regmap_update_bits(chip->regmap, reg,
    265				PF8X00_SWXPHASE_MASK,
    266				phase);
    267	} else
    268		dev_warn(chip->dev, "nxp,phase-shift used with incorrect regulator (%d)\n", id);
    269
    270}
    271
    272static int pf8x00_of_parse_cb(struct device_node *np,
    273			      const struct regulator_desc *desc,
    274			      struct regulator_config *config)
    275{
    276
    277	handle_ilim_property(np, desc, config);
    278	handle_shift_property(np, desc, config);
    279
    280	return 0;
    281}
    282
    283static int pf8x00_suspend_enable(struct regulator_dev *rdev)
    284{
    285	struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
    286	struct regmap *rmap = rdev_get_regmap(rdev);
    287
    288	return regmap_update_bits(rmap, regl->suspend_enable_reg,
    289				  regl->suspend_enable_mask,
    290				  regl->suspend_enable_mask);
    291}
    292
    293static int pf8x00_suspend_disable(struct regulator_dev *rdev)
    294{
    295	struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
    296	struct regmap *rmap = rdev_get_regmap(rdev);
    297
    298	return regmap_update_bits(rmap, regl->suspend_enable_reg,
    299				  regl->suspend_enable_mask, 0);
    300}
    301
    302static int pf8x00_set_suspend_voltage(struct regulator_dev *rdev, int uV)
    303{
    304	struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
    305	int ret;
    306
    307	if (regl->suspend_voltage_cache == uV)
    308		return 0;
    309
    310	ret = regulator_map_voltage_iterate(rdev, uV, uV);
    311	if (ret < 0) {
    312		dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
    313		return ret;
    314	}
    315
    316	dev_dbg(rdev_get_dev(rdev), "uV: %i, reg: 0x%x, msk: 0x%x, val: 0x%x\n",
    317		uV, regl->suspend_voltage_reg, regl->desc.vsel_mask, ret);
    318	ret = regmap_update_bits(rdev->regmap, regl->suspend_voltage_reg,
    319				 regl->desc.vsel_mask, ret);
    320	if (ret < 0) {
    321		dev_err(rdev_get_dev(rdev), "failed to set %i uV\n", uV);
    322		return ret;
    323	}
    324
    325	regl->suspend_voltage_cache = uV;
    326
    327	return 0;
    328}
    329
    330static const struct regulator_ops pf8x00_ldo_ops = {
    331	.enable = regulator_enable_regmap,
    332	.disable = regulator_disable_regmap,
    333	.is_enabled = regulator_is_enabled_regmap,
    334	.list_voltage = regulator_list_voltage_table,
    335	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    336	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    337	.set_suspend_enable = pf8x00_suspend_enable,
    338	.set_suspend_disable = pf8x00_suspend_disable,
    339	.set_suspend_voltage = pf8x00_set_suspend_voltage,
    340};
    341
    342
    343static const struct regulator_ops pf8x00_buck1_6_ops = {
    344	.enable = regulator_enable_regmap,
    345	.disable = regulator_disable_regmap,
    346	.is_enabled = regulator_is_enabled_regmap,
    347	.list_voltage = regulator_list_voltage_linear_range,
    348	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    349	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    350	.get_current_limit = regulator_get_current_limit_regmap,
    351	.set_current_limit = regulator_set_current_limit_regmap,
    352	.set_suspend_enable = pf8x00_suspend_enable,
    353	.set_suspend_disable = pf8x00_suspend_disable,
    354	.set_suspend_voltage = pf8x00_set_suspend_voltage,
    355};
    356
    357static const struct regulator_ops pf8x00_buck7_ops = {
    358	.enable = regulator_enable_regmap,
    359	.disable = regulator_disable_regmap,
    360	.is_enabled = regulator_is_enabled_regmap,
    361	.list_voltage = regulator_list_voltage_table,
    362	.map_voltage = regulator_map_voltage_ascend,
    363	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    364	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    365	.get_current_limit = regulator_get_current_limit_regmap,
    366	.set_current_limit = regulator_set_current_limit_regmap,
    367	.set_suspend_enable = pf8x00_suspend_enable,
    368	.set_suspend_disable = pf8x00_suspend_disable,
    369};
    370
    371static const struct regulator_ops pf8x00_vsnvs_ops = {
    372	.enable = regulator_enable_regmap,
    373	.disable = regulator_disable_regmap,
    374	.is_enabled = regulator_is_enabled_regmap,
    375	.list_voltage = regulator_list_voltage_table,
    376	.map_voltage = regulator_map_voltage_ascend,
    377	.set_voltage_sel = regulator_set_voltage_sel_regmap,
    378	.get_voltage_sel = regulator_get_voltage_sel_regmap,
    379};
    380
    381#define PF8X00LDO(_id, _name, base, voltages)			\
    382	[PF8X00_LDO ## _id] = {					\
    383		.desc = {					\
    384			.name = _name,				\
    385			.of_match = _name,			\
    386			.regulators_node = "regulators",	\
    387			.n_voltages = ARRAY_SIZE(voltages),	\
    388			.ops = &pf8x00_ldo_ops,			\
    389			.type = REGULATOR_VOLTAGE,		\
    390			.id = PF8X00_LDO ## _id,		\
    391			.owner = THIS_MODULE,			\
    392			.volt_table = voltages,			\
    393			.vsel_reg = (base) + LDO_RUN_VOLT,	\
    394			.vsel_mask = 0xff,			\
    395			.enable_reg = (base) + LDO_CONFIG2,	\
    396			.enable_val = 0x2,			\
    397			.disable_val = 0x0,			\
    398			.enable_mask = 2,			\
    399		},						\
    400		.suspend_enable_reg = (base) + LDO_CONFIG2,	\
    401		.suspend_enable_mask = 1,			\
    402		.suspend_voltage_reg = (base) + LDO_STBY_VOLT,	\
    403	}
    404
    405#define PF8X00BUCK(_id, _name, base, voltages)			\
    406	[PF8X00_BUCK ## _id] = {				\
    407		.desc = {					\
    408			.name = _name,				\
    409			.of_match = _name,			\
    410			.regulators_node = "regulators",	\
    411			.of_parse_cb = pf8x00_of_parse_cb,	\
    412			.n_voltages = PF8XOO_SW1_6_VOLTAGE_NUM,	\
    413			.ops = &pf8x00_buck1_6_ops,		\
    414			.type = REGULATOR_VOLTAGE,		\
    415			.id = PF8X00_BUCK ## _id,		\
    416			.owner = THIS_MODULE,			\
    417			.ramp_delay = 19000,			\
    418			.linear_ranges = pf8x00_sw1_to_6_voltages, \
    419			.n_linear_ranges = \
    420				ARRAY_SIZE(pf8x00_sw1_to_6_voltages), \
    421			.vsel_reg = (base) + SW_RUN_VOLT,	\
    422			.vsel_mask = 0xff,			\
    423			.curr_table = pf8x00_sw_current_table, \
    424			.n_current_limits = \
    425				ARRAY_SIZE(pf8x00_sw_current_table), \
    426			.csel_reg = (base) + SW_CONFIG2,	\
    427			.csel_mask = PF8X00_SWXILIM_MASK,	\
    428			.enable_reg = (base) + SW_MODE1,	\
    429			.enable_val = 0x3,			\
    430			.disable_val = 0x0,			\
    431			.enable_mask = 0x3,			\
    432			.enable_time = 500,			\
    433		},						\
    434		.suspend_enable_reg = (base) + SW_MODE1,	\
    435		.suspend_enable_mask = 0xc,			\
    436		.suspend_voltage_reg = (base) + SW_STBY_VOLT,	\
    437	}
    438
    439#define PF8X00BUCK7(_name, base, voltages)			\
    440	[PF8X00_BUCK7] = {				\
    441		.desc = {					\
    442			.name = _name,				\
    443			.of_match = _name,			\
    444			.regulators_node = "regulators",	\
    445			.of_parse_cb = pf8x00_of_parse_cb,	\
    446			.n_voltages = ARRAY_SIZE(voltages),	\
    447			.ops = &pf8x00_buck7_ops,		\
    448			.type = REGULATOR_VOLTAGE,		\
    449			.id = PF8X00_BUCK7,		\
    450			.owner = THIS_MODULE,			\
    451			.ramp_delay = 19000,			\
    452			.volt_table = voltages,			\
    453			.vsel_reg = (base) + SW_RUN_VOLT,	\
    454			.vsel_mask = 0xff,			\
    455			.curr_table = pf8x00_sw_current_table, \
    456			.n_current_limits = \
    457				ARRAY_SIZE(pf8x00_sw_current_table), \
    458			.csel_reg = (base) + SW_CONFIG2,	\
    459			.csel_mask = PF8X00_SWXILIM_MASK,	\
    460			.enable_reg = (base) + SW_MODE1,	\
    461			.enable_val = 0x3,			\
    462			.disable_val = 0x0,			\
    463			.enable_mask = 0x3,			\
    464			.enable_time = 500,			\
    465		},						\
    466	}
    467
    468
    469#define PF8X00VSNVS(_name, base, voltages)			\
    470	[PF8X00_VSNVS] = {					\
    471		.desc = {					\
    472			.name = _name,				\
    473			.of_match = _name,			\
    474			.regulators_node = "regulators",	\
    475			.n_voltages = ARRAY_SIZE(voltages),	\
    476			.ops = &pf8x00_vsnvs_ops,		\
    477			.type = REGULATOR_VOLTAGE,		\
    478			.id = PF8X00_VSNVS,			\
    479			.owner = THIS_MODULE,			\
    480			.volt_table = voltages,			\
    481			.vsel_reg = (base),			\
    482			.vsel_mask = 0x3,			\
    483		},						\
    484	}
    485
    486static struct pf8x00_regulator_data pf8x00_regs_data[PF8X00_MAX_REGULATORS] = {
    487	PF8X00LDO(1, "ldo1", PF8X00_LDO_BASE(PF8X00_LDO1), pf8x00_ldo_voltages),
    488	PF8X00LDO(2, "ldo2", PF8X00_LDO_BASE(PF8X00_LDO2), pf8x00_ldo_voltages),
    489	PF8X00LDO(3, "ldo3", PF8X00_LDO_BASE(PF8X00_LDO3), pf8x00_ldo_voltages),
    490	PF8X00LDO(4, "ldo4", PF8X00_LDO_BASE(PF8X00_LDO4), pf8x00_ldo_voltages),
    491	PF8X00BUCK(1, "buck1", PF8X00_SW_BASE(PF8X00_BUCK1), pf8x00_sw1_to_6_voltages),
    492	PF8X00BUCK(2, "buck2", PF8X00_SW_BASE(PF8X00_BUCK2), pf8x00_sw1_to_6_voltages),
    493	PF8X00BUCK(3, "buck3", PF8X00_SW_BASE(PF8X00_BUCK3), pf8x00_sw1_to_6_voltages),
    494	PF8X00BUCK(4, "buck4", PF8X00_SW_BASE(PF8X00_BUCK4), pf8x00_sw1_to_6_voltages),
    495	PF8X00BUCK(5, "buck5", PF8X00_SW_BASE(PF8X00_BUCK5), pf8x00_sw1_to_6_voltages),
    496	PF8X00BUCK(6, "buck6", PF8X00_SW_BASE(PF8X00_BUCK6), pf8x00_sw1_to_6_voltages),
    497	PF8X00BUCK7("buck7", PF8X00_SW_BASE(PF8X00_BUCK7), pf8x00_sw7_voltages),
    498	PF8X00VSNVS("vsnvs", PF8X00_VSNVS_CONFIG1, pf8x00_vsnvs_voltages),
    499};
    500
    501static int pf8x00_identify(struct pf8x00_chip *chip)
    502{
    503	unsigned int value;
    504	u8 dev_fam, dev_id;
    505	const char *name = NULL;
    506	int ret;
    507
    508	ret = regmap_read(chip->regmap, PF8X00_DEVICEID, &value);
    509	if (ret) {
    510		dev_err(chip->dev, "failed to read chip family\n");
    511		return ret;
    512	}
    513
    514	dev_fam = value & PF8X00_DEVICE_FAM_MASK;
    515	switch (dev_fam) {
    516	case PF8X00_FAM:
    517		break;
    518	default:
    519		dev_err(chip->dev,
    520			"Chip 0x%x is not from PF8X00 family\n", dev_fam);
    521		return ret;
    522	}
    523
    524	dev_id = value & PF8X00_DEVICE_ID_MASK;
    525	switch (dev_id) {
    526	case PF8100:
    527		name = "PF8100";
    528		break;
    529	case PF8121A:
    530		name = "PF8121A";
    531		break;
    532	case PF8200:
    533		name = "PF8200";
    534		break;
    535	default:
    536		dev_err(chip->dev, "Unknown pf8x00 device id 0x%x\n", dev_id);
    537		return -ENODEV;
    538	}
    539
    540	dev_info(chip->dev, "%s PMIC found.\n", name);
    541
    542	return 0;
    543}
    544
    545static int pf8x00_i2c_probe(struct i2c_client *client)
    546{
    547	struct regulator_config config = { NULL, };
    548	struct pf8x00_chip *chip;
    549	int id;
    550	int ret;
    551
    552	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
    553	if (!chip)
    554		return -ENOMEM;
    555
    556	i2c_set_clientdata(client, chip);
    557	chip->dev = &client->dev;
    558
    559	chip->regmap = devm_regmap_init_i2c(client, &pf8x00_regmap_config);
    560	if (IS_ERR(chip->regmap)) {
    561		ret = PTR_ERR(chip->regmap);
    562		dev_err(&client->dev,
    563			"regmap allocation failed with err %d\n", ret);
    564		return ret;
    565	}
    566
    567	ret = pf8x00_identify(chip);
    568	if (ret)
    569		return ret;
    570
    571	for (id = 0; id < ARRAY_SIZE(pf8x00_regs_data); id++) {
    572		struct pf8x00_regulator_data *data = &pf8x00_regs_data[id];
    573		struct regulator_dev *rdev;
    574
    575		config.dev = chip->dev;
    576		config.driver_data = data;
    577		config.regmap = chip->regmap;
    578
    579		rdev = devm_regulator_register(&client->dev, &data->desc, &config);
    580		if (IS_ERR(rdev)) {
    581			dev_err(&client->dev,
    582				"failed to register %s regulator\n", data->desc.name);
    583			return PTR_ERR(rdev);
    584		}
    585	}
    586
    587	return 0;
    588}
    589
    590static const struct of_device_id pf8x00_dt_ids[] = {
    591	{ .compatible = "nxp,pf8100",},
    592	{ .compatible = "nxp,pf8121a",},
    593	{ .compatible = "nxp,pf8200",},
    594	{ }
    595};
    596MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
    597
    598static const struct i2c_device_id pf8x00_i2c_id[] = {
    599	{ "pf8100", 0 },
    600	{ "pf8121a", 0 },
    601	{ "pf8200", 0 },
    602	{},
    603};
    604MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
    605
    606static struct i2c_driver pf8x00_regulator_driver = {
    607	.id_table = pf8x00_i2c_id,
    608	.driver = {
    609		.name = "pf8x00",
    610		.of_match_table = pf8x00_dt_ids,
    611	},
    612	.probe_new = pf8x00_i2c_probe,
    613};
    614module_i2c_driver(pf8x00_regulator_driver);
    615
    616MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
    617MODULE_AUTHOR("Troy Kisky <troy.kisky@boundarydevices.com>");
    618MODULE_DESCRIPTION("Regulator Driver for NXP's PF8100/PF8121A/PF8200 PMIC");
    619MODULE_LICENSE("GPL v2");