Lines Matching +full:drv +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
29 #define SPM_CTL_INDEX 0x7f
31 #define SPM_CTL_EN BIT(0)
34 #define SPM_VCTL_VLVL GENMASK(7, 0)
35 #define SPM_PMIC_DATA_0_VLVL GENMASK(7, 0)
36 #define SPM_PMIC_DATA_1_MIN_VSEL GENMASK(5, 0)
91 [SPM_REG_AVS_CTL] = 0x904,
92 [SPM_REG_AVS_LIMIT] = 0x908,
97 .avs_ctl = 0x1010031,
98 .avs_limit = 0x4580458,
103 .avs_ctl = 0x101c031,
104 .avs_limit = 0x4580458,
109 .avs_ctl = 0x1010031,
110 .avs_limit = 0x4700470,
115 .avs_ctl = 0x1010031,
116 .avs_limit = 0x4200420,
120 [SPM_REG_CFG] = 0x08,
121 [SPM_REG_SPM_CTL] = 0x30,
122 [SPM_REG_DLY] = 0x34,
123 [SPM_REG_SEQ_ENTRY] = 0x400,
129 .spm_cfg = 0x1,
130 .spm_dly = 0x3C102800,
131 .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
132 0x5B, 0x60, 0x03, 0x60, 0x76, 0x76, 0x0B, 0x94, 0x5B, 0x80,
133 0x10, 0x26, 0x30, 0x0F },
134 .start_index[PM_SLEEP_MODE_STBY] = 0,
141 .spm_cfg = 0x1,
142 .spm_dly = 0x3C102800,
143 .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
144 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B,
145 0x80, 0x10, 0x26, 0x30, 0x0F },
146 .start_index[PM_SLEEP_MODE_STBY] = 0,
152 .spm_cfg = 0x1,
153 .spm_dly = 0x3C102800,
154 .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x50, 0x1B, 0x10, 0x80,
155 0x30, 0x90, 0x5B, 0x60, 0x50, 0x03, 0x60, 0x76, 0x76, 0x0B,
156 0x50, 0x1B, 0x94, 0x5B, 0x80, 0x10, 0x26, 0x30, 0x50, 0x0F },
157 .start_index[PM_SLEEP_MODE_STBY] = 0,
162 [SPM_REG_CFG] = 0x08,
163 [SPM_REG_SPM_CTL] = 0x30,
164 [SPM_REG_DLY] = 0x34,
165 [SPM_REG_PMIC_DATA_0] = 0x40,
166 [SPM_REG_PMIC_DATA_1] = 0x44,
172 .spm_cfg = 0x14,
173 .spm_dly = 0x3c11840a,
174 .pmic_data[0] = 0x03030080,
175 .pmic_data[1] = 0x00030000,
176 .start_index[PM_SLEEP_MODE_STBY] = 0,
182 .spm_cfg = 0x14,
183 .spm_dly = 0x3c102800,
184 .pmic_data[0] = 0x03030080,
185 .pmic_data[1] = 0x00030000,
186 .start_index[PM_SLEEP_MODE_STBY] = 0,
191 [SPM_REG_CFG] = 0x08,
192 [SPM_REG_SPM_CTL] = 0x30,
193 [SPM_REG_DLY] = 0x34,
194 [SPM_REG_SEQ_ENTRY] = 0x80,
200 .spm_cfg = 0x1,
201 .spm_dly = 0x3C102800,
202 .seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03,
203 0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30,
204 0x0F },
205 .start_index[PM_SLEEP_MODE_STBY] = 0,
212 .spm_cfg = 0x0,
213 .spm_dly = 0x3C102800,
214 .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
215 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B,
216 0x80, 0x10, 0x26, 0x30, 0x0F },
217 .start_index[PM_SLEEP_MODE_STBY] = 0,
222 [SPM_REG_CFG] = 0x08,
223 [SPM_REG_STS0] = 0x0c,
224 [SPM_REG_STS1] = 0x10,
225 [SPM_REG_VCTL] = 0x14,
226 [SPM_REG_AVS_CTL] = 0x18,
227 [SPM_REG_SPM_CTL] = 0x20,
228 [SPM_REG_PMIC_DLY] = 0x24,
229 [SPM_REG_PMIC_DATA_0] = 0x28,
230 [SPM_REG_PMIC_DATA_1] = 0x2C,
231 [SPM_REG_SEQ_ENTRY] = 0x80,
238 REGULATOR_LINEAR_RANGE(700000, 0, 56, 12500);
242 .spm_cfg = 0x1F,
243 .pmic_dly = 0x02020004,
244 .pmic_data[0] = 0x0084009C,
245 .pmic_data[1] = 0x00A4001C,
246 .seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01,
247 0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F },
248 .start_index[PM_SLEEP_MODE_STBY] = 0,
256 static inline void spm_register_write(struct spm_driver_data *drv, in spm_register_write() argument
259 if (drv->reg_data->reg_offset[reg]) in spm_register_write()
260 writel_relaxed(val, drv->reg_base + in spm_register_write()
261 drv->reg_data->reg_offset[reg]); in spm_register_write()
265 static inline void spm_register_write_sync(struct spm_driver_data *drv, in spm_register_write_sync() argument
270 if (!drv->reg_data->reg_offset[reg]) in spm_register_write_sync()
274 writel_relaxed(val, drv->reg_base + in spm_register_write_sync()
275 drv->reg_data->reg_offset[reg]); in spm_register_write_sync()
276 ret = readl_relaxed(drv->reg_base + in spm_register_write_sync()
277 drv->reg_data->reg_offset[reg]); in spm_register_write_sync()
284 static inline u32 spm_register_read(struct spm_driver_data *drv, in spm_register_read() argument
287 return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]); in spm_register_read()
290 void spm_set_low_power_mode(struct spm_driver_data *drv, in spm_set_low_power_mode() argument
296 start_index = drv->reg_data->start_index[mode]; in spm_set_low_power_mode()
298 ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL); in spm_set_low_power_mode()
302 spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val); in spm_set_low_power_mode()
307 struct spm_driver_data *drv = rdev_get_drvdata(rdev); in spm_set_voltage_sel() local
309 drv->volt_sel = selector; in spm_set_voltage_sel()
312 return smp_call_function_single(drv->reg_cpu, drv->reg_data->set_vdd, drv, true); in spm_set_voltage_sel()
317 struct spm_driver_data *drv = rdev_get_drvdata(rdev); in spm_get_voltage_sel() local
319 return drv->volt_sel; in spm_get_voltage_sel()
331 struct spm_driver_data *drv = data; in smp_set_vdd_v1_1() local
336 volt_sel = drv->volt_sel; in smp_set_vdd_v1_1()
337 vlevel = volt_sel | 0x80; /* band */ in smp_set_vdd_v1_1()
339 avs_ctl = spm_register_read(drv, SPM_REG_AVS_CTL); in smp_set_vdd_v1_1()
340 vctl = spm_register_read(drv, SPM_REG_VCTL); in smp_set_vdd_v1_1()
341 data0 = spm_register_read(drv, SPM_REG_PMIC_DATA_0); in smp_set_vdd_v1_1()
342 data1 = spm_register_read(drv, SPM_REG_PMIC_DATA_1); in smp_set_vdd_v1_1()
349 spm_register_write(drv, SPM_REG_AVS_CTL, avs_ctl); in smp_set_vdd_v1_1()
353 spm_register_write(drv, SPM_REG_RST, 1); in smp_set_vdd_v1_1()
360 spm_register_write(drv, SPM_REG_VCTL, vctl); in smp_set_vdd_v1_1()
361 spm_register_write(drv, SPM_REG_PMIC_DATA_0, data0); in smp_set_vdd_v1_1()
362 spm_register_write(drv, SPM_REG_PMIC_DATA_1, data1); in smp_set_vdd_v1_1()
367 drv, SPM_REG_STS1)) { in smp_set_vdd_v1_1()
368 dev_err_ratelimited(drv->dev, "timeout setting the voltage (%x %x)!\n", sts, vlevel); in smp_set_vdd_v1_1()
374 unsigned int min_avs = max(max_avs, 4U) - 4; in smp_set_vdd_v1_1()
378 spm_register_write(drv, SPM_REG_AVS_CTL, avs_ctl); in smp_set_vdd_v1_1()
384 spm_register_write(drv, SPM_REG_AVS_CTL, avs_ctl); in smp_set_vdd_v1_1()
400 saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); in spm_get_cpu()
401 found = (saw_node == dev->of_node); in spm_get_cpu()
411 return -EOPNOTSUPP; in spm_get_cpu()
414 static int spm_register_regulator(struct device *dev, struct spm_driver_data *drv) in spm_register_regulator() argument
418 .driver_data = drv, in spm_register_regulator()
425 if (!drv->reg_data->set_vdd) in spm_register_regulator()
426 return 0; in spm_register_regulator()
430 return -ENOMEM; in spm_register_regulator()
432 rdesc->name = "spm"; in spm_register_regulator()
433 rdesc->of_match = of_match_ptr("regulator"); in spm_register_regulator()
434 rdesc->type = REGULATOR_VOLTAGE; in spm_register_regulator()
435 rdesc->owner = THIS_MODULE; in spm_register_regulator()
436 rdesc->ops = &spm_reg_ops; in spm_register_regulator()
438 rdesc->linear_ranges = drv->reg_data->range; in spm_register_regulator()
439 rdesc->n_linear_ranges = 1; in spm_register_regulator()
440 rdesc->n_voltages = rdesc->linear_ranges[rdesc->n_linear_ranges - 1].max_sel + 1; in spm_register_regulator()
441 rdesc->ramp_delay = drv->reg_data->ramp_delay; in spm_register_regulator()
444 if (ret < 0) in spm_register_regulator()
447 drv->reg_cpu = ret; in spm_register_regulator()
448 dev_dbg(dev, "SAW2 bound to CPU %d\n", drv->reg_cpu); in spm_register_regulator()
454 drv->volt_sel = DIV_ROUND_UP(drv->reg_data->init_uV - rdesc->min_uV, in spm_register_regulator()
455 rdesc->uV_step); in spm_register_regulator()
456 ret = linear_range_get_selector_high(drv->reg_data->range, in spm_register_regulator()
457 drv->reg_data->init_uV, in spm_register_regulator()
458 &drv->volt_sel, in spm_register_regulator()
466 smp_call_function_single(drv->reg_cpu, drv->reg_data->set_vdd, drv, true); in spm_register_regulator()
474 return 0; in spm_register_regulator()
478 { .compatible = "qcom,sdm660-gold-saw2-v4.1-l2",
480 { .compatible = "qcom,sdm660-silver-saw2-v4.1-l2",
482 { .compatible = "qcom,msm8226-saw2-v2.1-cpu",
484 { .compatible = "qcom,msm8909-saw2-v3.0-cpu",
486 { .compatible = "qcom,msm8916-saw2-v3.0-cpu",
488 { .compatible = "qcom,msm8939-saw2-v3.0-cpu",
490 { .compatible = "qcom,msm8974-saw2-v2.1-cpu",
492 { .compatible = "qcom,msm8976-gold-saw2-v2.3-l2",
494 { .compatible = "qcom,msm8976-silver-saw2-v2.3-l2",
496 { .compatible = "qcom,msm8998-gold-saw2-v4.1-l2",
498 { .compatible = "qcom,msm8998-silver-saw2-v4.1-l2",
500 { .compatible = "qcom,apq8084-saw2-v2.1-cpu",
502 { .compatible = "qcom,apq8064-saw2-v1.1-cpu",
511 struct spm_driver_data *drv; in spm_dev_probe() local
514 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); in spm_dev_probe()
515 if (!drv) in spm_dev_probe()
516 return -ENOMEM; in spm_dev_probe()
518 drv->reg_base = devm_platform_ioremap_resource(pdev, 0); in spm_dev_probe()
519 if (IS_ERR(drv->reg_base)) in spm_dev_probe()
520 return PTR_ERR(drv->reg_base); in spm_dev_probe()
522 match_id = of_match_node(spm_match_table, pdev->dev.of_node); in spm_dev_probe()
524 return -ENODEV; in spm_dev_probe()
526 drv->reg_data = match_id->data; in spm_dev_probe()
527 drv->dev = &pdev->dev; in spm_dev_probe()
528 platform_set_drvdata(pdev, drv); in spm_dev_probe()
531 addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY]; in spm_dev_probe()
532 __iowrite32_copy(addr, drv->reg_data->seq, in spm_dev_probe()
533 ARRAY_SIZE(drv->reg_data->seq) / 4); in spm_dev_probe()
541 spm_register_write(drv, SPM_REG_AVS_CTL, drv->reg_data->avs_ctl); in spm_dev_probe()
542 spm_register_write(drv, SPM_REG_AVS_LIMIT, drv->reg_data->avs_limit); in spm_dev_probe()
543 spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); in spm_dev_probe()
544 spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); in spm_dev_probe()
545 spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); in spm_dev_probe()
546 spm_register_write(drv, SPM_REG_PMIC_DATA_0, in spm_dev_probe()
547 drv->reg_data->pmic_data[0]); in spm_dev_probe()
548 spm_register_write(drv, SPM_REG_PMIC_DATA_1, in spm_dev_probe()
549 drv->reg_data->pmic_data[1]); in spm_dev_probe()
552 if (drv->reg_data->reg_offset[SPM_REG_SPM_CTL]) in spm_dev_probe()
553 spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); in spm_dev_probe()
556 return spm_register_regulator(&pdev->dev, drv); in spm_dev_probe()
558 return 0; in spm_dev_probe()