1*069f0b63SChristophe Kerello // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2*069f0b63SChristophe Kerello /* 3*069f0b63SChristophe Kerello * Copyright (C) 2018, STMicroelectronics - All Rights Reserved 4*069f0b63SChristophe Kerello * Author: Christophe Kerello <christophe.kerello@st.com> 5*069f0b63SChristophe Kerello */ 6*069f0b63SChristophe Kerello 7*069f0b63SChristophe Kerello #include <common.h> 8*069f0b63SChristophe Kerello #include <dm.h> 9*069f0b63SChristophe Kerello #include <errno.h> 10*069f0b63SChristophe Kerello #include <power/pmic.h> 11*069f0b63SChristophe Kerello #include <power/regulator.h> 12*069f0b63SChristophe Kerello #include <power/stpmu1.h> 13*069f0b63SChristophe Kerello 14*069f0b63SChristophe Kerello struct stpmu1_range { 15*069f0b63SChristophe Kerello int min_uv; 16*069f0b63SChristophe Kerello int min_sel; 17*069f0b63SChristophe Kerello int max_sel; 18*069f0b63SChristophe Kerello int step; 19*069f0b63SChristophe Kerello }; 20*069f0b63SChristophe Kerello 21*069f0b63SChristophe Kerello struct stpmu1_output_range { 22*069f0b63SChristophe Kerello const struct stpmu1_range *ranges; 23*069f0b63SChristophe Kerello int nbranges; 24*069f0b63SChristophe Kerello }; 25*069f0b63SChristophe Kerello 26*069f0b63SChristophe Kerello #define STPMU1_MODE(_id, _val, _name) { \ 27*069f0b63SChristophe Kerello .id = _id, \ 28*069f0b63SChristophe Kerello .register_value = _val, \ 29*069f0b63SChristophe Kerello .name = _name, \ 30*069f0b63SChristophe Kerello } 31*069f0b63SChristophe Kerello 32*069f0b63SChristophe Kerello #define STPMU1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \ 33*069f0b63SChristophe Kerello .min_uv = _min_uv, \ 34*069f0b63SChristophe Kerello .min_sel = _min_sel, \ 35*069f0b63SChristophe Kerello .max_sel = _max_sel, \ 36*069f0b63SChristophe Kerello .step = _step, \ 37*069f0b63SChristophe Kerello } 38*069f0b63SChristophe Kerello 39*069f0b63SChristophe Kerello #define STPMU1_OUTPUT_RANGE(_ranges, _nbranges) { \ 40*069f0b63SChristophe Kerello .ranges = _ranges, \ 41*069f0b63SChristophe Kerello .nbranges = _nbranges, \ 42*069f0b63SChristophe Kerello } 43*069f0b63SChristophe Kerello 44*069f0b63SChristophe Kerello static int stpmu1_output_find_uv(int sel, 45*069f0b63SChristophe Kerello const struct stpmu1_output_range *output_range) 46*069f0b63SChristophe Kerello { 47*069f0b63SChristophe Kerello const struct stpmu1_range *range; 48*069f0b63SChristophe Kerello int i; 49*069f0b63SChristophe Kerello 50*069f0b63SChristophe Kerello for (i = 0, range = output_range->ranges; 51*069f0b63SChristophe Kerello i < output_range->nbranges; i++, range++) { 52*069f0b63SChristophe Kerello if (sel >= range->min_sel && sel <= range->max_sel) 53*069f0b63SChristophe Kerello return range->min_uv + 54*069f0b63SChristophe Kerello (sel - range->min_sel) * range->step; 55*069f0b63SChristophe Kerello } 56*069f0b63SChristophe Kerello 57*069f0b63SChristophe Kerello return -EINVAL; 58*069f0b63SChristophe Kerello } 59*069f0b63SChristophe Kerello 60*069f0b63SChristophe Kerello static int stpmu1_output_find_sel(int uv, 61*069f0b63SChristophe Kerello const struct stpmu1_output_range *output_range) 62*069f0b63SChristophe Kerello { 63*069f0b63SChristophe Kerello const struct stpmu1_range *range; 64*069f0b63SChristophe Kerello int i; 65*069f0b63SChristophe Kerello 66*069f0b63SChristophe Kerello for (i = 0, range = output_range->ranges; 67*069f0b63SChristophe Kerello i < output_range->nbranges; i++, range++) { 68*069f0b63SChristophe Kerello if (uv == range->min_uv && !range->step) 69*069f0b63SChristophe Kerello return range->min_sel; 70*069f0b63SChristophe Kerello 71*069f0b63SChristophe Kerello if (uv >= range->min_uv && 72*069f0b63SChristophe Kerello uv <= range->min_uv + 73*069f0b63SChristophe Kerello (range->max_sel - range->min_sel) * range->step) 74*069f0b63SChristophe Kerello return range->min_sel + 75*069f0b63SChristophe Kerello (uv - range->min_uv) / range->step; 76*069f0b63SChristophe Kerello } 77*069f0b63SChristophe Kerello 78*069f0b63SChristophe Kerello return -EINVAL; 79*069f0b63SChristophe Kerello } 80*069f0b63SChristophe Kerello 81*069f0b63SChristophe Kerello /* 82*069f0b63SChristophe Kerello * BUCK regulators 83*069f0b63SChristophe Kerello */ 84*069f0b63SChristophe Kerello 85*069f0b63SChristophe Kerello static const struct stpmu1_range buck1_ranges[] = { 86*069f0b63SChristophe Kerello STPMU1_RANGE(600000, 0, 30, 25000), 87*069f0b63SChristophe Kerello STPMU1_RANGE(1350000, 31, 63, 0), 88*069f0b63SChristophe Kerello }; 89*069f0b63SChristophe Kerello 90*069f0b63SChristophe Kerello static const struct stpmu1_range buck2_ranges[] = { 91*069f0b63SChristophe Kerello STPMU1_RANGE(1000000, 0, 17, 0), 92*069f0b63SChristophe Kerello STPMU1_RANGE(1050000, 18, 19, 0), 93*069f0b63SChristophe Kerello STPMU1_RANGE(1100000, 20, 21, 0), 94*069f0b63SChristophe Kerello STPMU1_RANGE(1150000, 22, 23, 0), 95*069f0b63SChristophe Kerello STPMU1_RANGE(1200000, 24, 25, 0), 96*069f0b63SChristophe Kerello STPMU1_RANGE(1250000, 26, 27, 0), 97*069f0b63SChristophe Kerello STPMU1_RANGE(1300000, 28, 29, 0), 98*069f0b63SChristophe Kerello STPMU1_RANGE(1350000, 30, 31, 0), 99*069f0b63SChristophe Kerello STPMU1_RANGE(1400000, 32, 33, 0), 100*069f0b63SChristophe Kerello STPMU1_RANGE(1450000, 34, 35, 0), 101*069f0b63SChristophe Kerello STPMU1_RANGE(1500000, 36, 63, 0), 102*069f0b63SChristophe Kerello }; 103*069f0b63SChristophe Kerello 104*069f0b63SChristophe Kerello static const struct stpmu1_range buck3_ranges[] = { 105*069f0b63SChristophe Kerello STPMU1_RANGE(1000000, 0, 19, 0), 106*069f0b63SChristophe Kerello STPMU1_RANGE(1100000, 20, 23, 0), 107*069f0b63SChristophe Kerello STPMU1_RANGE(1200000, 24, 27, 0), 108*069f0b63SChristophe Kerello STPMU1_RANGE(1300000, 28, 31, 0), 109*069f0b63SChristophe Kerello STPMU1_RANGE(1400000, 32, 35, 0), 110*069f0b63SChristophe Kerello STPMU1_RANGE(1500000, 36, 55, 100000), 111*069f0b63SChristophe Kerello STPMU1_RANGE(3400000, 56, 63, 0), 112*069f0b63SChristophe Kerello }; 113*069f0b63SChristophe Kerello 114*069f0b63SChristophe Kerello static const struct stpmu1_range buck4_ranges[] = { 115*069f0b63SChristophe Kerello STPMU1_RANGE(600000, 0, 27, 25000), 116*069f0b63SChristophe Kerello STPMU1_RANGE(1300000, 28, 29, 0), 117*069f0b63SChristophe Kerello STPMU1_RANGE(1350000, 30, 31, 0), 118*069f0b63SChristophe Kerello STPMU1_RANGE(1400000, 32, 33, 0), 119*069f0b63SChristophe Kerello STPMU1_RANGE(1450000, 34, 35, 0), 120*069f0b63SChristophe Kerello STPMU1_RANGE(1500000, 36, 60, 100000), 121*069f0b63SChristophe Kerello STPMU1_RANGE(3900000, 61, 63, 0), 122*069f0b63SChristophe Kerello }; 123*069f0b63SChristophe Kerello 124*069f0b63SChristophe Kerello /* BUCK: 1,2,3,4 - voltage ranges */ 125*069f0b63SChristophe Kerello static const struct stpmu1_output_range buck_voltage_range[] = { 126*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(buck1_ranges, ARRAY_SIZE(buck1_ranges)), 127*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(buck2_ranges, ARRAY_SIZE(buck2_ranges)), 128*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(buck3_ranges, ARRAY_SIZE(buck3_ranges)), 129*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(buck4_ranges, ARRAY_SIZE(buck4_ranges)), 130*069f0b63SChristophe Kerello }; 131*069f0b63SChristophe Kerello 132*069f0b63SChristophe Kerello /* BUCK modes */ 133*069f0b63SChristophe Kerello static const struct dm_regulator_mode buck_modes[] = { 134*069f0b63SChristophe Kerello STPMU1_MODE(STPMU1_BUCK_MODE_HP, STPMU1_BUCK_MODE_HP, "HP"), 135*069f0b63SChristophe Kerello STPMU1_MODE(STPMU1_BUCK_MODE_LP, STPMU1_BUCK_MODE_LP, "LP"), 136*069f0b63SChristophe Kerello }; 137*069f0b63SChristophe Kerello 138*069f0b63SChristophe Kerello static int stpmu1_buck_get_uv(struct udevice *dev, int buck) 139*069f0b63SChristophe Kerello { 140*069f0b63SChristophe Kerello int sel; 141*069f0b63SChristophe Kerello 142*069f0b63SChristophe Kerello sel = pmic_reg_read(dev, STPMU1_BUCKX_CTRL_REG(buck)); 143*069f0b63SChristophe Kerello if (sel < 0) 144*069f0b63SChristophe Kerello return sel; 145*069f0b63SChristophe Kerello 146*069f0b63SChristophe Kerello sel &= STPMU1_BUCK_OUTPUT_MASK; 147*069f0b63SChristophe Kerello sel >>= STPMU1_BUCK_OUTPUT_SHIFT; 148*069f0b63SChristophe Kerello 149*069f0b63SChristophe Kerello return stpmu1_output_find_uv(sel, &buck_voltage_range[buck]); 150*069f0b63SChristophe Kerello } 151*069f0b63SChristophe Kerello 152*069f0b63SChristophe Kerello static int stpmu1_buck_get_value(struct udevice *dev) 153*069f0b63SChristophe Kerello { 154*069f0b63SChristophe Kerello return stpmu1_buck_get_uv(dev->parent, dev->driver_data - 1); 155*069f0b63SChristophe Kerello } 156*069f0b63SChristophe Kerello 157*069f0b63SChristophe Kerello static int stpmu1_buck_set_value(struct udevice *dev, int uv) 158*069f0b63SChristophe Kerello { 159*069f0b63SChristophe Kerello int sel, buck = dev->driver_data - 1; 160*069f0b63SChristophe Kerello 161*069f0b63SChristophe Kerello sel = stpmu1_output_find_sel(uv, &buck_voltage_range[buck]); 162*069f0b63SChristophe Kerello if (sel < 0) 163*069f0b63SChristophe Kerello return sel; 164*069f0b63SChristophe Kerello 165*069f0b63SChristophe Kerello return pmic_clrsetbits(dev->parent, 166*069f0b63SChristophe Kerello STPMU1_BUCKX_CTRL_REG(buck), 167*069f0b63SChristophe Kerello STPMU1_BUCK_OUTPUT_MASK, 168*069f0b63SChristophe Kerello sel << STPMU1_BUCK_OUTPUT_SHIFT); 169*069f0b63SChristophe Kerello } 170*069f0b63SChristophe Kerello 171*069f0b63SChristophe Kerello static int stpmu1_buck_get_enable(struct udevice *dev) 172*069f0b63SChristophe Kerello { 173*069f0b63SChristophe Kerello int ret; 174*069f0b63SChristophe Kerello 175*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, 176*069f0b63SChristophe Kerello STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1)); 177*069f0b63SChristophe Kerello if (ret < 0) 178*069f0b63SChristophe Kerello return false; 179*069f0b63SChristophe Kerello 180*069f0b63SChristophe Kerello return ret & STPMU1_BUCK_EN ? true : false; 181*069f0b63SChristophe Kerello } 182*069f0b63SChristophe Kerello 183*069f0b63SChristophe Kerello static int stpmu1_buck_set_enable(struct udevice *dev, bool enable) 184*069f0b63SChristophe Kerello { 185*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 186*069f0b63SChristophe Kerello int ret, uv; 187*069f0b63SChristophe Kerello 188*069f0b63SChristophe Kerello /* if regulator is already in the wanted state, nothing to do */ 189*069f0b63SChristophe Kerello if (stpmu1_buck_get_enable(dev) == enable) 190*069f0b63SChristophe Kerello return 0; 191*069f0b63SChristophe Kerello 192*069f0b63SChristophe Kerello if (enable) { 193*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 194*069f0b63SChristophe Kerello uv = stpmu1_buck_get_value(dev); 195*069f0b63SChristophe Kerello if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV)) 196*069f0b63SChristophe Kerello stpmu1_buck_set_value(dev, uc_pdata->min_uV); 197*069f0b63SChristophe Kerello } 198*069f0b63SChristophe Kerello 199*069f0b63SChristophe Kerello ret = pmic_clrsetbits(dev->parent, 200*069f0b63SChristophe Kerello STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1), 201*069f0b63SChristophe Kerello STPMU1_BUCK_EN, enable ? STPMU1_BUCK_EN : 0); 202*069f0b63SChristophe Kerello if (enable) 203*069f0b63SChristophe Kerello mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); 204*069f0b63SChristophe Kerello 205*069f0b63SChristophe Kerello return ret; 206*069f0b63SChristophe Kerello } 207*069f0b63SChristophe Kerello 208*069f0b63SChristophe Kerello static int stpmu1_buck_get_mode(struct udevice *dev) 209*069f0b63SChristophe Kerello { 210*069f0b63SChristophe Kerello int ret; 211*069f0b63SChristophe Kerello 212*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, 213*069f0b63SChristophe Kerello STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1)); 214*069f0b63SChristophe Kerello if (ret < 0) 215*069f0b63SChristophe Kerello return ret; 216*069f0b63SChristophe Kerello 217*069f0b63SChristophe Kerello return ret & STPMU1_BUCK_MODE ? STPMU1_BUCK_MODE_LP : 218*069f0b63SChristophe Kerello STPMU1_BUCK_MODE_HP; 219*069f0b63SChristophe Kerello } 220*069f0b63SChristophe Kerello 221*069f0b63SChristophe Kerello static int stpmu1_buck_set_mode(struct udevice *dev, int mode) 222*069f0b63SChristophe Kerello { 223*069f0b63SChristophe Kerello return pmic_clrsetbits(dev->parent, 224*069f0b63SChristophe Kerello STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1), 225*069f0b63SChristophe Kerello STPMU1_BUCK_MODE, 226*069f0b63SChristophe Kerello mode ? STPMU1_BUCK_MODE : 0); 227*069f0b63SChristophe Kerello } 228*069f0b63SChristophe Kerello 229*069f0b63SChristophe Kerello static int stpmu1_buck_probe(struct udevice *dev) 230*069f0b63SChristophe Kerello { 231*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 232*069f0b63SChristophe Kerello 233*069f0b63SChristophe Kerello if (!dev->driver_data || dev->driver_data > STPMU1_MAX_BUCK) 234*069f0b63SChristophe Kerello return -EINVAL; 235*069f0b63SChristophe Kerello 236*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 237*069f0b63SChristophe Kerello 238*069f0b63SChristophe Kerello uc_pdata->type = REGULATOR_TYPE_BUCK; 239*069f0b63SChristophe Kerello uc_pdata->mode = (struct dm_regulator_mode *)buck_modes; 240*069f0b63SChristophe Kerello uc_pdata->mode_count = ARRAY_SIZE(buck_modes); 241*069f0b63SChristophe Kerello 242*069f0b63SChristophe Kerello return 0; 243*069f0b63SChristophe Kerello } 244*069f0b63SChristophe Kerello 245*069f0b63SChristophe Kerello static const struct dm_regulator_ops stpmu1_buck_ops = { 246*069f0b63SChristophe Kerello .get_value = stpmu1_buck_get_value, 247*069f0b63SChristophe Kerello .set_value = stpmu1_buck_set_value, 248*069f0b63SChristophe Kerello .get_enable = stpmu1_buck_get_enable, 249*069f0b63SChristophe Kerello .set_enable = stpmu1_buck_set_enable, 250*069f0b63SChristophe Kerello .get_mode = stpmu1_buck_get_mode, 251*069f0b63SChristophe Kerello .set_mode = stpmu1_buck_set_mode, 252*069f0b63SChristophe Kerello }; 253*069f0b63SChristophe Kerello 254*069f0b63SChristophe Kerello U_BOOT_DRIVER(stpmu1_buck) = { 255*069f0b63SChristophe Kerello .name = "stpmu1_buck", 256*069f0b63SChristophe Kerello .id = UCLASS_REGULATOR, 257*069f0b63SChristophe Kerello .ops = &stpmu1_buck_ops, 258*069f0b63SChristophe Kerello .probe = stpmu1_buck_probe, 259*069f0b63SChristophe Kerello }; 260*069f0b63SChristophe Kerello 261*069f0b63SChristophe Kerello /* 262*069f0b63SChristophe Kerello * LDO regulators 263*069f0b63SChristophe Kerello */ 264*069f0b63SChristophe Kerello 265*069f0b63SChristophe Kerello static const struct stpmu1_range ldo12_ranges[] = { 266*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 0, 7, 0), 267*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 8, 24, 100000), 268*069f0b63SChristophe Kerello STPMU1_RANGE(3300000, 25, 31, 0), 269*069f0b63SChristophe Kerello }; 270*069f0b63SChristophe Kerello 271*069f0b63SChristophe Kerello static const struct stpmu1_range ldo3_ranges[] = { 272*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 0, 7, 0), 273*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 8, 24, 100000), 274*069f0b63SChristophe Kerello STPMU1_RANGE(3300000, 25, 30, 0), 275*069f0b63SChristophe Kerello /* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */ 276*069f0b63SChristophe Kerello }; 277*069f0b63SChristophe Kerello 278*069f0b63SChristophe Kerello static const struct stpmu1_range ldo5_ranges[] = { 279*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 0, 7, 0), 280*069f0b63SChristophe Kerello STPMU1_RANGE(1700000, 8, 30, 100000), 281*069f0b63SChristophe Kerello STPMU1_RANGE(3900000, 31, 31, 0), 282*069f0b63SChristophe Kerello }; 283*069f0b63SChristophe Kerello 284*069f0b63SChristophe Kerello static const struct stpmu1_range ldo6_ranges[] = { 285*069f0b63SChristophe Kerello STPMU1_RANGE(900000, 0, 24, 100000), 286*069f0b63SChristophe Kerello STPMU1_RANGE(3300000, 25, 31, 0), 287*069f0b63SChristophe Kerello }; 288*069f0b63SChristophe Kerello 289*069f0b63SChristophe Kerello /* LDO: 1,2,3,4,5,6 - voltage ranges */ 290*069f0b63SChristophe Kerello static const struct stpmu1_output_range ldo_voltage_range[] = { 291*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), 292*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), 293*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)), 294*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(NULL, 0), 295*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)), 296*069f0b63SChristophe Kerello STPMU1_OUTPUT_RANGE(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)), 297*069f0b63SChristophe Kerello }; 298*069f0b63SChristophe Kerello 299*069f0b63SChristophe Kerello /* LDO modes */ 300*069f0b63SChristophe Kerello static const struct dm_regulator_mode ldo_modes[] = { 301*069f0b63SChristophe Kerello STPMU1_MODE(STPMU1_LDO_MODE_NORMAL, 302*069f0b63SChristophe Kerello STPMU1_LDO_MODE_NORMAL, "NORMAL"), 303*069f0b63SChristophe Kerello STPMU1_MODE(STPMU1_LDO_MODE_BYPASS, 304*069f0b63SChristophe Kerello STPMU1_LDO_MODE_BYPASS, "BYPASS"), 305*069f0b63SChristophe Kerello STPMU1_MODE(STPMU1_LDO_MODE_SINK_SOURCE, 306*069f0b63SChristophe Kerello STPMU1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"), 307*069f0b63SChristophe Kerello }; 308*069f0b63SChristophe Kerello 309*069f0b63SChristophe Kerello static int stpmu1_ldo_get_value(struct udevice *dev) 310*069f0b63SChristophe Kerello { 311*069f0b63SChristophe Kerello int sel, ldo = dev->driver_data - 1; 312*069f0b63SChristophe Kerello 313*069f0b63SChristophe Kerello sel = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); 314*069f0b63SChristophe Kerello if (sel < 0) 315*069f0b63SChristophe Kerello return sel; 316*069f0b63SChristophe Kerello 317*069f0b63SChristophe Kerello /* ldo4 => 3,3V */ 318*069f0b63SChristophe Kerello if (ldo == STPMU1_LDO4) 319*069f0b63SChristophe Kerello return STPMU1_LDO4_UV; 320*069f0b63SChristophe Kerello 321*069f0b63SChristophe Kerello sel &= STPMU1_LDO12356_OUTPUT_MASK; 322*069f0b63SChristophe Kerello sel >>= STPMU1_LDO12356_OUTPUT_SHIFT; 323*069f0b63SChristophe Kerello 324*069f0b63SChristophe Kerello /* ldo3, sel = 31 => BUCK2/2 */ 325*069f0b63SChristophe Kerello if (ldo == STPMU1_LDO3 && sel == STPMU1_LDO3_DDR_SEL) 326*069f0b63SChristophe Kerello return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2; 327*069f0b63SChristophe Kerello 328*069f0b63SChristophe Kerello return stpmu1_output_find_uv(sel, &ldo_voltage_range[ldo]); 329*069f0b63SChristophe Kerello } 330*069f0b63SChristophe Kerello 331*069f0b63SChristophe Kerello static int stpmu1_ldo_set_value(struct udevice *dev, int uv) 332*069f0b63SChristophe Kerello { 333*069f0b63SChristophe Kerello int sel, ldo = dev->driver_data - 1; 334*069f0b63SChristophe Kerello 335*069f0b63SChristophe Kerello /* ldo4 => not possible */ 336*069f0b63SChristophe Kerello if (ldo == STPMU1_LDO4) 337*069f0b63SChristophe Kerello return -EINVAL; 338*069f0b63SChristophe Kerello 339*069f0b63SChristophe Kerello sel = stpmu1_output_find_sel(uv, &ldo_voltage_range[ldo]); 340*069f0b63SChristophe Kerello if (sel < 0) 341*069f0b63SChristophe Kerello return sel; 342*069f0b63SChristophe Kerello 343*069f0b63SChristophe Kerello return pmic_clrsetbits(dev->parent, 344*069f0b63SChristophe Kerello STPMU1_LDOX_CTRL_REG(ldo), 345*069f0b63SChristophe Kerello STPMU1_LDO12356_OUTPUT_MASK, 346*069f0b63SChristophe Kerello sel << STPMU1_LDO12356_OUTPUT_SHIFT); 347*069f0b63SChristophe Kerello } 348*069f0b63SChristophe Kerello 349*069f0b63SChristophe Kerello static int stpmu1_ldo_get_enable(struct udevice *dev) 350*069f0b63SChristophe Kerello { 351*069f0b63SChristophe Kerello int ret; 352*069f0b63SChristophe Kerello 353*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, 354*069f0b63SChristophe Kerello STPMU1_LDOX_CTRL_REG(dev->driver_data - 1)); 355*069f0b63SChristophe Kerello if (ret < 0) 356*069f0b63SChristophe Kerello return false; 357*069f0b63SChristophe Kerello 358*069f0b63SChristophe Kerello return ret & STPMU1_LDO_EN ? true : false; 359*069f0b63SChristophe Kerello } 360*069f0b63SChristophe Kerello 361*069f0b63SChristophe Kerello static int stpmu1_ldo_set_enable(struct udevice *dev, bool enable) 362*069f0b63SChristophe Kerello { 363*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 364*069f0b63SChristophe Kerello int ret, uv; 365*069f0b63SChristophe Kerello 366*069f0b63SChristophe Kerello /* if regulator is already in the wanted state, nothing to do */ 367*069f0b63SChristophe Kerello if (stpmu1_ldo_get_enable(dev) == enable) 368*069f0b63SChristophe Kerello return 0; 369*069f0b63SChristophe Kerello 370*069f0b63SChristophe Kerello if (enable) { 371*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 372*069f0b63SChristophe Kerello uv = stpmu1_ldo_get_value(dev); 373*069f0b63SChristophe Kerello if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV)) 374*069f0b63SChristophe Kerello stpmu1_ldo_set_value(dev, uc_pdata->min_uV); 375*069f0b63SChristophe Kerello } 376*069f0b63SChristophe Kerello 377*069f0b63SChristophe Kerello ret = pmic_clrsetbits(dev->parent, 378*069f0b63SChristophe Kerello STPMU1_LDOX_CTRL_REG(dev->driver_data - 1), 379*069f0b63SChristophe Kerello STPMU1_LDO_EN, enable ? STPMU1_LDO_EN : 0); 380*069f0b63SChristophe Kerello if (enable) 381*069f0b63SChristophe Kerello mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); 382*069f0b63SChristophe Kerello 383*069f0b63SChristophe Kerello return ret; 384*069f0b63SChristophe Kerello } 385*069f0b63SChristophe Kerello 386*069f0b63SChristophe Kerello static int stpmu1_ldo_get_mode(struct udevice *dev) 387*069f0b63SChristophe Kerello { 388*069f0b63SChristophe Kerello int ret, ldo = dev->driver_data - 1; 389*069f0b63SChristophe Kerello 390*069f0b63SChristophe Kerello if (ldo != STPMU1_LDO3) 391*069f0b63SChristophe Kerello return -EINVAL; 392*069f0b63SChristophe Kerello 393*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); 394*069f0b63SChristophe Kerello if (ret < 0) 395*069f0b63SChristophe Kerello return ret; 396*069f0b63SChristophe Kerello 397*069f0b63SChristophe Kerello if (ret & STPMU1_LDO3_MODE) 398*069f0b63SChristophe Kerello return STPMU1_LDO_MODE_BYPASS; 399*069f0b63SChristophe Kerello 400*069f0b63SChristophe Kerello ret &= STPMU1_LDO12356_OUTPUT_MASK; 401*069f0b63SChristophe Kerello ret >>= STPMU1_LDO12356_OUTPUT_SHIFT; 402*069f0b63SChristophe Kerello 403*069f0b63SChristophe Kerello return ret == STPMU1_LDO3_DDR_SEL ? STPMU1_LDO_MODE_SINK_SOURCE : 404*069f0b63SChristophe Kerello STPMU1_LDO_MODE_NORMAL; 405*069f0b63SChristophe Kerello } 406*069f0b63SChristophe Kerello 407*069f0b63SChristophe Kerello static int stpmu1_ldo_set_mode(struct udevice *dev, int mode) 408*069f0b63SChristophe Kerello { 409*069f0b63SChristophe Kerello int ret, ldo = dev->driver_data - 1; 410*069f0b63SChristophe Kerello 411*069f0b63SChristophe Kerello if (ldo != STPMU1_LDO3) 412*069f0b63SChristophe Kerello return -EINVAL; 413*069f0b63SChristophe Kerello 414*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); 415*069f0b63SChristophe Kerello if (ret < 0) 416*069f0b63SChristophe Kerello return ret; 417*069f0b63SChristophe Kerello 418*069f0b63SChristophe Kerello switch (mode) { 419*069f0b63SChristophe Kerello case STPMU1_LDO_MODE_SINK_SOURCE: 420*069f0b63SChristophe Kerello ret &= ~STPMU1_LDO12356_OUTPUT_MASK; 421*069f0b63SChristophe Kerello ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; 422*069f0b63SChristophe Kerello case STPMU1_LDO_MODE_NORMAL: 423*069f0b63SChristophe Kerello ret &= ~STPMU1_LDO3_MODE; 424*069f0b63SChristophe Kerello break; 425*069f0b63SChristophe Kerello case STPMU1_LDO_MODE_BYPASS: 426*069f0b63SChristophe Kerello ret |= STPMU1_LDO3_MODE; 427*069f0b63SChristophe Kerello break; 428*069f0b63SChristophe Kerello } 429*069f0b63SChristophe Kerello 430*069f0b63SChristophe Kerello return pmic_reg_write(dev->parent, STPMU1_LDOX_CTRL_REG(ldo), ret); 431*069f0b63SChristophe Kerello } 432*069f0b63SChristophe Kerello 433*069f0b63SChristophe Kerello static int stpmu1_ldo_probe(struct udevice *dev) 434*069f0b63SChristophe Kerello { 435*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 436*069f0b63SChristophe Kerello 437*069f0b63SChristophe Kerello if (!dev->driver_data || dev->driver_data > STPMU1_MAX_LDO) 438*069f0b63SChristophe Kerello return -EINVAL; 439*069f0b63SChristophe Kerello 440*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 441*069f0b63SChristophe Kerello 442*069f0b63SChristophe Kerello uc_pdata->type = REGULATOR_TYPE_LDO; 443*069f0b63SChristophe Kerello if (dev->driver_data - 1 == STPMU1_LDO3) { 444*069f0b63SChristophe Kerello uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes; 445*069f0b63SChristophe Kerello uc_pdata->mode_count = ARRAY_SIZE(ldo_modes); 446*069f0b63SChristophe Kerello } else { 447*069f0b63SChristophe Kerello uc_pdata->mode_count = 0; 448*069f0b63SChristophe Kerello } 449*069f0b63SChristophe Kerello 450*069f0b63SChristophe Kerello return 0; 451*069f0b63SChristophe Kerello } 452*069f0b63SChristophe Kerello 453*069f0b63SChristophe Kerello static const struct dm_regulator_ops stpmu1_ldo_ops = { 454*069f0b63SChristophe Kerello .get_value = stpmu1_ldo_get_value, 455*069f0b63SChristophe Kerello .set_value = stpmu1_ldo_set_value, 456*069f0b63SChristophe Kerello .get_enable = stpmu1_ldo_get_enable, 457*069f0b63SChristophe Kerello .set_enable = stpmu1_ldo_set_enable, 458*069f0b63SChristophe Kerello .get_mode = stpmu1_ldo_get_mode, 459*069f0b63SChristophe Kerello .set_mode = stpmu1_ldo_set_mode, 460*069f0b63SChristophe Kerello }; 461*069f0b63SChristophe Kerello 462*069f0b63SChristophe Kerello U_BOOT_DRIVER(stpmu1_ldo) = { 463*069f0b63SChristophe Kerello .name = "stpmu1_ldo", 464*069f0b63SChristophe Kerello .id = UCLASS_REGULATOR, 465*069f0b63SChristophe Kerello .ops = &stpmu1_ldo_ops, 466*069f0b63SChristophe Kerello .probe = stpmu1_ldo_probe, 467*069f0b63SChristophe Kerello }; 468*069f0b63SChristophe Kerello 469*069f0b63SChristophe Kerello /* 470*069f0b63SChristophe Kerello * VREF DDR regulator 471*069f0b63SChristophe Kerello */ 472*069f0b63SChristophe Kerello 473*069f0b63SChristophe Kerello static int stpmu1_vref_ddr_get_value(struct udevice *dev) 474*069f0b63SChristophe Kerello { 475*069f0b63SChristophe Kerello /* BUCK2/2 */ 476*069f0b63SChristophe Kerello return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2; 477*069f0b63SChristophe Kerello } 478*069f0b63SChristophe Kerello 479*069f0b63SChristophe Kerello static int stpmu1_vref_ddr_get_enable(struct udevice *dev) 480*069f0b63SChristophe Kerello { 481*069f0b63SChristophe Kerello int ret; 482*069f0b63SChristophe Kerello 483*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_VREF_CTRL_REG); 484*069f0b63SChristophe Kerello if (ret < 0) 485*069f0b63SChristophe Kerello return false; 486*069f0b63SChristophe Kerello 487*069f0b63SChristophe Kerello return ret & STPMU1_VREF_EN ? true : false; 488*069f0b63SChristophe Kerello } 489*069f0b63SChristophe Kerello 490*069f0b63SChristophe Kerello static int stpmu1_vref_ddr_set_enable(struct udevice *dev, bool enable) 491*069f0b63SChristophe Kerello { 492*069f0b63SChristophe Kerello int ret; 493*069f0b63SChristophe Kerello 494*069f0b63SChristophe Kerello /* if regulator is already in the wanted state, nothing to do */ 495*069f0b63SChristophe Kerello if (stpmu1_vref_ddr_get_enable(dev) == enable) 496*069f0b63SChristophe Kerello return 0; 497*069f0b63SChristophe Kerello 498*069f0b63SChristophe Kerello ret = pmic_clrsetbits(dev->parent, STPMU1_VREF_CTRL_REG, 499*069f0b63SChristophe Kerello STPMU1_VREF_EN, enable ? STPMU1_VREF_EN : 0); 500*069f0b63SChristophe Kerello if (enable) 501*069f0b63SChristophe Kerello mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); 502*069f0b63SChristophe Kerello 503*069f0b63SChristophe Kerello return ret; 504*069f0b63SChristophe Kerello } 505*069f0b63SChristophe Kerello 506*069f0b63SChristophe Kerello static int stpmu1_vref_ddr_probe(struct udevice *dev) 507*069f0b63SChristophe Kerello { 508*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 509*069f0b63SChristophe Kerello 510*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 511*069f0b63SChristophe Kerello 512*069f0b63SChristophe Kerello uc_pdata->type = REGULATOR_TYPE_FIXED; 513*069f0b63SChristophe Kerello uc_pdata->mode_count = 0; 514*069f0b63SChristophe Kerello 515*069f0b63SChristophe Kerello return 0; 516*069f0b63SChristophe Kerello } 517*069f0b63SChristophe Kerello 518*069f0b63SChristophe Kerello static const struct dm_regulator_ops stpmu1_vref_ddr_ops = { 519*069f0b63SChristophe Kerello .get_value = stpmu1_vref_ddr_get_value, 520*069f0b63SChristophe Kerello .get_enable = stpmu1_vref_ddr_get_enable, 521*069f0b63SChristophe Kerello .set_enable = stpmu1_vref_ddr_set_enable, 522*069f0b63SChristophe Kerello }; 523*069f0b63SChristophe Kerello 524*069f0b63SChristophe Kerello U_BOOT_DRIVER(stpmu1_vref_ddr) = { 525*069f0b63SChristophe Kerello .name = "stpmu1_vref_ddr", 526*069f0b63SChristophe Kerello .id = UCLASS_REGULATOR, 527*069f0b63SChristophe Kerello .ops = &stpmu1_vref_ddr_ops, 528*069f0b63SChristophe Kerello .probe = stpmu1_vref_ddr_probe, 529*069f0b63SChristophe Kerello }; 530*069f0b63SChristophe Kerello 531*069f0b63SChristophe Kerello /* 532*069f0b63SChristophe Kerello * BOOST regulator 533*069f0b63SChristophe Kerello */ 534*069f0b63SChristophe Kerello 535*069f0b63SChristophe Kerello static int stpmu1_boost_get_enable(struct udevice *dev) 536*069f0b63SChristophe Kerello { 537*069f0b63SChristophe Kerello int ret; 538*069f0b63SChristophe Kerello 539*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); 540*069f0b63SChristophe Kerello if (ret < 0) 541*069f0b63SChristophe Kerello return false; 542*069f0b63SChristophe Kerello 543*069f0b63SChristophe Kerello return ret & STPMU1_USB_BOOST_EN ? true : false; 544*069f0b63SChristophe Kerello } 545*069f0b63SChristophe Kerello 546*069f0b63SChristophe Kerello static int stpmu1_boost_set_enable(struct udevice *dev, bool enable) 547*069f0b63SChristophe Kerello { 548*069f0b63SChristophe Kerello int ret; 549*069f0b63SChristophe Kerello 550*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); 551*069f0b63SChristophe Kerello if (ret < 0) 552*069f0b63SChristophe Kerello return ret; 553*069f0b63SChristophe Kerello 554*069f0b63SChristophe Kerello if (!enable && ret & STPMU1_USB_PWR_SW_EN) 555*069f0b63SChristophe Kerello return -EINVAL; 556*069f0b63SChristophe Kerello 557*069f0b63SChristophe Kerello /* if regulator is already in the wanted state, nothing to do */ 558*069f0b63SChristophe Kerello if (!!(ret & STPMU1_USB_BOOST_EN) == enable) 559*069f0b63SChristophe Kerello return 0; 560*069f0b63SChristophe Kerello 561*069f0b63SChristophe Kerello ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, 562*069f0b63SChristophe Kerello STPMU1_USB_BOOST_EN, 563*069f0b63SChristophe Kerello enable ? STPMU1_USB_BOOST_EN : 0); 564*069f0b63SChristophe Kerello if (enable) 565*069f0b63SChristophe Kerello mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS); 566*069f0b63SChristophe Kerello 567*069f0b63SChristophe Kerello return ret; 568*069f0b63SChristophe Kerello } 569*069f0b63SChristophe Kerello 570*069f0b63SChristophe Kerello static int stpmu1_boost_probe(struct udevice *dev) 571*069f0b63SChristophe Kerello { 572*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 573*069f0b63SChristophe Kerello 574*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 575*069f0b63SChristophe Kerello 576*069f0b63SChristophe Kerello uc_pdata->type = REGULATOR_TYPE_FIXED; 577*069f0b63SChristophe Kerello uc_pdata->mode_count = 0; 578*069f0b63SChristophe Kerello 579*069f0b63SChristophe Kerello return 0; 580*069f0b63SChristophe Kerello } 581*069f0b63SChristophe Kerello 582*069f0b63SChristophe Kerello static const struct dm_regulator_ops stpmu1_boost_ops = { 583*069f0b63SChristophe Kerello .get_enable = stpmu1_boost_get_enable, 584*069f0b63SChristophe Kerello .set_enable = stpmu1_boost_set_enable, 585*069f0b63SChristophe Kerello }; 586*069f0b63SChristophe Kerello 587*069f0b63SChristophe Kerello U_BOOT_DRIVER(stpmu1_boost) = { 588*069f0b63SChristophe Kerello .name = "stpmu1_boost", 589*069f0b63SChristophe Kerello .id = UCLASS_REGULATOR, 590*069f0b63SChristophe Kerello .ops = &stpmu1_boost_ops, 591*069f0b63SChristophe Kerello .probe = stpmu1_boost_probe, 592*069f0b63SChristophe Kerello }; 593*069f0b63SChristophe Kerello 594*069f0b63SChristophe Kerello /* 595*069f0b63SChristophe Kerello * USB power switch 596*069f0b63SChristophe Kerello */ 597*069f0b63SChristophe Kerello 598*069f0b63SChristophe Kerello static int stpmu1_pwr_sw_get_enable(struct udevice *dev) 599*069f0b63SChristophe Kerello { 600*069f0b63SChristophe Kerello uint mask = 1 << dev->driver_data; 601*069f0b63SChristophe Kerello int ret; 602*069f0b63SChristophe Kerello 603*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); 604*069f0b63SChristophe Kerello if (ret < 0) 605*069f0b63SChristophe Kerello return false; 606*069f0b63SChristophe Kerello 607*069f0b63SChristophe Kerello return ret & mask ? true : false; 608*069f0b63SChristophe Kerello } 609*069f0b63SChristophe Kerello 610*069f0b63SChristophe Kerello static int stpmu1_pwr_sw_set_enable(struct udevice *dev, bool enable) 611*069f0b63SChristophe Kerello { 612*069f0b63SChristophe Kerello uint mask = 1 << dev->driver_data; 613*069f0b63SChristophe Kerello int ret; 614*069f0b63SChristophe Kerello 615*069f0b63SChristophe Kerello ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); 616*069f0b63SChristophe Kerello if (ret < 0) 617*069f0b63SChristophe Kerello return ret; 618*069f0b63SChristophe Kerello 619*069f0b63SChristophe Kerello /* if regulator is already in the wanted state, nothing to do */ 620*069f0b63SChristophe Kerello if (!!(ret & mask) == enable) 621*069f0b63SChristophe Kerello return 0; 622*069f0b63SChristophe Kerello 623*069f0b63SChristophe Kerello /* Boost management */ 624*069f0b63SChristophe Kerello if (enable && !(ret & STPMU1_USB_BOOST_EN)) { 625*069f0b63SChristophe Kerello pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, 626*069f0b63SChristophe Kerello STPMU1_USB_BOOST_EN, STPMU1_USB_BOOST_EN); 627*069f0b63SChristophe Kerello mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS); 628*069f0b63SChristophe Kerello } else if (!enable && ret & STPMU1_USB_BOOST_EN && 629*069f0b63SChristophe Kerello (ret & STPMU1_USB_PWR_SW_EN) != STPMU1_USB_PWR_SW_EN) { 630*069f0b63SChristophe Kerello pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, 631*069f0b63SChristophe Kerello STPMU1_USB_BOOST_EN, 0); 632*069f0b63SChristophe Kerello } 633*069f0b63SChristophe Kerello 634*069f0b63SChristophe Kerello ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, 635*069f0b63SChristophe Kerello mask, enable ? mask : 0); 636*069f0b63SChristophe Kerello if (enable) 637*069f0b63SChristophe Kerello mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); 638*069f0b63SChristophe Kerello 639*069f0b63SChristophe Kerello return ret; 640*069f0b63SChristophe Kerello } 641*069f0b63SChristophe Kerello 642*069f0b63SChristophe Kerello static int stpmu1_pwr_sw_probe(struct udevice *dev) 643*069f0b63SChristophe Kerello { 644*069f0b63SChristophe Kerello struct dm_regulator_uclass_platdata *uc_pdata; 645*069f0b63SChristophe Kerello 646*069f0b63SChristophe Kerello if (!dev->driver_data || dev->driver_data > STPMU1_MAX_PWR_SW) 647*069f0b63SChristophe Kerello return -EINVAL; 648*069f0b63SChristophe Kerello 649*069f0b63SChristophe Kerello uc_pdata = dev_get_uclass_platdata(dev); 650*069f0b63SChristophe Kerello 651*069f0b63SChristophe Kerello uc_pdata->type = REGULATOR_TYPE_FIXED; 652*069f0b63SChristophe Kerello uc_pdata->mode_count = 0; 653*069f0b63SChristophe Kerello 654*069f0b63SChristophe Kerello return 0; 655*069f0b63SChristophe Kerello } 656*069f0b63SChristophe Kerello 657*069f0b63SChristophe Kerello static const struct dm_regulator_ops stpmu1_pwr_sw_ops = { 658*069f0b63SChristophe Kerello .get_enable = stpmu1_pwr_sw_get_enable, 659*069f0b63SChristophe Kerello .set_enable = stpmu1_pwr_sw_set_enable, 660*069f0b63SChristophe Kerello }; 661*069f0b63SChristophe Kerello 662*069f0b63SChristophe Kerello U_BOOT_DRIVER(stpmu1_pwr_sw) = { 663*069f0b63SChristophe Kerello .name = "stpmu1_pwr_sw", 664*069f0b63SChristophe Kerello .id = UCLASS_REGULATOR, 665*069f0b63SChristophe Kerello .ops = &stpmu1_pwr_sw_ops, 666*069f0b63SChristophe Kerello .probe = stpmu1_pwr_sw_probe, 667*069f0b63SChristophe Kerello }; 668