1*9dee7a72SMatthias Kaehlcke /* 2*9dee7a72SMatthias Kaehlcke * Driver for voltage controller regulators 3*9dee7a72SMatthias Kaehlcke * 4*9dee7a72SMatthias Kaehlcke * Copyright (C) 2017 Google, Inc. 5*9dee7a72SMatthias Kaehlcke * 6*9dee7a72SMatthias Kaehlcke * This software is licensed under the terms of the GNU General Public 7*9dee7a72SMatthias Kaehlcke * License version 2, as published by the Free Software Foundation, and 8*9dee7a72SMatthias Kaehlcke * may be copied, distributed, and modified under those terms. 9*9dee7a72SMatthias Kaehlcke * 10*9dee7a72SMatthias Kaehlcke * This program is distributed in the hope that it will be useful, 11*9dee7a72SMatthias Kaehlcke * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*9dee7a72SMatthias Kaehlcke * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*9dee7a72SMatthias Kaehlcke * GNU General Public License for more details. 14*9dee7a72SMatthias Kaehlcke */ 15*9dee7a72SMatthias Kaehlcke 16*9dee7a72SMatthias Kaehlcke #include <linux/delay.h> 17*9dee7a72SMatthias Kaehlcke #include <linux/err.h> 18*9dee7a72SMatthias Kaehlcke #include <linux/init.h> 19*9dee7a72SMatthias Kaehlcke #include <linux/module.h> 20*9dee7a72SMatthias Kaehlcke #include <linux/of.h> 21*9dee7a72SMatthias Kaehlcke #include <linux/of_device.h> 22*9dee7a72SMatthias Kaehlcke #include <linux/regulator/driver.h> 23*9dee7a72SMatthias Kaehlcke #include <linux/regulator/of_regulator.h> 24*9dee7a72SMatthias Kaehlcke #include <linux/sort.h> 25*9dee7a72SMatthias Kaehlcke 26*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range { 27*9dee7a72SMatthias Kaehlcke int min_uV; 28*9dee7a72SMatthias Kaehlcke int max_uV; 29*9dee7a72SMatthias Kaehlcke }; 30*9dee7a72SMatthias Kaehlcke 31*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_ranges { 32*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range ctrl; 33*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range out; 34*9dee7a72SMatthias Kaehlcke }; 35*9dee7a72SMatthias Kaehlcke 36*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_table { 37*9dee7a72SMatthias Kaehlcke int ctrl; 38*9dee7a72SMatthias Kaehlcke int out; 39*9dee7a72SMatthias Kaehlcke int ovp_min_sel; 40*9dee7a72SMatthias Kaehlcke }; 41*9dee7a72SMatthias Kaehlcke 42*9dee7a72SMatthias Kaehlcke struct vctrl_data { 43*9dee7a72SMatthias Kaehlcke struct regulator_dev *rdev; 44*9dee7a72SMatthias Kaehlcke struct regulator_desc desc; 45*9dee7a72SMatthias Kaehlcke struct regulator *ctrl_reg; 46*9dee7a72SMatthias Kaehlcke bool enabled; 47*9dee7a72SMatthias Kaehlcke unsigned int min_slew_down_rate; 48*9dee7a72SMatthias Kaehlcke unsigned int ovp_threshold; 49*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_ranges vrange; 50*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_table *vtable; 51*9dee7a72SMatthias Kaehlcke unsigned int sel; 52*9dee7a72SMatthias Kaehlcke }; 53*9dee7a72SMatthias Kaehlcke 54*9dee7a72SMatthias Kaehlcke static int vctrl_calc_ctrl_voltage(struct vctrl_data *vctrl, int out_uV) 55*9dee7a72SMatthias Kaehlcke { 56*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl; 57*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *out = &vctrl->vrange.out; 58*9dee7a72SMatthias Kaehlcke 59*9dee7a72SMatthias Kaehlcke return ctrl->min_uV + 60*9dee7a72SMatthias Kaehlcke DIV_ROUND_CLOSEST_ULL((s64)(out_uV - out->min_uV) * 61*9dee7a72SMatthias Kaehlcke (ctrl->max_uV - ctrl->min_uV), 62*9dee7a72SMatthias Kaehlcke out->max_uV - out->min_uV); 63*9dee7a72SMatthias Kaehlcke } 64*9dee7a72SMatthias Kaehlcke 65*9dee7a72SMatthias Kaehlcke static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV) 66*9dee7a72SMatthias Kaehlcke { 67*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl; 68*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *out = &vctrl->vrange.out; 69*9dee7a72SMatthias Kaehlcke 70*9dee7a72SMatthias Kaehlcke if (ctrl_uV < 0) { 71*9dee7a72SMatthias Kaehlcke pr_err("vctrl: failed to get control voltage\n"); 72*9dee7a72SMatthias Kaehlcke return ctrl_uV; 73*9dee7a72SMatthias Kaehlcke } 74*9dee7a72SMatthias Kaehlcke 75*9dee7a72SMatthias Kaehlcke if (ctrl_uV < ctrl->min_uV) 76*9dee7a72SMatthias Kaehlcke return out->min_uV; 77*9dee7a72SMatthias Kaehlcke 78*9dee7a72SMatthias Kaehlcke if (ctrl_uV > ctrl->max_uV) 79*9dee7a72SMatthias Kaehlcke return out->max_uV; 80*9dee7a72SMatthias Kaehlcke 81*9dee7a72SMatthias Kaehlcke return out->min_uV + 82*9dee7a72SMatthias Kaehlcke DIV_ROUND_CLOSEST_ULL((s64)(ctrl_uV - ctrl->min_uV) * 83*9dee7a72SMatthias Kaehlcke (out->max_uV - out->min_uV), 84*9dee7a72SMatthias Kaehlcke ctrl->max_uV - ctrl->min_uV); 85*9dee7a72SMatthias Kaehlcke } 86*9dee7a72SMatthias Kaehlcke 87*9dee7a72SMatthias Kaehlcke static int vctrl_get_voltage(struct regulator_dev *rdev) 88*9dee7a72SMatthias Kaehlcke { 89*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 90*9dee7a72SMatthias Kaehlcke int ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg); 91*9dee7a72SMatthias Kaehlcke 92*9dee7a72SMatthias Kaehlcke return vctrl_calc_output_voltage(vctrl, ctrl_uV); 93*9dee7a72SMatthias Kaehlcke } 94*9dee7a72SMatthias Kaehlcke 95*9dee7a72SMatthias Kaehlcke static int vctrl_set_voltage(struct regulator_dev *rdev, 96*9dee7a72SMatthias Kaehlcke int req_min_uV, int req_max_uV, 97*9dee7a72SMatthias Kaehlcke unsigned int *selector) 98*9dee7a72SMatthias Kaehlcke { 99*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 100*9dee7a72SMatthias Kaehlcke struct regulator *ctrl_reg = vctrl->ctrl_reg; 101*9dee7a72SMatthias Kaehlcke int orig_ctrl_uV = regulator_get_voltage(ctrl_reg); 102*9dee7a72SMatthias Kaehlcke int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV); 103*9dee7a72SMatthias Kaehlcke int ret; 104*9dee7a72SMatthias Kaehlcke 105*9dee7a72SMatthias Kaehlcke if (req_min_uV >= uV || !vctrl->ovp_threshold) 106*9dee7a72SMatthias Kaehlcke /* voltage rising or no OVP */ 107*9dee7a72SMatthias Kaehlcke return regulator_set_voltage( 108*9dee7a72SMatthias Kaehlcke ctrl_reg, 109*9dee7a72SMatthias Kaehlcke vctrl_calc_ctrl_voltage(vctrl, req_min_uV), 110*9dee7a72SMatthias Kaehlcke vctrl_calc_ctrl_voltage(vctrl, req_max_uV)); 111*9dee7a72SMatthias Kaehlcke 112*9dee7a72SMatthias Kaehlcke while (uV > req_min_uV) { 113*9dee7a72SMatthias Kaehlcke int max_drop_uV = (uV * vctrl->ovp_threshold) / 100; 114*9dee7a72SMatthias Kaehlcke int next_uV; 115*9dee7a72SMatthias Kaehlcke int next_ctrl_uV; 116*9dee7a72SMatthias Kaehlcke int delay; 117*9dee7a72SMatthias Kaehlcke 118*9dee7a72SMatthias Kaehlcke /* Make sure no infinite loop even in crazy cases */ 119*9dee7a72SMatthias Kaehlcke if (max_drop_uV == 0) 120*9dee7a72SMatthias Kaehlcke max_drop_uV = 1; 121*9dee7a72SMatthias Kaehlcke 122*9dee7a72SMatthias Kaehlcke next_uV = max_t(int, req_min_uV, uV - max_drop_uV); 123*9dee7a72SMatthias Kaehlcke next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV); 124*9dee7a72SMatthias Kaehlcke 125*9dee7a72SMatthias Kaehlcke ret = regulator_set_voltage(ctrl_reg, 126*9dee7a72SMatthias Kaehlcke next_ctrl_uV, 127*9dee7a72SMatthias Kaehlcke next_ctrl_uV); 128*9dee7a72SMatthias Kaehlcke if (ret) 129*9dee7a72SMatthias Kaehlcke goto err; 130*9dee7a72SMatthias Kaehlcke 131*9dee7a72SMatthias Kaehlcke delay = DIV_ROUND_UP(uV - next_uV, vctrl->min_slew_down_rate); 132*9dee7a72SMatthias Kaehlcke usleep_range(delay, delay + DIV_ROUND_UP(delay, 10)); 133*9dee7a72SMatthias Kaehlcke 134*9dee7a72SMatthias Kaehlcke uV = next_uV; 135*9dee7a72SMatthias Kaehlcke } 136*9dee7a72SMatthias Kaehlcke 137*9dee7a72SMatthias Kaehlcke return 0; 138*9dee7a72SMatthias Kaehlcke 139*9dee7a72SMatthias Kaehlcke err: 140*9dee7a72SMatthias Kaehlcke /* Try to go back to original voltage */ 141*9dee7a72SMatthias Kaehlcke regulator_set_voltage(ctrl_reg, orig_ctrl_uV, orig_ctrl_uV); 142*9dee7a72SMatthias Kaehlcke 143*9dee7a72SMatthias Kaehlcke return ret; 144*9dee7a72SMatthias Kaehlcke } 145*9dee7a72SMatthias Kaehlcke 146*9dee7a72SMatthias Kaehlcke static int vctrl_get_voltage_sel(struct regulator_dev *rdev) 147*9dee7a72SMatthias Kaehlcke { 148*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 149*9dee7a72SMatthias Kaehlcke 150*9dee7a72SMatthias Kaehlcke return vctrl->sel; 151*9dee7a72SMatthias Kaehlcke } 152*9dee7a72SMatthias Kaehlcke 153*9dee7a72SMatthias Kaehlcke static int vctrl_set_voltage_sel(struct regulator_dev *rdev, 154*9dee7a72SMatthias Kaehlcke unsigned int selector) 155*9dee7a72SMatthias Kaehlcke { 156*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 157*9dee7a72SMatthias Kaehlcke struct regulator *ctrl_reg = vctrl->ctrl_reg; 158*9dee7a72SMatthias Kaehlcke unsigned int orig_sel = vctrl->sel; 159*9dee7a72SMatthias Kaehlcke int ret; 160*9dee7a72SMatthias Kaehlcke 161*9dee7a72SMatthias Kaehlcke if (selector >= rdev->desc->n_voltages) 162*9dee7a72SMatthias Kaehlcke return -EINVAL; 163*9dee7a72SMatthias Kaehlcke 164*9dee7a72SMatthias Kaehlcke if (selector >= vctrl->sel || !vctrl->ovp_threshold) { 165*9dee7a72SMatthias Kaehlcke /* voltage rising or no OVP */ 166*9dee7a72SMatthias Kaehlcke ret = regulator_set_voltage(ctrl_reg, 167*9dee7a72SMatthias Kaehlcke vctrl->vtable[selector].ctrl, 168*9dee7a72SMatthias Kaehlcke vctrl->vtable[selector].ctrl); 169*9dee7a72SMatthias Kaehlcke if (!ret) 170*9dee7a72SMatthias Kaehlcke vctrl->sel = selector; 171*9dee7a72SMatthias Kaehlcke 172*9dee7a72SMatthias Kaehlcke return ret; 173*9dee7a72SMatthias Kaehlcke } 174*9dee7a72SMatthias Kaehlcke 175*9dee7a72SMatthias Kaehlcke while (vctrl->sel != selector) { 176*9dee7a72SMatthias Kaehlcke unsigned int next_sel; 177*9dee7a72SMatthias Kaehlcke int delay; 178*9dee7a72SMatthias Kaehlcke 179*9dee7a72SMatthias Kaehlcke if (selector >= vctrl->vtable[vctrl->sel].ovp_min_sel) 180*9dee7a72SMatthias Kaehlcke next_sel = selector; 181*9dee7a72SMatthias Kaehlcke else 182*9dee7a72SMatthias Kaehlcke next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel; 183*9dee7a72SMatthias Kaehlcke 184*9dee7a72SMatthias Kaehlcke ret = regulator_set_voltage(ctrl_reg, 185*9dee7a72SMatthias Kaehlcke vctrl->vtable[next_sel].ctrl, 186*9dee7a72SMatthias Kaehlcke vctrl->vtable[next_sel].ctrl); 187*9dee7a72SMatthias Kaehlcke if (ret) { 188*9dee7a72SMatthias Kaehlcke dev_err(&rdev->dev, 189*9dee7a72SMatthias Kaehlcke "failed to set control voltage to %duV\n", 190*9dee7a72SMatthias Kaehlcke vctrl->vtable[next_sel].ctrl); 191*9dee7a72SMatthias Kaehlcke goto err; 192*9dee7a72SMatthias Kaehlcke } 193*9dee7a72SMatthias Kaehlcke vctrl->sel = next_sel; 194*9dee7a72SMatthias Kaehlcke 195*9dee7a72SMatthias Kaehlcke delay = DIV_ROUND_UP(vctrl->vtable[vctrl->sel].out - 196*9dee7a72SMatthias Kaehlcke vctrl->vtable[next_sel].out, 197*9dee7a72SMatthias Kaehlcke vctrl->min_slew_down_rate); 198*9dee7a72SMatthias Kaehlcke usleep_range(delay, delay + DIV_ROUND_UP(delay, 10)); 199*9dee7a72SMatthias Kaehlcke } 200*9dee7a72SMatthias Kaehlcke 201*9dee7a72SMatthias Kaehlcke return 0; 202*9dee7a72SMatthias Kaehlcke 203*9dee7a72SMatthias Kaehlcke err: 204*9dee7a72SMatthias Kaehlcke if (vctrl->sel != orig_sel) { 205*9dee7a72SMatthias Kaehlcke /* Try to go back to original voltage */ 206*9dee7a72SMatthias Kaehlcke if (!regulator_set_voltage(ctrl_reg, 207*9dee7a72SMatthias Kaehlcke vctrl->vtable[orig_sel].ctrl, 208*9dee7a72SMatthias Kaehlcke vctrl->vtable[orig_sel].ctrl)) 209*9dee7a72SMatthias Kaehlcke vctrl->sel = orig_sel; 210*9dee7a72SMatthias Kaehlcke else 211*9dee7a72SMatthias Kaehlcke dev_warn(&rdev->dev, 212*9dee7a72SMatthias Kaehlcke "failed to restore original voltage\n"); 213*9dee7a72SMatthias Kaehlcke } 214*9dee7a72SMatthias Kaehlcke 215*9dee7a72SMatthias Kaehlcke return ret; 216*9dee7a72SMatthias Kaehlcke } 217*9dee7a72SMatthias Kaehlcke 218*9dee7a72SMatthias Kaehlcke static int vctrl_list_voltage(struct regulator_dev *rdev, 219*9dee7a72SMatthias Kaehlcke unsigned int selector) 220*9dee7a72SMatthias Kaehlcke { 221*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 222*9dee7a72SMatthias Kaehlcke 223*9dee7a72SMatthias Kaehlcke if (selector >= rdev->desc->n_voltages) 224*9dee7a72SMatthias Kaehlcke return -EINVAL; 225*9dee7a72SMatthias Kaehlcke 226*9dee7a72SMatthias Kaehlcke return vctrl->vtable[selector].out; 227*9dee7a72SMatthias Kaehlcke } 228*9dee7a72SMatthias Kaehlcke 229*9dee7a72SMatthias Kaehlcke static int vctrl_parse_dt(struct platform_device *pdev, 230*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl) 231*9dee7a72SMatthias Kaehlcke { 232*9dee7a72SMatthias Kaehlcke int ret; 233*9dee7a72SMatthias Kaehlcke struct device_node *np = pdev->dev.of_node; 234*9dee7a72SMatthias Kaehlcke u32 pval; 235*9dee7a72SMatthias Kaehlcke u32 vrange_ctrl[2]; 236*9dee7a72SMatthias Kaehlcke 237*9dee7a72SMatthias Kaehlcke vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl"); 238*9dee7a72SMatthias Kaehlcke if (IS_ERR(vctrl->ctrl_reg)) 239*9dee7a72SMatthias Kaehlcke return PTR_ERR(vctrl->ctrl_reg); 240*9dee7a72SMatthias Kaehlcke 241*9dee7a72SMatthias Kaehlcke ret = of_property_read_u32(np, "ovp-threshold-percent", &pval); 242*9dee7a72SMatthias Kaehlcke if (!ret) { 243*9dee7a72SMatthias Kaehlcke vctrl->ovp_threshold = pval; 244*9dee7a72SMatthias Kaehlcke if (vctrl->ovp_threshold > 100) { 245*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, 246*9dee7a72SMatthias Kaehlcke "ovp-threshold-percent (%u) > 100\n", 247*9dee7a72SMatthias Kaehlcke vctrl->ovp_threshold); 248*9dee7a72SMatthias Kaehlcke return -EINVAL; 249*9dee7a72SMatthias Kaehlcke } 250*9dee7a72SMatthias Kaehlcke } 251*9dee7a72SMatthias Kaehlcke 252*9dee7a72SMatthias Kaehlcke ret = of_property_read_u32(np, "min-slew-down-rate", &pval); 253*9dee7a72SMatthias Kaehlcke if (!ret) { 254*9dee7a72SMatthias Kaehlcke vctrl->min_slew_down_rate = pval; 255*9dee7a72SMatthias Kaehlcke 256*9dee7a72SMatthias Kaehlcke /* We use the value as int and as divider; sanity check */ 257*9dee7a72SMatthias Kaehlcke if (vctrl->min_slew_down_rate == 0) { 258*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, 259*9dee7a72SMatthias Kaehlcke "min-slew-down-rate must not be 0\n"); 260*9dee7a72SMatthias Kaehlcke return -EINVAL; 261*9dee7a72SMatthias Kaehlcke } else if (vctrl->min_slew_down_rate > INT_MAX) { 262*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "min-slew-down-rate (%u) too big\n", 263*9dee7a72SMatthias Kaehlcke vctrl->min_slew_down_rate); 264*9dee7a72SMatthias Kaehlcke return -EINVAL; 265*9dee7a72SMatthias Kaehlcke } 266*9dee7a72SMatthias Kaehlcke } 267*9dee7a72SMatthias Kaehlcke 268*9dee7a72SMatthias Kaehlcke if (vctrl->ovp_threshold && !vctrl->min_slew_down_rate) { 269*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, 270*9dee7a72SMatthias Kaehlcke "ovp-threshold-percent requires min-slew-down-rate\n"); 271*9dee7a72SMatthias Kaehlcke return -EINVAL; 272*9dee7a72SMatthias Kaehlcke } 273*9dee7a72SMatthias Kaehlcke 274*9dee7a72SMatthias Kaehlcke ret = of_property_read_u32(np, "regulator-min-microvolt", &pval); 275*9dee7a72SMatthias Kaehlcke if (ret) { 276*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, 277*9dee7a72SMatthias Kaehlcke "failed to read regulator-min-microvolt: %d\n", ret); 278*9dee7a72SMatthias Kaehlcke return ret; 279*9dee7a72SMatthias Kaehlcke } 280*9dee7a72SMatthias Kaehlcke vctrl->vrange.out.min_uV = pval; 281*9dee7a72SMatthias Kaehlcke 282*9dee7a72SMatthias Kaehlcke ret = of_property_read_u32(np, "regulator-max-microvolt", &pval); 283*9dee7a72SMatthias Kaehlcke if (ret) { 284*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, 285*9dee7a72SMatthias Kaehlcke "failed to read regulator-max-microvolt: %d\n", ret); 286*9dee7a72SMatthias Kaehlcke return ret; 287*9dee7a72SMatthias Kaehlcke } 288*9dee7a72SMatthias Kaehlcke vctrl->vrange.out.max_uV = pval; 289*9dee7a72SMatthias Kaehlcke 290*9dee7a72SMatthias Kaehlcke ret = of_property_read_u32_array(np, "ctrl-voltage-range", vrange_ctrl, 291*9dee7a72SMatthias Kaehlcke 2); 292*9dee7a72SMatthias Kaehlcke if (ret) { 293*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "failed to read ctrl-voltage-range: %d\n", 294*9dee7a72SMatthias Kaehlcke ret); 295*9dee7a72SMatthias Kaehlcke return ret; 296*9dee7a72SMatthias Kaehlcke } 297*9dee7a72SMatthias Kaehlcke 298*9dee7a72SMatthias Kaehlcke if (vrange_ctrl[0] >= vrange_ctrl[1]) { 299*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "ctrl-voltage-range is invalid: %d-%d\n", 300*9dee7a72SMatthias Kaehlcke vrange_ctrl[0], vrange_ctrl[1]); 301*9dee7a72SMatthias Kaehlcke return -EINVAL; 302*9dee7a72SMatthias Kaehlcke } 303*9dee7a72SMatthias Kaehlcke 304*9dee7a72SMatthias Kaehlcke vctrl->vrange.ctrl.min_uV = vrange_ctrl[0]; 305*9dee7a72SMatthias Kaehlcke vctrl->vrange.ctrl.max_uV = vrange_ctrl[1]; 306*9dee7a72SMatthias Kaehlcke 307*9dee7a72SMatthias Kaehlcke return 0; 308*9dee7a72SMatthias Kaehlcke } 309*9dee7a72SMatthias Kaehlcke 310*9dee7a72SMatthias Kaehlcke static int vctrl_cmp_ctrl_uV(const void *a, const void *b) 311*9dee7a72SMatthias Kaehlcke { 312*9dee7a72SMatthias Kaehlcke const struct vctrl_voltage_table *at = a; 313*9dee7a72SMatthias Kaehlcke const struct vctrl_voltage_table *bt = b; 314*9dee7a72SMatthias Kaehlcke 315*9dee7a72SMatthias Kaehlcke return at->ctrl - bt->ctrl; 316*9dee7a72SMatthias Kaehlcke } 317*9dee7a72SMatthias Kaehlcke 318*9dee7a72SMatthias Kaehlcke static int vctrl_init_vtable(struct platform_device *pdev) 319*9dee7a72SMatthias Kaehlcke { 320*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = platform_get_drvdata(pdev); 321*9dee7a72SMatthias Kaehlcke struct regulator_desc *rdesc = &vctrl->desc; 322*9dee7a72SMatthias Kaehlcke struct regulator *ctrl_reg = vctrl->ctrl_reg; 323*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl; 324*9dee7a72SMatthias Kaehlcke int n_voltages; 325*9dee7a72SMatthias Kaehlcke int ctrl_uV; 326*9dee7a72SMatthias Kaehlcke int i, idx_vt; 327*9dee7a72SMatthias Kaehlcke 328*9dee7a72SMatthias Kaehlcke n_voltages = regulator_count_voltages(ctrl_reg); 329*9dee7a72SMatthias Kaehlcke 330*9dee7a72SMatthias Kaehlcke rdesc->n_voltages = n_voltages; 331*9dee7a72SMatthias Kaehlcke 332*9dee7a72SMatthias Kaehlcke /* determine number of steps within the range of the vctrl regulator */ 333*9dee7a72SMatthias Kaehlcke for (i = 0; i < n_voltages; i++) { 334*9dee7a72SMatthias Kaehlcke ctrl_uV = regulator_list_voltage(ctrl_reg, i); 335*9dee7a72SMatthias Kaehlcke 336*9dee7a72SMatthias Kaehlcke if (ctrl_uV < vrange_ctrl->min_uV || 337*9dee7a72SMatthias Kaehlcke ctrl_uV > vrange_ctrl->max_uV) { 338*9dee7a72SMatthias Kaehlcke rdesc->n_voltages--; 339*9dee7a72SMatthias Kaehlcke continue; 340*9dee7a72SMatthias Kaehlcke } 341*9dee7a72SMatthias Kaehlcke } 342*9dee7a72SMatthias Kaehlcke 343*9dee7a72SMatthias Kaehlcke if (rdesc->n_voltages == 0) { 344*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "invalid configuration\n"); 345*9dee7a72SMatthias Kaehlcke return -EINVAL; 346*9dee7a72SMatthias Kaehlcke } 347*9dee7a72SMatthias Kaehlcke 348*9dee7a72SMatthias Kaehlcke vctrl->vtable = devm_kmalloc_array( 349*9dee7a72SMatthias Kaehlcke &pdev->dev, sizeof(struct vctrl_voltage_table), 350*9dee7a72SMatthias Kaehlcke rdesc->n_voltages, GFP_KERNEL | __GFP_ZERO); 351*9dee7a72SMatthias Kaehlcke if (!vctrl->vtable) 352*9dee7a72SMatthias Kaehlcke return -ENOMEM; 353*9dee7a72SMatthias Kaehlcke 354*9dee7a72SMatthias Kaehlcke /* create mapping control <=> output voltage */ 355*9dee7a72SMatthias Kaehlcke for (i = 0, idx_vt = 0; i < n_voltages; i++) { 356*9dee7a72SMatthias Kaehlcke ctrl_uV = regulator_list_voltage(ctrl_reg, i); 357*9dee7a72SMatthias Kaehlcke 358*9dee7a72SMatthias Kaehlcke if (ctrl_uV < vrange_ctrl->min_uV || 359*9dee7a72SMatthias Kaehlcke ctrl_uV > vrange_ctrl->max_uV) 360*9dee7a72SMatthias Kaehlcke continue; 361*9dee7a72SMatthias Kaehlcke 362*9dee7a72SMatthias Kaehlcke vctrl->vtable[idx_vt].ctrl = ctrl_uV; 363*9dee7a72SMatthias Kaehlcke vctrl->vtable[idx_vt].out = 364*9dee7a72SMatthias Kaehlcke vctrl_calc_output_voltage(vctrl, ctrl_uV); 365*9dee7a72SMatthias Kaehlcke idx_vt++; 366*9dee7a72SMatthias Kaehlcke } 367*9dee7a72SMatthias Kaehlcke 368*9dee7a72SMatthias Kaehlcke /* we rely on the table to be ordered by ascending voltage */ 369*9dee7a72SMatthias Kaehlcke sort(vctrl->vtable, rdesc->n_voltages, 370*9dee7a72SMatthias Kaehlcke sizeof(struct vctrl_voltage_table), vctrl_cmp_ctrl_uV, 371*9dee7a72SMatthias Kaehlcke NULL); 372*9dee7a72SMatthias Kaehlcke 373*9dee7a72SMatthias Kaehlcke /* pre-calculate OVP-safe downward transitions */ 374*9dee7a72SMatthias Kaehlcke for (i = n_voltages - 1; i > 0; i--) { 375*9dee7a72SMatthias Kaehlcke int j; 376*9dee7a72SMatthias Kaehlcke int ovp_min_uV = (vctrl->vtable[i].out * 377*9dee7a72SMatthias Kaehlcke (100 - vctrl->ovp_threshold)) / 100; 378*9dee7a72SMatthias Kaehlcke 379*9dee7a72SMatthias Kaehlcke for (j = 0; j < i; j++) { 380*9dee7a72SMatthias Kaehlcke if (vctrl->vtable[j].out >= ovp_min_uV) { 381*9dee7a72SMatthias Kaehlcke vctrl->vtable[i].ovp_min_sel = j; 382*9dee7a72SMatthias Kaehlcke break; 383*9dee7a72SMatthias Kaehlcke } 384*9dee7a72SMatthias Kaehlcke } 385*9dee7a72SMatthias Kaehlcke 386*9dee7a72SMatthias Kaehlcke if (j == i) { 387*9dee7a72SMatthias Kaehlcke dev_warn(&pdev->dev, "switching down from %duV may cause OVP shutdown\n", 388*9dee7a72SMatthias Kaehlcke vctrl->vtable[i].out); 389*9dee7a72SMatthias Kaehlcke /* use next lowest voltage */ 390*9dee7a72SMatthias Kaehlcke vctrl->vtable[i].ovp_min_sel = i - 1; 391*9dee7a72SMatthias Kaehlcke } 392*9dee7a72SMatthias Kaehlcke } 393*9dee7a72SMatthias Kaehlcke 394*9dee7a72SMatthias Kaehlcke return 0; 395*9dee7a72SMatthias Kaehlcke } 396*9dee7a72SMatthias Kaehlcke 397*9dee7a72SMatthias Kaehlcke static int vctrl_enable(struct regulator_dev *rdev) 398*9dee7a72SMatthias Kaehlcke { 399*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 400*9dee7a72SMatthias Kaehlcke int ret = regulator_enable(vctrl->ctrl_reg); 401*9dee7a72SMatthias Kaehlcke 402*9dee7a72SMatthias Kaehlcke if (!ret) 403*9dee7a72SMatthias Kaehlcke vctrl->enabled = true; 404*9dee7a72SMatthias Kaehlcke 405*9dee7a72SMatthias Kaehlcke return ret; 406*9dee7a72SMatthias Kaehlcke } 407*9dee7a72SMatthias Kaehlcke 408*9dee7a72SMatthias Kaehlcke static int vctrl_disable(struct regulator_dev *rdev) 409*9dee7a72SMatthias Kaehlcke { 410*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 411*9dee7a72SMatthias Kaehlcke int ret = regulator_disable(vctrl->ctrl_reg); 412*9dee7a72SMatthias Kaehlcke 413*9dee7a72SMatthias Kaehlcke if (!ret) 414*9dee7a72SMatthias Kaehlcke vctrl->enabled = false; 415*9dee7a72SMatthias Kaehlcke 416*9dee7a72SMatthias Kaehlcke return ret; 417*9dee7a72SMatthias Kaehlcke } 418*9dee7a72SMatthias Kaehlcke 419*9dee7a72SMatthias Kaehlcke static int vctrl_is_enabled(struct regulator_dev *rdev) 420*9dee7a72SMatthias Kaehlcke { 421*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 422*9dee7a72SMatthias Kaehlcke 423*9dee7a72SMatthias Kaehlcke return vctrl->enabled; 424*9dee7a72SMatthias Kaehlcke } 425*9dee7a72SMatthias Kaehlcke 426*9dee7a72SMatthias Kaehlcke static const struct regulator_ops vctrl_ops_cont = { 427*9dee7a72SMatthias Kaehlcke .enable = vctrl_enable, 428*9dee7a72SMatthias Kaehlcke .disable = vctrl_disable, 429*9dee7a72SMatthias Kaehlcke .is_enabled = vctrl_is_enabled, 430*9dee7a72SMatthias Kaehlcke .get_voltage = vctrl_get_voltage, 431*9dee7a72SMatthias Kaehlcke .set_voltage = vctrl_set_voltage, 432*9dee7a72SMatthias Kaehlcke }; 433*9dee7a72SMatthias Kaehlcke 434*9dee7a72SMatthias Kaehlcke static const struct regulator_ops vctrl_ops_non_cont = { 435*9dee7a72SMatthias Kaehlcke .enable = vctrl_enable, 436*9dee7a72SMatthias Kaehlcke .disable = vctrl_disable, 437*9dee7a72SMatthias Kaehlcke .is_enabled = vctrl_is_enabled, 438*9dee7a72SMatthias Kaehlcke .set_voltage_sel = vctrl_set_voltage_sel, 439*9dee7a72SMatthias Kaehlcke .get_voltage_sel = vctrl_get_voltage_sel, 440*9dee7a72SMatthias Kaehlcke .list_voltage = vctrl_list_voltage, 441*9dee7a72SMatthias Kaehlcke .map_voltage = regulator_map_voltage_iterate, 442*9dee7a72SMatthias Kaehlcke }; 443*9dee7a72SMatthias Kaehlcke 444*9dee7a72SMatthias Kaehlcke static int vctrl_probe(struct platform_device *pdev) 445*9dee7a72SMatthias Kaehlcke { 446*9dee7a72SMatthias Kaehlcke struct device_node *np = pdev->dev.of_node; 447*9dee7a72SMatthias Kaehlcke struct vctrl_data *vctrl; 448*9dee7a72SMatthias Kaehlcke const struct regulator_init_data *init_data; 449*9dee7a72SMatthias Kaehlcke struct regulator_desc *rdesc; 450*9dee7a72SMatthias Kaehlcke struct regulator_config cfg = { }; 451*9dee7a72SMatthias Kaehlcke struct vctrl_voltage_range *vrange_ctrl; 452*9dee7a72SMatthias Kaehlcke int ctrl_uV; 453*9dee7a72SMatthias Kaehlcke int ret; 454*9dee7a72SMatthias Kaehlcke 455*9dee7a72SMatthias Kaehlcke vctrl = devm_kzalloc(&pdev->dev, sizeof(struct vctrl_data), 456*9dee7a72SMatthias Kaehlcke GFP_KERNEL); 457*9dee7a72SMatthias Kaehlcke if (!vctrl) 458*9dee7a72SMatthias Kaehlcke return -ENOMEM; 459*9dee7a72SMatthias Kaehlcke 460*9dee7a72SMatthias Kaehlcke platform_set_drvdata(pdev, vctrl); 461*9dee7a72SMatthias Kaehlcke 462*9dee7a72SMatthias Kaehlcke ret = vctrl_parse_dt(pdev, vctrl); 463*9dee7a72SMatthias Kaehlcke if (ret) 464*9dee7a72SMatthias Kaehlcke return ret; 465*9dee7a72SMatthias Kaehlcke 466*9dee7a72SMatthias Kaehlcke vrange_ctrl = &vctrl->vrange.ctrl; 467*9dee7a72SMatthias Kaehlcke 468*9dee7a72SMatthias Kaehlcke rdesc = &vctrl->desc; 469*9dee7a72SMatthias Kaehlcke rdesc->name = "vctrl"; 470*9dee7a72SMatthias Kaehlcke rdesc->type = REGULATOR_VOLTAGE; 471*9dee7a72SMatthias Kaehlcke rdesc->owner = THIS_MODULE; 472*9dee7a72SMatthias Kaehlcke 473*9dee7a72SMatthias Kaehlcke if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) || 474*9dee7a72SMatthias Kaehlcke (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) { 475*9dee7a72SMatthias Kaehlcke rdesc->continuous_voltage_range = true; 476*9dee7a72SMatthias Kaehlcke rdesc->ops = &vctrl_ops_cont; 477*9dee7a72SMatthias Kaehlcke } else { 478*9dee7a72SMatthias Kaehlcke rdesc->ops = &vctrl_ops_non_cont; 479*9dee7a72SMatthias Kaehlcke } 480*9dee7a72SMatthias Kaehlcke 481*9dee7a72SMatthias Kaehlcke init_data = of_get_regulator_init_data(&pdev->dev, np, rdesc); 482*9dee7a72SMatthias Kaehlcke if (!init_data) 483*9dee7a72SMatthias Kaehlcke return -ENOMEM; 484*9dee7a72SMatthias Kaehlcke 485*9dee7a72SMatthias Kaehlcke cfg.of_node = np; 486*9dee7a72SMatthias Kaehlcke cfg.dev = &pdev->dev; 487*9dee7a72SMatthias Kaehlcke cfg.driver_data = vctrl; 488*9dee7a72SMatthias Kaehlcke cfg.init_data = init_data; 489*9dee7a72SMatthias Kaehlcke 490*9dee7a72SMatthias Kaehlcke if (!rdesc->continuous_voltage_range) { 491*9dee7a72SMatthias Kaehlcke ret = vctrl_init_vtable(pdev); 492*9dee7a72SMatthias Kaehlcke if (ret) 493*9dee7a72SMatthias Kaehlcke return ret; 494*9dee7a72SMatthias Kaehlcke 495*9dee7a72SMatthias Kaehlcke ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg); 496*9dee7a72SMatthias Kaehlcke if (ctrl_uV < 0) { 497*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "failed to get control voltage\n"); 498*9dee7a72SMatthias Kaehlcke return ctrl_uV; 499*9dee7a72SMatthias Kaehlcke } 500*9dee7a72SMatthias Kaehlcke 501*9dee7a72SMatthias Kaehlcke /* determine current voltage selector from control voltage */ 502*9dee7a72SMatthias Kaehlcke if (ctrl_uV < vrange_ctrl->min_uV) { 503*9dee7a72SMatthias Kaehlcke vctrl->sel = 0; 504*9dee7a72SMatthias Kaehlcke } else if (ctrl_uV > vrange_ctrl->max_uV) { 505*9dee7a72SMatthias Kaehlcke vctrl->sel = rdesc->n_voltages - 1; 506*9dee7a72SMatthias Kaehlcke } else { 507*9dee7a72SMatthias Kaehlcke int i; 508*9dee7a72SMatthias Kaehlcke 509*9dee7a72SMatthias Kaehlcke for (i = 0; i < rdesc->n_voltages; i++) { 510*9dee7a72SMatthias Kaehlcke if (ctrl_uV == vctrl->vtable[i].ctrl) { 511*9dee7a72SMatthias Kaehlcke vctrl->sel = i; 512*9dee7a72SMatthias Kaehlcke break; 513*9dee7a72SMatthias Kaehlcke } 514*9dee7a72SMatthias Kaehlcke } 515*9dee7a72SMatthias Kaehlcke } 516*9dee7a72SMatthias Kaehlcke } 517*9dee7a72SMatthias Kaehlcke 518*9dee7a72SMatthias Kaehlcke vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg); 519*9dee7a72SMatthias Kaehlcke if (IS_ERR(vctrl->rdev)) { 520*9dee7a72SMatthias Kaehlcke ret = PTR_ERR(vctrl->rdev); 521*9dee7a72SMatthias Kaehlcke dev_err(&pdev->dev, "failed to register regulator: %d\n", ret); 522*9dee7a72SMatthias Kaehlcke return ret; 523*9dee7a72SMatthias Kaehlcke } 524*9dee7a72SMatthias Kaehlcke 525*9dee7a72SMatthias Kaehlcke return 0; 526*9dee7a72SMatthias Kaehlcke } 527*9dee7a72SMatthias Kaehlcke 528*9dee7a72SMatthias Kaehlcke static const struct of_device_id vctrl_of_match[] = { 529*9dee7a72SMatthias Kaehlcke { .compatible = "vctrl-regulator", }, 530*9dee7a72SMatthias Kaehlcke {}, 531*9dee7a72SMatthias Kaehlcke }; 532*9dee7a72SMatthias Kaehlcke MODULE_DEVICE_TABLE(of, vctrl_of_match); 533*9dee7a72SMatthias Kaehlcke 534*9dee7a72SMatthias Kaehlcke static struct platform_driver vctrl_driver = { 535*9dee7a72SMatthias Kaehlcke .probe = vctrl_probe, 536*9dee7a72SMatthias Kaehlcke .driver = { 537*9dee7a72SMatthias Kaehlcke .name = "vctrl-regulator", 538*9dee7a72SMatthias Kaehlcke .of_match_table = of_match_ptr(vctrl_of_match), 539*9dee7a72SMatthias Kaehlcke }, 540*9dee7a72SMatthias Kaehlcke }; 541*9dee7a72SMatthias Kaehlcke 542*9dee7a72SMatthias Kaehlcke module_platform_driver(vctrl_driver); 543*9dee7a72SMatthias Kaehlcke 544*9dee7a72SMatthias Kaehlcke MODULE_DESCRIPTION("Voltage Controlled Regulator Driver"); 545*9dee7a72SMatthias Kaehlcke MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>"); 546*9dee7a72SMatthias Kaehlcke MODULE_LICENSE("GPL v2"); 547