162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// MP8867/MP8869 regulator driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (C) 2020 Synaptics Incorporated
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci// Author: Jisheng Zhang <jszhang@kernel.org>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1062306a36Sopenharmony_ci#include <linux/i2c.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/regmap.h>
1462306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1562306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define MP886X_VSEL		0x00
1862306a36Sopenharmony_ci#define  MP886X_V_BOOT		(1 << 7)
1962306a36Sopenharmony_ci#define MP886X_SYSCNTLREG1	0x01
2062306a36Sopenharmony_ci#define  MP886X_MODE		(1 << 0)
2162306a36Sopenharmony_ci#define  MP886X_SLEW_SHIFT	3
2262306a36Sopenharmony_ci#define  MP886X_SLEW_MASK	(0x7 << MP886X_SLEW_SHIFT)
2362306a36Sopenharmony_ci#define  MP886X_GO		(1 << 6)
2462306a36Sopenharmony_ci#define  MP886X_EN		(1 << 7)
2562306a36Sopenharmony_ci#define MP8869_SYSCNTLREG2	0x02
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistruct mp886x_cfg_info {
2862306a36Sopenharmony_ci	const struct regulator_ops *rops;
2962306a36Sopenharmony_ci	const unsigned int slew_rates[8];
3062306a36Sopenharmony_ci	const int switch_freq[4];
3162306a36Sopenharmony_ci	const u8 fs_reg;
3262306a36Sopenharmony_ci	const u8 fs_shift;
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct mp886x_device_info {
3662306a36Sopenharmony_ci	struct device *dev;
3762306a36Sopenharmony_ci	struct regulator_desc desc;
3862306a36Sopenharmony_ci	struct regulator_init_data *regulator;
3962306a36Sopenharmony_ci	struct gpio_desc *en_gpio;
4062306a36Sopenharmony_ci	const struct mp886x_cfg_info *ci;
4162306a36Sopenharmony_ci	u32 r[2];
4262306a36Sopenharmony_ci	unsigned int sel;
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic void mp886x_set_switch_freq(struct mp886x_device_info *di,
4662306a36Sopenharmony_ci				   struct regmap *regmap,
4762306a36Sopenharmony_ci				   u32 freq)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	const struct mp886x_cfg_info *ci = di->ci;
5062306a36Sopenharmony_ci	int i;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) {
5362306a36Sopenharmony_ci		if (freq == ci->switch_freq[i]) {
5462306a36Sopenharmony_ci			regmap_update_bits(regmap, ci->fs_reg,
5562306a36Sopenharmony_ci				  0x3 << ci->fs_shift, i << ci->fs_shift);
5662306a36Sopenharmony_ci			return;
5762306a36Sopenharmony_ci		}
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	dev_err(di->dev, "invalid frequency %d\n", freq);
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	switch (mode) {
6662306a36Sopenharmony_ci	case REGULATOR_MODE_FAST:
6762306a36Sopenharmony_ci		regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
6862306a36Sopenharmony_ci				   MP886X_MODE, MP886X_MODE);
6962306a36Sopenharmony_ci		break;
7062306a36Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
7162306a36Sopenharmony_ci		regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
7262306a36Sopenharmony_ci				   MP886X_MODE, 0);
7362306a36Sopenharmony_ci		break;
7462306a36Sopenharmony_ci	default:
7562306a36Sopenharmony_ci		return -EINVAL;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci	return 0;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic unsigned int mp886x_get_mode(struct regulator_dev *rdev)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	u32 val;
8362306a36Sopenharmony_ci	int ret;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val);
8662306a36Sopenharmony_ci	if (ret < 0)
8762306a36Sopenharmony_ci		return ret;
8862306a36Sopenharmony_ci	if (val & MP886X_MODE)
8962306a36Sopenharmony_ci		return REGULATOR_MODE_FAST;
9062306a36Sopenharmony_ci	else
9162306a36Sopenharmony_ci		return REGULATOR_MODE_NORMAL;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	int ret;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
9962306a36Sopenharmony_ci				 MP886X_GO, MP886X_GO);
10062306a36Sopenharmony_ci	if (ret < 0)
10162306a36Sopenharmony_ci		return ret;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	sel <<= ffs(rdev->desc->vsel_mask) - 1;
10462306a36Sopenharmony_ci	return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
10562306a36Sopenharmony_ci				  MP886X_V_BOOT | rdev->desc->vsel_mask, sel);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	u32 tmp = uv * r1 / r2;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return uv + tmp;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int mp8869_get_voltage_sel(struct regulator_dev *rdev)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct mp886x_device_info *di = rdev_get_drvdata(rdev);
11862306a36Sopenharmony_ci	int ret, uv;
11962306a36Sopenharmony_ci	unsigned int val;
12062306a36Sopenharmony_ci	bool fbloop;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
12362306a36Sopenharmony_ci	if (ret)
12462306a36Sopenharmony_ci		return ret;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	fbloop = val & MP886X_V_BOOT;
12762306a36Sopenharmony_ci	if (fbloop) {
12862306a36Sopenharmony_ci		uv = rdev->desc->min_uV;
12962306a36Sopenharmony_ci		uv = mp8869_scale(uv, di->r[0], di->r[1]);
13062306a36Sopenharmony_ci		return regulator_map_voltage_linear(rdev, uv, uv);
13162306a36Sopenharmony_ci	}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	val &= rdev->desc->vsel_mask;
13462306a36Sopenharmony_ci	val >>= ffs(rdev->desc->vsel_mask) - 1;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	return val;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic const struct regulator_ops mp8869_regulator_ops = {
14062306a36Sopenharmony_ci	.set_voltage_sel = mp8869_set_voltage_sel,
14162306a36Sopenharmony_ci	.get_voltage_sel = mp8869_get_voltage_sel,
14262306a36Sopenharmony_ci	.set_voltage_time_sel = regulator_set_voltage_time_sel,
14362306a36Sopenharmony_ci	.map_voltage = regulator_map_voltage_linear,
14462306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
14562306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
14662306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
14762306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
14862306a36Sopenharmony_ci	.set_mode = mp886x_set_mode,
14962306a36Sopenharmony_ci	.get_mode = mp886x_get_mode,
15062306a36Sopenharmony_ci	.set_ramp_delay = regulator_set_ramp_delay_regmap,
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic const struct mp886x_cfg_info mp8869_ci = {
15462306a36Sopenharmony_ci	.rops = &mp8869_regulator_ops,
15562306a36Sopenharmony_ci	.slew_rates = {
15662306a36Sopenharmony_ci		40000,
15762306a36Sopenharmony_ci		30000,
15862306a36Sopenharmony_ci		20000,
15962306a36Sopenharmony_ci		10000,
16062306a36Sopenharmony_ci		5000,
16162306a36Sopenharmony_ci		2500,
16262306a36Sopenharmony_ci		1250,
16362306a36Sopenharmony_ci		625,
16462306a36Sopenharmony_ci	},
16562306a36Sopenharmony_ci	.switch_freq = {
16662306a36Sopenharmony_ci		500000,
16762306a36Sopenharmony_ci		750000,
16862306a36Sopenharmony_ci		1000000,
16962306a36Sopenharmony_ci		1250000,
17062306a36Sopenharmony_ci	},
17162306a36Sopenharmony_ci	.fs_reg = MP8869_SYSCNTLREG2,
17262306a36Sopenharmony_ci	.fs_shift = 4,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	struct mp886x_device_info *di = rdev_get_drvdata(rdev);
17862306a36Sopenharmony_ci	int ret, delta;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ret = mp8869_set_voltage_sel(rdev, sel);
18162306a36Sopenharmony_ci	if (ret < 0)
18262306a36Sopenharmony_ci		return ret;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	delta = di->sel - sel;
18562306a36Sopenharmony_ci	if (abs(delta) <= 5)
18662306a36Sopenharmony_ci		ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
18762306a36Sopenharmony_ci					 MP886X_GO, 0);
18862306a36Sopenharmony_ci	di->sel = sel;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	return ret;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic int mp8867_get_voltage_sel(struct regulator_dev *rdev)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct mp886x_device_info *di = rdev_get_drvdata(rdev);
19662306a36Sopenharmony_ci	int ret, uv;
19762306a36Sopenharmony_ci	unsigned int val;
19862306a36Sopenharmony_ci	bool fbloop;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
20162306a36Sopenharmony_ci	if (ret)
20262306a36Sopenharmony_ci		return ret;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	fbloop = val & MP886X_V_BOOT;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	val &= rdev->desc->vsel_mask;
20762306a36Sopenharmony_ci	val >>= ffs(rdev->desc->vsel_mask) - 1;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (fbloop) {
21062306a36Sopenharmony_ci		uv = regulator_list_voltage_linear(rdev, val);
21162306a36Sopenharmony_ci		uv = mp8869_scale(uv, di->r[0], di->r[1]);
21262306a36Sopenharmony_ci		return regulator_map_voltage_linear(rdev, uv, uv);
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	return val;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic const struct regulator_ops mp8867_regulator_ops = {
21962306a36Sopenharmony_ci	.set_voltage_sel = mp8867_set_voltage_sel,
22062306a36Sopenharmony_ci	.get_voltage_sel = mp8867_get_voltage_sel,
22162306a36Sopenharmony_ci	.set_voltage_time_sel = regulator_set_voltage_time_sel,
22262306a36Sopenharmony_ci	.map_voltage = regulator_map_voltage_linear,
22362306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear,
22462306a36Sopenharmony_ci	.enable = regulator_enable_regmap,
22562306a36Sopenharmony_ci	.disable = regulator_disable_regmap,
22662306a36Sopenharmony_ci	.is_enabled = regulator_is_enabled_regmap,
22762306a36Sopenharmony_ci	.set_mode = mp886x_set_mode,
22862306a36Sopenharmony_ci	.get_mode = mp886x_get_mode,
22962306a36Sopenharmony_ci	.set_ramp_delay = regulator_set_ramp_delay_regmap,
23062306a36Sopenharmony_ci};
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic const struct mp886x_cfg_info mp8867_ci = {
23362306a36Sopenharmony_ci	.rops = &mp8867_regulator_ops,
23462306a36Sopenharmony_ci	.slew_rates = {
23562306a36Sopenharmony_ci		64000,
23662306a36Sopenharmony_ci		32000,
23762306a36Sopenharmony_ci		16000,
23862306a36Sopenharmony_ci		8000,
23962306a36Sopenharmony_ci		4000,
24062306a36Sopenharmony_ci		2000,
24162306a36Sopenharmony_ci		1000,
24262306a36Sopenharmony_ci		500,
24362306a36Sopenharmony_ci	},
24462306a36Sopenharmony_ci	.switch_freq = {
24562306a36Sopenharmony_ci		500000,
24662306a36Sopenharmony_ci		750000,
24762306a36Sopenharmony_ci		1000000,
24862306a36Sopenharmony_ci		1500000,
24962306a36Sopenharmony_ci	},
25062306a36Sopenharmony_ci	.fs_reg = MP886X_SYSCNTLREG1,
25162306a36Sopenharmony_ci	.fs_shift = 1,
25262306a36Sopenharmony_ci};
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic int mp886x_regulator_register(struct mp886x_device_info *di,
25562306a36Sopenharmony_ci				     struct regulator_config *config)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	struct regulator_desc *rdesc = &di->desc;
25862306a36Sopenharmony_ci	struct regulator_dev *rdev;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	rdesc->name = "mp886x-reg";
26162306a36Sopenharmony_ci	rdesc->supply_name = "vin";
26262306a36Sopenharmony_ci	rdesc->ops = di->ci->rops;
26362306a36Sopenharmony_ci	rdesc->type = REGULATOR_VOLTAGE;
26462306a36Sopenharmony_ci	rdesc->n_voltages = 128;
26562306a36Sopenharmony_ci	rdesc->enable_reg = MP886X_SYSCNTLREG1;
26662306a36Sopenharmony_ci	rdesc->enable_mask = MP886X_EN;
26762306a36Sopenharmony_ci	rdesc->min_uV = 600000;
26862306a36Sopenharmony_ci	rdesc->uV_step = 10000;
26962306a36Sopenharmony_ci	rdesc->vsel_reg = MP886X_VSEL;
27062306a36Sopenharmony_ci	rdesc->vsel_mask = 0x3f;
27162306a36Sopenharmony_ci	rdesc->ramp_reg = MP886X_SYSCNTLREG1;
27262306a36Sopenharmony_ci	rdesc->ramp_mask = MP886X_SLEW_MASK;
27362306a36Sopenharmony_ci	rdesc->ramp_delay_table = di->ci->slew_rates;
27462306a36Sopenharmony_ci	rdesc->n_ramp_values = ARRAY_SIZE(di->ci->slew_rates);
27562306a36Sopenharmony_ci	rdesc->owner = THIS_MODULE;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	rdev = devm_regulator_register(di->dev, &di->desc, config);
27862306a36Sopenharmony_ci	if (IS_ERR(rdev))
27962306a36Sopenharmony_ci		return PTR_ERR(rdev);
28062306a36Sopenharmony_ci	di->sel = rdesc->ops->get_voltage_sel(rdev);
28162306a36Sopenharmony_ci	return 0;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic const struct regmap_config mp886x_regmap_config = {
28562306a36Sopenharmony_ci	.reg_bits = 8,
28662306a36Sopenharmony_ci	.val_bits = 8,
28762306a36Sopenharmony_ci};
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic int mp886x_i2c_probe(struct i2c_client *client)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct device *dev = &client->dev;
29262306a36Sopenharmony_ci	struct device_node *np = dev->of_node;
29362306a36Sopenharmony_ci	struct mp886x_device_info *di;
29462306a36Sopenharmony_ci	struct regulator_config config = { };
29562306a36Sopenharmony_ci	struct regmap *regmap;
29662306a36Sopenharmony_ci	u32 freq;
29762306a36Sopenharmony_ci	int ret;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL);
30062306a36Sopenharmony_ci	if (!di)
30162306a36Sopenharmony_ci		return -ENOMEM;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
30462306a36Sopenharmony_ci	if (!di->regulator) {
30562306a36Sopenharmony_ci		dev_err(dev, "Platform data not found!\n");
30662306a36Sopenharmony_ci		return -EINVAL;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	ret = of_property_read_u32_array(np, "mps,fb-voltage-divider",
31062306a36Sopenharmony_ci					 di->r, 2);
31162306a36Sopenharmony_ci	if (ret)
31262306a36Sopenharmony_ci		return ret;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
31562306a36Sopenharmony_ci	if (IS_ERR(di->en_gpio))
31662306a36Sopenharmony_ci		return PTR_ERR(di->en_gpio);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	di->ci = of_device_get_match_data(dev);
31962306a36Sopenharmony_ci	di->dev = dev;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config);
32262306a36Sopenharmony_ci	if (IS_ERR(regmap)) {
32362306a36Sopenharmony_ci		dev_err(dev, "Failed to allocate regmap!\n");
32462306a36Sopenharmony_ci		return PTR_ERR(regmap);
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci	i2c_set_clientdata(client, di);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	config.dev = di->dev;
32962306a36Sopenharmony_ci	config.init_data = di->regulator;
33062306a36Sopenharmony_ci	config.regmap = regmap;
33162306a36Sopenharmony_ci	config.driver_data = di;
33262306a36Sopenharmony_ci	config.of_node = np;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (!of_property_read_u32(np, "mps,switch-frequency-hz", &freq))
33562306a36Sopenharmony_ci		mp886x_set_switch_freq(di, regmap, freq);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	ret = mp886x_regulator_register(di, &config);
33862306a36Sopenharmony_ci	if (ret < 0)
33962306a36Sopenharmony_ci		dev_err(dev, "Failed to register regulator!\n");
34062306a36Sopenharmony_ci	return ret;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic const struct of_device_id mp886x_dt_ids[] = {
34462306a36Sopenharmony_ci	{
34562306a36Sopenharmony_ci		.compatible = "mps,mp8867",
34662306a36Sopenharmony_ci		.data = &mp8867_ci
34762306a36Sopenharmony_ci	},
34862306a36Sopenharmony_ci	{
34962306a36Sopenharmony_ci		.compatible = "mps,mp8869",
35062306a36Sopenharmony_ci		.data = &mp8869_ci
35162306a36Sopenharmony_ci	},
35262306a36Sopenharmony_ci	{ }
35362306a36Sopenharmony_ci};
35462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mp886x_dt_ids);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic const struct i2c_device_id mp886x_id[] = {
35762306a36Sopenharmony_ci	{ "mp886x", },
35862306a36Sopenharmony_ci	{ },
35962306a36Sopenharmony_ci};
36062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, mp886x_id);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic struct i2c_driver mp886x_regulator_driver = {
36362306a36Sopenharmony_ci	.driver = {
36462306a36Sopenharmony_ci		.name = "mp886x-regulator",
36562306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
36662306a36Sopenharmony_ci		.of_match_table = mp886x_dt_ids,
36762306a36Sopenharmony_ci	},
36862306a36Sopenharmony_ci	.probe = mp886x_i2c_probe,
36962306a36Sopenharmony_ci	.id_table = mp886x_id,
37062306a36Sopenharmony_ci};
37162306a36Sopenharmony_cimodule_i2c_driver(mp886x_regulator_driver);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ciMODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
37462306a36Sopenharmony_ciMODULE_DESCRIPTION("MP886x regulator driver");
37562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
376