1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/bitops.h> 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/of.h> 7 #include <linux/platform_device.h> 8 #include <linux/regmap.h> 9 #include <linux/regulator/consumer.h> 10 #include <linux/regulator/driver.h> 11 12 enum { 13 DSV_OUT_VLCM = 0, 14 DSV_OUT_VPOS, 15 DSV_OUT_VNEG, 16 DSV_OUT_MAX 17 }; 18 19 #define RT4831_REG_DSVEN 0x09 20 #define RT4831_REG_VLCM 0x0c 21 #define RT4831_REG_VPOS 0x0d 22 #define RT4831_REG_VNEG 0x0e 23 #define RT4831_REG_FLAGS 0x0f 24 25 #define RT4831_VOLT_MASK GENMASK(5, 0) 26 #define RT4831_DSVMODE_SHIFT 5 27 #define RT4831_DSVMODE_MASK GENMASK(7, 5) 28 #define RT4831_POSADEN_MASK BIT(4) 29 #define RT4831_NEGADEN_MASK BIT(3) 30 #define RT4831_POSEN_MASK BIT(2) 31 #define RT4831_NEGEN_MASK BIT(1) 32 33 #define RT4831_OTP_MASK BIT(6) 34 #define RT4831_LCMOVP_MASK BIT(5) 35 #define RT4831_VPOSSCP_MASK BIT(3) 36 #define RT4831_VNEGSCP_MASK BIT(2) 37 38 #define DSV_MODE_NORMAL (0x4 << RT4831_DSVMODE_SHIFT) 39 #define DSV_MODE_BYPASS (0x6 << RT4831_DSVMODE_SHIFT) 40 #define STEP_UV 50000 41 #define VLCM_MIN_UV 4000000 42 #define VLCM_MAX_UV 7150000 43 #define VLCM_N_VOLTAGES ((VLCM_MAX_UV - VLCM_MIN_UV) / STEP_UV + 1) 44 #define VPN_MIN_UV 4000000 45 #define VPN_MAX_UV 6500000 46 #define VPN_N_VOLTAGES ((VPN_MAX_UV - VPN_MIN_UV) / STEP_UV + 1) 47 48 static int rt4831_get_error_flags(struct regulator_dev *rdev, unsigned int *flags) 49 { 50 struct regmap *regmap = rdev_get_regmap(rdev); 51 int rid = rdev_get_id(rdev); 52 unsigned int val, events = 0; 53 int ret; 54 55 ret = regmap_read(regmap, RT4831_REG_FLAGS, &val); 56 if (ret) 57 return ret; 58 59 if (val & RT4831_OTP_MASK) 60 events |= REGULATOR_ERROR_OVER_TEMP; 61 62 if (rid == DSV_OUT_VLCM && (val & RT4831_LCMOVP_MASK)) 63 events |= REGULATOR_ERROR_OVER_CURRENT; 64 65 if (rid == DSV_OUT_VPOS && (val & RT4831_VPOSSCP_MASK)) 66 events |= REGULATOR_ERROR_OVER_CURRENT; 67 68 if (rid == DSV_OUT_VNEG && (val & RT4831_VNEGSCP_MASK)) 69 events |= REGULATOR_ERROR_OVER_CURRENT; 70 71 *flags = events; 72 return 0; 73 } 74 75 static const struct regulator_ops rt4831_dsvlcm_ops = { 76 .list_voltage = regulator_list_voltage_linear, 77 .set_voltage_sel = regulator_set_voltage_sel_regmap, 78 .get_voltage_sel = regulator_get_voltage_sel_regmap, 79 .set_bypass = regulator_set_bypass_regmap, 80 .get_bypass = regulator_get_bypass_regmap, 81 .get_error_flags = rt4831_get_error_flags, 82 }; 83 84 static const struct regulator_ops rt4831_dsvpn_ops = { 85 .list_voltage = regulator_list_voltage_linear, 86 .set_voltage_sel = regulator_set_voltage_sel_regmap, 87 .get_voltage_sel = regulator_get_voltage_sel_regmap, 88 .enable = regulator_enable_regmap, 89 .disable = regulator_disable_regmap, 90 .is_enabled = regulator_is_enabled_regmap, 91 .set_active_discharge = regulator_set_active_discharge_regmap, 92 .get_error_flags = rt4831_get_error_flags, 93 }; 94 95 static const struct regulator_desc rt4831_regulator_descs[] = { 96 { 97 .name = "DSVLCM", 98 .ops = &rt4831_dsvlcm_ops, 99 .of_match = of_match_ptr("DSVLCM"), 100 .regulators_node = of_match_ptr("regulators"), 101 .type = REGULATOR_VOLTAGE, 102 .id = DSV_OUT_VLCM, 103 .n_voltages = VLCM_N_VOLTAGES, 104 .min_uV = VLCM_MIN_UV, 105 .uV_step = STEP_UV, 106 .vsel_reg = RT4831_REG_VLCM, 107 .vsel_mask = RT4831_VOLT_MASK, 108 .bypass_reg = RT4831_REG_DSVEN, 109 .bypass_mask = RT4831_DSVMODE_MASK, 110 .bypass_val_on = DSV_MODE_BYPASS, 111 .bypass_val_off = DSV_MODE_NORMAL, 112 .owner = THIS_MODULE, 113 }, 114 { 115 .name = "DSVP", 116 .ops = &rt4831_dsvpn_ops, 117 .of_match = of_match_ptr("DSVP"), 118 .regulators_node = of_match_ptr("regulators"), 119 .type = REGULATOR_VOLTAGE, 120 .id = DSV_OUT_VPOS, 121 .n_voltages = VPN_N_VOLTAGES, 122 .min_uV = VPN_MIN_UV, 123 .uV_step = STEP_UV, 124 .vsel_reg = RT4831_REG_VPOS, 125 .vsel_mask = RT4831_VOLT_MASK, 126 .enable_reg = RT4831_REG_DSVEN, 127 .enable_mask = RT4831_POSEN_MASK, 128 .active_discharge_reg = RT4831_REG_DSVEN, 129 .active_discharge_mask = RT4831_POSADEN_MASK, 130 .owner = THIS_MODULE, 131 }, 132 { 133 .name = "DSVN", 134 .ops = &rt4831_dsvpn_ops, 135 .of_match = of_match_ptr("DSVN"), 136 .regulators_node = of_match_ptr("regulators"), 137 .type = REGULATOR_VOLTAGE, 138 .id = DSV_OUT_VNEG, 139 .n_voltages = VPN_N_VOLTAGES, 140 .min_uV = VPN_MIN_UV, 141 .uV_step = STEP_UV, 142 .vsel_reg = RT4831_REG_VNEG, 143 .vsel_mask = RT4831_VOLT_MASK, 144 .enable_reg = RT4831_REG_DSVEN, 145 .enable_mask = RT4831_NEGEN_MASK, 146 .active_discharge_reg = RT4831_REG_DSVEN, 147 .active_discharge_mask = RT4831_NEGADEN_MASK, 148 .owner = THIS_MODULE, 149 } 150 }; 151 152 static int rt4831_regulator_probe(struct platform_device *pdev) 153 { 154 struct regmap *regmap; 155 struct regulator_dev *rdev; 156 struct regulator_config config = {}; 157 int i, ret; 158 159 regmap = dev_get_regmap(pdev->dev.parent, NULL); 160 if (!regmap) { 161 dev_err(&pdev->dev, "Failed to init regmap\n"); 162 return -ENODEV; 163 } 164 165 /* Configure DSV mode to normal by default */ 166 ret = regmap_update_bits(regmap, RT4831_REG_DSVEN, RT4831_DSVMODE_MASK, DSV_MODE_NORMAL); 167 if (ret) { 168 dev_err(&pdev->dev, "Failed to configure dsv mode to normal\n"); 169 return ret; 170 } 171 172 config.dev = pdev->dev.parent; 173 config.regmap = regmap; 174 175 for (i = 0; i < DSV_OUT_MAX; i++) { 176 rdev = devm_regulator_register(&pdev->dev, rt4831_regulator_descs + i, &config); 177 if (IS_ERR(rdev)) { 178 dev_err(&pdev->dev, "Failed to register %d regulator\n", i); 179 return PTR_ERR(rdev); 180 } 181 } 182 183 return 0; 184 } 185 186 static const struct platform_device_id rt4831_regulator_match[] = { 187 { "rt4831-regulator", 0 }, 188 {} 189 }; 190 MODULE_DEVICE_TABLE(platform, rt4831_regulator_match); 191 192 static struct platform_driver rt4831_regulator_driver = { 193 .driver = { 194 .name = "rt4831-regulator", 195 }, 196 .id_table = rt4831_regulator_match, 197 .probe = rt4831_regulator_probe, 198 }; 199 module_platform_driver(rt4831_regulator_driver); 200 201 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 202 MODULE_LICENSE("GPL v2"); 203