hi6421v600-regulator.c (7846B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Device driver for regulators in Hisi IC 4// 5// Copyright (c) 2013 Linaro Ltd. 6// Copyright (c) 2011 HiSilicon Ltd. 7// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd. 8// 9// Guodong Xu <guodong.xu@linaro.org> 10 11#include <linux/delay.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <linux/platform_device.h> 15#include <linux/regmap.h> 16#include <linux/regulator/driver.h> 17#include <linux/spmi.h> 18 19struct hi6421_spmi_reg_priv { 20 /* Serialize regulator enable logic */ 21 struct mutex enable_mutex; 22}; 23 24struct hi6421_spmi_reg_info { 25 struct regulator_desc desc; 26 u8 eco_mode_mask; 27 u32 eco_uA; 28}; 29 30static const unsigned int range_1v5_to_2v0[] = { 31 1500000, 1550000, 1600000, 1650000, 32 1700000, 1725000, 1750000, 1775000, 33 1800000, 1825000, 1850000, 1875000, 34 1900000, 1925000, 1950000, 2000000 35}; 36 37static const unsigned int range_1v725_to_1v9[] = { 38 1725000, 1750000, 1775000, 1800000, 39 1825000, 1850000, 1875000, 1900000 40}; 41 42static const unsigned int range_1v75_to_3v3[] = { 43 1750000, 1800000, 1825000, 2800000, 44 2850000, 2950000, 3000000, 3300000 45}; 46 47static const unsigned int range_1v8_to_3v0[] = { 48 1800000, 1850000, 2400000, 2600000, 49 2700000, 2850000, 2950000, 3000000 50}; 51 52static const unsigned int range_2v5_to_3v3[] = { 53 2500000, 2600000, 2700000, 2800000, 54 3000000, 3100000, 3200000, 3300000 55}; 56 57static const unsigned int range_2v6_to_3v3[] = { 58 2600000, 2700000, 2800000, 2900000, 59 3000000, 3100000, 3200000, 3300000 60}; 61 62/** 63 * HI6421V600_LDO() - specify a LDO power line 64 * @_id: LDO id name string 65 * @vtable: voltage table 66 * @ereg: enable register 67 * @emask: enable mask 68 * @vreg: voltage select register 69 * @odelay: off/on delay time in uS 70 * @etime: enable time in uS 71 * @ecomask: eco mode mask 72 * @ecoamp: eco mode load uppler limit in uA 73 */ 74#define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \ 75 odelay, etime, ecomask, ecoamp) \ 76 [hi6421v600_##_id] = { \ 77 .desc = { \ 78 .name = #_id, \ 79 .of_match = of_match_ptr(#_id), \ 80 .regulators_node = of_match_ptr("regulators"), \ 81 .ops = &hi6421_spmi_ldo_rops, \ 82 .type = REGULATOR_VOLTAGE, \ 83 .id = hi6421v600_##_id, \ 84 .owner = THIS_MODULE, \ 85 .volt_table = vtable, \ 86 .n_voltages = ARRAY_SIZE(vtable), \ 87 .vsel_mask = ARRAY_SIZE(vtable) - 1, \ 88 .vsel_reg = vreg, \ 89 .enable_reg = ereg, \ 90 .enable_mask = emask, \ 91 .enable_time = etime, \ 92 .ramp_delay = etime, \ 93 .off_on_delay = odelay, \ 94 }, \ 95 .eco_mode_mask = ecomask, \ 96 .eco_uA = ecoamp, \ 97 } 98 99static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) 100{ 101 struct hi6421_spmi_reg_priv *priv = rdev_get_drvdata(rdev); 102 int ret; 103 104 /* cannot enable more than one regulator at one time */ 105 mutex_lock(&priv->enable_mutex); 106 107 ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 108 rdev->desc->enable_mask, 109 rdev->desc->enable_mask); 110 111 /* Avoid powering up multiple devices at the same time */ 112 usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 60); 113 114 mutex_unlock(&priv->enable_mutex); 115 116 return ret; 117} 118 119static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) 120{ 121 struct hi6421_spmi_reg_info *sreg; 122 unsigned int reg_val; 123 124 sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc); 125 regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); 126 127 if (reg_val & sreg->eco_mode_mask) 128 return REGULATOR_MODE_IDLE; 129 130 return REGULATOR_MODE_NORMAL; 131} 132 133static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, 134 unsigned int mode) 135{ 136 struct hi6421_spmi_reg_info *sreg; 137 unsigned int val; 138 139 sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc); 140 switch (mode) { 141 case REGULATOR_MODE_NORMAL: 142 val = 0; 143 break; 144 case REGULATOR_MODE_IDLE: 145 if (!sreg->eco_mode_mask) 146 return -EINVAL; 147 148 val = sreg->eco_mode_mask; 149 break; 150 default: 151 return -EINVAL; 152 } 153 154 return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 155 sreg->eco_mode_mask, val); 156} 157 158static unsigned int 159hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, 160 int input_uV, int output_uV, 161 int load_uA) 162{ 163 struct hi6421_spmi_reg_info *sreg; 164 165 sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc); 166 167 if (!sreg->eco_uA || ((unsigned int)load_uA > sreg->eco_uA)) 168 return REGULATOR_MODE_NORMAL; 169 170 return REGULATOR_MODE_IDLE; 171} 172 173static const struct regulator_ops hi6421_spmi_ldo_rops = { 174 .is_enabled = regulator_is_enabled_regmap, 175 .enable = hi6421_spmi_regulator_enable, 176 .disable = regulator_disable_regmap, 177 .list_voltage = regulator_list_voltage_table, 178 .map_voltage = regulator_map_voltage_ascend, 179 .get_voltage_sel = regulator_get_voltage_sel_regmap, 180 .set_voltage_sel = regulator_set_voltage_sel_regmap, 181 .get_mode = hi6421_spmi_regulator_get_mode, 182 .set_mode = hi6421_spmi_regulator_set_mode, 183 .get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode, 184}; 185 186/* HI6421v600 regulators with known registers */ 187enum hi6421_spmi_regulator_id { 188 hi6421v600_ldo3, 189 hi6421v600_ldo4, 190 hi6421v600_ldo9, 191 hi6421v600_ldo15, 192 hi6421v600_ldo16, 193 hi6421v600_ldo17, 194 hi6421v600_ldo33, 195 hi6421v600_ldo34, 196}; 197 198static struct hi6421_spmi_reg_info regulator_info[] = { 199 HI6421V600_LDO(ldo3, range_1v5_to_2v0, 200 0x16, 0x01, 0x51, 201 20000, 120, 202 0, 0), 203 HI6421V600_LDO(ldo4, range_1v725_to_1v9, 204 0x17, 0x01, 0x52, 205 20000, 120, 206 0x10, 10000), 207 HI6421V600_LDO(ldo9, range_1v75_to_3v3, 208 0x1c, 0x01, 0x57, 209 20000, 360, 210 0x10, 10000), 211 HI6421V600_LDO(ldo15, range_1v8_to_3v0, 212 0x21, 0x01, 0x5c, 213 20000, 360, 214 0x10, 10000), 215 HI6421V600_LDO(ldo16, range_1v8_to_3v0, 216 0x22, 0x01, 0x5d, 217 20000, 360, 218 0x10, 10000), 219 HI6421V600_LDO(ldo17, range_2v5_to_3v3, 220 0x23, 0x01, 0x5e, 221 20000, 120, 222 0x10, 10000), 223 HI6421V600_LDO(ldo33, range_2v5_to_3v3, 224 0x32, 0x01, 0x6d, 225 20000, 120, 226 0, 0), 227 HI6421V600_LDO(ldo34, range_2v6_to_3v3, 228 0x33, 0x01, 0x6e, 229 20000, 120, 230 0, 0), 231}; 232 233static int hi6421_spmi_regulator_probe(struct platform_device *pdev) 234{ 235 struct device *pmic_dev = pdev->dev.parent; 236 struct regulator_config config = { }; 237 struct hi6421_spmi_reg_priv *priv; 238 struct hi6421_spmi_reg_info *info; 239 struct device *dev = &pdev->dev; 240 struct regmap *regmap; 241 struct regulator_dev *rdev; 242 int i; 243 244 /* 245 * This driver is meant to be called by hi6421-spmi-core, 246 * which should first set drvdata. If this doesn't happen, hit 247 * a warn on and return. 248 */ 249 regmap = dev_get_drvdata(pmic_dev); 250 if (WARN_ON(!regmap)) 251 return -ENODEV; 252 253 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 254 if (!priv) 255 return -ENOMEM; 256 257 mutex_init(&priv->enable_mutex); 258 259 for (i = 0; i < ARRAY_SIZE(regulator_info); i++) { 260 info = ®ulator_info[i]; 261 262 config.dev = pdev->dev.parent; 263 config.driver_data = priv; 264 config.regmap = regmap; 265 266 rdev = devm_regulator_register(dev, &info->desc, &config); 267 if (IS_ERR(rdev)) { 268 dev_err(dev, "failed to register %s\n", 269 info->desc.name); 270 return PTR_ERR(rdev); 271 } 272 } 273 274 return 0; 275} 276 277static const struct platform_device_id hi6421_spmi_regulator_table[] = { 278 { .name = "hi6421v600-regulator" }, 279 {}, 280}; 281MODULE_DEVICE_TABLE(platform, hi6421_spmi_regulator_table); 282 283static struct platform_driver hi6421_spmi_regulator_driver = { 284 .id_table = hi6421_spmi_regulator_table, 285 .driver = { 286 .name = "hi6421v600-regulator", 287 }, 288 .probe = hi6421_spmi_regulator_probe, 289}; 290module_platform_driver(hi6421_spmi_regulator_driver); 291 292MODULE_DESCRIPTION("Hi6421v600 SPMI regulator driver"); 293MODULE_LICENSE("GPL v2"); 294