xref: /linux/drivers/regulator/da9121-regulator.c (revision ed7171ff9fabc49ae6ed42fbd082a576473836fc)
1e6ff10f2SVincent Whitchurch // SPDX-License-Identifier: GPL-2.0-only
2c860476bSAdam Ward //
3c860476bSAdam Ward // DA9121 Single-channel dual-phase 10A buck converter
4c860476bSAdam Ward //
5c860476bSAdam Ward // Copyright (C) 2020 Axis Communications AB
6c860476bSAdam Ward //
7c860476bSAdam Ward // DA9130 Single-channel dual-phase 10A buck converter (Automotive)
8c860476bSAdam Ward // DA9217 Single-channel dual-phase  6A buck converter
9c860476bSAdam Ward // DA9122 Dual-channel single-phase  5A buck converter
10c860476bSAdam Ward // DA9131 Dual-channel single-phase  5A buck converter (Automotive)
11c860476bSAdam Ward // DA9220 Dual-channel single-phase  3A buck converter
12c860476bSAdam Ward // DA9132 Dual-channel single-phase  3A buck converter (Automotive)
13c860476bSAdam Ward //
14c860476bSAdam Ward // Copyright (C) 2020 Dialog Semiconductor
15e6ff10f2SVincent Whitchurch 
1646537a86SRob Herring #include <linux/of.h>
17b4b27776SArnd Bergmann #include <linux/gpio/consumer.h>
18e6ff10f2SVincent Whitchurch #include <linux/regulator/of_regulator.h>
19e6ff10f2SVincent Whitchurch #include <linux/regulator/machine.h>
20e6ff10f2SVincent Whitchurch #include <linux/regulator/driver.h>
21e6ff10f2SVincent Whitchurch #include <linux/module.h>
22e6ff10f2SVincent Whitchurch #include <linux/regmap.h>
23e6ff10f2SVincent Whitchurch #include <linux/err.h>
24e6ff10f2SVincent Whitchurch #include <linux/i2c.h>
25c860476bSAdam Ward #include <linux/regulator/da9121.h>
2640bb5b02SAdam Ward #include <linux/interrupt.h>
2740bb5b02SAdam Ward #include <linux/workqueue.h>
28c860476bSAdam Ward 
2986f162c9SAdam Ward #include "da9121-regulator.h"
30e6ff10f2SVincent Whitchurch 
31f3fbd556SAdam Ward /* Chip data */
32f3fbd556SAdam Ward struct da9121 {
33f3fbd556SAdam Ward 	struct device *dev;
3440bb5b02SAdam Ward 	struct delayed_work work;
3546c413d5SAdam Ward 	struct da9121_pdata *pdata;
36c860476bSAdam Ward 	struct regmap *regmap;
379929900dSAdam Ward 	struct regulator_dev *rdev[DA9121_IDX_MAX];
3840bb5b02SAdam Ward 	unsigned int persistent[2];
3940bb5b02SAdam Ward 	unsigned int passive_delay;
4040bb5b02SAdam Ward 	int chip_irq;
41f3fbd556SAdam Ward 	int variant_id;
42013592beSAdam Ward 	int subvariant_id;
43f3fbd556SAdam Ward };
44f3fbd556SAdam Ward 
4546c413d5SAdam Ward /* Define ranges for different variants, enabling translation to/from
4646c413d5SAdam Ward  * registers. Maximums give scope to allow for transients.
4746c413d5SAdam Ward  */
4846c413d5SAdam Ward struct da9121_range {
4946c413d5SAdam Ward 	int val_min;
5046c413d5SAdam Ward 	int val_max;
5146c413d5SAdam Ward 	int val_stp;
5246c413d5SAdam Ward 	int reg_min;
5346c413d5SAdam Ward 	int reg_max;
5446c413d5SAdam Ward };
5546c413d5SAdam Ward 
56c8dbf2f2SZou Wei static struct da9121_range da9121_10A_2phase_current = {
5746c413d5SAdam Ward 	.val_min =  7000000,
5846c413d5SAdam Ward 	.val_max = 20000000,
5946c413d5SAdam Ward 	.val_stp =  1000000,
6046c413d5SAdam Ward 	.reg_min = 1,
6146c413d5SAdam Ward 	.reg_max = 14,
6246c413d5SAdam Ward };
6346c413d5SAdam Ward 
64c8dbf2f2SZou Wei static struct da9121_range da9121_6A_2phase_current = {
6546c413d5SAdam Ward 	.val_min =  7000000,
6646c413d5SAdam Ward 	.val_max = 12000000,
6746c413d5SAdam Ward 	.val_stp =  1000000,
6846c413d5SAdam Ward 	.reg_min = 1,
6946c413d5SAdam Ward 	.reg_max = 6,
7046c413d5SAdam Ward };
7146c413d5SAdam Ward 
72c8dbf2f2SZou Wei static struct da9121_range da9121_5A_1phase_current = {
7346c413d5SAdam Ward 	.val_min =  3500000,
7446c413d5SAdam Ward 	.val_max = 10000000,
7546c413d5SAdam Ward 	.val_stp =   500000,
7646c413d5SAdam Ward 	.reg_min = 1,
7746c413d5SAdam Ward 	.reg_max = 14,
7846c413d5SAdam Ward };
7946c413d5SAdam Ward 
80c8dbf2f2SZou Wei static struct da9121_range da9121_3A_1phase_current = {
8146c413d5SAdam Ward 	.val_min = 3500000,
8246c413d5SAdam Ward 	.val_max = 6000000,
8346c413d5SAdam Ward 	.val_stp =  500000,
8446c413d5SAdam Ward 	.reg_min = 1,
8546c413d5SAdam Ward 	.reg_max = 6,
8646c413d5SAdam Ward };
8746c413d5SAdam Ward 
88c5187a24SAdam Ward static struct da9121_range da914x_40A_4phase_current = {
89f0fdfc04SAdam Ward 	.val_min = 26000000,
90f0fdfc04SAdam Ward 	.val_max = 78000000,
91f0fdfc04SAdam Ward 	.val_stp =  4000000,
92c5187a24SAdam Ward 	.reg_min = 1,
93c5187a24SAdam Ward 	.reg_max = 14,
94c5187a24SAdam Ward };
95c5187a24SAdam Ward 
96c5187a24SAdam Ward static struct da9121_range da914x_20A_2phase_current = {
97f0fdfc04SAdam Ward 	.val_min = 13000000,
98f0fdfc04SAdam Ward 	.val_max = 39000000,
99c5187a24SAdam Ward 	.val_stp =  2000000,
100c5187a24SAdam Ward 	.reg_min = 1,
101c5187a24SAdam Ward 	.reg_max = 14,
102c5187a24SAdam Ward };
103c5187a24SAdam Ward 
10446c413d5SAdam Ward struct da9121_variant_info {
10546c413d5SAdam Ward 	int num_bucks;
10646c413d5SAdam Ward 	int num_phases;
10746c413d5SAdam Ward 	struct da9121_range *current_range;
10846c413d5SAdam Ward };
10946c413d5SAdam Ward 
11046c413d5SAdam Ward static const struct da9121_variant_info variant_parameters[] = {
11146c413d5SAdam Ward 	{ 1, 2, &da9121_10A_2phase_current },	//DA9121_TYPE_DA9121_DA9130
11246c413d5SAdam Ward 	{ 2, 1, &da9121_3A_1phase_current  },	//DA9121_TYPE_DA9220_DA9132
11346c413d5SAdam Ward 	{ 2, 1, &da9121_5A_1phase_current  },	//DA9121_TYPE_DA9122_DA9131
11446c413d5SAdam Ward 	{ 1, 2, &da9121_6A_2phase_current  },	//DA9121_TYPE_DA9217
115c5187a24SAdam Ward 	{ 1, 4, &da914x_40A_4phase_current },   //DA9121_TYPE_DA9141
116c5187a24SAdam Ward 	{ 1, 2, &da914x_20A_2phase_current },   //DA9121_TYPE_DA9142
11746c413d5SAdam Ward };
11846c413d5SAdam Ward 
1195c4b62afSAdam Ward struct da9121_field {
1205c4b62afSAdam Ward 	unsigned int reg;
1215c4b62afSAdam Ward 	unsigned int msk;
1225c4b62afSAdam Ward };
1235c4b62afSAdam Ward 
1245c4b62afSAdam Ward static const struct da9121_field da9121_current_field[2] = {
1255c4b62afSAdam Ward 	{ DA9121_REG_BUCK_BUCK1_2, DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM },
1265c4b62afSAdam Ward 	{ DA9xxx_REG_BUCK_BUCK2_2, DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM },
1275c4b62afSAdam Ward };
1285c4b62afSAdam Ward 
12965ac9704SAdam Ward static const struct da9121_field da9121_mode_field[2] = {
13065ac9704SAdam Ward 	{ DA9121_REG_BUCK_BUCK1_4, DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE },
13165ac9704SAdam Ward 	{ DA9xxx_REG_BUCK_BUCK2_4, DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE },
13265ac9704SAdam Ward };
13365ac9704SAdam Ward 
13440bb5b02SAdam Ward struct status_event_data {
13540bb5b02SAdam Ward 	int buck_id; /* 0=core, 1/2-buck */
13640bb5b02SAdam Ward 	int reg_index;  /* index for status/event/mask register selection */
13740bb5b02SAdam Ward 	int status_bit; /* bit masks... */
13840bb5b02SAdam Ward 	int event_bit;
13940bb5b02SAdam Ward 	int mask_bit;
14040bb5b02SAdam Ward 	unsigned long notification; /* Notification for status inception */
14140bb5b02SAdam Ward 	char *warn; /* if NULL, notify - otherwise dev_warn this string */
14240bb5b02SAdam Ward };
14340bb5b02SAdam Ward 
14440bb5b02SAdam Ward #define DA9121_STATUS(id, bank, name, notification, warning) \
14540bb5b02SAdam Ward 	{ id, bank, \
14640bb5b02SAdam Ward 	DA9121_MASK_SYS_STATUS_##bank##_##name, \
14740bb5b02SAdam Ward 	DA9121_MASK_SYS_EVENT_##bank##_E_##name, \
14840bb5b02SAdam Ward 	DA9121_MASK_SYS_MASK_##bank##_M_##name, \
14940bb5b02SAdam Ward 	notification, warning }
15040bb5b02SAdam Ward 
15140bb5b02SAdam Ward /* For second buck related event bits that are specific to DA9122, DA9220 variants */
15240bb5b02SAdam Ward #define DA9xxx_STATUS(id, bank, name, notification, warning) \
15340bb5b02SAdam Ward 	{ id, bank, \
15440bb5b02SAdam Ward 	DA9xxx_MASK_SYS_STATUS_##bank##_##name, \
15540bb5b02SAdam Ward 	DA9xxx_MASK_SYS_EVENT_##bank##_E_##name, \
15640bb5b02SAdam Ward 	DA9xxx_MASK_SYS_MASK_##bank##_M_##name, \
15740bb5b02SAdam Ward 	notification, warning }
15840bb5b02SAdam Ward 
15940bb5b02SAdam Ward /* The status signals that may need servicing, depending on device variant.
16040bb5b02SAdam Ward  * After assertion, they persist; so event is notified, the IRQ disabled,
16140bb5b02SAdam Ward  * and status polled until clear again and IRQ is reenabled.
16240bb5b02SAdam Ward  *
16340bb5b02SAdam Ward  * SG/PG1/PG2 should be set when device first powers up and should never
16440bb5b02SAdam Ward  * re-occur. When this driver starts, it is expected that these will have
16540bb5b02SAdam Ward  * self-cleared for when the IRQs are enabled, so these should never be seen.
16640bb5b02SAdam Ward  * If seen, the implication is that the device has reset.
16740bb5b02SAdam Ward  *
16840bb5b02SAdam Ward  * GPIO0/1/2 are not configured for use by default, so should not be seen.
16940bb5b02SAdam Ward  */
170c8dbf2f2SZou Wei static const struct status_event_data status_event_handling[] = {
17140bb5b02SAdam Ward 	DA9xxx_STATUS(0, 0, SG, 0, "Handled E_SG\n"),
17240bb5b02SAdam Ward 	DA9121_STATUS(0, 0, TEMP_CRIT, (REGULATOR_EVENT_OVER_TEMP|REGULATOR_EVENT_DISABLE), NULL),
17340bb5b02SAdam Ward 	DA9121_STATUS(0, 0, TEMP_WARN, REGULATOR_EVENT_OVER_TEMP, NULL),
17440bb5b02SAdam Ward 	DA9121_STATUS(1, 1, PG1, 0, "Handled E_PG1\n"),
17540bb5b02SAdam Ward 	DA9121_STATUS(1, 1, OV1, REGULATOR_EVENT_REGULATION_OUT, NULL),
17640bb5b02SAdam Ward 	DA9121_STATUS(1, 1, UV1, REGULATOR_EVENT_UNDER_VOLTAGE, NULL),
17740bb5b02SAdam Ward 	DA9121_STATUS(1, 1, OC1, REGULATOR_EVENT_OVER_CURRENT, NULL),
17840bb5b02SAdam Ward 	DA9xxx_STATUS(2, 1, PG2, 0, "Handled E_PG2\n"),
17940bb5b02SAdam Ward 	DA9xxx_STATUS(2, 1, OV2, REGULATOR_EVENT_REGULATION_OUT, NULL),
18040bb5b02SAdam Ward 	DA9xxx_STATUS(2, 1, UV2, REGULATOR_EVENT_UNDER_VOLTAGE, NULL),
18140bb5b02SAdam Ward 	DA9xxx_STATUS(2, 1, OC2, REGULATOR_EVENT_OVER_CURRENT, NULL),
18240bb5b02SAdam Ward 	DA9121_STATUS(0, 2, GPIO0, 0, "Handled E_GPIO0\n"),
18340bb5b02SAdam Ward 	DA9121_STATUS(0, 2, GPIO1, 0, "Handled E_GPIO1\n"),
18440bb5b02SAdam Ward 	DA9121_STATUS(0, 2, GPIO2, 0, "Handled E_GPIO2\n"),
18540bb5b02SAdam Ward };
18640bb5b02SAdam Ward 
1875c4b62afSAdam Ward static int da9121_get_current_limit(struct regulator_dev *rdev)
1885c4b62afSAdam Ward {
1895c4b62afSAdam Ward 	struct da9121 *chip = rdev_get_drvdata(rdev);
1905c4b62afSAdam Ward 	int id = rdev_get_id(rdev);
1915c4b62afSAdam Ward 	struct da9121_range *range =
1925c4b62afSAdam Ward 		variant_parameters[chip->variant_id].current_range;
1935c4b62afSAdam Ward 	unsigned int val = 0;
1945c4b62afSAdam Ward 	int ret = 0;
1955c4b62afSAdam Ward 
1965c4b62afSAdam Ward 	ret = regmap_read(chip->regmap, da9121_current_field[id].reg, &val);
1975c4b62afSAdam Ward 	if (ret < 0) {
1985c4b62afSAdam Ward 		dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret);
1995c4b62afSAdam Ward 		goto error;
2005c4b62afSAdam Ward 	}
2015c4b62afSAdam Ward 
2025c4b62afSAdam Ward 	if (val < range->reg_min) {
2035c4b62afSAdam Ward 		ret = -EACCES;
2045c4b62afSAdam Ward 		goto error;
2055c4b62afSAdam Ward 	}
2065c4b62afSAdam Ward 
2075c4b62afSAdam Ward 	if (val > range->reg_max) {
2085c4b62afSAdam Ward 		ret = -EINVAL;
2095c4b62afSAdam Ward 		goto error;
2105c4b62afSAdam Ward 	}
2115c4b62afSAdam Ward 
2125c4b62afSAdam Ward 	return range->val_min + (range->val_stp * (val - range->reg_min));
2135c4b62afSAdam Ward error:
2145c4b62afSAdam Ward 	return ret;
2155c4b62afSAdam Ward }
2165c4b62afSAdam Ward 
2175c4b62afSAdam Ward static int da9121_ceiling_selector(struct regulator_dev *rdev,
2185c4b62afSAdam Ward 		int min, int max,
2195c4b62afSAdam Ward 		unsigned int *selector)
2205c4b62afSAdam Ward {
2215c4b62afSAdam Ward 	struct da9121 *chip = rdev_get_drvdata(rdev);
2225c4b62afSAdam Ward 	struct da9121_range *range =
2235c4b62afSAdam Ward 		variant_parameters[chip->variant_id].current_range;
2245c4b62afSAdam Ward 	unsigned int level;
2255c4b62afSAdam Ward 	unsigned int i = 0;
2265c4b62afSAdam Ward 	unsigned int sel = 0;
2275c4b62afSAdam Ward 	int ret = 0;
2285c4b62afSAdam Ward 
2295c4b62afSAdam Ward 	if (range->val_min > max || range->val_max < min) {
2305c4b62afSAdam Ward 		dev_err(chip->dev,
2315c4b62afSAdam Ward 			"Requested current out of regulator capability\n");
2325c4b62afSAdam Ward 		ret = -EINVAL;
2335c4b62afSAdam Ward 		goto error;
2345c4b62afSAdam Ward 	}
2355c4b62afSAdam Ward 
2365c4b62afSAdam Ward 	level = range->val_max;
2375c4b62afSAdam Ward 	for (i = range->reg_max; i >= range->reg_min; i--) {
2385c4b62afSAdam Ward 		if (level <= max) {
2395c4b62afSAdam Ward 			sel = i;
2405c4b62afSAdam Ward 			break;
2415c4b62afSAdam Ward 		}
2425c4b62afSAdam Ward 		level -= range->val_stp;
2435c4b62afSAdam Ward 	}
2445c4b62afSAdam Ward 
2455c4b62afSAdam Ward 	if (level < min) {
2465c4b62afSAdam Ward 		dev_err(chip->dev,
2475c4b62afSAdam Ward 			"Best match falls below minimum requested current\n");
2485c4b62afSAdam Ward 		ret = -EINVAL;
2495c4b62afSAdam Ward 		goto error;
2505c4b62afSAdam Ward 	}
2515c4b62afSAdam Ward 
2525c4b62afSAdam Ward 	*selector = sel;
2535c4b62afSAdam Ward error:
2545c4b62afSAdam Ward 	return ret;
2555c4b62afSAdam Ward }
2565c4b62afSAdam Ward 
2575c4b62afSAdam Ward static int da9121_set_current_limit(struct regulator_dev *rdev,
2585c4b62afSAdam Ward 				int min_ua, int max_ua)
2595c4b62afSAdam Ward {
2605c4b62afSAdam Ward 	struct da9121 *chip = rdev_get_drvdata(rdev);
2615c4b62afSAdam Ward 	int id = rdev_get_id(rdev);
2625c4b62afSAdam Ward 	struct da9121_range *range =
2635c4b62afSAdam Ward 		variant_parameters[chip->variant_id].current_range;
2645c4b62afSAdam Ward 	unsigned int sel = 0;
2655c4b62afSAdam Ward 	int ret = 0;
2665c4b62afSAdam Ward 
2675c4b62afSAdam Ward 	if (min_ua < range->val_min ||
2685c4b62afSAdam Ward 	    max_ua > range->val_max) {
2695c4b62afSAdam Ward 		ret = -EINVAL;
2705c4b62afSAdam Ward 		goto error;
2715c4b62afSAdam Ward 	}
2725c4b62afSAdam Ward 
27324f08532SAdam Ward 	if (rdev->desc->ops->is_enabled(rdev)) {
27424f08532SAdam Ward 		ret = -EBUSY;
27524f08532SAdam Ward 		goto error;
27624f08532SAdam Ward 	}
27724f08532SAdam Ward 
2785c4b62afSAdam Ward 	ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel);
2795c4b62afSAdam Ward 	if (ret < 0)
2805c4b62afSAdam Ward 		goto error;
2815c4b62afSAdam Ward 
2825c4b62afSAdam Ward 	ret = regmap_update_bits(chip->regmap,
2835c4b62afSAdam Ward 				da9121_current_field[id].reg,
2845c4b62afSAdam Ward 				da9121_current_field[id].msk,
2855c4b62afSAdam Ward 				(unsigned int)sel);
2865c4b62afSAdam Ward 	if (ret < 0)
2875c4b62afSAdam Ward 		dev_err(chip->dev, "Cannot update BUCK current limit, err: %d\n", ret);
2885c4b62afSAdam Ward 
2895c4b62afSAdam Ward error:
2905c4b62afSAdam Ward 	return ret;
2915c4b62afSAdam Ward }
2925c4b62afSAdam Ward 
29365ac9704SAdam Ward static unsigned int da9121_map_mode(unsigned int mode)
29465ac9704SAdam Ward {
29565ac9704SAdam Ward 	switch (mode) {
29665ac9704SAdam Ward 	case DA9121_BUCK_MODE_FORCE_PWM:
29765ac9704SAdam Ward 		return REGULATOR_MODE_FAST;
29865ac9704SAdam Ward 	case DA9121_BUCK_MODE_FORCE_PWM_SHEDDING:
29965ac9704SAdam Ward 		return REGULATOR_MODE_NORMAL;
30065ac9704SAdam Ward 	case DA9121_BUCK_MODE_AUTO:
30165ac9704SAdam Ward 		return REGULATOR_MODE_IDLE;
30265ac9704SAdam Ward 	case DA9121_BUCK_MODE_FORCE_PFM:
30365ac9704SAdam Ward 		return REGULATOR_MODE_STANDBY;
30465ac9704SAdam Ward 	default:
3050b1e5526SAxel Lin 		return REGULATOR_MODE_INVALID;
30665ac9704SAdam Ward 	}
30765ac9704SAdam Ward }
30865ac9704SAdam Ward 
30965ac9704SAdam Ward static int da9121_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
31065ac9704SAdam Ward {
31165ac9704SAdam Ward 	struct da9121 *chip = rdev_get_drvdata(rdev);
31265ac9704SAdam Ward 	int id = rdev_get_id(rdev);
31365ac9704SAdam Ward 	unsigned int val;
31465ac9704SAdam Ward 
31565ac9704SAdam Ward 	switch (mode) {
31665ac9704SAdam Ward 	case REGULATOR_MODE_FAST:
31765ac9704SAdam Ward 		val = DA9121_BUCK_MODE_FORCE_PWM;
31865ac9704SAdam Ward 		break;
31965ac9704SAdam Ward 	case REGULATOR_MODE_NORMAL:
32065ac9704SAdam Ward 		val = DA9121_BUCK_MODE_FORCE_PWM_SHEDDING;
32165ac9704SAdam Ward 		break;
32265ac9704SAdam Ward 	case REGULATOR_MODE_IDLE:
32365ac9704SAdam Ward 		val = DA9121_BUCK_MODE_AUTO;
32465ac9704SAdam Ward 		break;
32565ac9704SAdam Ward 	case REGULATOR_MODE_STANDBY:
32665ac9704SAdam Ward 		val = DA9121_BUCK_MODE_FORCE_PFM;
32765ac9704SAdam Ward 		break;
32865ac9704SAdam Ward 	default:
32965ac9704SAdam Ward 		return -EINVAL;
33065ac9704SAdam Ward 	}
33165ac9704SAdam Ward 
33265ac9704SAdam Ward 	return regmap_update_bits(chip->regmap,
33365ac9704SAdam Ward 				  da9121_mode_field[id].reg,
33465ac9704SAdam Ward 				  da9121_mode_field[id].msk,
33565ac9704SAdam Ward 				  val);
33665ac9704SAdam Ward }
33765ac9704SAdam Ward 
33865ac9704SAdam Ward static unsigned int da9121_buck_get_mode(struct regulator_dev *rdev)
33965ac9704SAdam Ward {
34065ac9704SAdam Ward 	struct da9121 *chip = rdev_get_drvdata(rdev);
34165ac9704SAdam Ward 	int id = rdev_get_id(rdev);
3420b1e5526SAxel Lin 	unsigned int val, mode;
34365ac9704SAdam Ward 	int ret = 0;
34465ac9704SAdam Ward 
34565ac9704SAdam Ward 	ret = regmap_read(chip->regmap, da9121_mode_field[id].reg, &val);
34665ac9704SAdam Ward 	if (ret < 0) {
34765ac9704SAdam Ward 		dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret);
34865ac9704SAdam Ward 		return -EINVAL;
34965ac9704SAdam Ward 	}
35065ac9704SAdam Ward 
3510b1e5526SAxel Lin 	mode = da9121_map_mode(val & da9121_mode_field[id].msk);
3520b1e5526SAxel Lin 	if (mode == REGULATOR_MODE_INVALID)
3530b1e5526SAxel Lin 		return -EINVAL;
3540b1e5526SAxel Lin 
3550b1e5526SAxel Lin 	return mode;
35665ac9704SAdam Ward }
35765ac9704SAdam Ward 
358e6ff10f2SVincent Whitchurch static const struct regulator_ops da9121_buck_ops = {
359e6ff10f2SVincent Whitchurch 	.enable = regulator_enable_regmap,
360e6ff10f2SVincent Whitchurch 	.disable = regulator_disable_regmap,
361e6ff10f2SVincent Whitchurch 	.is_enabled = regulator_is_enabled_regmap,
362e6ff10f2SVincent Whitchurch 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
363e6ff10f2SVincent Whitchurch 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
364e6ff10f2SVincent Whitchurch 	.list_voltage = regulator_list_voltage_linear,
3655c4b62afSAdam Ward 	.get_current_limit = da9121_get_current_limit,
3665c4b62afSAdam Ward 	.set_current_limit = da9121_set_current_limit,
36765ac9704SAdam Ward 	.set_mode = da9121_buck_set_mode,
36865ac9704SAdam Ward 	.get_mode = da9121_buck_get_mode,
369e6ff10f2SVincent Whitchurch };
370e6ff10f2SVincent Whitchurch 
37191863239SAdam Ward static struct of_regulator_match da9121_matches[] = {
37291863239SAdam Ward 	[DA9121_IDX_BUCK1] = { .name = "buck1" },
37391863239SAdam Ward 	[DA9121_IDX_BUCK2] = { .name = "buck2" },
37491863239SAdam Ward };
37591863239SAdam Ward 
37646c413d5SAdam Ward static int da9121_of_parse_cb(struct device_node *np,
37746c413d5SAdam Ward 				const struct regulator_desc *desc,
37846c413d5SAdam Ward 				struct regulator_config *config)
37946c413d5SAdam Ward {
38046c413d5SAdam Ward 	struct da9121 *chip = config->driver_data;
38146c413d5SAdam Ward 	struct da9121_pdata *pdata;
38246c413d5SAdam Ward 	struct gpio_desc *ena_gpiod;
38346c413d5SAdam Ward 
38446c413d5SAdam Ward 	if (chip->pdata == NULL) {
38546c413d5SAdam Ward 		pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
38646c413d5SAdam Ward 		if (!pdata)
38746c413d5SAdam Ward 			return -ENOMEM;
38846c413d5SAdam Ward 	} else {
38946c413d5SAdam Ward 		pdata = chip->pdata;
39046c413d5SAdam Ward 	}
39146c413d5SAdam Ward 
39246c413d5SAdam Ward 	pdata->num_buck++;
39346c413d5SAdam Ward 
39446c413d5SAdam Ward 	if (pdata->num_buck > variant_parameters[chip->variant_id].num_bucks) {
39546c413d5SAdam Ward 		dev_err(chip->dev, "Error: excessive regulators for device\n");
39646c413d5SAdam Ward 		return -ENODEV;
39746c413d5SAdam Ward 	}
39846c413d5SAdam Ward 
39946c413d5SAdam Ward 	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
40046c413d5SAdam Ward 						GPIOD_OUT_HIGH |
40146c413d5SAdam Ward 						GPIOD_FLAGS_BIT_NONEXCLUSIVE,
40246c413d5SAdam Ward 						"da9121-enable");
40346c413d5SAdam Ward 	if (!IS_ERR(ena_gpiod))
40446c413d5SAdam Ward 		config->ena_gpiod = ena_gpiod;
40546c413d5SAdam Ward 
40646c413d5SAdam Ward 	if (variant_parameters[chip->variant_id].num_bucks == 2) {
40746c413d5SAdam Ward 		uint32_t ripple_cancel;
40846c413d5SAdam Ward 		uint32_t ripple_reg;
40946c413d5SAdam Ward 		int ret;
41046c413d5SAdam Ward 
4119536ce63SAdam Ward 		if (of_property_read_u32(da9121_matches[pdata->num_buck-1].of_node,
41246c413d5SAdam Ward 				"dlg,ripple-cancel", &ripple_cancel)) {
41346c413d5SAdam Ward 			if (pdata->num_buck > 1)
41446c413d5SAdam Ward 				ripple_reg = DA9xxx_REG_BUCK_BUCK2_7;
41546c413d5SAdam Ward 			else
41646c413d5SAdam Ward 				ripple_reg = DA9121_REG_BUCK_BUCK1_7;
41746c413d5SAdam Ward 
41846c413d5SAdam Ward 			ret = regmap_update_bits(chip->regmap, ripple_reg,
41946c413d5SAdam Ward 				DA9xxx_MASK_BUCK_BUCKx_7_CHx_RIPPLE_CANCEL,
42046c413d5SAdam Ward 				ripple_cancel);
42146c413d5SAdam Ward 			if (ret < 0)
42246c413d5SAdam Ward 				dev_err(chip->dev, "Cannot set ripple mode, err: %d\n", ret);
42346c413d5SAdam Ward 		}
42446c413d5SAdam Ward 	}
42546c413d5SAdam Ward 
42646c413d5SAdam Ward 	return 0;
42746c413d5SAdam Ward }
42846c413d5SAdam Ward 
429c860476bSAdam Ward #define DA9121_MIN_MV		300
430c860476bSAdam Ward #define DA9121_MAX_MV		1900
431c860476bSAdam Ward #define DA9121_STEP_MV		10
432c860476bSAdam Ward #define DA9121_MIN_SEL		(DA9121_MIN_MV / DA9121_STEP_MV)
433c860476bSAdam Ward #define DA9121_N_VOLTAGES	(((DA9121_MAX_MV - DA9121_MIN_MV) / DA9121_STEP_MV) \
434c860476bSAdam Ward 				 + 1 + DA9121_MIN_SEL)
435c860476bSAdam Ward 
436e6ff10f2SVincent Whitchurch static const struct regulator_desc da9121_reg = {
43791863239SAdam Ward 	.id = DA9121_IDX_BUCK1,
438e6ff10f2SVincent Whitchurch 	.name = "da9121",
439e6ff10f2SVincent Whitchurch 	.of_match = "buck1",
44046c413d5SAdam Ward 	.of_parse_cb = da9121_of_parse_cb,
441e6ff10f2SVincent Whitchurch 	.owner = THIS_MODULE,
4423a6d93ebSChen Jiahao 	.regulators_node = "regulators",
44365ac9704SAdam Ward 	.of_map_mode = da9121_map_mode,
444e6ff10f2SVincent Whitchurch 	.ops = &da9121_buck_ops,
445e6ff10f2SVincent Whitchurch 	.type = REGULATOR_VOLTAGE,
446e6ff10f2SVincent Whitchurch 	.n_voltages = DA9121_N_VOLTAGES,
447e6ff10f2SVincent Whitchurch 	.min_uV = DA9121_MIN_MV * 1000,
448e6ff10f2SVincent Whitchurch 	.uV_step = DA9121_STEP_MV * 1000,
449e6ff10f2SVincent Whitchurch 	.linear_min_sel = DA9121_MIN_SEL,
45086f162c9SAdam Ward 	.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
45186f162c9SAdam Ward 	.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
45286f162c9SAdam Ward 	.enable_reg = DA9121_REG_BUCK_BUCK1_0,
45386f162c9SAdam Ward 	.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
454e6ff10f2SVincent Whitchurch 	/* Default value of BUCK_BUCK1_0.CH1_SRC_DVC_UP */
455e6ff10f2SVincent Whitchurch 	.ramp_delay = 20000,
456e6ff10f2SVincent Whitchurch 	/* tBUCK_EN */
457e6ff10f2SVincent Whitchurch 	.enable_time = 20,
458e6ff10f2SVincent Whitchurch };
459e6ff10f2SVincent Whitchurch 
46091863239SAdam Ward static const struct regulator_desc da9220_reg[2] = {
46191863239SAdam Ward 	{
46291863239SAdam Ward 		.id = DA9121_IDX_BUCK1,
46391863239SAdam Ward 		.name = "DA9220/DA9132 BUCK1",
46491863239SAdam Ward 		.of_match = "buck1",
46546c413d5SAdam Ward 		.of_parse_cb = da9121_of_parse_cb,
46691863239SAdam Ward 		.owner = THIS_MODULE,
4673a6d93ebSChen Jiahao 		.regulators_node = "regulators",
46865ac9704SAdam Ward 		.of_map_mode = da9121_map_mode,
46991863239SAdam Ward 		.ops = &da9121_buck_ops,
47091863239SAdam Ward 		.type = REGULATOR_VOLTAGE,
47191863239SAdam Ward 		.n_voltages = DA9121_N_VOLTAGES,
47291863239SAdam Ward 		.min_uV = DA9121_MIN_MV * 1000,
47391863239SAdam Ward 		.uV_step = DA9121_STEP_MV * 1000,
47491863239SAdam Ward 		.linear_min_sel = DA9121_MIN_SEL,
47591863239SAdam Ward 		.enable_reg = DA9121_REG_BUCK_BUCK1_0,
47691863239SAdam Ward 		.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
47791863239SAdam Ward 		.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
47891863239SAdam Ward 		.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
47991863239SAdam Ward 	},
48091863239SAdam Ward 	{
48191863239SAdam Ward 		.id = DA9121_IDX_BUCK2,
48291863239SAdam Ward 		.name = "DA9220/DA9132 BUCK2",
48391863239SAdam Ward 		.of_match = "buck2",
48446c413d5SAdam Ward 		.of_parse_cb = da9121_of_parse_cb,
48591863239SAdam Ward 		.owner = THIS_MODULE,
4863a6d93ebSChen Jiahao 		.regulators_node = "regulators",
48765ac9704SAdam Ward 		.of_map_mode = da9121_map_mode,
48891863239SAdam Ward 		.ops = &da9121_buck_ops,
48991863239SAdam Ward 		.type = REGULATOR_VOLTAGE,
49091863239SAdam Ward 		.n_voltages = DA9121_N_VOLTAGES,
49191863239SAdam Ward 		.min_uV = DA9121_MIN_MV * 1000,
49291863239SAdam Ward 		.uV_step = DA9121_STEP_MV * 1000,
49391863239SAdam Ward 		.linear_min_sel = DA9121_MIN_SEL,
49491863239SAdam Ward 		.enable_reg = DA9xxx_REG_BUCK_BUCK2_0,
49591863239SAdam Ward 		.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
49691863239SAdam Ward 		.vsel_reg = DA9xxx_REG_BUCK_BUCK2_5,
49791863239SAdam Ward 		.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
49891863239SAdam Ward 	}
49991863239SAdam Ward };
50091863239SAdam Ward 
50191863239SAdam Ward static const struct regulator_desc da9122_reg[2] = {
50291863239SAdam Ward 	{
50391863239SAdam Ward 		.id = DA9121_IDX_BUCK1,
50491863239SAdam Ward 		.name = "DA9122/DA9131 BUCK1",
50591863239SAdam Ward 		.of_match = "buck1",
50646c413d5SAdam Ward 		.of_parse_cb = da9121_of_parse_cb,
50791863239SAdam Ward 		.owner = THIS_MODULE,
5083a6d93ebSChen Jiahao 		.regulators_node = "regulators",
50965ac9704SAdam Ward 		.of_map_mode = da9121_map_mode,
51091863239SAdam Ward 		.ops = &da9121_buck_ops,
51191863239SAdam Ward 		.type = REGULATOR_VOLTAGE,
51291863239SAdam Ward 		.n_voltages = DA9121_N_VOLTAGES,
51391863239SAdam Ward 		.min_uV = DA9121_MIN_MV * 1000,
51491863239SAdam Ward 		.uV_step = DA9121_STEP_MV * 1000,
51591863239SAdam Ward 		.linear_min_sel = DA9121_MIN_SEL,
51691863239SAdam Ward 		.enable_reg = DA9121_REG_BUCK_BUCK1_0,
51791863239SAdam Ward 		.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
51891863239SAdam Ward 		.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
51991863239SAdam Ward 		.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
52091863239SAdam Ward 	},
52191863239SAdam Ward 	{
52291863239SAdam Ward 		.id = DA9121_IDX_BUCK2,
52391863239SAdam Ward 		.name = "DA9122/DA9131 BUCK2",
52491863239SAdam Ward 		.of_match = "buck2",
52546c413d5SAdam Ward 		.of_parse_cb = da9121_of_parse_cb,
52691863239SAdam Ward 		.owner = THIS_MODULE,
5273a6d93ebSChen Jiahao 		.regulators_node = "regulators",
52865ac9704SAdam Ward 		.of_map_mode = da9121_map_mode,
52991863239SAdam Ward 		.ops = &da9121_buck_ops,
53091863239SAdam Ward 		.type = REGULATOR_VOLTAGE,
53191863239SAdam Ward 		.n_voltages = DA9121_N_VOLTAGES,
53291863239SAdam Ward 		.min_uV = DA9121_MIN_MV * 1000,
53391863239SAdam Ward 		.uV_step = DA9121_STEP_MV * 1000,
53491863239SAdam Ward 		.linear_min_sel = DA9121_MIN_SEL,
53591863239SAdam Ward 		.enable_reg = DA9xxx_REG_BUCK_BUCK2_0,
53691863239SAdam Ward 		.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
53791863239SAdam Ward 		.vsel_reg = DA9xxx_REG_BUCK_BUCK2_5,
53891863239SAdam Ward 		.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
53991863239SAdam Ward 	}
54091863239SAdam Ward };
54191863239SAdam Ward 
54291863239SAdam Ward static const struct regulator_desc da9217_reg = {
54391863239SAdam Ward 	.id = DA9121_IDX_BUCK1,
54491863239SAdam Ward 	.name = "DA9217 BUCK1",
54591863239SAdam Ward 	.of_match = "buck1",
54646c413d5SAdam Ward 	.of_parse_cb = da9121_of_parse_cb,
54791863239SAdam Ward 	.owner = THIS_MODULE,
5483a6d93ebSChen Jiahao 	.regulators_node = "regulators",
54965ac9704SAdam Ward 	.of_map_mode = da9121_map_mode,
55091863239SAdam Ward 	.ops = &da9121_buck_ops,
55191863239SAdam Ward 	.type = REGULATOR_VOLTAGE,
55291863239SAdam Ward 	.n_voltages = DA9121_N_VOLTAGES,
55391863239SAdam Ward 	.min_uV = DA9121_MIN_MV * 1000,
55491863239SAdam Ward 	.uV_step = DA9121_STEP_MV * 1000,
55591863239SAdam Ward 	.linear_min_sel = DA9121_MIN_SEL,
55691863239SAdam Ward 	.enable_reg = DA9121_REG_BUCK_BUCK1_0,
55791863239SAdam Ward 	.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
55891863239SAdam Ward 	.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
55991863239SAdam Ward 	.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
56091863239SAdam Ward };
56191863239SAdam Ward 
562c5187a24SAdam Ward #define DA914X_MIN_MV		500
563c8c57fbcSAdam Ward #define DA914X_MAX_MV		1300
564c5187a24SAdam Ward #define DA914X_STEP_MV		10
565c5187a24SAdam Ward #define DA914X_MIN_SEL		(DA914X_MIN_MV / DA914X_STEP_MV)
566c5187a24SAdam Ward #define DA914X_N_VOLTAGES	(((DA914X_MAX_MV - DA914X_MIN_MV) / DA914X_STEP_MV) \
567c5187a24SAdam Ward 				 + 1 + DA914X_MIN_SEL)
568c5187a24SAdam Ward 
569c5187a24SAdam Ward static const struct regulator_desc da9141_reg = {
570c5187a24SAdam Ward 	.id = DA9121_IDX_BUCK1,
571c5187a24SAdam Ward 	.name = "DA9141",
572c5187a24SAdam Ward 	.of_match = "buck1",
573c5187a24SAdam Ward 	.of_parse_cb = da9121_of_parse_cb,
574c5187a24SAdam Ward 	.owner = THIS_MODULE,
5753a6d93ebSChen Jiahao 	.regulators_node = "regulators",
576c5187a24SAdam Ward 	.of_map_mode = da9121_map_mode,
577c5187a24SAdam Ward 	.ops = &da9121_buck_ops,
578c5187a24SAdam Ward 	.type = REGULATOR_VOLTAGE,
579c5187a24SAdam Ward 	.n_voltages = DA914X_N_VOLTAGES,
580c5187a24SAdam Ward 	.min_uV = DA914X_MIN_MV * 1000,
581c5187a24SAdam Ward 	.uV_step = DA914X_STEP_MV * 1000,
582c5187a24SAdam Ward 	.linear_min_sel = DA914X_MIN_SEL,
583c5187a24SAdam Ward 	.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
584c5187a24SAdam Ward 	.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
585c5187a24SAdam Ward 	.enable_reg = DA9121_REG_BUCK_BUCK1_0,
586c5187a24SAdam Ward 	.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
587c5187a24SAdam Ward };
588c5187a24SAdam Ward 
589c5187a24SAdam Ward static const struct regulator_desc da9142_reg = {
590c5187a24SAdam Ward 	.id = DA9121_IDX_BUCK1,
591c5187a24SAdam Ward 	.name = "DA9142 BUCK1",
592c5187a24SAdam Ward 	.of_match = "buck1",
593c5187a24SAdam Ward 	.of_parse_cb = da9121_of_parse_cb,
594c5187a24SAdam Ward 	.owner = THIS_MODULE,
5953a6d93ebSChen Jiahao 	.regulators_node = "regulators",
596c5187a24SAdam Ward 	.of_map_mode = da9121_map_mode,
597c5187a24SAdam Ward 	.ops = &da9121_buck_ops,
598c5187a24SAdam Ward 	.type = REGULATOR_VOLTAGE,
599c5187a24SAdam Ward 	.n_voltages = DA914X_N_VOLTAGES,
600c5187a24SAdam Ward 	.min_uV = DA914X_MIN_MV * 1000,
601c5187a24SAdam Ward 	.uV_step = DA914X_STEP_MV * 1000,
602c5187a24SAdam Ward 	.linear_min_sel = DA914X_MIN_SEL,
603c5187a24SAdam Ward 	.enable_reg = DA9121_REG_BUCK_BUCK1_0,
604c5187a24SAdam Ward 	.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
605c5187a24SAdam Ward 	.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
606c5187a24SAdam Ward 	.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
607c5187a24SAdam Ward };
608c5187a24SAdam Ward 
609c5187a24SAdam Ward 
61091863239SAdam Ward static const struct regulator_desc *local_da9121_regulators[][DA9121_IDX_MAX] = {
61191863239SAdam Ward 	[DA9121_TYPE_DA9121_DA9130] = { &da9121_reg, NULL },
61291863239SAdam Ward 	[DA9121_TYPE_DA9220_DA9132] = { &da9220_reg[0], &da9220_reg[1] },
61391863239SAdam Ward 	[DA9121_TYPE_DA9122_DA9131] = { &da9122_reg[0], &da9122_reg[1] },
61491863239SAdam Ward 	[DA9121_TYPE_DA9217] = { &da9217_reg, NULL },
615c5187a24SAdam Ward 	[DA9121_TYPE_DA9141] = { &da9141_reg, NULL },
616c5187a24SAdam Ward 	[DA9121_TYPE_DA9142] = { &da9142_reg, NULL },
61791863239SAdam Ward };
61891863239SAdam Ward 
61940bb5b02SAdam Ward static void da9121_status_poll_on(struct work_struct *work)
62040bb5b02SAdam Ward {
62140bb5b02SAdam Ward 	struct da9121 *chip = container_of(work, struct da9121, work.work);
62240bb5b02SAdam Ward 	int status[3] = {0};
62340bb5b02SAdam Ward 	int clear[3] = {0};
62440bb5b02SAdam Ward 	unsigned long delay;
62540bb5b02SAdam Ward 	int i;
62640bb5b02SAdam Ward 	int ret;
62740bb5b02SAdam Ward 
62840bb5b02SAdam Ward 	ret = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_STATUS_0, status, 2);
62940bb5b02SAdam Ward 	if (ret < 0) {
63040bb5b02SAdam Ward 		dev_err(chip->dev,
63140bb5b02SAdam Ward 			"Failed to read STATUS registers: %d\n", ret);
63240bb5b02SAdam Ward 		goto error;
63340bb5b02SAdam Ward 	}
63440bb5b02SAdam Ward 
63540bb5b02SAdam Ward 	/* Possible events are tested to be within range for the variant, potentially
63640bb5b02SAdam Ward 	 * masked by the IRQ handler (not just warned about), as having been masked,
63740bb5b02SAdam Ward 	 * and the respective state cleared - then flagged to unmask for next IRQ.
63840bb5b02SAdam Ward 	 */
63940bb5b02SAdam Ward 	for (i = 0; i < ARRAY_SIZE(status_event_handling); i++) {
64040bb5b02SAdam Ward 		const struct status_event_data *item = &status_event_handling[i];
64140bb5b02SAdam Ward 		int reg_idx = item->reg_index;
64240bb5b02SAdam Ward 		bool relevant = (item->buck_id <= variant_parameters[chip->variant_id].num_bucks);
64340bb5b02SAdam Ward 		bool supported = (item->warn == NULL);
64440bb5b02SAdam Ward 		bool persisting = (chip->persistent[reg_idx] & item->event_bit);
64540bb5b02SAdam Ward 		bool now_cleared = !(status[reg_idx] & item->status_bit);
64640bb5b02SAdam Ward 
64740bb5b02SAdam Ward 		if (relevant && supported && persisting && now_cleared) {
64840bb5b02SAdam Ward 			clear[reg_idx] |= item->mask_bit;
64940bb5b02SAdam Ward 			chip->persistent[reg_idx] &= ~item->event_bit;
65040bb5b02SAdam Ward 		}
65140bb5b02SAdam Ward 	}
65240bb5b02SAdam Ward 
65340bb5b02SAdam Ward 	for (i = 0; i < 2; i++) {
65440bb5b02SAdam Ward 		if (clear[i]) {
65540bb5b02SAdam Ward 			unsigned int reg = DA9121_REG_SYS_MASK_0 + i;
65640bb5b02SAdam Ward 			unsigned int mbit = clear[i];
65740bb5b02SAdam Ward 
65840bb5b02SAdam Ward 			ret = regmap_update_bits(chip->regmap, reg, mbit, 0);
65940bb5b02SAdam Ward 			if (ret < 0) {
66040bb5b02SAdam Ward 				dev_err(chip->dev,
66140bb5b02SAdam Ward 					"Failed to unmask 0x%02x %d\n",
66240bb5b02SAdam Ward 					reg, ret);
66340bb5b02SAdam Ward 				goto error;
66440bb5b02SAdam Ward 			}
66540bb5b02SAdam Ward 		}
66640bb5b02SAdam Ward 	}
66740bb5b02SAdam Ward 
66840bb5b02SAdam Ward 	if (chip->persistent[0] | chip->persistent[1]) {
66940bb5b02SAdam Ward 		delay = msecs_to_jiffies(chip->passive_delay);
67040bb5b02SAdam Ward 		queue_delayed_work(system_freezable_wq, &chip->work, delay);
67140bb5b02SAdam Ward 	}
67240bb5b02SAdam Ward 
67340bb5b02SAdam Ward error:
67440bb5b02SAdam Ward 	return;
67540bb5b02SAdam Ward }
67640bb5b02SAdam Ward 
67740bb5b02SAdam Ward static irqreturn_t da9121_irq_handler(int irq, void *data)
67840bb5b02SAdam Ward {
67940bb5b02SAdam Ward 	struct da9121 *chip = data;
68040bb5b02SAdam Ward 	struct regulator_dev *rdev;
68140bb5b02SAdam Ward 	int event[3] = {0};
68240bb5b02SAdam Ward 	int handled[3] = {0};
68340bb5b02SAdam Ward 	int mask[3] = {0};
68440bb5b02SAdam Ward 	int ret = IRQ_NONE;
68540bb5b02SAdam Ward 	int i;
68640bb5b02SAdam Ward 	int err;
68740bb5b02SAdam Ward 
68840bb5b02SAdam Ward 	err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_EVENT_0, event, 3);
68940bb5b02SAdam Ward 	if (err < 0) {
69040bb5b02SAdam Ward 		dev_err(chip->dev, "Failed to read EVENT registers %d\n", err);
69140bb5b02SAdam Ward 		ret = IRQ_NONE;
69240bb5b02SAdam Ward 		goto error;
69340bb5b02SAdam Ward 	}
69440bb5b02SAdam Ward 
69540bb5b02SAdam Ward 	err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_MASK_0, mask, 3);
69640bb5b02SAdam Ward 	if (err < 0) {
69740bb5b02SAdam Ward 		dev_err(chip->dev,
69840bb5b02SAdam Ward 			"Failed to read MASK registers: %d\n", ret);
69940bb5b02SAdam Ward 		ret = IRQ_NONE;
70040bb5b02SAdam Ward 		goto error;
70140bb5b02SAdam Ward 	}
70240bb5b02SAdam Ward 
70340bb5b02SAdam Ward 	rdev = chip->rdev[DA9121_IDX_BUCK1];
70440bb5b02SAdam Ward 
70540bb5b02SAdam Ward 	/* Possible events are tested to be within range for the variant, currently
70640bb5b02SAdam Ward 	 * enabled, and having triggered this IRQ. The event may then be notified,
70740bb5b02SAdam Ward 	 * or a warning given for unexpected events - those from device POR, and
70840bb5b02SAdam Ward 	 * currently unsupported GPIO configurations.
70940bb5b02SAdam Ward 	 */
71040bb5b02SAdam Ward 	for (i = 0; i < ARRAY_SIZE(status_event_handling); i++) {
71140bb5b02SAdam Ward 		const struct status_event_data *item = &status_event_handling[i];
71240bb5b02SAdam Ward 		int reg_idx = item->reg_index;
71340bb5b02SAdam Ward 		bool relevant = (item->buck_id <= variant_parameters[chip->variant_id].num_bucks);
71440bb5b02SAdam Ward 		bool enabled = !(mask[reg_idx] & item->mask_bit);
71540bb5b02SAdam Ward 		bool active = (event[reg_idx] & item->event_bit);
71640bb5b02SAdam Ward 		bool notify = (item->warn == NULL);
71740bb5b02SAdam Ward 
71840bb5b02SAdam Ward 		if (relevant && enabled && active) {
71940bb5b02SAdam Ward 			if (notify) {
72040bb5b02SAdam Ward 				chip->persistent[reg_idx] |= item->event_bit;
72140bb5b02SAdam Ward 				regulator_notifier_call_chain(rdev, item->notification, NULL);
72240bb5b02SAdam Ward 			} else {
72340bb5b02SAdam Ward 				dev_warn(chip->dev, item->warn);
72440bb5b02SAdam Ward 				handled[reg_idx] |= item->event_bit;
72540bb5b02SAdam Ward 				ret = IRQ_HANDLED;
72640bb5b02SAdam Ward 			}
72740bb5b02SAdam Ward 		}
72840bb5b02SAdam Ward 	}
72940bb5b02SAdam Ward 
73040bb5b02SAdam Ward 	for (i = 0; i < 3; i++) {
73140bb5b02SAdam Ward 		if (event[i] != handled[i]) {
73240bb5b02SAdam Ward 			dev_warn(chip->dev,
73340bb5b02SAdam Ward 				"Unhandled event(s) in bank%d 0x%02x\n", i,
73440bb5b02SAdam Ward 				event[i] ^ handled[i]);
73540bb5b02SAdam Ward 		}
73640bb5b02SAdam Ward 	}
73740bb5b02SAdam Ward 
73840bb5b02SAdam Ward 	/* Mask the interrupts for persistent events OV, OC, UV, WARN, CRIT */
73940bb5b02SAdam Ward 	for (i = 0; i < 2; i++) {
74040bb5b02SAdam Ward 		if (handled[i]) {
74140bb5b02SAdam Ward 			unsigned int reg = DA9121_REG_SYS_MASK_0 + i;
74240bb5b02SAdam Ward 			unsigned int mbit = handled[i];
74340bb5b02SAdam Ward 
74440bb5b02SAdam Ward 			err = regmap_update_bits(chip->regmap, reg, mbit, mbit);
74540bb5b02SAdam Ward 			if (err < 0) {
74640bb5b02SAdam Ward 				dev_err(chip->dev,
74740bb5b02SAdam Ward 					"Failed to mask 0x%02x interrupt %d\n",
74840bb5b02SAdam Ward 					reg, err);
74940bb5b02SAdam Ward 				ret = IRQ_NONE;
75040bb5b02SAdam Ward 				goto error;
75140bb5b02SAdam Ward 			}
75240bb5b02SAdam Ward 		}
75340bb5b02SAdam Ward 	}
75440bb5b02SAdam Ward 
75540bb5b02SAdam Ward 	/* clear the events */
75640bb5b02SAdam Ward 	if (handled[0] | handled[1] | handled[2]) {
75740bb5b02SAdam Ward 		err = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_EVENT_0, handled, 3);
75840bb5b02SAdam Ward 		if (err < 0) {
75940bb5b02SAdam Ward 			dev_err(chip->dev, "Fail to write EVENTs %d\n", err);
76040bb5b02SAdam Ward 			ret = IRQ_NONE;
76140bb5b02SAdam Ward 			goto error;
76240bb5b02SAdam Ward 		}
76340bb5b02SAdam Ward 	}
76440bb5b02SAdam Ward 
76540bb5b02SAdam Ward 	queue_delayed_work(system_freezable_wq, &chip->work, 0);
76640bb5b02SAdam Ward error:
76740bb5b02SAdam Ward 	return ret;
76840bb5b02SAdam Ward }
76940bb5b02SAdam Ward 
7709929900dSAdam Ward static int da9121_set_regulator_config(struct da9121 *chip)
7719929900dSAdam Ward {
7729929900dSAdam Ward 	struct regulator_config config = { };
7739929900dSAdam Ward 	unsigned int max_matches = variant_parameters[chip->variant_id].num_bucks;
7749929900dSAdam Ward 	int ret = 0;
7759929900dSAdam Ward 	int i;
7769929900dSAdam Ward 
7779929900dSAdam Ward 	for (i = 0; i < max_matches; i++) {
7789929900dSAdam Ward 		const struct regulator_desc *regl_desc =
7799929900dSAdam Ward 			local_da9121_regulators[chip->variant_id][i];
7809929900dSAdam Ward 
7819929900dSAdam Ward 		config.dev = chip->dev;
7829929900dSAdam Ward 		config.driver_data = chip;
7839929900dSAdam Ward 		config.regmap = chip->regmap;
7849929900dSAdam Ward 
7859929900dSAdam Ward 		chip->rdev[i] = devm_regulator_register(chip->dev,
7869929900dSAdam Ward 					regl_desc, &config);
7879929900dSAdam Ward 		if (IS_ERR(chip->rdev[i])) {
7889929900dSAdam Ward 			dev_err(chip->dev, "Failed to register regulator %s, %d/%d\n",
7899929900dSAdam Ward 				regl_desc->name, (i+1), max_matches);
7909929900dSAdam Ward 			ret = PTR_ERR(chip->rdev[i]);
7919929900dSAdam Ward 			goto error;
7929929900dSAdam Ward 		}
7939929900dSAdam Ward 	}
7949929900dSAdam Ward 
7959929900dSAdam Ward error:
7969929900dSAdam Ward 	return ret;
7979929900dSAdam Ward }
7989929900dSAdam Ward 
799c860476bSAdam Ward /* DA9121 chip register model */
800c860476bSAdam Ward static const struct regmap_range da9121_1ch_readable_ranges[] = {
801c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3),
802c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
803c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
804c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6),
805c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID),
806c860476bSAdam Ward };
807c860476bSAdam Ward 
808c860476bSAdam Ward static const struct regmap_access_table da9121_1ch_readable_table = {
809c860476bSAdam Ward 	.yes_ranges = da9121_1ch_readable_ranges,
810c860476bSAdam Ward 	.n_yes_ranges = ARRAY_SIZE(da9121_1ch_readable_ranges),
811c860476bSAdam Ward };
812c860476bSAdam Ward 
813c860476bSAdam Ward static const struct regmap_range da9121_2ch_readable_ranges[] = {
814c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3),
815c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
816c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
817c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_7),
818c860476bSAdam Ward 	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_7),
819c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID),
820c860476bSAdam Ward };
821c860476bSAdam Ward 
822c860476bSAdam Ward static const struct regmap_access_table da9121_2ch_readable_table = {
823c860476bSAdam Ward 	.yes_ranges = da9121_2ch_readable_ranges,
824c860476bSAdam Ward 	.n_yes_ranges = ARRAY_SIZE(da9121_2ch_readable_ranges),
825c860476bSAdam Ward };
826c860476bSAdam Ward 
827c860476bSAdam Ward static const struct regmap_range da9121_1ch_writeable_ranges[] = {
828c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3),
829c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
830c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
831c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2),
832c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_6),
833c860476bSAdam Ward };
834c860476bSAdam Ward 
835c860476bSAdam Ward static const struct regmap_access_table da9121_1ch_writeable_table = {
836c860476bSAdam Ward 	.yes_ranges = da9121_1ch_writeable_ranges,
837c860476bSAdam Ward 	.n_yes_ranges = ARRAY_SIZE(da9121_1ch_writeable_ranges),
838c860476bSAdam Ward };
839c860476bSAdam Ward 
840c860476bSAdam Ward static const struct regmap_range da9121_2ch_writeable_ranges[] = {
841c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3),
842c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
843c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
844c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2),
845c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_7),
846c860476bSAdam Ward 	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_2),
847c860476bSAdam Ward 	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_4, DA9xxx_REG_BUCK_BUCK2_7),
848c860476bSAdam Ward };
849c860476bSAdam Ward 
850c860476bSAdam Ward static const struct regmap_access_table da9121_2ch_writeable_table = {
851c860476bSAdam Ward 	.yes_ranges = da9121_2ch_writeable_ranges,
852c860476bSAdam Ward 	.n_yes_ranges = ARRAY_SIZE(da9121_2ch_writeable_ranges),
853c860476bSAdam Ward };
854c860476bSAdam Ward 
855c860476bSAdam Ward 
856c860476bSAdam Ward static const struct regmap_range da9121_volatile_ranges[] = {
857c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_EVENT_2),
858c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
859c860476bSAdam Ward 	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6),
860c860476bSAdam Ward };
861c860476bSAdam Ward 
862c860476bSAdam Ward static const struct regmap_access_table da9121_volatile_table = {
863c860476bSAdam Ward 	.yes_ranges = da9121_volatile_ranges,
864c860476bSAdam Ward 	.n_yes_ranges = ARRAY_SIZE(da9121_volatile_ranges),
865c860476bSAdam Ward };
866c860476bSAdam Ward 
867c860476bSAdam Ward /* DA9121 regmap config for 1 channel variants */
868*05db2e27SJavier Carrasco static const struct regmap_config da9121_1ch_regmap_config = {
869c860476bSAdam Ward 	.reg_bits = 8,
870c860476bSAdam Ward 	.val_bits = 8,
871c860476bSAdam Ward 	.max_register = DA9121_REG_OTP_CONFIG_ID,
872c860476bSAdam Ward 	.rd_table = &da9121_1ch_readable_table,
873c860476bSAdam Ward 	.wr_table = &da9121_1ch_writeable_table,
874c860476bSAdam Ward 	.volatile_table = &da9121_volatile_table,
875d92eb7c3SBo Liu 	.cache_type = REGCACHE_MAPLE,
876c860476bSAdam Ward };
877c860476bSAdam Ward 
878c860476bSAdam Ward /* DA9121 regmap config for 2 channel variants */
879*05db2e27SJavier Carrasco static const struct regmap_config da9121_2ch_regmap_config = {
880c860476bSAdam Ward 	.reg_bits = 8,
881c860476bSAdam Ward 	.val_bits = 8,
882c860476bSAdam Ward 	.max_register = DA9121_REG_OTP_CONFIG_ID,
883c860476bSAdam Ward 	.rd_table = &da9121_2ch_readable_table,
884c860476bSAdam Ward 	.wr_table = &da9121_2ch_writeable_table,
885c860476bSAdam Ward 	.volatile_table = &da9121_volatile_table,
886d92eb7c3SBo Liu 	.cache_type = REGCACHE_MAPLE,
887c860476bSAdam Ward };
888c860476bSAdam Ward 
889c860476bSAdam Ward static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
890c860476bSAdam Ward {
891c860476bSAdam Ward 	u32 device_id;
892c860476bSAdam Ward 	u32 variant_id;
893c860476bSAdam Ward 	u8 variant_mrc, variant_vrc;
894c860476bSAdam Ward 	char *type;
895c860476bSAdam Ward 	bool config_match = false;
896c860476bSAdam Ward 	int ret = 0;
897c860476bSAdam Ward 
898c860476bSAdam Ward 	ret = regmap_read(chip->regmap, DA9121_REG_OTP_DEVICE_ID, &device_id);
899c860476bSAdam Ward 	if (ret < 0) {
900c860476bSAdam Ward 		dev_err(chip->dev, "Cannot read device ID: %d\n", ret);
901c860476bSAdam Ward 		goto error;
902c860476bSAdam Ward 	}
903c860476bSAdam Ward 
904c860476bSAdam Ward 	ret = regmap_read(chip->regmap, DA9121_REG_OTP_VARIANT_ID, &variant_id);
905c860476bSAdam Ward 	if (ret < 0) {
906c860476bSAdam Ward 		dev_err(chip->dev, "Cannot read variant ID: %d\n", ret);
907c860476bSAdam Ward 		goto error;
908c860476bSAdam Ward 	}
909c860476bSAdam Ward 
910c5187a24SAdam Ward 	if ((device_id != DA9121_DEVICE_ID) && (device_id != DA914x_DEVICE_ID)) {
911c860476bSAdam Ward 		dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
912c860476bSAdam Ward 		ret = -ENODEV;
913c860476bSAdam Ward 		goto error;
914c860476bSAdam Ward 	}
915c860476bSAdam Ward 
916c860476bSAdam Ward 	variant_vrc = variant_id & DA9121_MASK_OTP_VARIANT_ID_VRC;
917c860476bSAdam Ward 
918013592beSAdam Ward 	switch (chip->subvariant_id) {
919013592beSAdam Ward 	case DA9121_SUBTYPE_DA9121:
920013592beSAdam Ward 		type = "DA9121";
921013592beSAdam Ward 		config_match = (variant_vrc == DA9121_VARIANT_VRC);
922c860476bSAdam Ward 		break;
923013592beSAdam Ward 	case DA9121_SUBTYPE_DA9130:
924013592beSAdam Ward 		type = "DA9130";
925013592beSAdam Ward 		config_match = (variant_vrc == DA9130_VARIANT_VRC);
926c860476bSAdam Ward 		break;
927013592beSAdam Ward 	case DA9121_SUBTYPE_DA9220:
928013592beSAdam Ward 		type = "DA9220";
929013592beSAdam Ward 		config_match = (variant_vrc == DA9220_VARIANT_VRC);
930c860476bSAdam Ward 		break;
931013592beSAdam Ward 	case DA9121_SUBTYPE_DA9132:
932013592beSAdam Ward 		type = "DA9132";
933013592beSAdam Ward 		config_match = (variant_vrc == DA9132_VARIANT_VRC);
934013592beSAdam Ward 		break;
935013592beSAdam Ward 	case DA9121_SUBTYPE_DA9122:
936013592beSAdam Ward 		type = "DA9122";
937013592beSAdam Ward 		config_match = (variant_vrc == DA9122_VARIANT_VRC);
938013592beSAdam Ward 		break;
939013592beSAdam Ward 	case DA9121_SUBTYPE_DA9131:
940013592beSAdam Ward 		type = "DA9131";
941013592beSAdam Ward 		config_match = (variant_vrc == DA9131_VARIANT_VRC);
942013592beSAdam Ward 		break;
943013592beSAdam Ward 	case DA9121_SUBTYPE_DA9217:
944c860476bSAdam Ward 		type = "DA9217";
945013592beSAdam Ward 		config_match = (variant_vrc == DA9217_VARIANT_VRC);
946c860476bSAdam Ward 		break;
947c860476bSAdam Ward 	default:
948c860476bSAdam Ward 		type = "Unknown";
949c860476bSAdam Ward 		break;
950c860476bSAdam Ward 	}
951c860476bSAdam Ward 
952c5187a24SAdam Ward 	if (device_id == DA914x_DEVICE_ID) {
953c5187a24SAdam Ward 		switch (chip->subvariant_id) {
954c5187a24SAdam Ward 		case DA9121_SUBTYPE_DA9141:
955c5187a24SAdam Ward 			type = "DA9141";
956c5187a24SAdam Ward 			config_match = (variant_vrc == DA9141_VARIANT_VRC);
957c5187a24SAdam Ward 			break;
958c5187a24SAdam Ward 		case DA9121_SUBTYPE_DA9142:
959c5187a24SAdam Ward 			type = "DA9142";
960c5187a24SAdam Ward 			config_match = (variant_vrc == DA9142_VARIANT_VRC);
961c5187a24SAdam Ward 			break;
962c5187a24SAdam Ward 		default:
963c5187a24SAdam Ward 			type = "Unknown";
964c5187a24SAdam Ward 			break;
965c5187a24SAdam Ward 		}
966c5187a24SAdam Ward 	}
967c5187a24SAdam Ward 
968c860476bSAdam Ward 	dev_info(chip->dev,
969c860476bSAdam Ward 		 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
970c860476bSAdam Ward 		 device_id, variant_id, type);
971c860476bSAdam Ward 
972c860476bSAdam Ward 	if (!config_match) {
973416c29e9SAdam Ward 		dev_err(chip->dev, "Device tree configuration does not match detected device.\n");
974c860476bSAdam Ward 		ret = -EINVAL;
975c860476bSAdam Ward 		goto error;
976c860476bSAdam Ward 	}
977c860476bSAdam Ward 
978c860476bSAdam Ward 	variant_mrc = (variant_id & DA9121_MASK_OTP_VARIANT_ID_MRC)
979c860476bSAdam Ward 			>> DA9121_SHIFT_OTP_VARIANT_ID_MRC;
980c860476bSAdam Ward 
981c5187a24SAdam Ward 	if (((device_id == DA9121_DEVICE_ID) &&
982c5187a24SAdam Ward 	     (variant_mrc < DA9121_VARIANT_MRC_BASE)) ||
983c5187a24SAdam Ward 	    ((device_id == DA914x_DEVICE_ID) &&
984c5187a24SAdam Ward 	     (variant_mrc != DA914x_VARIANT_MRC_BASE))) {
985c860476bSAdam Ward 		dev_err(chip->dev,
986c860476bSAdam Ward 			"Cannot support variant MRC: 0x%02X\n", variant_mrc);
987c860476bSAdam Ward 		ret = -EINVAL;
988c860476bSAdam Ward 	}
989c860476bSAdam Ward error:
990c860476bSAdam Ward 	return ret;
991c860476bSAdam Ward }
992c860476bSAdam Ward 
993c860476bSAdam Ward static int da9121_assign_chip_model(struct i2c_client *i2c,
994c860476bSAdam Ward 			struct da9121 *chip)
995c860476bSAdam Ward {
996*05db2e27SJavier Carrasco 	const struct regmap_config *regmap;
997c860476bSAdam Ward 	int ret = 0;
998c860476bSAdam Ward 
999c860476bSAdam Ward 	chip->dev = &i2c->dev;
1000c860476bSAdam Ward 
1001013592beSAdam Ward 	/* Use configured subtype to select the regulator descriptor index and
1002013592beSAdam Ward 	 * register map, common to both consumer and automotive grade variants
1003013592beSAdam Ward 	 */
1004013592beSAdam Ward 	switch (chip->subvariant_id) {
1005013592beSAdam Ward 	case DA9121_SUBTYPE_DA9121:
1006013592beSAdam Ward 	case DA9121_SUBTYPE_DA9130:
1007013592beSAdam Ward 		chip->variant_id = DA9121_TYPE_DA9121_DA9130;
1008c860476bSAdam Ward 		regmap = &da9121_1ch_regmap_config;
1009c860476bSAdam Ward 		break;
1010013592beSAdam Ward 	case DA9121_SUBTYPE_DA9217:
1011013592beSAdam Ward 		chip->variant_id = DA9121_TYPE_DA9217;
1012013592beSAdam Ward 		regmap = &da9121_1ch_regmap_config;
1013013592beSAdam Ward 		break;
1014013592beSAdam Ward 	case DA9121_SUBTYPE_DA9122:
1015013592beSAdam Ward 	case DA9121_SUBTYPE_DA9131:
1016013592beSAdam Ward 		chip->variant_id = DA9121_TYPE_DA9122_DA9131;
1017013592beSAdam Ward 		regmap = &da9121_2ch_regmap_config;
1018013592beSAdam Ward 		break;
1019013592beSAdam Ward 	case DA9121_SUBTYPE_DA9220:
1020013592beSAdam Ward 	case DA9121_SUBTYPE_DA9132:
1021013592beSAdam Ward 		chip->variant_id = DA9121_TYPE_DA9220_DA9132;
1022c860476bSAdam Ward 		regmap = &da9121_2ch_regmap_config;
1023c860476bSAdam Ward 		break;
1024c5187a24SAdam Ward 	case DA9121_SUBTYPE_DA9141:
1025c5187a24SAdam Ward 		chip->variant_id = DA9121_TYPE_DA9141;
1026c5187a24SAdam Ward 		regmap = &da9121_1ch_regmap_config;
1027c5187a24SAdam Ward 		break;
1028c5187a24SAdam Ward 	case DA9121_SUBTYPE_DA9142:
1029c5187a24SAdam Ward 		chip->variant_id = DA9121_TYPE_DA9142;
1030c5187a24SAdam Ward 		regmap = &da9121_2ch_regmap_config;
1031c5187a24SAdam Ward 		break;
1032bab76514SWei Yongjun 	default:
1033bab76514SWei Yongjun 		return -EINVAL;
1034c860476bSAdam Ward 	}
1035c860476bSAdam Ward 
103691863239SAdam Ward 	/* Set these up for of_regulator_match call which may want .of_map_modes */
103791863239SAdam Ward 	da9121_matches[0].desc = local_da9121_regulators[chip->variant_id][0];
103891863239SAdam Ward 	da9121_matches[1].desc = local_da9121_regulators[chip->variant_id][1];
103991863239SAdam Ward 
1040c860476bSAdam Ward 	chip->regmap = devm_regmap_init_i2c(i2c, regmap);
1041c860476bSAdam Ward 	if (IS_ERR(chip->regmap)) {
1042c860476bSAdam Ward 		ret = PTR_ERR(chip->regmap);
1043c860476bSAdam Ward 		dev_err(chip->dev, "Failed to configure a register map: %d\n",
1044c860476bSAdam Ward 			ret);
10458db06423SDan Carpenter 		return ret;
1046c860476bSAdam Ward 	}
1047c860476bSAdam Ward 
1048c860476bSAdam Ward 	ret = da9121_check_device_type(i2c, chip);
1049c860476bSAdam Ward 
1050c860476bSAdam Ward 	return ret;
1051c860476bSAdam Ward }
1052c860476bSAdam Ward 
105340bb5b02SAdam Ward static int da9121_config_irq(struct i2c_client *i2c,
105440bb5b02SAdam Ward 			struct da9121 *chip)
105540bb5b02SAdam Ward {
105640bb5b02SAdam Ward 	unsigned int p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS;
105740bb5b02SAdam Ward 	const int mask_all[4] = { 0, 0, 0xFF, 0xFF };
105840bb5b02SAdam Ward 	int ret = 0;
105940bb5b02SAdam Ward 
106040bb5b02SAdam Ward 	chip->chip_irq = i2c->irq;
106140bb5b02SAdam Ward 
106240bb5b02SAdam Ward 	if (chip->chip_irq != 0) {
106340bb5b02SAdam Ward 		if (!of_property_read_u32(chip->dev->of_node,
106440bb5b02SAdam Ward 					  "dlg,irq-polling-delay-passive-ms",
106540bb5b02SAdam Ward 					  &p_delay)) {
106640bb5b02SAdam Ward 			if (p_delay < DA9121_MIN_POLLING_PERIOD_MS ||
106740bb5b02SAdam Ward 			    p_delay > DA9121_MAX_POLLING_PERIOD_MS) {
106840bb5b02SAdam Ward 				dev_warn(chip->dev,
106940bb5b02SAdam Ward 					 "Out-of-range polling period %d ms\n",
107040bb5b02SAdam Ward 					 p_delay);
107140bb5b02SAdam Ward 				p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS;
107240bb5b02SAdam Ward 			}
107340bb5b02SAdam Ward 		}
107440bb5b02SAdam Ward 
107540bb5b02SAdam Ward 		chip->passive_delay = p_delay;
107640bb5b02SAdam Ward 
10775e191d2eSAdam Ward 		ret = request_threaded_irq(chip->chip_irq, NULL,
107840bb5b02SAdam Ward 					da9121_irq_handler,
107940bb5b02SAdam Ward 					IRQF_TRIGGER_LOW|IRQF_ONESHOT,
108040bb5b02SAdam Ward 					"da9121", chip);
108140bb5b02SAdam Ward 		if (ret != 0) {
108240bb5b02SAdam Ward 			dev_err(chip->dev, "Failed IRQ request: %d\n",
108340bb5b02SAdam Ward 				chip->chip_irq);
108440bb5b02SAdam Ward 			goto error;
108540bb5b02SAdam Ward 		}
108640bb5b02SAdam Ward 
108740bb5b02SAdam Ward 		ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4);
108840bb5b02SAdam Ward 		if (ret != 0) {
108940bb5b02SAdam Ward 			dev_err(chip->dev, "Failed to set IRQ masks: %d\n",
109040bb5b02SAdam Ward 				ret);
10915e191d2eSAdam Ward 			goto regmap_error;
109240bb5b02SAdam Ward 		}
109340bb5b02SAdam Ward 
109440bb5b02SAdam Ward 		INIT_DELAYED_WORK(&chip->work, da9121_status_poll_on);
109540bb5b02SAdam Ward 		dev_info(chip->dev, "Interrupt polling period set at %d ms\n",
109640bb5b02SAdam Ward 			 chip->passive_delay);
109740bb5b02SAdam Ward 	}
109840bb5b02SAdam Ward error:
109940bb5b02SAdam Ward 	return ret;
11005e191d2eSAdam Ward regmap_error:
11015e191d2eSAdam Ward 	free_irq(chip->chip_irq, chip);
11025e191d2eSAdam Ward 	return ret;
110340bb5b02SAdam Ward }
110440bb5b02SAdam Ward 
1105e6ff10f2SVincent Whitchurch static const struct of_device_id da9121_dt_ids[] = {
1106013592beSAdam Ward 	{ .compatible = "dlg,da9121", .data = (void *) DA9121_SUBTYPE_DA9121 },
1107013592beSAdam Ward 	{ .compatible = "dlg,da9130", .data = (void *) DA9121_SUBTYPE_DA9130 },
1108013592beSAdam Ward 	{ .compatible = "dlg,da9217", .data = (void *) DA9121_SUBTYPE_DA9217 },
1109013592beSAdam Ward 	{ .compatible = "dlg,da9122", .data = (void *) DA9121_SUBTYPE_DA9122 },
1110013592beSAdam Ward 	{ .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 },
1111013592beSAdam Ward 	{ .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 },
1112013592beSAdam Ward 	{ .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 },
1113c5187a24SAdam Ward 	{ .compatible = "dlg,da9141", .data = (void *) DA9121_SUBTYPE_DA9141 },
1114c5187a24SAdam Ward 	{ .compatible = "dlg,da9142", .data = (void *) DA9121_SUBTYPE_DA9142 },
1115e6ff10f2SVincent Whitchurch 	{ }
1116e6ff10f2SVincent Whitchurch };
1117e6ff10f2SVincent Whitchurch MODULE_DEVICE_TABLE(of, da9121_dt_ids);
1118e6ff10f2SVincent Whitchurch 
1119020cf73bSUwe Kleine-König static int da9121_i2c_probe(struct i2c_client *i2c)
1120e6ff10f2SVincent Whitchurch {
1121f3fbd556SAdam Ward 	struct da9121 *chip;
112240bb5b02SAdam Ward 	const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
1123f3fbd556SAdam Ward 	int ret = 0;
1124e6ff10f2SVincent Whitchurch 
1125f3fbd556SAdam Ward 	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9121), GFP_KERNEL);
1126f3fbd556SAdam Ward 	if (!chip) {
1127f3fbd556SAdam Ward 		ret = -ENOMEM;
1128f3fbd556SAdam Ward 		goto error;
1129f3fbd556SAdam Ward 	}
1130f3fbd556SAdam Ward 
113146c413d5SAdam Ward 	chip->pdata = i2c->dev.platform_data;
113246537a86SRob Herring 	chip->subvariant_id = (enum da9121_subvariant)i2c_get_match_data(i2c);
1133f3fbd556SAdam Ward 
1134c860476bSAdam Ward 	ret = da9121_assign_chip_model(i2c, chip);
1135c860476bSAdam Ward 	if (ret < 0)
1136c860476bSAdam Ward 		goto error;
1137e6ff10f2SVincent Whitchurch 
113840bb5b02SAdam Ward 	ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4);
113940bb5b02SAdam Ward 	if (ret != 0) {
114040bb5b02SAdam Ward 		dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret);
114140bb5b02SAdam Ward 		goto error;
114240bb5b02SAdam Ward 	}
114340bb5b02SAdam Ward 
11449929900dSAdam Ward 	ret = da9121_set_regulator_config(chip);
114540bb5b02SAdam Ward 	if (ret < 0)
114640bb5b02SAdam Ward 		goto error;
114740bb5b02SAdam Ward 
114840bb5b02SAdam Ward 	ret = da9121_config_irq(i2c, chip);
1149e6ff10f2SVincent Whitchurch 
1150f3fbd556SAdam Ward error:
1151f3fbd556SAdam Ward 	return ret;
1152e6ff10f2SVincent Whitchurch }
1153e6ff10f2SVincent Whitchurch 
1154ed5c2f5fSUwe Kleine-König static void da9121_i2c_remove(struct i2c_client *i2c)
115540bb5b02SAdam Ward {
115640bb5b02SAdam Ward 	struct da9121 *chip = i2c_get_clientdata(i2c);
115740bb5b02SAdam Ward 	const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
11584950486cSUwe Kleine-König 	int ret;
115940bb5b02SAdam Ward 
11605e191d2eSAdam Ward 	free_irq(chip->chip_irq, chip);
116140bb5b02SAdam Ward 	cancel_delayed_work_sync(&chip->work);
116240bb5b02SAdam Ward 
116340bb5b02SAdam Ward 	ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4);
116440bb5b02SAdam Ward 	if (ret != 0)
116540bb5b02SAdam Ward 		dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret);
116640bb5b02SAdam Ward }
116740bb5b02SAdam Ward 
1168e6ff10f2SVincent Whitchurch static const struct i2c_device_id da9121_i2c_id[] = {
1169f3fbd556SAdam Ward 	{"da9121", DA9121_TYPE_DA9121_DA9130},
1170f3fbd556SAdam Ward 	{"da9130", DA9121_TYPE_DA9121_DA9130},
1171f3fbd556SAdam Ward 	{"da9217", DA9121_TYPE_DA9217},
1172f3fbd556SAdam Ward 	{"da9122", DA9121_TYPE_DA9122_DA9131},
1173f3fbd556SAdam Ward 	{"da9131", DA9121_TYPE_DA9122_DA9131},
1174f3fbd556SAdam Ward 	{"da9220", DA9121_TYPE_DA9220_DA9132},
1175f3fbd556SAdam Ward 	{"da9132", DA9121_TYPE_DA9220_DA9132},
1176c5187a24SAdam Ward 	{"da9141", DA9121_TYPE_DA9141},
1177c5187a24SAdam Ward 	{"da9142", DA9121_TYPE_DA9142},
1178e6ff10f2SVincent Whitchurch 	{},
1179e6ff10f2SVincent Whitchurch };
1180e6ff10f2SVincent Whitchurch MODULE_DEVICE_TABLE(i2c, da9121_i2c_id);
1181e6ff10f2SVincent Whitchurch 
1182e6ff10f2SVincent Whitchurch static struct i2c_driver da9121_regulator_driver = {
1183e6ff10f2SVincent Whitchurch 	.driver = {
1184e6ff10f2SVincent Whitchurch 		.name = "da9121",
118546600ab1SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
11863a6d93ebSChen Jiahao 		.of_match_table = da9121_dt_ids,
1187e6ff10f2SVincent Whitchurch 	},
1188964e1865SUwe Kleine-König 	.probe = da9121_i2c_probe,
118940bb5b02SAdam Ward 	.remove = da9121_i2c_remove,
1190e6ff10f2SVincent Whitchurch 	.id_table = da9121_i2c_id,
1191e6ff10f2SVincent Whitchurch };
1192e6ff10f2SVincent Whitchurch 
1193e6ff10f2SVincent Whitchurch module_i2c_driver(da9121_regulator_driver);
1194e6ff10f2SVincent Whitchurch 
11958a2744f2SJeff Johnson MODULE_DESCRIPTION("Dialog Semiconductor DA9121/DA9122/DA9220/DA9217/DA9130/DA9131/DA9132 regulator driver");
1196e6ff10f2SVincent Whitchurch MODULE_LICENSE("GPL v2");
1197