Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 302 lines 8.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2// 3// Copyright (c) 2021 MediaTek Inc. 4 5#include <linux/module.h> 6#include <linux/of.h> 7#include <linux/regmap.h> 8#include <linux/regulator/driver.h> 9#include <linux/regulator/machine.h> 10#include <linux/regulator/mt6315-regulator.h> 11#include <linux/regulator/of_regulator.h> 12#include <linux/spmi.h> 13 14#define MT6315_BUCK_MODE_AUTO 0 15#define MT6315_BUCK_MODE_FORCE_PWM 1 16#define MT6315_BUCK_MODE_LP 2 17 18struct mt6315_regulator_info { 19 struct regulator_desc desc; 20 u32 status_reg; 21 u32 lp_mode_mask; 22 u32 lp_mode_shift; 23}; 24 25struct mt_regulator_init_data { 26 u32 modeset_mask[MT6315_VBUCK_MAX]; 27}; 28 29struct mt6315_chip { 30 struct device *dev; 31 struct regmap *regmap; 32}; 33 34#define MT_BUCK(_name, _bid, _supply, _vsel) \ 35[_bid] = { \ 36 .desc = { \ 37 .name = _name, \ 38 .supply_name = _supply, \ 39 .of_match = of_match_ptr(_name), \ 40 .regulators_node = "regulators", \ 41 .ops = &mt6315_volt_range_ops, \ 42 .type = REGULATOR_VOLTAGE, \ 43 .id = _bid, \ 44 .owner = THIS_MODULE, \ 45 .n_voltages = 0xc0, \ 46 .linear_ranges = mt_volt_range1, \ 47 .n_linear_ranges = ARRAY_SIZE(mt_volt_range1), \ 48 .vsel_reg = _vsel, \ 49 .vsel_mask = 0xff, \ 50 .enable_reg = MT6315_BUCK_TOP_CON0, \ 51 .enable_mask = BIT(_bid), \ 52 .of_map_mode = mt6315_map_mode, \ 53 }, \ 54 .status_reg = _bid##_DBG4, \ 55 .lp_mode_mask = BIT(_bid), \ 56 .lp_mode_shift = _bid, \ 57} 58 59static const struct linear_range mt_volt_range1[] = { 60 REGULATOR_LINEAR_RANGE(0, 0, 0xbf, 6250), 61}; 62 63static unsigned int mt6315_map_mode(unsigned int mode) 64{ 65 switch (mode) { 66 case MT6315_BUCK_MODE_AUTO: 67 return REGULATOR_MODE_NORMAL; 68 case MT6315_BUCK_MODE_FORCE_PWM: 69 return REGULATOR_MODE_FAST; 70 case MT6315_BUCK_MODE_LP: 71 return REGULATOR_MODE_IDLE; 72 default: 73 return REGULATOR_MODE_INVALID; 74 } 75} 76 77static unsigned int mt6315_regulator_get_mode(struct regulator_dev *rdev) 78{ 79 struct mt_regulator_init_data *init = rdev_get_drvdata(rdev); 80 const struct mt6315_regulator_info *info; 81 int ret, regval; 82 u32 modeset_mask; 83 84 info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc); 85 modeset_mask = init->modeset_mask[rdev_get_id(rdev)]; 86 ret = regmap_read(rdev->regmap, MT6315_BUCK_TOP_4PHASE_ANA_CON42, &regval); 87 if (ret != 0) { 88 dev_err(&rdev->dev, "Failed to get mode: %d\n", ret); 89 return ret; 90 } 91 92 if ((regval & modeset_mask) == modeset_mask) 93 return REGULATOR_MODE_FAST; 94 95 ret = regmap_read(rdev->regmap, MT6315_BUCK_TOP_CON1, &regval); 96 if (ret != 0) { 97 dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret); 98 return ret; 99 } 100 101 if (regval & info->lp_mode_mask) 102 return REGULATOR_MODE_IDLE; 103 else 104 return REGULATOR_MODE_NORMAL; 105} 106 107static int mt6315_regulator_set_mode(struct regulator_dev *rdev, 108 u32 mode) 109{ 110 struct mt_regulator_init_data *init = rdev_get_drvdata(rdev); 111 const struct mt6315_regulator_info *info; 112 int ret, val, curr_mode; 113 u32 modeset_mask; 114 115 info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc); 116 modeset_mask = init->modeset_mask[rdev_get_id(rdev)]; 117 curr_mode = mt6315_regulator_get_mode(rdev); 118 switch (mode) { 119 case REGULATOR_MODE_FAST: 120 ret = regmap_update_bits(rdev->regmap, 121 MT6315_BUCK_TOP_4PHASE_ANA_CON42, 122 modeset_mask, 123 modeset_mask); 124 break; 125 case REGULATOR_MODE_NORMAL: 126 if (curr_mode == REGULATOR_MODE_FAST) { 127 ret = regmap_update_bits(rdev->regmap, 128 MT6315_BUCK_TOP_4PHASE_ANA_CON42, 129 modeset_mask, 130 0); 131 } else if (curr_mode == REGULATOR_MODE_IDLE) { 132 ret = regmap_update_bits(rdev->regmap, 133 MT6315_BUCK_TOP_CON1, 134 info->lp_mode_mask, 135 0); 136 usleep_range(100, 110); 137 } else { 138 ret = -EINVAL; 139 } 140 break; 141 case REGULATOR_MODE_IDLE: 142 val = MT6315_BUCK_MODE_LP >> 1; 143 val <<= info->lp_mode_shift; 144 ret = regmap_update_bits(rdev->regmap, 145 MT6315_BUCK_TOP_CON1, 146 info->lp_mode_mask, 147 val); 148 break; 149 default: 150 ret = -EINVAL; 151 dev_err(&rdev->dev, "Unsupported mode: %d\n", mode); 152 break; 153 } 154 155 if (ret != 0) { 156 dev_err(&rdev->dev, "Failed to set mode: %d\n", ret); 157 return ret; 158 } 159 160 return 0; 161} 162 163static int mt6315_get_status(struct regulator_dev *rdev) 164{ 165 const struct mt6315_regulator_info *info; 166 int ret; 167 u32 regval; 168 169 info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc); 170 ret = regmap_read(rdev->regmap, info->status_reg, &regval); 171 if (ret < 0) { 172 dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret); 173 return ret; 174 } 175 176 return (regval & BIT(0)) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF; 177} 178 179static const struct regulator_ops mt6315_volt_range_ops = { 180 .list_voltage = regulator_list_voltage_linear_range, 181 .map_voltage = regulator_map_voltage_linear_range, 182 .set_voltage_sel = regulator_set_voltage_sel_regmap, 183 .get_voltage_sel = regulator_get_voltage_sel_regmap, 184 .set_voltage_time_sel = regulator_set_voltage_time_sel, 185 .enable = regulator_enable_regmap, 186 .disable = regulator_disable_regmap, 187 .is_enabled = regulator_is_enabled_regmap, 188 .get_status = mt6315_get_status, 189 .set_mode = mt6315_regulator_set_mode, 190 .get_mode = mt6315_regulator_get_mode, 191}; 192 193static const struct mt6315_regulator_info mt6315_regulators[MT6315_VBUCK_MAX] = { 194 MT_BUCK("vbuck1", MT6315_VBUCK1, "pvdd1", MT6315_BUCK_TOP_ELR0), 195 MT_BUCK("vbuck2", MT6315_VBUCK2, "pvdd2", MT6315_BUCK_TOP_ELR2), 196 MT_BUCK("vbuck3", MT6315_VBUCK3, "pvdd3", MT6315_BUCK_TOP_ELR4), 197 MT_BUCK("vbuck4", MT6315_VBUCK4, "pvdd4", MT6315_BUCK_TOP_ELR6), 198}; 199 200static const struct regmap_config mt6315_regmap_config = { 201 .reg_bits = 16, 202 .val_bits = 8, 203 .max_register = 0x16d0, 204 .fast_io = true, 205}; 206 207static const struct of_device_id mt6315_of_match[] = { 208 { 209 .compatible = "mediatek,mt6315-regulator", 210 }, { 211 /* sentinel */ 212 }, 213}; 214MODULE_DEVICE_TABLE(of, mt6315_of_match); 215 216static int mt6315_regulator_probe(struct spmi_device *pdev) 217{ 218 struct device *dev = &pdev->dev; 219 struct regmap *regmap; 220 struct mt6315_chip *chip; 221 struct mt_regulator_init_data *init_data; 222 struct regulator_config config = {}; 223 struct regulator_dev *rdev; 224 int i; 225 226 regmap = devm_regmap_init_spmi_ext(pdev, &mt6315_regmap_config); 227 if (IS_ERR(regmap)) 228 return PTR_ERR(regmap); 229 230 chip = devm_kzalloc(dev, sizeof(struct mt6315_chip), GFP_KERNEL); 231 if (!chip) 232 return -ENOMEM; 233 234 init_data = devm_kzalloc(dev, sizeof(struct mt_regulator_init_data), GFP_KERNEL); 235 if (!init_data) 236 return -ENOMEM; 237 238 switch (pdev->usid) { 239 case MT6315_PP: 240 init_data->modeset_mask[MT6315_VBUCK1] = BIT(MT6315_VBUCK1) | BIT(MT6315_VBUCK2) | 241 BIT(MT6315_VBUCK4); 242 break; 243 case MT6315_SP: 244 case MT6315_RP: 245 init_data->modeset_mask[MT6315_VBUCK1] = BIT(MT6315_VBUCK1) | BIT(MT6315_VBUCK2); 246 break; 247 default: 248 init_data->modeset_mask[MT6315_VBUCK1] = BIT(MT6315_VBUCK1); 249 break; 250 } 251 for (i = MT6315_VBUCK2; i < MT6315_VBUCK_MAX; i++) 252 init_data->modeset_mask[i] = BIT(i); 253 254 chip->dev = dev; 255 chip->regmap = regmap; 256 dev_set_drvdata(dev, chip); 257 258 config.dev = dev; 259 config.regmap = regmap; 260 for (i = MT6315_VBUCK1; i < MT6315_VBUCK_MAX; i++) { 261 config.driver_data = init_data; 262 rdev = devm_regulator_register(dev, &mt6315_regulators[i].desc, &config); 263 if (IS_ERR(rdev)) { 264 dev_err(dev, "Failed to register %s\n", 265 mt6315_regulators[i].desc.name); 266 return PTR_ERR(rdev); 267 } 268 } 269 270 return 0; 271} 272 273static void mt6315_regulator_shutdown(struct spmi_device *pdev) 274{ 275 struct mt6315_chip *chip = dev_get_drvdata(&pdev->dev); 276 int ret = 0; 277 278 ret |= regmap_write(chip->regmap, MT6315_TOP_TMA_KEY_H, PROTECTION_KEY_H); 279 ret |= regmap_write(chip->regmap, MT6315_TOP_TMA_KEY, PROTECTION_KEY); 280 ret |= regmap_update_bits(chip->regmap, MT6315_TOP2_ELR7, 1, 1); 281 ret |= regmap_write(chip->regmap, MT6315_TOP_TMA_KEY, 0); 282 ret |= regmap_write(chip->regmap, MT6315_TOP_TMA_KEY_H, 0); 283 if (ret < 0) 284 dev_err(&pdev->dev, "[%#x] Failed to enable power off sequence. %d\n", 285 pdev->usid, ret); 286} 287 288static struct spmi_driver mt6315_regulator_driver = { 289 .driver = { 290 .name = "mt6315-regulator", 291 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 292 .of_match_table = mt6315_of_match, 293 }, 294 .probe = mt6315_regulator_probe, 295 .shutdown = mt6315_regulator_shutdown, 296}; 297 298module_spmi_driver(mt6315_regulator_driver); 299 300MODULE_AUTHOR("Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>"); 301MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6315 PMIC"); 302MODULE_LICENSE("GPL");