1ed2f4c74SNaresh Solanki // SPDX-License-Identifier: GPL-2.0 2ed2f4c74SNaresh Solanki /* 3ed2f4c74SNaresh Solanki * Device driver for regulators in MAX5970 and MAX5978 IC 4ed2f4c74SNaresh Solanki * 5ed2f4c74SNaresh Solanki * Copyright (c) 2022 9elements GmbH 6ed2f4c74SNaresh Solanki * 7ed2f4c74SNaresh Solanki * Author: Patrick Rudolph <patrick.rudolph@9elements.com> 8ed2f4c74SNaresh Solanki */ 9ed2f4c74SNaresh Solanki 10ed2f4c74SNaresh Solanki #include <linux/bitops.h> 11ed2f4c74SNaresh Solanki #include <linux/device.h> 12ed2f4c74SNaresh Solanki #include <linux/err.h> 13f5afdd13SNaresh Solanki #include <linux/hwmon.h> 14ed2f4c74SNaresh Solanki #include <linux/module.h> 15ed2f4c74SNaresh Solanki #include <linux/io.h> 16ed2f4c74SNaresh Solanki #include <linux/of.h> 17ed2f4c74SNaresh Solanki #include <linux/i2c.h> 18ed2f4c74SNaresh Solanki #include <linux/regmap.h> 19ed2f4c74SNaresh Solanki #include <linux/regulator/driver.h> 20ed2f4c74SNaresh Solanki #include <linux/regulator/machine.h> 21ed2f4c74SNaresh Solanki #include <linux/regulator/of_regulator.h> 22ed2f4c74SNaresh Solanki #include <linux/platform_device.h> 23ed2f4c74SNaresh Solanki 24ed2f4c74SNaresh Solanki #include <linux/mfd/max5970.h> 25ed2f4c74SNaresh Solanki 26ed2f4c74SNaresh Solanki struct max5970_regulator { 27ed2f4c74SNaresh Solanki int num_switches, mon_rng, irng, shunt_micro_ohms, lim_uA; 28ed2f4c74SNaresh Solanki struct regmap *regmap; 29ed2f4c74SNaresh Solanki }; 30ed2f4c74SNaresh Solanki 31ed2f4c74SNaresh Solanki enum max597x_regulator_id { 32e5d40e9aSNaresh Solanki MAX597X_sw0, 33e5d40e9aSNaresh Solanki MAX597X_sw1, 34ed2f4c74SNaresh Solanki }; 35ed2f4c74SNaresh Solanki 36f5afdd13SNaresh Solanki static int max5970_read_adc(struct regmap *regmap, int reg, long *val) 37f5afdd13SNaresh Solanki { 38f5afdd13SNaresh Solanki u8 reg_data[2]; 39f5afdd13SNaresh Solanki int ret; 40f5afdd13SNaresh Solanki 41f5afdd13SNaresh Solanki ret = regmap_bulk_read(regmap, reg, ®_data[0], 2); 42f5afdd13SNaresh Solanki if (ret < 0) 43f5afdd13SNaresh Solanki return ret; 44f5afdd13SNaresh Solanki 45f5afdd13SNaresh Solanki *val = (reg_data[0] << 2) | (reg_data[1] & 3); 46f5afdd13SNaresh Solanki 47f5afdd13SNaresh Solanki return 0; 48f5afdd13SNaresh Solanki } 49f5afdd13SNaresh Solanki 50f5afdd13SNaresh Solanki static int max5970_read(struct device *dev, enum hwmon_sensor_types type, 51f5afdd13SNaresh Solanki u32 attr, int channel, long *val) 52f5afdd13SNaresh Solanki { 53f5afdd13SNaresh Solanki struct regulator_dev **rdevs = dev_get_drvdata(dev); 54f5afdd13SNaresh Solanki struct max5970_regulator *ddata = rdev_get_drvdata(rdevs[channel]); 55f5afdd13SNaresh Solanki struct regmap *regmap = ddata->regmap; 56f5afdd13SNaresh Solanki int ret; 57f5afdd13SNaresh Solanki 58f5afdd13SNaresh Solanki switch (type) { 59f5afdd13SNaresh Solanki case hwmon_curr: 60f5afdd13SNaresh Solanki switch (attr) { 61f5afdd13SNaresh Solanki case hwmon_curr_input: 62f5afdd13SNaresh Solanki ret = max5970_read_adc(regmap, MAX5970_REG_CURRENT_H(channel), val); 63f5afdd13SNaresh Solanki if (ret < 0) 64f5afdd13SNaresh Solanki return ret; 65f5afdd13SNaresh Solanki /* 66f5afdd13SNaresh Solanki * Calculate current from ADC value, IRNG range & shunt resistor value. 67f5afdd13SNaresh Solanki * ddata->irng holds the voltage corresponding to the maximum value the 68f5afdd13SNaresh Solanki * 10-bit ADC can measure. 69f5afdd13SNaresh Solanki * To obtain the output, multiply the ADC value by the IRNG range (in 70f5afdd13SNaresh Solanki * millivolts) and then divide it by the maximum value of the 10-bit ADC. 71f5afdd13SNaresh Solanki */ 72f5afdd13SNaresh Solanki *val = (*val * ddata->irng) >> 10; 73*886fee35SYu Jiaoliang /* Convert the voltage measurement across shunt resistor to current */ 74f5afdd13SNaresh Solanki *val = (*val * 1000) / ddata->shunt_micro_ohms; 75f5afdd13SNaresh Solanki return 0; 76f5afdd13SNaresh Solanki default: 77f5afdd13SNaresh Solanki return -EOPNOTSUPP; 78f5afdd13SNaresh Solanki } 79f5afdd13SNaresh Solanki 80f5afdd13SNaresh Solanki case hwmon_in: 81f5afdd13SNaresh Solanki switch (attr) { 82f5afdd13SNaresh Solanki case hwmon_in_input: 83f5afdd13SNaresh Solanki ret = max5970_read_adc(regmap, MAX5970_REG_VOLTAGE_H(channel), val); 84f5afdd13SNaresh Solanki if (ret < 0) 85f5afdd13SNaresh Solanki return ret; 86f5afdd13SNaresh Solanki /* 87f5afdd13SNaresh Solanki * Calculate voltage from ADC value and MON range. 88f5afdd13SNaresh Solanki * ddata->mon_rng holds the voltage corresponding to the maximum value the 89f5afdd13SNaresh Solanki * 10-bit ADC can measure. 90f5afdd13SNaresh Solanki * To obtain the output, multiply the ADC value by the MON range (in 91f5afdd13SNaresh Solanki * microvolts) and then divide it by the maximum value of the 10-bit ADC. 92f5afdd13SNaresh Solanki */ 93f5afdd13SNaresh Solanki *val = mul_u64_u32_shr(*val, ddata->mon_rng, 10); 94f5afdd13SNaresh Solanki /* uV to mV */ 95f5afdd13SNaresh Solanki *val = *val / 1000; 96f5afdd13SNaresh Solanki return 0; 97f5afdd13SNaresh Solanki default: 98f5afdd13SNaresh Solanki return -EOPNOTSUPP; 99f5afdd13SNaresh Solanki } 100f5afdd13SNaresh Solanki default: 101f5afdd13SNaresh Solanki return -EOPNOTSUPP; 102f5afdd13SNaresh Solanki } 103f5afdd13SNaresh Solanki } 104f5afdd13SNaresh Solanki 105f5afdd13SNaresh Solanki static umode_t max5970_is_visible(const void *data, 106f5afdd13SNaresh Solanki enum hwmon_sensor_types type, 107f5afdd13SNaresh Solanki u32 attr, int channel) 108f5afdd13SNaresh Solanki { 109f5afdd13SNaresh Solanki struct regulator_dev **rdevs = (struct regulator_dev **)data; 110f5afdd13SNaresh Solanki struct max5970_regulator *ddata; 111f5afdd13SNaresh Solanki 112f5afdd13SNaresh Solanki if (channel >= MAX5970_NUM_SWITCHES || !rdevs[channel]) 113f5afdd13SNaresh Solanki return 0; 114f5afdd13SNaresh Solanki 115f5afdd13SNaresh Solanki ddata = rdev_get_drvdata(rdevs[channel]); 116f5afdd13SNaresh Solanki 117f5afdd13SNaresh Solanki if (channel >= ddata->num_switches) 118f5afdd13SNaresh Solanki return 0; 119f5afdd13SNaresh Solanki 120f5afdd13SNaresh Solanki switch (type) { 121f5afdd13SNaresh Solanki case hwmon_in: 122f5afdd13SNaresh Solanki switch (attr) { 123f5afdd13SNaresh Solanki case hwmon_in_input: 124f5afdd13SNaresh Solanki return 0444; 125f5afdd13SNaresh Solanki default: 126f5afdd13SNaresh Solanki break; 127f5afdd13SNaresh Solanki } 128f5afdd13SNaresh Solanki break; 129f5afdd13SNaresh Solanki case hwmon_curr: 130f5afdd13SNaresh Solanki switch (attr) { 131f5afdd13SNaresh Solanki case hwmon_curr_input: 132f5afdd13SNaresh Solanki /* Current measurement requires knowledge of the shunt resistor value. */ 133f5afdd13SNaresh Solanki if (ddata->shunt_micro_ohms) 134f5afdd13SNaresh Solanki return 0444; 135f5afdd13SNaresh Solanki break; 136f5afdd13SNaresh Solanki default: 137f5afdd13SNaresh Solanki break; 138f5afdd13SNaresh Solanki } 139f5afdd13SNaresh Solanki break; 140f5afdd13SNaresh Solanki default: 141f5afdd13SNaresh Solanki break; 142f5afdd13SNaresh Solanki } 143f5afdd13SNaresh Solanki return 0; 144f5afdd13SNaresh Solanki } 145f5afdd13SNaresh Solanki 146f5afdd13SNaresh Solanki static const struct hwmon_ops max5970_hwmon_ops = { 147f5afdd13SNaresh Solanki .is_visible = max5970_is_visible, 148f5afdd13SNaresh Solanki .read = max5970_read, 149f5afdd13SNaresh Solanki }; 150f5afdd13SNaresh Solanki 151f5afdd13SNaresh Solanki static const struct hwmon_channel_info *max5970_info[] = { 152f5afdd13SNaresh Solanki HWMON_CHANNEL_INFO(in, HWMON_I_INPUT, HWMON_I_INPUT), 153f5afdd13SNaresh Solanki HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT, HWMON_C_INPUT), 154f5afdd13SNaresh Solanki NULL 155f5afdd13SNaresh Solanki }; 156f5afdd13SNaresh Solanki 157f5afdd13SNaresh Solanki static const struct hwmon_chip_info max5970_chip_info = { 158f5afdd13SNaresh Solanki .ops = &max5970_hwmon_ops, 159f5afdd13SNaresh Solanki .info = max5970_info, 160f5afdd13SNaresh Solanki }; 161f5afdd13SNaresh Solanki 162ed2f4c74SNaresh Solanki static int max597x_uvp_ovp_check_mode(struct regulator_dev *rdev, int severity) 163ed2f4c74SNaresh Solanki { 164ed2f4c74SNaresh Solanki int ret, reg; 165ed2f4c74SNaresh Solanki 166ed2f4c74SNaresh Solanki /* Status1 register contains the soft strap values sampled at POR */ 167ed2f4c74SNaresh Solanki ret = regmap_read(rdev->regmap, MAX5970_REG_STATUS1, ®); 168ed2f4c74SNaresh Solanki if (ret) 169ed2f4c74SNaresh Solanki return ret; 170ed2f4c74SNaresh Solanki 171ed2f4c74SNaresh Solanki /* Check soft straps match requested mode */ 172ed2f4c74SNaresh Solanki if (severity == REGULATOR_SEVERITY_PROT) { 173ed2f4c74SNaresh Solanki if (STATUS1_PROT(reg) != STATUS1_PROT_SHUTDOWN) 174ed2f4c74SNaresh Solanki return -EOPNOTSUPP; 175ed2f4c74SNaresh Solanki 176ed2f4c74SNaresh Solanki return 0; 177ed2f4c74SNaresh Solanki } 178ed2f4c74SNaresh Solanki if (STATUS1_PROT(reg) == STATUS1_PROT_SHUTDOWN) 179ed2f4c74SNaresh Solanki return -EOPNOTSUPP; 180ed2f4c74SNaresh Solanki 181ed2f4c74SNaresh Solanki return 0; 182ed2f4c74SNaresh Solanki } 183ed2f4c74SNaresh Solanki 184ed2f4c74SNaresh Solanki static int max597x_set_vp(struct regulator_dev *rdev, int lim_uV, int severity, 185ed2f4c74SNaresh Solanki bool enable, bool overvoltage) 186ed2f4c74SNaresh Solanki { 187ed2f4c74SNaresh Solanki int off_h, off_l, reg, ret; 188ed2f4c74SNaresh Solanki struct max5970_regulator *data = rdev_get_drvdata(rdev); 189ed2f4c74SNaresh Solanki int channel = rdev_get_id(rdev); 190ed2f4c74SNaresh Solanki 191ed2f4c74SNaresh Solanki if (overvoltage) { 192ed2f4c74SNaresh Solanki if (severity == REGULATOR_SEVERITY_WARN) { 193ed2f4c74SNaresh Solanki off_h = MAX5970_REG_CH_OV_WARN_H(channel); 194ed2f4c74SNaresh Solanki off_l = MAX5970_REG_CH_OV_WARN_L(channel); 195ed2f4c74SNaresh Solanki } else { 196ed2f4c74SNaresh Solanki off_h = MAX5970_REG_CH_OV_CRIT_H(channel); 197ed2f4c74SNaresh Solanki off_l = MAX5970_REG_CH_OV_CRIT_L(channel); 198ed2f4c74SNaresh Solanki } 199ed2f4c74SNaresh Solanki } else { 200ed2f4c74SNaresh Solanki if (severity == REGULATOR_SEVERITY_WARN) { 201ed2f4c74SNaresh Solanki off_h = MAX5970_REG_CH_UV_WARN_H(channel); 202ed2f4c74SNaresh Solanki off_l = MAX5970_REG_CH_UV_WARN_L(channel); 203ed2f4c74SNaresh Solanki } else { 204ed2f4c74SNaresh Solanki off_h = MAX5970_REG_CH_UV_CRIT_H(channel); 205ed2f4c74SNaresh Solanki off_l = MAX5970_REG_CH_UV_CRIT_L(channel); 206ed2f4c74SNaresh Solanki } 207ed2f4c74SNaresh Solanki } 208ed2f4c74SNaresh Solanki 209ed2f4c74SNaresh Solanki if (enable) 210ed2f4c74SNaresh Solanki /* reg = ADC_MASK * (lim_uV / 1000000) / (data->mon_rng / 1000000) */ 211ed2f4c74SNaresh Solanki reg = ADC_MASK * lim_uV / data->mon_rng; 212ed2f4c74SNaresh Solanki else 213ed2f4c74SNaresh Solanki reg = 0; 214ed2f4c74SNaresh Solanki 215ed2f4c74SNaresh Solanki ret = regmap_write(rdev->regmap, off_h, MAX5970_VAL2REG_H(reg)); 216ed2f4c74SNaresh Solanki if (ret) 217ed2f4c74SNaresh Solanki return ret; 218ed2f4c74SNaresh Solanki 219ed2f4c74SNaresh Solanki ret = regmap_write(rdev->regmap, off_l, MAX5970_VAL2REG_L(reg)); 220ed2f4c74SNaresh Solanki if (ret) 221ed2f4c74SNaresh Solanki return ret; 222ed2f4c74SNaresh Solanki 223ed2f4c74SNaresh Solanki return 0; 224ed2f4c74SNaresh Solanki } 225ed2f4c74SNaresh Solanki 226ed2f4c74SNaresh Solanki static int max597x_set_uvp(struct regulator_dev *rdev, int lim_uV, int severity, 227ed2f4c74SNaresh Solanki bool enable) 228ed2f4c74SNaresh Solanki { 229ed2f4c74SNaresh Solanki int ret; 230ed2f4c74SNaresh Solanki 231ed2f4c74SNaresh Solanki /* 232ed2f4c74SNaresh Solanki * MAX5970 has enable control as a special value in limit reg. Can't 233ed2f4c74SNaresh Solanki * set limit but keep feature disabled or enable W/O given limit. 234ed2f4c74SNaresh Solanki */ 235ed2f4c74SNaresh Solanki if ((lim_uV && !enable) || (!lim_uV && enable)) 236ed2f4c74SNaresh Solanki return -EINVAL; 237ed2f4c74SNaresh Solanki 238ed2f4c74SNaresh Solanki ret = max597x_uvp_ovp_check_mode(rdev, severity); 239ed2f4c74SNaresh Solanki if (ret) 240ed2f4c74SNaresh Solanki return ret; 241ed2f4c74SNaresh Solanki 242ed2f4c74SNaresh Solanki return max597x_set_vp(rdev, lim_uV, severity, enable, false); 243ed2f4c74SNaresh Solanki } 244ed2f4c74SNaresh Solanki 245ed2f4c74SNaresh Solanki static int max597x_set_ovp(struct regulator_dev *rdev, int lim_uV, int severity, 246ed2f4c74SNaresh Solanki bool enable) 247ed2f4c74SNaresh Solanki { 248ed2f4c74SNaresh Solanki int ret; 249ed2f4c74SNaresh Solanki 250ed2f4c74SNaresh Solanki /* 251ed2f4c74SNaresh Solanki * MAX5970 has enable control as a special value in limit reg. Can't 252ed2f4c74SNaresh Solanki * set limit but keep feature disabled or enable W/O given limit. 253ed2f4c74SNaresh Solanki */ 254ed2f4c74SNaresh Solanki if ((lim_uV && !enable) || (!lim_uV && enable)) 255ed2f4c74SNaresh Solanki return -EINVAL; 256ed2f4c74SNaresh Solanki 257ed2f4c74SNaresh Solanki ret = max597x_uvp_ovp_check_mode(rdev, severity); 258ed2f4c74SNaresh Solanki if (ret) 259ed2f4c74SNaresh Solanki return ret; 260ed2f4c74SNaresh Solanki 261ed2f4c74SNaresh Solanki return max597x_set_vp(rdev, lim_uV, severity, enable, true); 262ed2f4c74SNaresh Solanki } 263ed2f4c74SNaresh Solanki 264ed2f4c74SNaresh Solanki static int max597x_set_ocp(struct regulator_dev *rdev, int lim_uA, 265ed2f4c74SNaresh Solanki int severity, bool enable) 266ed2f4c74SNaresh Solanki { 267ed2f4c74SNaresh Solanki int val, reg; 268ed2f4c74SNaresh Solanki unsigned int vthst, vthfst; 269ed2f4c74SNaresh Solanki 270ed2f4c74SNaresh Solanki struct max5970_regulator *data = rdev_get_drvdata(rdev); 271ed2f4c74SNaresh Solanki int rdev_id = rdev_get_id(rdev); 272ed2f4c74SNaresh Solanki /* 273ed2f4c74SNaresh Solanki * MAX5970 doesn't has enable control for ocp. 274ed2f4c74SNaresh Solanki * If limit is specified but enable is not set then hold the value in 275ed2f4c74SNaresh Solanki * variable & later use it when ocp needs to be enabled. 276ed2f4c74SNaresh Solanki */ 277ed2f4c74SNaresh Solanki if (lim_uA != 0 && lim_uA != data->lim_uA) 278ed2f4c74SNaresh Solanki data->lim_uA = lim_uA; 279ed2f4c74SNaresh Solanki 280ed2f4c74SNaresh Solanki if (severity != REGULATOR_SEVERITY_PROT) 281ed2f4c74SNaresh Solanki return -EINVAL; 282ed2f4c74SNaresh Solanki 283ed2f4c74SNaresh Solanki if (enable) { 284ed2f4c74SNaresh Solanki 285ed2f4c74SNaresh Solanki /* Calc Vtrip threshold in uV. */ 286ed2f4c74SNaresh Solanki vthst = 287ed2f4c74SNaresh Solanki div_u64(mul_u32_u32(data->shunt_micro_ohms, data->lim_uA), 288ed2f4c74SNaresh Solanki 1000000); 289ed2f4c74SNaresh Solanki 290ed2f4c74SNaresh Solanki /* 291ed2f4c74SNaresh Solanki * As recommended in datasheed, add 20% margin to avoid 292ed2f4c74SNaresh Solanki * spurious event & passive component tolerance. 293ed2f4c74SNaresh Solanki */ 294ed2f4c74SNaresh Solanki vthst = div_u64(mul_u32_u32(vthst, 120), 100); 295ed2f4c74SNaresh Solanki 296ed2f4c74SNaresh Solanki /* Calc fast Vtrip threshold in uV */ 297ed2f4c74SNaresh Solanki vthfst = vthst * (MAX5970_FAST2SLOW_RATIO / 100); 298ed2f4c74SNaresh Solanki 299ed2f4c74SNaresh Solanki if (vthfst > data->irng) { 300ed2f4c74SNaresh Solanki dev_err(&rdev->dev, "Current limit out of range\n"); 301ed2f4c74SNaresh Solanki return -EINVAL; 302ed2f4c74SNaresh Solanki } 303ed2f4c74SNaresh Solanki /* Fast trip threshold to be programmed */ 304ed2f4c74SNaresh Solanki val = div_u64(mul_u32_u32(0xFF, vthfst), data->irng); 305ed2f4c74SNaresh Solanki } else 306ed2f4c74SNaresh Solanki /* 307ed2f4c74SNaresh Solanki * Since there is no option to disable ocp, set limit to max 308ed2f4c74SNaresh Solanki * value 309ed2f4c74SNaresh Solanki */ 310ed2f4c74SNaresh Solanki val = 0xFF; 311ed2f4c74SNaresh Solanki 312ed2f4c74SNaresh Solanki reg = MAX5970_REG_DAC_FAST(rdev_id); 313ed2f4c74SNaresh Solanki 314ed2f4c74SNaresh Solanki return regmap_write(rdev->regmap, reg, val); 315ed2f4c74SNaresh Solanki } 316ed2f4c74SNaresh Solanki 317ed2f4c74SNaresh Solanki static int max597x_get_status(struct regulator_dev *rdev) 318ed2f4c74SNaresh Solanki { 319ed2f4c74SNaresh Solanki int val, ret; 320ed2f4c74SNaresh Solanki 321ed2f4c74SNaresh Solanki ret = regmap_read(rdev->regmap, MAX5970_REG_STATUS3, &val); 322ed2f4c74SNaresh Solanki if (ret) 323ed2f4c74SNaresh Solanki return ret; 324ed2f4c74SNaresh Solanki 325ed2f4c74SNaresh Solanki if (val & MAX5970_STATUS3_ALERT) 326ed2f4c74SNaresh Solanki return REGULATOR_STATUS_ERROR; 327ed2f4c74SNaresh Solanki 328ed2f4c74SNaresh Solanki ret = regulator_is_enabled_regmap(rdev); 329ed2f4c74SNaresh Solanki if (ret < 0) 330ed2f4c74SNaresh Solanki return ret; 331ed2f4c74SNaresh Solanki 332ed2f4c74SNaresh Solanki if (ret) 333ed2f4c74SNaresh Solanki return REGULATOR_STATUS_ON; 334ed2f4c74SNaresh Solanki 335ed2f4c74SNaresh Solanki return REGULATOR_STATUS_OFF; 336ed2f4c74SNaresh Solanki } 337ed2f4c74SNaresh Solanki 338ed2f4c74SNaresh Solanki static const struct regulator_ops max597x_switch_ops = { 339ed2f4c74SNaresh Solanki .enable = regulator_enable_regmap, 340ed2f4c74SNaresh Solanki .disable = regulator_disable_regmap, 341ed2f4c74SNaresh Solanki .is_enabled = regulator_is_enabled_regmap, 342ed2f4c74SNaresh Solanki .get_status = max597x_get_status, 343ed2f4c74SNaresh Solanki .set_over_voltage_protection = max597x_set_ovp, 344ed2f4c74SNaresh Solanki .set_under_voltage_protection = max597x_set_uvp, 345ed2f4c74SNaresh Solanki .set_over_current_protection = max597x_set_ocp, 346ed2f4c74SNaresh Solanki }; 347ed2f4c74SNaresh Solanki 348ed2f4c74SNaresh Solanki static int max597x_dt_parse(struct device_node *np, 349ed2f4c74SNaresh Solanki const struct regulator_desc *desc, 350ed2f4c74SNaresh Solanki struct regulator_config *cfg) 351ed2f4c74SNaresh Solanki { 352ed2f4c74SNaresh Solanki struct max5970_regulator *data = cfg->driver_data; 353ed2f4c74SNaresh Solanki int ret = 0; 354ed2f4c74SNaresh Solanki 355ed2f4c74SNaresh Solanki ret = 356ed2f4c74SNaresh Solanki of_property_read_u32(np, "shunt-resistor-micro-ohms", 357ed2f4c74SNaresh Solanki &data->shunt_micro_ohms); 358ed2f4c74SNaresh Solanki if (ret < 0) 359ed2f4c74SNaresh Solanki dev_err(cfg->dev, 360ed2f4c74SNaresh Solanki "property 'shunt-resistor-micro-ohms' not found, err %d\n", 361ed2f4c74SNaresh Solanki ret); 362ed2f4c74SNaresh Solanki return ret; 363ed2f4c74SNaresh Solanki 364ed2f4c74SNaresh Solanki } 365ed2f4c74SNaresh Solanki 366ed2f4c74SNaresh Solanki #define MAX597X_SWITCH(_ID, _ereg, _chan, _supply) { \ 367ed2f4c74SNaresh Solanki .name = #_ID, \ 368ed2f4c74SNaresh Solanki .of_match = of_match_ptr(#_ID), \ 369ed2f4c74SNaresh Solanki .ops = &max597x_switch_ops, \ 370ed2f4c74SNaresh Solanki .regulators_node = of_match_ptr("regulators"), \ 371ed2f4c74SNaresh Solanki .type = REGULATOR_VOLTAGE, \ 372ed2f4c74SNaresh Solanki .id = MAX597X_##_ID, \ 373ed2f4c74SNaresh Solanki .owner = THIS_MODULE, \ 374ed2f4c74SNaresh Solanki .supply_name = _supply, \ 375ed2f4c74SNaresh Solanki .enable_reg = _ereg, \ 376ed2f4c74SNaresh Solanki .enable_mask = CHXEN((_chan)), \ 377ed2f4c74SNaresh Solanki .of_parse_cb = max597x_dt_parse, \ 378ed2f4c74SNaresh Solanki } 379ed2f4c74SNaresh Solanki 380ed2f4c74SNaresh Solanki static const struct regulator_desc regulators[] = { 381e5d40e9aSNaresh Solanki MAX597X_SWITCH(sw0, MAX5970_REG_CHXEN, 0, "vss1"), 382e5d40e9aSNaresh Solanki MAX597X_SWITCH(sw1, MAX5970_REG_CHXEN, 1, "vss2"), 383ed2f4c74SNaresh Solanki }; 384ed2f4c74SNaresh Solanki 385ed2f4c74SNaresh Solanki static int max597x_regmap_read_clear(struct regmap *map, unsigned int reg, 386ed2f4c74SNaresh Solanki unsigned int *val) 387ed2f4c74SNaresh Solanki { 388ed2f4c74SNaresh Solanki int ret; 389ed2f4c74SNaresh Solanki 390ed2f4c74SNaresh Solanki ret = regmap_read(map, reg, val); 391ed2f4c74SNaresh Solanki if (ret) 392ed2f4c74SNaresh Solanki return ret; 393ed2f4c74SNaresh Solanki 394ed2f4c74SNaresh Solanki if (*val) 395a3fa9838SPatrick Rudolph return regmap_write(map, reg, 0); 396ed2f4c74SNaresh Solanki 397ed2f4c74SNaresh Solanki return 0; 398ed2f4c74SNaresh Solanki } 399ed2f4c74SNaresh Solanki 400ed2f4c74SNaresh Solanki static int max597x_irq_handler(int irq, struct regulator_irq_data *rid, 401ed2f4c74SNaresh Solanki unsigned long *dev_mask) 402ed2f4c74SNaresh Solanki { 403ed2f4c74SNaresh Solanki struct regulator_err_state *stat; 404ed2f4c74SNaresh Solanki struct max5970_regulator *d = (struct max5970_regulator *)rid->data; 405ed2f4c74SNaresh Solanki int val, ret, i; 406ed2f4c74SNaresh Solanki 407ed2f4c74SNaresh Solanki ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT0, &val); 408ed2f4c74SNaresh Solanki if (ret) 409ed2f4c74SNaresh Solanki return REGULATOR_FAILED_RETRY; 410ed2f4c74SNaresh Solanki 411ed2f4c74SNaresh Solanki *dev_mask = 0; 412ed2f4c74SNaresh Solanki for (i = 0; i < d->num_switches; i++) { 413ed2f4c74SNaresh Solanki stat = &rid->states[i]; 414ed2f4c74SNaresh Solanki stat->notifs = 0; 415ed2f4c74SNaresh Solanki stat->errors = 0; 416ed2f4c74SNaresh Solanki } 417ed2f4c74SNaresh Solanki 418ed2f4c74SNaresh Solanki for (i = 0; i < d->num_switches; i++) { 419ed2f4c74SNaresh Solanki stat = &rid->states[i]; 420ed2f4c74SNaresh Solanki 421ed2f4c74SNaresh Solanki if (val & UV_STATUS_CRIT(i)) { 422ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 423ed2f4c74SNaresh Solanki stat->notifs |= REGULATOR_EVENT_UNDER_VOLTAGE; 424ed2f4c74SNaresh Solanki stat->errors |= REGULATOR_ERROR_UNDER_VOLTAGE; 425ed2f4c74SNaresh Solanki } else if (val & UV_STATUS_WARN(i)) { 426ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 427ed2f4c74SNaresh Solanki stat->notifs |= REGULATOR_EVENT_UNDER_VOLTAGE_WARN; 428ed2f4c74SNaresh Solanki stat->errors |= REGULATOR_ERROR_UNDER_VOLTAGE_WARN; 429ed2f4c74SNaresh Solanki } 430ed2f4c74SNaresh Solanki } 431ed2f4c74SNaresh Solanki 432ed2f4c74SNaresh Solanki ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT1, &val); 433ed2f4c74SNaresh Solanki if (ret) 434ed2f4c74SNaresh Solanki return REGULATOR_FAILED_RETRY; 435ed2f4c74SNaresh Solanki 436ed2f4c74SNaresh Solanki for (i = 0; i < d->num_switches; i++) { 437ed2f4c74SNaresh Solanki stat = &rid->states[i]; 438ed2f4c74SNaresh Solanki 439ed2f4c74SNaresh Solanki if (val & OV_STATUS_CRIT(i)) { 440ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 441ed2f4c74SNaresh Solanki stat->notifs |= REGULATOR_EVENT_REGULATION_OUT; 442ed2f4c74SNaresh Solanki stat->errors |= REGULATOR_ERROR_REGULATION_OUT; 443ed2f4c74SNaresh Solanki } else if (val & OV_STATUS_WARN(i)) { 444ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 445ed2f4c74SNaresh Solanki stat->notifs |= REGULATOR_EVENT_OVER_VOLTAGE_WARN; 446ed2f4c74SNaresh Solanki stat->errors |= REGULATOR_ERROR_OVER_VOLTAGE_WARN; 447ed2f4c74SNaresh Solanki } 448ed2f4c74SNaresh Solanki } 449ed2f4c74SNaresh Solanki 450ed2f4c74SNaresh Solanki ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT2, &val); 451ed2f4c74SNaresh Solanki if (ret) 452ed2f4c74SNaresh Solanki return REGULATOR_FAILED_RETRY; 453ed2f4c74SNaresh Solanki 454ed2f4c74SNaresh Solanki for (i = 0; i < d->num_switches; i++) { 455ed2f4c74SNaresh Solanki stat = &rid->states[i]; 456ed2f4c74SNaresh Solanki 457ed2f4c74SNaresh Solanki if (val & OC_STATUS_WARN(i)) { 458ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 459ed2f4c74SNaresh Solanki stat->notifs |= REGULATOR_EVENT_OVER_CURRENT_WARN; 460ed2f4c74SNaresh Solanki stat->errors |= REGULATOR_ERROR_OVER_CURRENT_WARN; 461ed2f4c74SNaresh Solanki } 462ed2f4c74SNaresh Solanki } 463ed2f4c74SNaresh Solanki 464ed2f4c74SNaresh Solanki ret = regmap_read(d->regmap, MAX5970_REG_STATUS0, &val); 465ed2f4c74SNaresh Solanki if (ret) 466ed2f4c74SNaresh Solanki return REGULATOR_FAILED_RETRY; 467ed2f4c74SNaresh Solanki 468ed2f4c74SNaresh Solanki for (i = 0; i < d->num_switches; i++) { 469ed2f4c74SNaresh Solanki stat = &rid->states[i]; 470ed2f4c74SNaresh Solanki 471ed2f4c74SNaresh Solanki if ((val & MAX5970_CB_IFAULTF(i)) 472ed2f4c74SNaresh Solanki || (val & MAX5970_CB_IFAULTS(i))) { 473ed2f4c74SNaresh Solanki *dev_mask |= 1 << i; 474ed2f4c74SNaresh Solanki stat->notifs |= 475ed2f4c74SNaresh Solanki REGULATOR_EVENT_OVER_CURRENT | 476ed2f4c74SNaresh Solanki REGULATOR_EVENT_DISABLE; 477ed2f4c74SNaresh Solanki stat->errors |= 478ed2f4c74SNaresh Solanki REGULATOR_ERROR_OVER_CURRENT | REGULATOR_ERROR_FAIL; 479ed2f4c74SNaresh Solanki 480ed2f4c74SNaresh Solanki /* Clear the sub-IRQ status */ 481ed2f4c74SNaresh Solanki regulator_disable_regmap(stat->rdev); 482ed2f4c74SNaresh Solanki } 483ed2f4c74SNaresh Solanki } 484ed2f4c74SNaresh Solanki return 0; 485ed2f4c74SNaresh Solanki } 486ed2f4c74SNaresh Solanki 487ed2f4c74SNaresh Solanki static int max597x_adc_range(struct regmap *regmap, const int ch, 488ed2f4c74SNaresh Solanki u32 *irng, u32 *mon_rng) 489ed2f4c74SNaresh Solanki { 490ed2f4c74SNaresh Solanki unsigned int reg; 491ed2f4c74SNaresh Solanki int ret; 492ed2f4c74SNaresh Solanki 493ed2f4c74SNaresh Solanki /* Decode current ADC range */ 494ed2f4c74SNaresh Solanki ret = regmap_read(regmap, MAX5970_REG_STATUS2, ®); 495ed2f4c74SNaresh Solanki if (ret) 496ed2f4c74SNaresh Solanki return ret; 497ed2f4c74SNaresh Solanki switch (MAX5970_IRNG(reg, ch)) { 498ed2f4c74SNaresh Solanki case 0: 499ed2f4c74SNaresh Solanki *irng = 100000; /* 100 mV */ 500ed2f4c74SNaresh Solanki break; 501ed2f4c74SNaresh Solanki case 1: 502ed2f4c74SNaresh Solanki *irng = 50000; /* 50 mV */ 503ed2f4c74SNaresh Solanki break; 504ed2f4c74SNaresh Solanki case 2: 505ed2f4c74SNaresh Solanki *irng = 25000; /* 25 mV */ 506ed2f4c74SNaresh Solanki break; 507ed2f4c74SNaresh Solanki default: 508ed2f4c74SNaresh Solanki return -EINVAL; 509ed2f4c74SNaresh Solanki } 510ed2f4c74SNaresh Solanki 511ed2f4c74SNaresh Solanki /* Decode current voltage monitor range */ 512ed2f4c74SNaresh Solanki ret = regmap_read(regmap, MAX5970_REG_MON_RANGE, ®); 513ed2f4c74SNaresh Solanki if (ret) 514ed2f4c74SNaresh Solanki return ret; 515ed2f4c74SNaresh Solanki 516ed2f4c74SNaresh Solanki *mon_rng = MAX5970_MON_MAX_RANGE_UV >> MAX5970_MON(reg, ch); 517ed2f4c74SNaresh Solanki 518ed2f4c74SNaresh Solanki return 0; 519ed2f4c74SNaresh Solanki } 520ed2f4c74SNaresh Solanki 521ed2f4c74SNaresh Solanki static int max597x_setup_irq(struct device *dev, 522ed2f4c74SNaresh Solanki int irq, 523ed2f4c74SNaresh Solanki struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES], 524ed2f4c74SNaresh Solanki int num_switches, struct max5970_regulator *data) 525ed2f4c74SNaresh Solanki { 526ed2f4c74SNaresh Solanki struct regulator_irq_desc max597x_notif = { 527ed2f4c74SNaresh Solanki .name = "max597x-irq", 528ed2f4c74SNaresh Solanki .map_event = max597x_irq_handler, 529ed2f4c74SNaresh Solanki .data = data, 530ed2f4c74SNaresh Solanki }; 531ed2f4c74SNaresh Solanki int errs = REGULATOR_ERROR_UNDER_VOLTAGE | 532ed2f4c74SNaresh Solanki REGULATOR_ERROR_UNDER_VOLTAGE_WARN | 533ed2f4c74SNaresh Solanki REGULATOR_ERROR_OVER_VOLTAGE_WARN | 534ed2f4c74SNaresh Solanki REGULATOR_ERROR_REGULATION_OUT | 535ed2f4c74SNaresh Solanki REGULATOR_ERROR_OVER_CURRENT | 536ed2f4c74SNaresh Solanki REGULATOR_ERROR_OVER_CURRENT_WARN | REGULATOR_ERROR_FAIL; 537ed2f4c74SNaresh Solanki void *irq_helper; 538ed2f4c74SNaresh Solanki 539ed2f4c74SNaresh Solanki /* Register notifiers - can fail if IRQ is not given */ 540ed2f4c74SNaresh Solanki irq_helper = devm_regulator_irq_helper(dev, &max597x_notif, 541ed2f4c74SNaresh Solanki irq, 0, errs, NULL, 542ed2f4c74SNaresh Solanki &rdevs[0], num_switches); 543ed2f4c74SNaresh Solanki if (IS_ERR(irq_helper)) { 544ed2f4c74SNaresh Solanki if (PTR_ERR(irq_helper) == -EPROBE_DEFER) 545ed2f4c74SNaresh Solanki return -EPROBE_DEFER; 546ed2f4c74SNaresh Solanki 547ed2f4c74SNaresh Solanki dev_warn(dev, "IRQ disabled %pe\n", irq_helper); 548ed2f4c74SNaresh Solanki } 549ed2f4c74SNaresh Solanki 550ed2f4c74SNaresh Solanki return 0; 551ed2f4c74SNaresh Solanki } 552ed2f4c74SNaresh Solanki 553ed2f4c74SNaresh Solanki static int max597x_regulator_probe(struct platform_device *pdev) 554ed2f4c74SNaresh Solanki { 555ed2f4c74SNaresh Solanki struct max5970_data *max597x; 556ed2f4c74SNaresh Solanki struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL); 557ed2f4c74SNaresh Solanki struct max5970_regulator *data; 558ed2f4c74SNaresh Solanki struct i2c_client *i2c = to_i2c_client(pdev->dev.parent); 559ed2f4c74SNaresh Solanki struct regulator_config config = { }; 560ed2f4c74SNaresh Solanki struct regulator_dev *rdev; 561f5afdd13SNaresh Solanki struct regulator_dev **rdevs = NULL; 562f5afdd13SNaresh Solanki struct device *hwmon_dev; 563ed2f4c74SNaresh Solanki int num_switches; 564ed2f4c74SNaresh Solanki int ret, i; 565ed2f4c74SNaresh Solanki 566ed2f4c74SNaresh Solanki if (!regmap) 567ed2f4c74SNaresh Solanki return -EPROBE_DEFER; 568ed2f4c74SNaresh Solanki 569ed2f4c74SNaresh Solanki max597x = devm_kzalloc(&i2c->dev, sizeof(struct max5970_data), GFP_KERNEL); 570ed2f4c74SNaresh Solanki if (!max597x) 571ed2f4c74SNaresh Solanki return -ENOMEM; 572ed2f4c74SNaresh Solanki 573f5afdd13SNaresh Solanki rdevs = devm_kcalloc(&i2c->dev, MAX5970_NUM_SWITCHES, sizeof(struct regulator_dev *), 574f5afdd13SNaresh Solanki GFP_KERNEL); 575f5afdd13SNaresh Solanki if (!rdevs) 576f5afdd13SNaresh Solanki return -ENOMEM; 577f5afdd13SNaresh Solanki 578ed2f4c74SNaresh Solanki i2c_set_clientdata(i2c, max597x); 579ed2f4c74SNaresh Solanki 580ed2f4c74SNaresh Solanki if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5978")) 581ed2f4c74SNaresh Solanki max597x->num_switches = MAX5978_NUM_SWITCHES; 582ed2f4c74SNaresh Solanki else if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5970")) 583ed2f4c74SNaresh Solanki max597x->num_switches = MAX5970_NUM_SWITCHES; 584ed2f4c74SNaresh Solanki else 585ed2f4c74SNaresh Solanki return -ENODEV; 586ed2f4c74SNaresh Solanki 587ed2f4c74SNaresh Solanki num_switches = max597x->num_switches; 588ed2f4c74SNaresh Solanki 589ed2f4c74SNaresh Solanki for (i = 0; i < num_switches; i++) { 590ed2f4c74SNaresh Solanki data = 591ed2f4c74SNaresh Solanki devm_kzalloc(&i2c->dev, sizeof(struct max5970_regulator), 592ed2f4c74SNaresh Solanki GFP_KERNEL); 593ed2f4c74SNaresh Solanki if (!data) 594ed2f4c74SNaresh Solanki return -ENOMEM; 595ed2f4c74SNaresh Solanki 596ed2f4c74SNaresh Solanki data->num_switches = num_switches; 597ed2f4c74SNaresh Solanki data->regmap = regmap; 598ed2f4c74SNaresh Solanki 599ed2f4c74SNaresh Solanki ret = max597x_adc_range(regmap, i, &max597x->irng[i], &max597x->mon_rng[i]); 600ed2f4c74SNaresh Solanki if (ret < 0) 601ed2f4c74SNaresh Solanki return ret; 602ed2f4c74SNaresh Solanki 603ed2f4c74SNaresh Solanki data->irng = max597x->irng[i]; 604ed2f4c74SNaresh Solanki data->mon_rng = max597x->mon_rng[i]; 605ed2f4c74SNaresh Solanki 606ed2f4c74SNaresh Solanki config.dev = &i2c->dev; 607ed2f4c74SNaresh Solanki config.driver_data = (void *)data; 608ed2f4c74SNaresh Solanki config.regmap = data->regmap; 609ed2f4c74SNaresh Solanki rdev = devm_regulator_register(&i2c->dev, 610ed2f4c74SNaresh Solanki ®ulators[i], &config); 611ed2f4c74SNaresh Solanki if (IS_ERR(rdev)) { 612ed2f4c74SNaresh Solanki dev_err(&i2c->dev, "failed to register regulator %s\n", 613ed2f4c74SNaresh Solanki regulators[i].name); 614ed2f4c74SNaresh Solanki return PTR_ERR(rdev); 615ed2f4c74SNaresh Solanki } 616ed2f4c74SNaresh Solanki rdevs[i] = rdev; 617ed2f4c74SNaresh Solanki max597x->shunt_micro_ohms[i] = data->shunt_micro_ohms; 618ed2f4c74SNaresh Solanki } 619ed2f4c74SNaresh Solanki 620f5afdd13SNaresh Solanki if (IS_REACHABLE(CONFIG_HWMON)) { 621f5afdd13SNaresh Solanki hwmon_dev = devm_hwmon_device_register_with_info(&i2c->dev, "max5970", rdevs, 622f5afdd13SNaresh Solanki &max5970_chip_info, NULL); 623f5afdd13SNaresh Solanki if (IS_ERR(hwmon_dev)) { 624f5afdd13SNaresh Solanki return dev_err_probe(&i2c->dev, PTR_ERR(hwmon_dev), 625f5afdd13SNaresh Solanki "Unable to register hwmon device\n"); 626f5afdd13SNaresh Solanki } 627f5afdd13SNaresh Solanki } 628f5afdd13SNaresh Solanki 629ed2f4c74SNaresh Solanki if (i2c->irq) { 630ed2f4c74SNaresh Solanki ret = 631ed2f4c74SNaresh Solanki max597x_setup_irq(&i2c->dev, i2c->irq, rdevs, num_switches, 632ed2f4c74SNaresh Solanki data); 633ed2f4c74SNaresh Solanki if (ret) { 634ed2f4c74SNaresh Solanki dev_err(&i2c->dev, "IRQ setup failed"); 635ed2f4c74SNaresh Solanki return ret; 636ed2f4c74SNaresh Solanki } 637ed2f4c74SNaresh Solanki } 638ed2f4c74SNaresh Solanki 639ed2f4c74SNaresh Solanki return ret; 640ed2f4c74SNaresh Solanki } 641ed2f4c74SNaresh Solanki 642ed2f4c74SNaresh Solanki static struct platform_driver max597x_regulator_driver = { 643ed2f4c74SNaresh Solanki .driver = { 644ed2f4c74SNaresh Solanki .name = "max5970-regulator", 645ed2f4c74SNaresh Solanki .probe_type = PROBE_PREFER_ASYNCHRONOUS, 646ed2f4c74SNaresh Solanki }, 647ed2f4c74SNaresh Solanki .probe = max597x_regulator_probe, 648ed2f4c74SNaresh Solanki }; 649ed2f4c74SNaresh Solanki 650ed2f4c74SNaresh Solanki module_platform_driver(max597x_regulator_driver); 651ed2f4c74SNaresh Solanki 652ed2f4c74SNaresh Solanki 653ed2f4c74SNaresh Solanki MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); 654ed2f4c74SNaresh Solanki MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); 655ed2f4c74SNaresh Solanki MODULE_LICENSE("GPL v2"); 656