162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// DA9121 Single-channel dual-phase 10A buck converter 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (C) 2020 Axis Communications AB 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// DA9130 Single-channel dual-phase 10A buck converter (Automotive) 862306a36Sopenharmony_ci// DA9217 Single-channel dual-phase 6A buck converter 962306a36Sopenharmony_ci// DA9122 Dual-channel single-phase 5A buck converter 1062306a36Sopenharmony_ci// DA9131 Dual-channel single-phase 5A buck converter (Automotive) 1162306a36Sopenharmony_ci// DA9220 Dual-channel single-phase 3A buck converter 1262306a36Sopenharmony_ci// DA9132 Dual-channel single-phase 3A buck converter (Automotive) 1362306a36Sopenharmony_ci// 1462306a36Sopenharmony_ci// Copyright (C) 2020 Dialog Semiconductor 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/of_device.h> 1762306a36Sopenharmony_ci#include <linux/of_gpio.h> 1862306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1962306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2062306a36Sopenharmony_ci#include <linux/regulator/machine.h> 2162306a36Sopenharmony_ci#include <linux/regulator/driver.h> 2262306a36Sopenharmony_ci#include <linux/module.h> 2362306a36Sopenharmony_ci#include <linux/regmap.h> 2462306a36Sopenharmony_ci#include <linux/err.h> 2562306a36Sopenharmony_ci#include <linux/i2c.h> 2662306a36Sopenharmony_ci#include <linux/regulator/da9121.h> 2762306a36Sopenharmony_ci#include <linux/interrupt.h> 2862306a36Sopenharmony_ci#include <linux/workqueue.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include "da9121-regulator.h" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Chip data */ 3362306a36Sopenharmony_cistruct da9121 { 3462306a36Sopenharmony_ci struct device *dev; 3562306a36Sopenharmony_ci struct delayed_work work; 3662306a36Sopenharmony_ci struct da9121_pdata *pdata; 3762306a36Sopenharmony_ci struct regmap *regmap; 3862306a36Sopenharmony_ci struct regulator_dev *rdev[DA9121_IDX_MAX]; 3962306a36Sopenharmony_ci unsigned int persistent[2]; 4062306a36Sopenharmony_ci unsigned int passive_delay; 4162306a36Sopenharmony_ci int chip_irq; 4262306a36Sopenharmony_ci int variant_id; 4362306a36Sopenharmony_ci int subvariant_id; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Define ranges for different variants, enabling translation to/from 4762306a36Sopenharmony_ci * registers. Maximums give scope to allow for transients. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_cistruct da9121_range { 5062306a36Sopenharmony_ci int val_min; 5162306a36Sopenharmony_ci int val_max; 5262306a36Sopenharmony_ci int val_stp; 5362306a36Sopenharmony_ci int reg_min; 5462306a36Sopenharmony_ci int reg_max; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic struct da9121_range da9121_10A_2phase_current = { 5862306a36Sopenharmony_ci .val_min = 7000000, 5962306a36Sopenharmony_ci .val_max = 20000000, 6062306a36Sopenharmony_ci .val_stp = 1000000, 6162306a36Sopenharmony_ci .reg_min = 1, 6262306a36Sopenharmony_ci .reg_max = 14, 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic struct da9121_range da9121_6A_2phase_current = { 6662306a36Sopenharmony_ci .val_min = 7000000, 6762306a36Sopenharmony_ci .val_max = 12000000, 6862306a36Sopenharmony_ci .val_stp = 1000000, 6962306a36Sopenharmony_ci .reg_min = 1, 7062306a36Sopenharmony_ci .reg_max = 6, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic struct da9121_range da9121_5A_1phase_current = { 7462306a36Sopenharmony_ci .val_min = 3500000, 7562306a36Sopenharmony_ci .val_max = 10000000, 7662306a36Sopenharmony_ci .val_stp = 500000, 7762306a36Sopenharmony_ci .reg_min = 1, 7862306a36Sopenharmony_ci .reg_max = 14, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic struct da9121_range da9121_3A_1phase_current = { 8262306a36Sopenharmony_ci .val_min = 3500000, 8362306a36Sopenharmony_ci .val_max = 6000000, 8462306a36Sopenharmony_ci .val_stp = 500000, 8562306a36Sopenharmony_ci .reg_min = 1, 8662306a36Sopenharmony_ci .reg_max = 6, 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic struct da9121_range da914x_40A_4phase_current = { 9062306a36Sopenharmony_ci .val_min = 26000000, 9162306a36Sopenharmony_ci .val_max = 78000000, 9262306a36Sopenharmony_ci .val_stp = 4000000, 9362306a36Sopenharmony_ci .reg_min = 1, 9462306a36Sopenharmony_ci .reg_max = 14, 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic struct da9121_range da914x_20A_2phase_current = { 9862306a36Sopenharmony_ci .val_min = 13000000, 9962306a36Sopenharmony_ci .val_max = 39000000, 10062306a36Sopenharmony_ci .val_stp = 2000000, 10162306a36Sopenharmony_ci .reg_min = 1, 10262306a36Sopenharmony_ci .reg_max = 14, 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct da9121_variant_info { 10662306a36Sopenharmony_ci int num_bucks; 10762306a36Sopenharmony_ci int num_phases; 10862306a36Sopenharmony_ci struct da9121_range *current_range; 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic const struct da9121_variant_info variant_parameters[] = { 11262306a36Sopenharmony_ci { 1, 2, &da9121_10A_2phase_current }, //DA9121_TYPE_DA9121_DA9130 11362306a36Sopenharmony_ci { 2, 1, &da9121_3A_1phase_current }, //DA9121_TYPE_DA9220_DA9132 11462306a36Sopenharmony_ci { 2, 1, &da9121_5A_1phase_current }, //DA9121_TYPE_DA9122_DA9131 11562306a36Sopenharmony_ci { 1, 2, &da9121_6A_2phase_current }, //DA9121_TYPE_DA9217 11662306a36Sopenharmony_ci { 1, 4, &da914x_40A_4phase_current }, //DA9121_TYPE_DA9141 11762306a36Sopenharmony_ci { 1, 2, &da914x_20A_2phase_current }, //DA9121_TYPE_DA9142 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistruct da9121_field { 12162306a36Sopenharmony_ci unsigned int reg; 12262306a36Sopenharmony_ci unsigned int msk; 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const struct da9121_field da9121_current_field[2] = { 12662306a36Sopenharmony_ci { DA9121_REG_BUCK_BUCK1_2, DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM }, 12762306a36Sopenharmony_ci { DA9xxx_REG_BUCK_BUCK2_2, DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM }, 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic const struct da9121_field da9121_mode_field[2] = { 13162306a36Sopenharmony_ci { DA9121_REG_BUCK_BUCK1_4, DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE }, 13262306a36Sopenharmony_ci { DA9xxx_REG_BUCK_BUCK2_4, DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE }, 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistruct status_event_data { 13662306a36Sopenharmony_ci int buck_id; /* 0=core, 1/2-buck */ 13762306a36Sopenharmony_ci int reg_index; /* index for status/event/mask register selection */ 13862306a36Sopenharmony_ci int status_bit; /* bit masks... */ 13962306a36Sopenharmony_ci int event_bit; 14062306a36Sopenharmony_ci int mask_bit; 14162306a36Sopenharmony_ci unsigned long notification; /* Notification for status inception */ 14262306a36Sopenharmony_ci char *warn; /* if NULL, notify - otherwise dev_warn this string */ 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define DA9121_STATUS(id, bank, name, notification, warning) \ 14662306a36Sopenharmony_ci { id, bank, \ 14762306a36Sopenharmony_ci DA9121_MASK_SYS_STATUS_##bank##_##name, \ 14862306a36Sopenharmony_ci DA9121_MASK_SYS_EVENT_##bank##_E_##name, \ 14962306a36Sopenharmony_ci DA9121_MASK_SYS_MASK_##bank##_M_##name, \ 15062306a36Sopenharmony_ci notification, warning } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* For second buck related event bits that are specific to DA9122, DA9220 variants */ 15362306a36Sopenharmony_ci#define DA9xxx_STATUS(id, bank, name, notification, warning) \ 15462306a36Sopenharmony_ci { id, bank, \ 15562306a36Sopenharmony_ci DA9xxx_MASK_SYS_STATUS_##bank##_##name, \ 15662306a36Sopenharmony_ci DA9xxx_MASK_SYS_EVENT_##bank##_E_##name, \ 15762306a36Sopenharmony_ci DA9xxx_MASK_SYS_MASK_##bank##_M_##name, \ 15862306a36Sopenharmony_ci notification, warning } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* The status signals that may need servicing, depending on device variant. 16162306a36Sopenharmony_ci * After assertion, they persist; so event is notified, the IRQ disabled, 16262306a36Sopenharmony_ci * and status polled until clear again and IRQ is reenabled. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * SG/PG1/PG2 should be set when device first powers up and should never 16562306a36Sopenharmony_ci * re-occur. When this driver starts, it is expected that these will have 16662306a36Sopenharmony_ci * self-cleared for when the IRQs are enabled, so these should never be seen. 16762306a36Sopenharmony_ci * If seen, the implication is that the device has reset. 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * GPIO0/1/2 are not configured for use by default, so should not be seen. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistatic const struct status_event_data status_event_handling[] = { 17262306a36Sopenharmony_ci DA9xxx_STATUS(0, 0, SG, 0, "Handled E_SG\n"), 17362306a36Sopenharmony_ci DA9121_STATUS(0, 0, TEMP_CRIT, (REGULATOR_EVENT_OVER_TEMP|REGULATOR_EVENT_DISABLE), NULL), 17462306a36Sopenharmony_ci DA9121_STATUS(0, 0, TEMP_WARN, REGULATOR_EVENT_OVER_TEMP, NULL), 17562306a36Sopenharmony_ci DA9121_STATUS(1, 1, PG1, 0, "Handled E_PG1\n"), 17662306a36Sopenharmony_ci DA9121_STATUS(1, 1, OV1, REGULATOR_EVENT_REGULATION_OUT, NULL), 17762306a36Sopenharmony_ci DA9121_STATUS(1, 1, UV1, REGULATOR_EVENT_UNDER_VOLTAGE, NULL), 17862306a36Sopenharmony_ci DA9121_STATUS(1, 1, OC1, REGULATOR_EVENT_OVER_CURRENT, NULL), 17962306a36Sopenharmony_ci DA9xxx_STATUS(2, 1, PG2, 0, "Handled E_PG2\n"), 18062306a36Sopenharmony_ci DA9xxx_STATUS(2, 1, OV2, REGULATOR_EVENT_REGULATION_OUT, NULL), 18162306a36Sopenharmony_ci DA9xxx_STATUS(2, 1, UV2, REGULATOR_EVENT_UNDER_VOLTAGE, NULL), 18262306a36Sopenharmony_ci DA9xxx_STATUS(2, 1, OC2, REGULATOR_EVENT_OVER_CURRENT, NULL), 18362306a36Sopenharmony_ci DA9121_STATUS(0, 2, GPIO0, 0, "Handled E_GPIO0\n"), 18462306a36Sopenharmony_ci DA9121_STATUS(0, 2, GPIO1, 0, "Handled E_GPIO1\n"), 18562306a36Sopenharmony_ci DA9121_STATUS(0, 2, GPIO2, 0, "Handled E_GPIO2\n"), 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic int da9121_get_current_limit(struct regulator_dev *rdev) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct da9121 *chip = rdev_get_drvdata(rdev); 19162306a36Sopenharmony_ci int id = rdev_get_id(rdev); 19262306a36Sopenharmony_ci struct da9121_range *range = 19362306a36Sopenharmony_ci variant_parameters[chip->variant_id].current_range; 19462306a36Sopenharmony_ci unsigned int val = 0; 19562306a36Sopenharmony_ci int ret = 0; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci ret = regmap_read(chip->regmap, da9121_current_field[id].reg, &val); 19862306a36Sopenharmony_ci if (ret < 0) { 19962306a36Sopenharmony_ci dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret); 20062306a36Sopenharmony_ci goto error; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (val < range->reg_min) { 20462306a36Sopenharmony_ci ret = -EACCES; 20562306a36Sopenharmony_ci goto error; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci if (val > range->reg_max) { 20962306a36Sopenharmony_ci ret = -EINVAL; 21062306a36Sopenharmony_ci goto error; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci return range->val_min + (range->val_stp * (val - range->reg_min)); 21462306a36Sopenharmony_cierror: 21562306a36Sopenharmony_ci return ret; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic int da9121_ceiling_selector(struct regulator_dev *rdev, 21962306a36Sopenharmony_ci int min, int max, 22062306a36Sopenharmony_ci unsigned int *selector) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct da9121 *chip = rdev_get_drvdata(rdev); 22362306a36Sopenharmony_ci struct da9121_range *range = 22462306a36Sopenharmony_ci variant_parameters[chip->variant_id].current_range; 22562306a36Sopenharmony_ci unsigned int level; 22662306a36Sopenharmony_ci unsigned int i = 0; 22762306a36Sopenharmony_ci unsigned int sel = 0; 22862306a36Sopenharmony_ci int ret = 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (range->val_min > max || range->val_max < min) { 23162306a36Sopenharmony_ci dev_err(chip->dev, 23262306a36Sopenharmony_ci "Requested current out of regulator capability\n"); 23362306a36Sopenharmony_ci ret = -EINVAL; 23462306a36Sopenharmony_ci goto error; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci level = range->val_max; 23862306a36Sopenharmony_ci for (i = range->reg_max; i >= range->reg_min; i--) { 23962306a36Sopenharmony_ci if (level <= max) { 24062306a36Sopenharmony_ci sel = i; 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci level -= range->val_stp; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci if (level < min) { 24762306a36Sopenharmony_ci dev_err(chip->dev, 24862306a36Sopenharmony_ci "Best match falls below minimum requested current\n"); 24962306a36Sopenharmony_ci ret = -EINVAL; 25062306a36Sopenharmony_ci goto error; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci *selector = sel; 25462306a36Sopenharmony_cierror: 25562306a36Sopenharmony_ci return ret; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int da9121_set_current_limit(struct regulator_dev *rdev, 25962306a36Sopenharmony_ci int min_ua, int max_ua) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci struct da9121 *chip = rdev_get_drvdata(rdev); 26262306a36Sopenharmony_ci int id = rdev_get_id(rdev); 26362306a36Sopenharmony_ci struct da9121_range *range = 26462306a36Sopenharmony_ci variant_parameters[chip->variant_id].current_range; 26562306a36Sopenharmony_ci unsigned int sel = 0; 26662306a36Sopenharmony_ci int ret = 0; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (min_ua < range->val_min || 26962306a36Sopenharmony_ci max_ua > range->val_max) { 27062306a36Sopenharmony_ci ret = -EINVAL; 27162306a36Sopenharmony_ci goto error; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (rdev->desc->ops->is_enabled(rdev)) { 27562306a36Sopenharmony_ci ret = -EBUSY; 27662306a36Sopenharmony_ci goto error; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel); 28062306a36Sopenharmony_ci if (ret < 0) 28162306a36Sopenharmony_ci goto error; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, 28462306a36Sopenharmony_ci da9121_current_field[id].reg, 28562306a36Sopenharmony_ci da9121_current_field[id].msk, 28662306a36Sopenharmony_ci (unsigned int)sel); 28762306a36Sopenharmony_ci if (ret < 0) 28862306a36Sopenharmony_ci dev_err(chip->dev, "Cannot update BUCK current limit, err: %d\n", ret); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cierror: 29162306a36Sopenharmony_ci return ret; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic unsigned int da9121_map_mode(unsigned int mode) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci switch (mode) { 29762306a36Sopenharmony_ci case DA9121_BUCK_MODE_FORCE_PWM: 29862306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 29962306a36Sopenharmony_ci case DA9121_BUCK_MODE_FORCE_PWM_SHEDDING: 30062306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 30162306a36Sopenharmony_ci case DA9121_BUCK_MODE_AUTO: 30262306a36Sopenharmony_ci return REGULATOR_MODE_IDLE; 30362306a36Sopenharmony_ci case DA9121_BUCK_MODE_FORCE_PFM: 30462306a36Sopenharmony_ci return REGULATOR_MODE_STANDBY; 30562306a36Sopenharmony_ci default: 30662306a36Sopenharmony_ci return REGULATOR_MODE_INVALID; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int da9121_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct da9121 *chip = rdev_get_drvdata(rdev); 31362306a36Sopenharmony_ci int id = rdev_get_id(rdev); 31462306a36Sopenharmony_ci unsigned int val; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci switch (mode) { 31762306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 31862306a36Sopenharmony_ci val = DA9121_BUCK_MODE_FORCE_PWM; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 32162306a36Sopenharmony_ci val = DA9121_BUCK_MODE_FORCE_PWM_SHEDDING; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case REGULATOR_MODE_IDLE: 32462306a36Sopenharmony_ci val = DA9121_BUCK_MODE_AUTO; 32562306a36Sopenharmony_ci break; 32662306a36Sopenharmony_ci case REGULATOR_MODE_STANDBY: 32762306a36Sopenharmony_ci val = DA9121_BUCK_MODE_FORCE_PFM; 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci default: 33062306a36Sopenharmony_ci return -EINVAL; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return regmap_update_bits(chip->regmap, 33462306a36Sopenharmony_ci da9121_mode_field[id].reg, 33562306a36Sopenharmony_ci da9121_mode_field[id].msk, 33662306a36Sopenharmony_ci val); 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic unsigned int da9121_buck_get_mode(struct regulator_dev *rdev) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct da9121 *chip = rdev_get_drvdata(rdev); 34262306a36Sopenharmony_ci int id = rdev_get_id(rdev); 34362306a36Sopenharmony_ci unsigned int val, mode; 34462306a36Sopenharmony_ci int ret = 0; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci ret = regmap_read(chip->regmap, da9121_mode_field[id].reg, &val); 34762306a36Sopenharmony_ci if (ret < 0) { 34862306a36Sopenharmony_ci dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret); 34962306a36Sopenharmony_ci return -EINVAL; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci mode = da9121_map_mode(val & da9121_mode_field[id].msk); 35362306a36Sopenharmony_ci if (mode == REGULATOR_MODE_INVALID) 35462306a36Sopenharmony_ci return -EINVAL; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return mode; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic const struct regulator_ops da9121_buck_ops = { 36062306a36Sopenharmony_ci .enable = regulator_enable_regmap, 36162306a36Sopenharmony_ci .disable = regulator_disable_regmap, 36262306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 36362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 36462306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 36562306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 36662306a36Sopenharmony_ci .get_current_limit = da9121_get_current_limit, 36762306a36Sopenharmony_ci .set_current_limit = da9121_set_current_limit, 36862306a36Sopenharmony_ci .set_mode = da9121_buck_set_mode, 36962306a36Sopenharmony_ci .get_mode = da9121_buck_get_mode, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic struct of_regulator_match da9121_matches[] = { 37362306a36Sopenharmony_ci [DA9121_IDX_BUCK1] = { .name = "buck1" }, 37462306a36Sopenharmony_ci [DA9121_IDX_BUCK2] = { .name = "buck2" }, 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic int da9121_of_parse_cb(struct device_node *np, 37862306a36Sopenharmony_ci const struct regulator_desc *desc, 37962306a36Sopenharmony_ci struct regulator_config *config) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct da9121 *chip = config->driver_data; 38262306a36Sopenharmony_ci struct da9121_pdata *pdata; 38362306a36Sopenharmony_ci struct gpio_desc *ena_gpiod; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (chip->pdata == NULL) { 38662306a36Sopenharmony_ci pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); 38762306a36Sopenharmony_ci if (!pdata) 38862306a36Sopenharmony_ci return -ENOMEM; 38962306a36Sopenharmony_ci } else { 39062306a36Sopenharmony_ci pdata = chip->pdata; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci pdata->num_buck++; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (pdata->num_buck > variant_parameters[chip->variant_id].num_bucks) { 39662306a36Sopenharmony_ci dev_err(chip->dev, "Error: excessive regulators for device\n"); 39762306a36Sopenharmony_ci return -ENODEV; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0, 40162306a36Sopenharmony_ci GPIOD_OUT_HIGH | 40262306a36Sopenharmony_ci GPIOD_FLAGS_BIT_NONEXCLUSIVE, 40362306a36Sopenharmony_ci "da9121-enable"); 40462306a36Sopenharmony_ci if (!IS_ERR(ena_gpiod)) 40562306a36Sopenharmony_ci config->ena_gpiod = ena_gpiod; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (variant_parameters[chip->variant_id].num_bucks == 2) { 40862306a36Sopenharmony_ci uint32_t ripple_cancel; 40962306a36Sopenharmony_ci uint32_t ripple_reg; 41062306a36Sopenharmony_ci int ret; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (of_property_read_u32(da9121_matches[pdata->num_buck-1].of_node, 41362306a36Sopenharmony_ci "dlg,ripple-cancel", &ripple_cancel)) { 41462306a36Sopenharmony_ci if (pdata->num_buck > 1) 41562306a36Sopenharmony_ci ripple_reg = DA9xxx_REG_BUCK_BUCK2_7; 41662306a36Sopenharmony_ci else 41762306a36Sopenharmony_ci ripple_reg = DA9121_REG_BUCK_BUCK1_7; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, ripple_reg, 42062306a36Sopenharmony_ci DA9xxx_MASK_BUCK_BUCKx_7_CHx_RIPPLE_CANCEL, 42162306a36Sopenharmony_ci ripple_cancel); 42262306a36Sopenharmony_ci if (ret < 0) 42362306a36Sopenharmony_ci dev_err(chip->dev, "Cannot set ripple mode, err: %d\n", ret); 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci return 0; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci#define DA9121_MIN_MV 300 43162306a36Sopenharmony_ci#define DA9121_MAX_MV 1900 43262306a36Sopenharmony_ci#define DA9121_STEP_MV 10 43362306a36Sopenharmony_ci#define DA9121_MIN_SEL (DA9121_MIN_MV / DA9121_STEP_MV) 43462306a36Sopenharmony_ci#define DA9121_N_VOLTAGES (((DA9121_MAX_MV - DA9121_MIN_MV) / DA9121_STEP_MV) \ 43562306a36Sopenharmony_ci + 1 + DA9121_MIN_SEL) 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic const struct regulator_desc da9121_reg = { 43862306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 43962306a36Sopenharmony_ci .name = "da9121", 44062306a36Sopenharmony_ci .of_match = "buck1", 44162306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 44262306a36Sopenharmony_ci .owner = THIS_MODULE, 44362306a36Sopenharmony_ci .regulators_node = "regulators", 44462306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 44562306a36Sopenharmony_ci .ops = &da9121_buck_ops, 44662306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 44762306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 44862306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 44962306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 45062306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 45162306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 45262306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 45362306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 45462306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 45562306a36Sopenharmony_ci /* Default value of BUCK_BUCK1_0.CH1_SRC_DVC_UP */ 45662306a36Sopenharmony_ci .ramp_delay = 20000, 45762306a36Sopenharmony_ci /* tBUCK_EN */ 45862306a36Sopenharmony_ci .enable_time = 20, 45962306a36Sopenharmony_ci}; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic const struct regulator_desc da9220_reg[2] = { 46262306a36Sopenharmony_ci { 46362306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 46462306a36Sopenharmony_ci .name = "DA9220/DA9132 BUCK1", 46562306a36Sopenharmony_ci .of_match = "buck1", 46662306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 46762306a36Sopenharmony_ci .owner = THIS_MODULE, 46862306a36Sopenharmony_ci .regulators_node = "regulators", 46962306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 47062306a36Sopenharmony_ci .ops = &da9121_buck_ops, 47162306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 47262306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 47362306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 47462306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 47562306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 47662306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 47762306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 47862306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 47962306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 48062306a36Sopenharmony_ci }, 48162306a36Sopenharmony_ci { 48262306a36Sopenharmony_ci .id = DA9121_IDX_BUCK2, 48362306a36Sopenharmony_ci .name = "DA9220/DA9132 BUCK2", 48462306a36Sopenharmony_ci .of_match = "buck2", 48562306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 48662306a36Sopenharmony_ci .owner = THIS_MODULE, 48762306a36Sopenharmony_ci .regulators_node = "regulators", 48862306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 48962306a36Sopenharmony_ci .ops = &da9121_buck_ops, 49062306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 49162306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 49262306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 49362306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 49462306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 49562306a36Sopenharmony_ci .enable_reg = DA9xxx_REG_BUCK_BUCK2_0, 49662306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 49762306a36Sopenharmony_ci .vsel_reg = DA9xxx_REG_BUCK_BUCK2_5, 49862306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci}; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic const struct regulator_desc da9122_reg[2] = { 50362306a36Sopenharmony_ci { 50462306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 50562306a36Sopenharmony_ci .name = "DA9122/DA9131 BUCK1", 50662306a36Sopenharmony_ci .of_match = "buck1", 50762306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 50862306a36Sopenharmony_ci .owner = THIS_MODULE, 50962306a36Sopenharmony_ci .regulators_node = "regulators", 51062306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 51162306a36Sopenharmony_ci .ops = &da9121_buck_ops, 51262306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 51362306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 51462306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 51562306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 51662306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 51762306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 51862306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 51962306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 52062306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 52162306a36Sopenharmony_ci }, 52262306a36Sopenharmony_ci { 52362306a36Sopenharmony_ci .id = DA9121_IDX_BUCK2, 52462306a36Sopenharmony_ci .name = "DA9122/DA9131 BUCK2", 52562306a36Sopenharmony_ci .of_match = "buck2", 52662306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 52762306a36Sopenharmony_ci .owner = THIS_MODULE, 52862306a36Sopenharmony_ci .regulators_node = "regulators", 52962306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 53062306a36Sopenharmony_ci .ops = &da9121_buck_ops, 53162306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 53262306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 53362306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 53462306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 53562306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 53662306a36Sopenharmony_ci .enable_reg = DA9xxx_REG_BUCK_BUCK2_0, 53762306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 53862306a36Sopenharmony_ci .vsel_reg = DA9xxx_REG_BUCK_BUCK2_5, 53962306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci}; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic const struct regulator_desc da9217_reg = { 54462306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 54562306a36Sopenharmony_ci .name = "DA9217 BUCK1", 54662306a36Sopenharmony_ci .of_match = "buck1", 54762306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 54862306a36Sopenharmony_ci .owner = THIS_MODULE, 54962306a36Sopenharmony_ci .regulators_node = "regulators", 55062306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 55162306a36Sopenharmony_ci .ops = &da9121_buck_ops, 55262306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 55362306a36Sopenharmony_ci .n_voltages = DA9121_N_VOLTAGES, 55462306a36Sopenharmony_ci .min_uV = DA9121_MIN_MV * 1000, 55562306a36Sopenharmony_ci .uV_step = DA9121_STEP_MV * 1000, 55662306a36Sopenharmony_ci .linear_min_sel = DA9121_MIN_SEL, 55762306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 55862306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 55962306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 56062306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 56162306a36Sopenharmony_ci}; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci#define DA914X_MIN_MV 500 56462306a36Sopenharmony_ci#define DA914X_MAX_MV 1300 56562306a36Sopenharmony_ci#define DA914X_STEP_MV 10 56662306a36Sopenharmony_ci#define DA914X_MIN_SEL (DA914X_MIN_MV / DA914X_STEP_MV) 56762306a36Sopenharmony_ci#define DA914X_N_VOLTAGES (((DA914X_MAX_MV - DA914X_MIN_MV) / DA914X_STEP_MV) \ 56862306a36Sopenharmony_ci + 1 + DA914X_MIN_SEL) 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic const struct regulator_desc da9141_reg = { 57162306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 57262306a36Sopenharmony_ci .name = "DA9141", 57362306a36Sopenharmony_ci .of_match = "buck1", 57462306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 57562306a36Sopenharmony_ci .owner = THIS_MODULE, 57662306a36Sopenharmony_ci .regulators_node = "regulators", 57762306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 57862306a36Sopenharmony_ci .ops = &da9121_buck_ops, 57962306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 58062306a36Sopenharmony_ci .n_voltages = DA914X_N_VOLTAGES, 58162306a36Sopenharmony_ci .min_uV = DA914X_MIN_MV * 1000, 58262306a36Sopenharmony_ci .uV_step = DA914X_STEP_MV * 1000, 58362306a36Sopenharmony_ci .linear_min_sel = DA914X_MIN_SEL, 58462306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 58562306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 58662306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 58762306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 58862306a36Sopenharmony_ci}; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic const struct regulator_desc da9142_reg = { 59162306a36Sopenharmony_ci .id = DA9121_IDX_BUCK1, 59262306a36Sopenharmony_ci .name = "DA9142 BUCK1", 59362306a36Sopenharmony_ci .of_match = "buck1", 59462306a36Sopenharmony_ci .of_parse_cb = da9121_of_parse_cb, 59562306a36Sopenharmony_ci .owner = THIS_MODULE, 59662306a36Sopenharmony_ci .regulators_node = "regulators", 59762306a36Sopenharmony_ci .of_map_mode = da9121_map_mode, 59862306a36Sopenharmony_ci .ops = &da9121_buck_ops, 59962306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 60062306a36Sopenharmony_ci .n_voltages = DA914X_N_VOLTAGES, 60162306a36Sopenharmony_ci .min_uV = DA914X_MIN_MV * 1000, 60262306a36Sopenharmony_ci .uV_step = DA914X_STEP_MV * 1000, 60362306a36Sopenharmony_ci .linear_min_sel = DA914X_MIN_SEL, 60462306a36Sopenharmony_ci .enable_reg = DA9121_REG_BUCK_BUCK1_0, 60562306a36Sopenharmony_ci .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, 60662306a36Sopenharmony_ci .vsel_reg = DA9121_REG_BUCK_BUCK1_5, 60762306a36Sopenharmony_ci .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, 60862306a36Sopenharmony_ci}; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic const struct regulator_desc *local_da9121_regulators[][DA9121_IDX_MAX] = { 61262306a36Sopenharmony_ci [DA9121_TYPE_DA9121_DA9130] = { &da9121_reg, NULL }, 61362306a36Sopenharmony_ci [DA9121_TYPE_DA9220_DA9132] = { &da9220_reg[0], &da9220_reg[1] }, 61462306a36Sopenharmony_ci [DA9121_TYPE_DA9122_DA9131] = { &da9122_reg[0], &da9122_reg[1] }, 61562306a36Sopenharmony_ci [DA9121_TYPE_DA9217] = { &da9217_reg, NULL }, 61662306a36Sopenharmony_ci [DA9121_TYPE_DA9141] = { &da9141_reg, NULL }, 61762306a36Sopenharmony_ci [DA9121_TYPE_DA9142] = { &da9142_reg, NULL }, 61862306a36Sopenharmony_ci}; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic void da9121_status_poll_on(struct work_struct *work) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci struct da9121 *chip = container_of(work, struct da9121, work.work); 62362306a36Sopenharmony_ci int status[3] = {0}; 62462306a36Sopenharmony_ci int clear[3] = {0}; 62562306a36Sopenharmony_ci unsigned long delay; 62662306a36Sopenharmony_ci int i; 62762306a36Sopenharmony_ci int ret; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci ret = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_STATUS_0, status, 2); 63062306a36Sopenharmony_ci if (ret < 0) { 63162306a36Sopenharmony_ci dev_err(chip->dev, 63262306a36Sopenharmony_ci "Failed to read STATUS registers: %d\n", ret); 63362306a36Sopenharmony_ci goto error; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* Possible events are tested to be within range for the variant, potentially 63762306a36Sopenharmony_ci * masked by the IRQ handler (not just warned about), as having been masked, 63862306a36Sopenharmony_ci * and the respective state cleared - then flagged to unmask for next IRQ. 63962306a36Sopenharmony_ci */ 64062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(status_event_handling); i++) { 64162306a36Sopenharmony_ci const struct status_event_data *item = &status_event_handling[i]; 64262306a36Sopenharmony_ci int reg_idx = item->reg_index; 64362306a36Sopenharmony_ci bool relevant = (item->buck_id <= variant_parameters[chip->variant_id].num_bucks); 64462306a36Sopenharmony_ci bool supported = (item->warn == NULL); 64562306a36Sopenharmony_ci bool persisting = (chip->persistent[reg_idx] & item->event_bit); 64662306a36Sopenharmony_ci bool now_cleared = !(status[reg_idx] & item->status_bit); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (relevant && supported && persisting && now_cleared) { 64962306a36Sopenharmony_ci clear[reg_idx] |= item->mask_bit; 65062306a36Sopenharmony_ci chip->persistent[reg_idx] &= ~item->event_bit; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 65562306a36Sopenharmony_ci if (clear[i]) { 65662306a36Sopenharmony_ci unsigned int reg = DA9121_REG_SYS_MASK_0 + i; 65762306a36Sopenharmony_ci unsigned int mbit = clear[i]; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, reg, mbit, 0); 66062306a36Sopenharmony_ci if (ret < 0) { 66162306a36Sopenharmony_ci dev_err(chip->dev, 66262306a36Sopenharmony_ci "Failed to unmask 0x%02x %d\n", 66362306a36Sopenharmony_ci reg, ret); 66462306a36Sopenharmony_ci goto error; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci if (chip->persistent[0] | chip->persistent[1]) { 67062306a36Sopenharmony_ci delay = msecs_to_jiffies(chip->passive_delay); 67162306a36Sopenharmony_ci queue_delayed_work(system_freezable_wq, &chip->work, delay); 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_cierror: 67562306a36Sopenharmony_ci return; 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic irqreturn_t da9121_irq_handler(int irq, void *data) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci struct da9121 *chip = data; 68162306a36Sopenharmony_ci struct regulator_dev *rdev; 68262306a36Sopenharmony_ci int event[3] = {0}; 68362306a36Sopenharmony_ci int handled[3] = {0}; 68462306a36Sopenharmony_ci int mask[3] = {0}; 68562306a36Sopenharmony_ci int ret = IRQ_NONE; 68662306a36Sopenharmony_ci int i; 68762306a36Sopenharmony_ci int err; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_EVENT_0, event, 3); 69062306a36Sopenharmony_ci if (err < 0) { 69162306a36Sopenharmony_ci dev_err(chip->dev, "Failed to read EVENT registers %d\n", err); 69262306a36Sopenharmony_ci ret = IRQ_NONE; 69362306a36Sopenharmony_ci goto error; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_MASK_0, mask, 3); 69762306a36Sopenharmony_ci if (err < 0) { 69862306a36Sopenharmony_ci dev_err(chip->dev, 69962306a36Sopenharmony_ci "Failed to read MASK registers: %d\n", ret); 70062306a36Sopenharmony_ci ret = IRQ_NONE; 70162306a36Sopenharmony_ci goto error; 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci rdev = chip->rdev[DA9121_IDX_BUCK1]; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci /* Possible events are tested to be within range for the variant, currently 70762306a36Sopenharmony_ci * enabled, and having triggered this IRQ. The event may then be notified, 70862306a36Sopenharmony_ci * or a warning given for unexpected events - those from device POR, and 70962306a36Sopenharmony_ci * currently unsupported GPIO configurations. 71062306a36Sopenharmony_ci */ 71162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(status_event_handling); i++) { 71262306a36Sopenharmony_ci const struct status_event_data *item = &status_event_handling[i]; 71362306a36Sopenharmony_ci int reg_idx = item->reg_index; 71462306a36Sopenharmony_ci bool relevant = (item->buck_id <= variant_parameters[chip->variant_id].num_bucks); 71562306a36Sopenharmony_ci bool enabled = !(mask[reg_idx] & item->mask_bit); 71662306a36Sopenharmony_ci bool active = (event[reg_idx] & item->event_bit); 71762306a36Sopenharmony_ci bool notify = (item->warn == NULL); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (relevant && enabled && active) { 72062306a36Sopenharmony_ci if (notify) { 72162306a36Sopenharmony_ci chip->persistent[reg_idx] |= item->event_bit; 72262306a36Sopenharmony_ci regulator_notifier_call_chain(rdev, item->notification, NULL); 72362306a36Sopenharmony_ci } else { 72462306a36Sopenharmony_ci dev_warn(chip->dev, item->warn); 72562306a36Sopenharmony_ci handled[reg_idx] |= item->event_bit; 72662306a36Sopenharmony_ci ret = IRQ_HANDLED; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 73262306a36Sopenharmony_ci if (event[i] != handled[i]) { 73362306a36Sopenharmony_ci dev_warn(chip->dev, 73462306a36Sopenharmony_ci "Unhandled event(s) in bank%d 0x%02x\n", i, 73562306a36Sopenharmony_ci event[i] ^ handled[i]); 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* Mask the interrupts for persistent events OV, OC, UV, WARN, CRIT */ 74062306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 74162306a36Sopenharmony_ci if (handled[i]) { 74262306a36Sopenharmony_ci unsigned int reg = DA9121_REG_SYS_MASK_0 + i; 74362306a36Sopenharmony_ci unsigned int mbit = handled[i]; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci err = regmap_update_bits(chip->regmap, reg, mbit, mbit); 74662306a36Sopenharmony_ci if (err < 0) { 74762306a36Sopenharmony_ci dev_err(chip->dev, 74862306a36Sopenharmony_ci "Failed to mask 0x%02x interrupt %d\n", 74962306a36Sopenharmony_ci reg, err); 75062306a36Sopenharmony_ci ret = IRQ_NONE; 75162306a36Sopenharmony_ci goto error; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci /* clear the events */ 75762306a36Sopenharmony_ci if (handled[0] | handled[1] | handled[2]) { 75862306a36Sopenharmony_ci err = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_EVENT_0, handled, 3); 75962306a36Sopenharmony_ci if (err < 0) { 76062306a36Sopenharmony_ci dev_err(chip->dev, "Fail to write EVENTs %d\n", err); 76162306a36Sopenharmony_ci ret = IRQ_NONE; 76262306a36Sopenharmony_ci goto error; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci queue_delayed_work(system_freezable_wq, &chip->work, 0); 76762306a36Sopenharmony_cierror: 76862306a36Sopenharmony_ci return ret; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic int da9121_set_regulator_config(struct da9121 *chip) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct regulator_config config = { }; 77462306a36Sopenharmony_ci unsigned int max_matches = variant_parameters[chip->variant_id].num_bucks; 77562306a36Sopenharmony_ci int ret = 0; 77662306a36Sopenharmony_ci int i; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci for (i = 0; i < max_matches; i++) { 77962306a36Sopenharmony_ci const struct regulator_desc *regl_desc = 78062306a36Sopenharmony_ci local_da9121_regulators[chip->variant_id][i]; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci config.dev = chip->dev; 78362306a36Sopenharmony_ci config.driver_data = chip; 78462306a36Sopenharmony_ci config.regmap = chip->regmap; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci chip->rdev[i] = devm_regulator_register(chip->dev, 78762306a36Sopenharmony_ci regl_desc, &config); 78862306a36Sopenharmony_ci if (IS_ERR(chip->rdev[i])) { 78962306a36Sopenharmony_ci dev_err(chip->dev, "Failed to register regulator %s, %d/%d\n", 79062306a36Sopenharmony_ci regl_desc->name, (i+1), max_matches); 79162306a36Sopenharmony_ci ret = PTR_ERR(chip->rdev[i]); 79262306a36Sopenharmony_ci goto error; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci } 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cierror: 79762306a36Sopenharmony_ci return ret; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci/* DA9121 chip register model */ 80162306a36Sopenharmony_cistatic const struct regmap_range da9121_1ch_readable_ranges[] = { 80262306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3), 80362306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3), 80462306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), 80562306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6), 80662306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID), 80762306a36Sopenharmony_ci}; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_cistatic const struct regmap_access_table da9121_1ch_readable_table = { 81062306a36Sopenharmony_ci .yes_ranges = da9121_1ch_readable_ranges, 81162306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9121_1ch_readable_ranges), 81262306a36Sopenharmony_ci}; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic const struct regmap_range da9121_2ch_readable_ranges[] = { 81562306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3), 81662306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3), 81762306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), 81862306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_7), 81962306a36Sopenharmony_ci regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_7), 82062306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID), 82162306a36Sopenharmony_ci}; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic const struct regmap_access_table da9121_2ch_readable_table = { 82462306a36Sopenharmony_ci .yes_ranges = da9121_2ch_readable_ranges, 82562306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9121_2ch_readable_ranges), 82662306a36Sopenharmony_ci}; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistatic const struct regmap_range da9121_1ch_writeable_ranges[] = { 82962306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3), 83062306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3), 83162306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), 83262306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2), 83362306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_6), 83462306a36Sopenharmony_ci}; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic const struct regmap_access_table da9121_1ch_writeable_table = { 83762306a36Sopenharmony_ci .yes_ranges = da9121_1ch_writeable_ranges, 83862306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9121_1ch_writeable_ranges), 83962306a36Sopenharmony_ci}; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_cistatic const struct regmap_range da9121_2ch_writeable_ranges[] = { 84262306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3), 84362306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3), 84462306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), 84562306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2), 84662306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_7), 84762306a36Sopenharmony_ci regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_2), 84862306a36Sopenharmony_ci regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_4, DA9xxx_REG_BUCK_BUCK2_7), 84962306a36Sopenharmony_ci}; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic const struct regmap_access_table da9121_2ch_writeable_table = { 85262306a36Sopenharmony_ci .yes_ranges = da9121_2ch_writeable_ranges, 85362306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9121_2ch_writeable_ranges), 85462306a36Sopenharmony_ci}; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic const struct regmap_range da9121_volatile_ranges[] = { 85862306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_EVENT_2), 85962306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), 86062306a36Sopenharmony_ci regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6), 86162306a36Sopenharmony_ci}; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic const struct regmap_access_table da9121_volatile_table = { 86462306a36Sopenharmony_ci .yes_ranges = da9121_volatile_ranges, 86562306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9121_volatile_ranges), 86662306a36Sopenharmony_ci}; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci/* DA9121 regmap config for 1 channel variants */ 86962306a36Sopenharmony_cistatic struct regmap_config da9121_1ch_regmap_config = { 87062306a36Sopenharmony_ci .reg_bits = 8, 87162306a36Sopenharmony_ci .val_bits = 8, 87262306a36Sopenharmony_ci .max_register = DA9121_REG_OTP_CONFIG_ID, 87362306a36Sopenharmony_ci .rd_table = &da9121_1ch_readable_table, 87462306a36Sopenharmony_ci .wr_table = &da9121_1ch_writeable_table, 87562306a36Sopenharmony_ci .volatile_table = &da9121_volatile_table, 87662306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci/* DA9121 regmap config for 2 channel variants */ 88062306a36Sopenharmony_cistatic struct regmap_config da9121_2ch_regmap_config = { 88162306a36Sopenharmony_ci .reg_bits = 8, 88262306a36Sopenharmony_ci .val_bits = 8, 88362306a36Sopenharmony_ci .max_register = DA9121_REG_OTP_CONFIG_ID, 88462306a36Sopenharmony_ci .rd_table = &da9121_2ch_readable_table, 88562306a36Sopenharmony_ci .wr_table = &da9121_2ch_writeable_table, 88662306a36Sopenharmony_ci .volatile_table = &da9121_volatile_table, 88762306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 88862306a36Sopenharmony_ci}; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cistatic int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci u32 device_id; 89362306a36Sopenharmony_ci u32 variant_id; 89462306a36Sopenharmony_ci u8 variant_mrc, variant_vrc; 89562306a36Sopenharmony_ci char *type; 89662306a36Sopenharmony_ci bool config_match = false; 89762306a36Sopenharmony_ci int ret = 0; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci ret = regmap_read(chip->regmap, DA9121_REG_OTP_DEVICE_ID, &device_id); 90062306a36Sopenharmony_ci if (ret < 0) { 90162306a36Sopenharmony_ci dev_err(chip->dev, "Cannot read device ID: %d\n", ret); 90262306a36Sopenharmony_ci goto error; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci ret = regmap_read(chip->regmap, DA9121_REG_OTP_VARIANT_ID, &variant_id); 90662306a36Sopenharmony_ci if (ret < 0) { 90762306a36Sopenharmony_ci dev_err(chip->dev, "Cannot read variant ID: %d\n", ret); 90862306a36Sopenharmony_ci goto error; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if ((device_id != DA9121_DEVICE_ID) && (device_id != DA914x_DEVICE_ID)) { 91262306a36Sopenharmony_ci dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); 91362306a36Sopenharmony_ci ret = -ENODEV; 91462306a36Sopenharmony_ci goto error; 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci variant_vrc = variant_id & DA9121_MASK_OTP_VARIANT_ID_VRC; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci switch (chip->subvariant_id) { 92062306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9121: 92162306a36Sopenharmony_ci type = "DA9121"; 92262306a36Sopenharmony_ci config_match = (variant_vrc == DA9121_VARIANT_VRC); 92362306a36Sopenharmony_ci break; 92462306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9130: 92562306a36Sopenharmony_ci type = "DA9130"; 92662306a36Sopenharmony_ci config_match = (variant_vrc == DA9130_VARIANT_VRC); 92762306a36Sopenharmony_ci break; 92862306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9220: 92962306a36Sopenharmony_ci type = "DA9220"; 93062306a36Sopenharmony_ci config_match = (variant_vrc == DA9220_VARIANT_VRC); 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9132: 93362306a36Sopenharmony_ci type = "DA9132"; 93462306a36Sopenharmony_ci config_match = (variant_vrc == DA9132_VARIANT_VRC); 93562306a36Sopenharmony_ci break; 93662306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9122: 93762306a36Sopenharmony_ci type = "DA9122"; 93862306a36Sopenharmony_ci config_match = (variant_vrc == DA9122_VARIANT_VRC); 93962306a36Sopenharmony_ci break; 94062306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9131: 94162306a36Sopenharmony_ci type = "DA9131"; 94262306a36Sopenharmony_ci config_match = (variant_vrc == DA9131_VARIANT_VRC); 94362306a36Sopenharmony_ci break; 94462306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9217: 94562306a36Sopenharmony_ci type = "DA9217"; 94662306a36Sopenharmony_ci config_match = (variant_vrc == DA9217_VARIANT_VRC); 94762306a36Sopenharmony_ci break; 94862306a36Sopenharmony_ci default: 94962306a36Sopenharmony_ci type = "Unknown"; 95062306a36Sopenharmony_ci break; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci if (device_id == DA914x_DEVICE_ID) { 95462306a36Sopenharmony_ci switch (chip->subvariant_id) { 95562306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9141: 95662306a36Sopenharmony_ci type = "DA9141"; 95762306a36Sopenharmony_ci config_match = (variant_vrc == DA9141_VARIANT_VRC); 95862306a36Sopenharmony_ci break; 95962306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9142: 96062306a36Sopenharmony_ci type = "DA9142"; 96162306a36Sopenharmony_ci config_match = (variant_vrc == DA9142_VARIANT_VRC); 96262306a36Sopenharmony_ci break; 96362306a36Sopenharmony_ci default: 96462306a36Sopenharmony_ci type = "Unknown"; 96562306a36Sopenharmony_ci break; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci dev_info(chip->dev, 97062306a36Sopenharmony_ci "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n", 97162306a36Sopenharmony_ci device_id, variant_id, type); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (!config_match) { 97462306a36Sopenharmony_ci dev_err(chip->dev, "Device tree configuration does not match detected device.\n"); 97562306a36Sopenharmony_ci ret = -EINVAL; 97662306a36Sopenharmony_ci goto error; 97762306a36Sopenharmony_ci } 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci variant_mrc = (variant_id & DA9121_MASK_OTP_VARIANT_ID_MRC) 98062306a36Sopenharmony_ci >> DA9121_SHIFT_OTP_VARIANT_ID_MRC; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (((device_id == DA9121_DEVICE_ID) && 98362306a36Sopenharmony_ci (variant_mrc < DA9121_VARIANT_MRC_BASE)) || 98462306a36Sopenharmony_ci ((device_id == DA914x_DEVICE_ID) && 98562306a36Sopenharmony_ci (variant_mrc != DA914x_VARIANT_MRC_BASE))) { 98662306a36Sopenharmony_ci dev_err(chip->dev, 98762306a36Sopenharmony_ci "Cannot support variant MRC: 0x%02X\n", variant_mrc); 98862306a36Sopenharmony_ci ret = -EINVAL; 98962306a36Sopenharmony_ci } 99062306a36Sopenharmony_cierror: 99162306a36Sopenharmony_ci return ret; 99262306a36Sopenharmony_ci} 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_cistatic int da9121_assign_chip_model(struct i2c_client *i2c, 99562306a36Sopenharmony_ci struct da9121 *chip) 99662306a36Sopenharmony_ci{ 99762306a36Sopenharmony_ci struct regmap_config *regmap; 99862306a36Sopenharmony_ci int ret = 0; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci chip->dev = &i2c->dev; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci /* Use configured subtype to select the regulator descriptor index and 100362306a36Sopenharmony_ci * register map, common to both consumer and automotive grade variants 100462306a36Sopenharmony_ci */ 100562306a36Sopenharmony_ci switch (chip->subvariant_id) { 100662306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9121: 100762306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9130: 100862306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9121_DA9130; 100962306a36Sopenharmony_ci regmap = &da9121_1ch_regmap_config; 101062306a36Sopenharmony_ci break; 101162306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9217: 101262306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9217; 101362306a36Sopenharmony_ci regmap = &da9121_1ch_regmap_config; 101462306a36Sopenharmony_ci break; 101562306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9122: 101662306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9131: 101762306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9122_DA9131; 101862306a36Sopenharmony_ci regmap = &da9121_2ch_regmap_config; 101962306a36Sopenharmony_ci break; 102062306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9220: 102162306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9132: 102262306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9220_DA9132; 102362306a36Sopenharmony_ci regmap = &da9121_2ch_regmap_config; 102462306a36Sopenharmony_ci break; 102562306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9141: 102662306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9141; 102762306a36Sopenharmony_ci regmap = &da9121_1ch_regmap_config; 102862306a36Sopenharmony_ci break; 102962306a36Sopenharmony_ci case DA9121_SUBTYPE_DA9142: 103062306a36Sopenharmony_ci chip->variant_id = DA9121_TYPE_DA9142; 103162306a36Sopenharmony_ci regmap = &da9121_2ch_regmap_config; 103262306a36Sopenharmony_ci break; 103362306a36Sopenharmony_ci default: 103462306a36Sopenharmony_ci return -EINVAL; 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* Set these up for of_regulator_match call which may want .of_map_modes */ 103862306a36Sopenharmony_ci da9121_matches[0].desc = local_da9121_regulators[chip->variant_id][0]; 103962306a36Sopenharmony_ci da9121_matches[1].desc = local_da9121_regulators[chip->variant_id][1]; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci chip->regmap = devm_regmap_init_i2c(i2c, regmap); 104262306a36Sopenharmony_ci if (IS_ERR(chip->regmap)) { 104362306a36Sopenharmony_ci ret = PTR_ERR(chip->regmap); 104462306a36Sopenharmony_ci dev_err(chip->dev, "Failed to configure a register map: %d\n", 104562306a36Sopenharmony_ci ret); 104662306a36Sopenharmony_ci return ret; 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci ret = da9121_check_device_type(i2c, chip); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci return ret; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_cistatic int da9121_config_irq(struct i2c_client *i2c, 105562306a36Sopenharmony_ci struct da9121 *chip) 105662306a36Sopenharmony_ci{ 105762306a36Sopenharmony_ci unsigned int p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS; 105862306a36Sopenharmony_ci const int mask_all[4] = { 0, 0, 0xFF, 0xFF }; 105962306a36Sopenharmony_ci int ret = 0; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci chip->chip_irq = i2c->irq; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci if (chip->chip_irq != 0) { 106462306a36Sopenharmony_ci if (!of_property_read_u32(chip->dev->of_node, 106562306a36Sopenharmony_ci "dlg,irq-polling-delay-passive-ms", 106662306a36Sopenharmony_ci &p_delay)) { 106762306a36Sopenharmony_ci if (p_delay < DA9121_MIN_POLLING_PERIOD_MS || 106862306a36Sopenharmony_ci p_delay > DA9121_MAX_POLLING_PERIOD_MS) { 106962306a36Sopenharmony_ci dev_warn(chip->dev, 107062306a36Sopenharmony_ci "Out-of-range polling period %d ms\n", 107162306a36Sopenharmony_ci p_delay); 107262306a36Sopenharmony_ci p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS; 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci chip->passive_delay = p_delay; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci ret = request_threaded_irq(chip->chip_irq, NULL, 107962306a36Sopenharmony_ci da9121_irq_handler, 108062306a36Sopenharmony_ci IRQF_TRIGGER_LOW|IRQF_ONESHOT, 108162306a36Sopenharmony_ci "da9121", chip); 108262306a36Sopenharmony_ci if (ret != 0) { 108362306a36Sopenharmony_ci dev_err(chip->dev, "Failed IRQ request: %d\n", 108462306a36Sopenharmony_ci chip->chip_irq); 108562306a36Sopenharmony_ci goto error; 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4); 108962306a36Sopenharmony_ci if (ret != 0) { 109062306a36Sopenharmony_ci dev_err(chip->dev, "Failed to set IRQ masks: %d\n", 109162306a36Sopenharmony_ci ret); 109262306a36Sopenharmony_ci goto regmap_error; 109362306a36Sopenharmony_ci } 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci INIT_DELAYED_WORK(&chip->work, da9121_status_poll_on); 109662306a36Sopenharmony_ci dev_info(chip->dev, "Interrupt polling period set at %d ms\n", 109762306a36Sopenharmony_ci chip->passive_delay); 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_cierror: 110062306a36Sopenharmony_ci return ret; 110162306a36Sopenharmony_ciregmap_error: 110262306a36Sopenharmony_ci free_irq(chip->chip_irq, chip); 110362306a36Sopenharmony_ci return ret; 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic const struct of_device_id da9121_dt_ids[] = { 110762306a36Sopenharmony_ci { .compatible = "dlg,da9121", .data = (void *) DA9121_SUBTYPE_DA9121 }, 110862306a36Sopenharmony_ci { .compatible = "dlg,da9130", .data = (void *) DA9121_SUBTYPE_DA9130 }, 110962306a36Sopenharmony_ci { .compatible = "dlg,da9217", .data = (void *) DA9121_SUBTYPE_DA9217 }, 111062306a36Sopenharmony_ci { .compatible = "dlg,da9122", .data = (void *) DA9121_SUBTYPE_DA9122 }, 111162306a36Sopenharmony_ci { .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 }, 111262306a36Sopenharmony_ci { .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 }, 111362306a36Sopenharmony_ci { .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 }, 111462306a36Sopenharmony_ci { .compatible = "dlg,da9141", .data = (void *) DA9121_SUBTYPE_DA9141 }, 111562306a36Sopenharmony_ci { .compatible = "dlg,da9142", .data = (void *) DA9121_SUBTYPE_DA9142 }, 111662306a36Sopenharmony_ci { } 111762306a36Sopenharmony_ci}; 111862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, da9121_dt_ids); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_cistatic inline int da9121_of_get_id(struct device *dev) 112162306a36Sopenharmony_ci{ 112262306a36Sopenharmony_ci const struct of_device_id *id = of_match_device(da9121_dt_ids, dev); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci if (!id) { 112562306a36Sopenharmony_ci dev_err(dev, "%s: Failed\n", __func__); 112662306a36Sopenharmony_ci return -EINVAL; 112762306a36Sopenharmony_ci } 112862306a36Sopenharmony_ci return (uintptr_t)id->data; 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic int da9121_i2c_probe(struct i2c_client *i2c) 113262306a36Sopenharmony_ci{ 113362306a36Sopenharmony_ci struct da9121 *chip; 113462306a36Sopenharmony_ci const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; 113562306a36Sopenharmony_ci int ret = 0; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci chip = devm_kzalloc(&i2c->dev, sizeof(struct da9121), GFP_KERNEL); 113862306a36Sopenharmony_ci if (!chip) { 113962306a36Sopenharmony_ci ret = -ENOMEM; 114062306a36Sopenharmony_ci goto error; 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci chip->pdata = i2c->dev.platform_data; 114462306a36Sopenharmony_ci chip->subvariant_id = da9121_of_get_id(&i2c->dev); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci ret = da9121_assign_chip_model(i2c, chip); 114762306a36Sopenharmony_ci if (ret < 0) 114862306a36Sopenharmony_ci goto error; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4); 115162306a36Sopenharmony_ci if (ret != 0) { 115262306a36Sopenharmony_ci dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret); 115362306a36Sopenharmony_ci goto error; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci ret = da9121_set_regulator_config(chip); 115762306a36Sopenharmony_ci if (ret < 0) 115862306a36Sopenharmony_ci goto error; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci ret = da9121_config_irq(i2c, chip); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_cierror: 116362306a36Sopenharmony_ci return ret; 116462306a36Sopenharmony_ci} 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_cistatic void da9121_i2c_remove(struct i2c_client *i2c) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci struct da9121 *chip = i2c_get_clientdata(i2c); 116962306a36Sopenharmony_ci const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; 117062306a36Sopenharmony_ci int ret; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci free_irq(chip->chip_irq, chip); 117362306a36Sopenharmony_ci cancel_delayed_work_sync(&chip->work); 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4); 117662306a36Sopenharmony_ci if (ret != 0) 117762306a36Sopenharmony_ci dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret); 117862306a36Sopenharmony_ci} 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_cistatic const struct i2c_device_id da9121_i2c_id[] = { 118162306a36Sopenharmony_ci {"da9121", DA9121_TYPE_DA9121_DA9130}, 118262306a36Sopenharmony_ci {"da9130", DA9121_TYPE_DA9121_DA9130}, 118362306a36Sopenharmony_ci {"da9217", DA9121_TYPE_DA9217}, 118462306a36Sopenharmony_ci {"da9122", DA9121_TYPE_DA9122_DA9131}, 118562306a36Sopenharmony_ci {"da9131", DA9121_TYPE_DA9122_DA9131}, 118662306a36Sopenharmony_ci {"da9220", DA9121_TYPE_DA9220_DA9132}, 118762306a36Sopenharmony_ci {"da9132", DA9121_TYPE_DA9220_DA9132}, 118862306a36Sopenharmony_ci {"da9141", DA9121_TYPE_DA9141}, 118962306a36Sopenharmony_ci {"da9142", DA9121_TYPE_DA9142}, 119062306a36Sopenharmony_ci {}, 119162306a36Sopenharmony_ci}; 119262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, da9121_i2c_id); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_cistatic struct i2c_driver da9121_regulator_driver = { 119562306a36Sopenharmony_ci .driver = { 119662306a36Sopenharmony_ci .name = "da9121", 119762306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 119862306a36Sopenharmony_ci .of_match_table = da9121_dt_ids, 119962306a36Sopenharmony_ci }, 120062306a36Sopenharmony_ci .probe = da9121_i2c_probe, 120162306a36Sopenharmony_ci .remove = da9121_i2c_remove, 120262306a36Sopenharmony_ci .id_table = da9121_i2c_id, 120362306a36Sopenharmony_ci}; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cimodule_i2c_driver(da9121_regulator_driver); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1208