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