Loading arch/arm/boot/dts/qcom/msm8909w-pm660-regulator.dtsi +96 −10 Original line number Diff line number Diff line Loading @@ -10,16 +10,6 @@ * GNU General Public License for more details. */ /* CPR controlled regulator */ &soc { apc_vreg_corner: regulator-apc-corner { compatible = "qcom,stub-regulator"; regulator-name = "apc_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <3>; }; }; &rpm_bus { /* CX supply */ rpm-regulator-smpa2 { Loading Loading @@ -315,3 +305,99 @@ }; }; }; /* SPM controlled regulators */ &spmi_bus { qcom,pm660@1 { pm660_s1: spm-regulator@1400 { compatible = "qcom,spm-regulator"; regulator-name = "pm660_s1"; reg = <0x1400 0x100>; regulator-min-microvolt = <1052000>; regulator-max-microvolt = <1352000>; /* TODO: remove after SAW support is enabled */ qcom,bypass-spm; }; }; }; /* CPR controlled regulator */ &soc { mem_acc_vreg_corner: regulator@1942130 { compatible = "qcom,mem-acc-regulator"; reg = <0x1942130 0x4>; reg-names = "acc-sel-l1"; regulator-name = "mem_acc_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <3>; qcom,acc-sel-l1-bit-pos = <0>; qcom,corner-acc-map = <0 1 1>; }; apc_vreg_corner: regulator@b018000 { compatible = "qcom,cpr-regulator"; reg = <0xb018000 0x1000>, <0xb011064 4>, <0x58000 0x1000>; reg-names = "rbcpr", "rbcpr_clk", "efuse_addr"; interrupts = <0 15 0>; regulator-name = "apc_corner"; qcom,cpr-fuse-corners = <3>; regulator-min-microvolt = <1>; regulator-max-microvolt = <9>; qcom,cpr-voltage-ceiling = <1052000 1228000 1352000>; qcom,cpr-voltage-floor = <1052000 1052000 1156000>; vdd-apc-supply = <&pm660_s1>; qcom,vdd-mx-corner-map = <4 5 7>; qcom,vdd-mx-vmin-method = <4>; vdd-mx-supply = <&pm660_s3_corner_ao>; qcom,vdd-mx-vmax = <7>; mem-acc-supply = <&mem_acc_vreg_corner>; qcom,cpr-ref-clk = <19200>; qcom,cpr-timer-delay = <5000>; qcom,cpr-timer-cons-up = <0>; qcom,cpr-timer-cons-down = <2>; qcom,cpr-irq-line = <0>; qcom,cpr-step-quotient = <10>; qcom,cpr-up-threshold = <0>; qcom,cpr-down-threshold = <2>; qcom,cpr-idle-clocks = <15>; qcom,cpr-gcnt-time = <1>; qcom,vdd-apc-step-up-limit = <1>; qcom,vdd-apc-step-down-limit = <1>; qcom,cpr-apc-volt-step = <4000>; qcom,cpr-fuse-row = <26 0>; qcom,cpr-fuse-target-quot = <42 24 6>; qcom,cpr-fuse-ro-sel = <61 61 54>; qcom,cpr-fuse-bp-cpr-disable = <58>; qcom,cpr-fuse-init-voltage = <26 36 6 0>, <26 18 6 0>, <26 0 6 0>; qcom,cpr-fuse-revision = <26 59 2 0>; qcom,cpr-init-voltage-ref = <1052000 1228000 1352000>; qcom,cpr-init-voltage-step = <10000>; qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>; qcom,cpr-init-voltage-as-ceiling; qcom,cpr-corner-frequency-map = <1 200000000>, <2 400000000>, <3 533330000>, <4 800000000>, <5 998400000>, <6 1094400000>, <7 1190400000>, <8 1248000000>, <9 1267200000>; qcom,speed-bin-fuse-sel = <1 34 3 0>; qcom,cpr-speed-bin-max-corners = <0 (-1) 2 4 9>, <2 (-1) 2 4 6>; qcom,cpr-quot-adjust-scaling-factor-max = <1400>; }; }; drivers/regulator/spm-regulator.c +110 −30 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -47,6 +47,7 @@ enum qpnp_regulator_uniq_type { QPNP_TYPE_HF, QPNP_TYPE_FTS2, QPNP_TYPE_FTS2p5, QPNP_TYPE_FTS426, QPNP_TYPE_ULT_HF, }; Loading @@ -54,6 +55,7 @@ enum qpnp_regulator_type { QPNP_HF_TYPE = 0x03, QPNP_FTS2_TYPE = 0x1C, QPNP_FTS2p5_TYPE = 0x1C, QPNP_FTS426_TYPE = 0x1C, QPNP_ULT_HF_TYPE = 0x22, }; Loading @@ -61,6 +63,7 @@ enum qpnp_regulator_subtype { QPNP_FTS2_SUBTYPE = 0x08, QPNP_HF_SUBTYPE = 0x08, QPNP_FTS2p5_SUBTYPE = 0x09, QPNP_FTS426_SUBTYPE = 0x0A, QPNP_ULT_HF_SUBTYPE = 0x0D, }; Loading @@ -70,6 +73,7 @@ static const struct voltage_range fts2p5_range0 = { 80000, 350000, 1355000, 5000}; static const struct voltage_range fts2p5_range1 = {160000, 700000, 2200000, 10000}; static const struct voltage_range fts426_range = {0, 320000, 1352000, 4000}; static const struct voltage_range ult_hf_range0 = {375000, 375000, 1562500, 12500}; static const struct voltage_range ult_hf_range1 = {750000, 750000, 1525000, Loading @@ -85,6 +89,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_REG_MODE 0x45 #define QPNP_SMPS_REG_STEP_CTRL 0x61 /* FTS426 voltage control registers */ #define QPNP_FTS426_REG_VOLTAGE_LB 0x40 #define QPNP_FTS426_REG_VOLTAGE_UB 0x41 #define QPNP_FTS426_REG_VOLTAGE_VALID_LB 0x42 #define QPNP_FTS426_REG_VOLTAGE_VALID_UB 0x43 #define QPNP_SMPS_MODE_PWM 0x80 #define QPNP_SMPS_MODE_AUTO 0x40 Loading @@ -92,9 +102,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_STEP_CTRL_STEP_SHIFT 3 #define QPNP_SMPS_STEP_CTRL_DELAY_MASK 0x07 #define QPNP_SMPS_STEP_CTRL_DELAY_SHIFT 0 #define QPNP_FTS426_STEP_CTRL_DELAY_MASK 0x03 #define QPNP_FTS426_STEP_CTRL_DELAY_SHIFT 0 /* Clock rate in kHz of the FTS2 regulator reference clock. */ #define QPNP_SMPS_CLOCK_RATE 19200 #define QPNP_FTS426_CLOCK_RATE 4800 /* Time to delay in us to ensure that a mode change has completed. */ #define QPNP_FTS2_MODE_CHANGE_DELAY 50 Loading @@ -105,6 +118,7 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, /* Minimum voltage stepper delay for each step. */ #define QPNP_FTS2_STEP_DELAY 8 #define QPNP_HF_STEP_DELAY 20 #define QPNP_FTS426_STEP_DELAY 2 /* Arbitrarily large max step size used to avoid possible numerical overflow */ #define SPM_REGULATOR_MAX_STEP_UV 10000000 Loading @@ -115,6 +129,8 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, */ #define QPNP_FTS2_STEP_MARGIN_NUM 4 #define QPNP_FTS2_STEP_MARGIN_DEN 5 #define QPNP_FTS426_STEP_MARGIN_NUM 10 #define QPNP_FTS426_STEP_MARGIN_DEN 11 /* * Settling delay for FTS2.5 Loading Loading @@ -160,6 +176,9 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) { int vlevel; if (vreg->regulator_type == QPNP_TYPE_FTS426) return roundup(uV, vreg->range->step_uV) / 1000; vlevel = DIV_ROUND_UP(uV - vreg->range->min_uV, vreg->range->step_uV); /* Fix VSET for ULT HF Buck */ Loading @@ -174,6 +193,8 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) static int spm_regulator_vlevel_to_uv(struct spm_vreg *vreg, int vlevel) { if (vreg->regulator_type == QPNP_TYPE_FTS426) return vlevel * 1000; /* * Calculate ULT HF buck VSET based on range: * In case of range 0: VSET is a 7 bit value. Loading Loading @@ -201,19 +222,63 @@ static unsigned spm_regulator_vlevel_to_selector(struct spm_vreg *vreg, static int qpnp_smps_read_voltage(struct spm_vreg *vreg) { int rc; u8 reg = 0; u8 reg[2] = {0,}; rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, ®, 1); if (vreg->regulator_type == QPNP_TYPE_FTS426) { rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_VALID_LB, reg, 2); if (rc) { dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n", dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint registers, rc=%d\n", __func__, rc); return rc; } vreg->last_set_vlevel = reg; vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, reg); vreg->last_set_vlevel = (reg[1] << 8) | reg[0]; } else { rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, reg, 1); if (rc) { dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n", __func__, rc); return rc; } vreg->last_set_vlevel = reg[0]; } vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, vreg->last_set_vlevel); return rc; } static int qpnp_smps_write_voltage(struct spm_vreg *vreg, unsigned vlevel) { int rc = 0; u8 reg[2]; /* Set voltage control registers via SPMI. */ reg[0] = vlevel & 0xFF; reg[1] = (vlevel >> 8) & 0xFF; if (vreg->regulator_type == QPNP_TYPE_FTS426) { rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_LB, reg, 2); } else { rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, reg, 1); } if (rc) pr_err("%s: spmi_ext_register_writel failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } Loading Loading @@ -267,7 +332,6 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) bool spm_failed = false; int rc = 0; u32 slew_delay; u8 reg; if (likely(!vreg->bypass_spm)) { /* Set voltage control register via SPM. */ Loading @@ -280,14 +344,9 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) } if (unlikely(vreg->bypass_spm || spm_failed)) { /* Set voltage control register via SPMI. */ reg = vlevel; rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, ®, 1); rc = qpnp_smps_write_voltage(vreg, vlevel); if (rc) { pr_err("%s: spmi_ext_register_writel failed, rc=%d\n", pr_err("%s: voltage write failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } Loading Loading @@ -531,7 +590,7 @@ static int spm_regulator_avs_set_voltage(struct regulator_dev *rdev, int min_uV, return -EINVAL; } vlevel_max = (uV - range->min_uV) / range->step_uV; vlevel_max = spm_regulator_uv_to_vlevel(vreg, uV); avs_max_uV = spm_regulator_vlevel_to_uv(vreg, vlevel_max); if (avs_max_uV < min_uV) { Loading Loading @@ -636,6 +695,9 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg) } else if (type[0] == QPNP_FTS2p5_TYPE && type[1] == QPNP_FTS2p5_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_FTS2p5; } else if (type[0] == QPNP_FTS426_TYPE && type[1] == QPNP_FTS426_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_FTS426; } else if (type[0] == QPNP_ULT_HF_TYPE && type[1] == QPNP_ULT_HF_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_ULT_HF; Loading Loading @@ -776,24 +838,39 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) return rc; } /* ULT buck does not support steps */ if (vreg->regulator_type != QPNP_TYPE_ULT_HF) /* ULT and FTS426 bucks do not support steps */ if (vreg->regulator_type != QPNP_TYPE_ULT_HF && vreg->regulator_type != QPNP_TYPE_FTS426) step = (reg & QPNP_SMPS_STEP_CTRL_STEP_MASK) >> QPNP_SMPS_STEP_CTRL_STEP_SHIFT; if (vreg->regulator_type == QPNP_TYPE_FTS426) { delay = (reg & QPNP_FTS426_STEP_CTRL_DELAY_MASK) >> QPNP_FTS426_STEP_CTRL_DELAY_SHIFT; /* step_rate has units of uV/us. */ vreg->step_rate = QPNP_FTS426_CLOCK_RATE * vreg->range->step_uV; } else { delay = (reg & QPNP_SMPS_STEP_CTRL_DELAY_MASK) >> QPNP_SMPS_STEP_CTRL_DELAY_SHIFT; /* step_rate has units of uV/us. */ vreg->step_rate = QPNP_SMPS_CLOCK_RATE * vreg->range->step_uV * (1 << step); } if ((vreg->regulator_type == QPNP_TYPE_ULT_HF) || (vreg->regulator_type == QPNP_TYPE_HF)) vreg->step_rate /= 1000 * (QPNP_HF_STEP_DELAY << delay); else if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->step_rate /= 1000 * (QPNP_FTS426_STEP_DELAY << delay); else vreg->step_rate /= 1000 * (QPNP_FTS2_STEP_DELAY << delay); if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->step_rate = vreg->step_rate * QPNP_FTS426_STEP_MARGIN_NUM / QPNP_FTS426_STEP_MARGIN_DEN; else vreg->step_rate = vreg->step_rate * QPNP_FTS2_STEP_MARGIN_NUM / QPNP_FTS2_STEP_MARGIN_DEN; Loading @@ -806,7 +883,8 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) static bool spm_regulator_using_range0(struct spm_vreg *vreg) { return vreg->range == &fts2_range0 || vreg->range == &fts2p5_range0 || vreg->range == &ult_hf_range0 || vreg->range == &hf_range0; || vreg->range == &ult_hf_range0 || vreg->range == &hf_range0 || vreg->range == &fts426_range; } /* Register a regulator to enable/disable AVS and set AVS min/max limits. */ Loading Loading @@ -937,6 +1015,8 @@ static int spm_regulator_probe(struct spmi_device *spmi) rc = qpnp_smps_init_range(vreg, &fts2_range0, &fts2_range1); else if (vreg->regulator_type == QPNP_TYPE_FTS2p5) rc = qpnp_smps_init_range(vreg, &fts2p5_range0, &fts2p5_range1); else if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->range = &fts426_range; else if (vreg->regulator_type == QPNP_TYPE_HF) rc = qpnp_smps_init_range(vreg, &hf_range0, &hf_range1); else if (vreg->regulator_type == QPNP_TYPE_ULT_HF) Loading Loading
arch/arm/boot/dts/qcom/msm8909w-pm660-regulator.dtsi +96 −10 Original line number Diff line number Diff line Loading @@ -10,16 +10,6 @@ * GNU General Public License for more details. */ /* CPR controlled regulator */ &soc { apc_vreg_corner: regulator-apc-corner { compatible = "qcom,stub-regulator"; regulator-name = "apc_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <3>; }; }; &rpm_bus { /* CX supply */ rpm-regulator-smpa2 { Loading Loading @@ -315,3 +305,99 @@ }; }; }; /* SPM controlled regulators */ &spmi_bus { qcom,pm660@1 { pm660_s1: spm-regulator@1400 { compatible = "qcom,spm-regulator"; regulator-name = "pm660_s1"; reg = <0x1400 0x100>; regulator-min-microvolt = <1052000>; regulator-max-microvolt = <1352000>; /* TODO: remove after SAW support is enabled */ qcom,bypass-spm; }; }; }; /* CPR controlled regulator */ &soc { mem_acc_vreg_corner: regulator@1942130 { compatible = "qcom,mem-acc-regulator"; reg = <0x1942130 0x4>; reg-names = "acc-sel-l1"; regulator-name = "mem_acc_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <3>; qcom,acc-sel-l1-bit-pos = <0>; qcom,corner-acc-map = <0 1 1>; }; apc_vreg_corner: regulator@b018000 { compatible = "qcom,cpr-regulator"; reg = <0xb018000 0x1000>, <0xb011064 4>, <0x58000 0x1000>; reg-names = "rbcpr", "rbcpr_clk", "efuse_addr"; interrupts = <0 15 0>; regulator-name = "apc_corner"; qcom,cpr-fuse-corners = <3>; regulator-min-microvolt = <1>; regulator-max-microvolt = <9>; qcom,cpr-voltage-ceiling = <1052000 1228000 1352000>; qcom,cpr-voltage-floor = <1052000 1052000 1156000>; vdd-apc-supply = <&pm660_s1>; qcom,vdd-mx-corner-map = <4 5 7>; qcom,vdd-mx-vmin-method = <4>; vdd-mx-supply = <&pm660_s3_corner_ao>; qcom,vdd-mx-vmax = <7>; mem-acc-supply = <&mem_acc_vreg_corner>; qcom,cpr-ref-clk = <19200>; qcom,cpr-timer-delay = <5000>; qcom,cpr-timer-cons-up = <0>; qcom,cpr-timer-cons-down = <2>; qcom,cpr-irq-line = <0>; qcom,cpr-step-quotient = <10>; qcom,cpr-up-threshold = <0>; qcom,cpr-down-threshold = <2>; qcom,cpr-idle-clocks = <15>; qcom,cpr-gcnt-time = <1>; qcom,vdd-apc-step-up-limit = <1>; qcom,vdd-apc-step-down-limit = <1>; qcom,cpr-apc-volt-step = <4000>; qcom,cpr-fuse-row = <26 0>; qcom,cpr-fuse-target-quot = <42 24 6>; qcom,cpr-fuse-ro-sel = <61 61 54>; qcom,cpr-fuse-bp-cpr-disable = <58>; qcom,cpr-fuse-init-voltage = <26 36 6 0>, <26 18 6 0>, <26 0 6 0>; qcom,cpr-fuse-revision = <26 59 2 0>; qcom,cpr-init-voltage-ref = <1052000 1228000 1352000>; qcom,cpr-init-voltage-step = <10000>; qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>; qcom,cpr-init-voltage-as-ceiling; qcom,cpr-corner-frequency-map = <1 200000000>, <2 400000000>, <3 533330000>, <4 800000000>, <5 998400000>, <6 1094400000>, <7 1190400000>, <8 1248000000>, <9 1267200000>; qcom,speed-bin-fuse-sel = <1 34 3 0>; qcom,cpr-speed-bin-max-corners = <0 (-1) 2 4 9>, <2 (-1) 2 4 6>; qcom,cpr-quot-adjust-scaling-factor-max = <1400>; }; };
drivers/regulator/spm-regulator.c +110 −30 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -47,6 +47,7 @@ enum qpnp_regulator_uniq_type { QPNP_TYPE_HF, QPNP_TYPE_FTS2, QPNP_TYPE_FTS2p5, QPNP_TYPE_FTS426, QPNP_TYPE_ULT_HF, }; Loading @@ -54,6 +55,7 @@ enum qpnp_regulator_type { QPNP_HF_TYPE = 0x03, QPNP_FTS2_TYPE = 0x1C, QPNP_FTS2p5_TYPE = 0x1C, QPNP_FTS426_TYPE = 0x1C, QPNP_ULT_HF_TYPE = 0x22, }; Loading @@ -61,6 +63,7 @@ enum qpnp_regulator_subtype { QPNP_FTS2_SUBTYPE = 0x08, QPNP_HF_SUBTYPE = 0x08, QPNP_FTS2p5_SUBTYPE = 0x09, QPNP_FTS426_SUBTYPE = 0x0A, QPNP_ULT_HF_SUBTYPE = 0x0D, }; Loading @@ -70,6 +73,7 @@ static const struct voltage_range fts2p5_range0 = { 80000, 350000, 1355000, 5000}; static const struct voltage_range fts2p5_range1 = {160000, 700000, 2200000, 10000}; static const struct voltage_range fts426_range = {0, 320000, 1352000, 4000}; static const struct voltage_range ult_hf_range0 = {375000, 375000, 1562500, 12500}; static const struct voltage_range ult_hf_range1 = {750000, 750000, 1525000, Loading @@ -85,6 +89,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_REG_MODE 0x45 #define QPNP_SMPS_REG_STEP_CTRL 0x61 /* FTS426 voltage control registers */ #define QPNP_FTS426_REG_VOLTAGE_LB 0x40 #define QPNP_FTS426_REG_VOLTAGE_UB 0x41 #define QPNP_FTS426_REG_VOLTAGE_VALID_LB 0x42 #define QPNP_FTS426_REG_VOLTAGE_VALID_UB 0x43 #define QPNP_SMPS_MODE_PWM 0x80 #define QPNP_SMPS_MODE_AUTO 0x40 Loading @@ -92,9 +102,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_STEP_CTRL_STEP_SHIFT 3 #define QPNP_SMPS_STEP_CTRL_DELAY_MASK 0x07 #define QPNP_SMPS_STEP_CTRL_DELAY_SHIFT 0 #define QPNP_FTS426_STEP_CTRL_DELAY_MASK 0x03 #define QPNP_FTS426_STEP_CTRL_DELAY_SHIFT 0 /* Clock rate in kHz of the FTS2 regulator reference clock. */ #define QPNP_SMPS_CLOCK_RATE 19200 #define QPNP_FTS426_CLOCK_RATE 4800 /* Time to delay in us to ensure that a mode change has completed. */ #define QPNP_FTS2_MODE_CHANGE_DELAY 50 Loading @@ -105,6 +118,7 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, /* Minimum voltage stepper delay for each step. */ #define QPNP_FTS2_STEP_DELAY 8 #define QPNP_HF_STEP_DELAY 20 #define QPNP_FTS426_STEP_DELAY 2 /* Arbitrarily large max step size used to avoid possible numerical overflow */ #define SPM_REGULATOR_MAX_STEP_UV 10000000 Loading @@ -115,6 +129,8 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, */ #define QPNP_FTS2_STEP_MARGIN_NUM 4 #define QPNP_FTS2_STEP_MARGIN_DEN 5 #define QPNP_FTS426_STEP_MARGIN_NUM 10 #define QPNP_FTS426_STEP_MARGIN_DEN 11 /* * Settling delay for FTS2.5 Loading Loading @@ -160,6 +176,9 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) { int vlevel; if (vreg->regulator_type == QPNP_TYPE_FTS426) return roundup(uV, vreg->range->step_uV) / 1000; vlevel = DIV_ROUND_UP(uV - vreg->range->min_uV, vreg->range->step_uV); /* Fix VSET for ULT HF Buck */ Loading @@ -174,6 +193,8 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) static int spm_regulator_vlevel_to_uv(struct spm_vreg *vreg, int vlevel) { if (vreg->regulator_type == QPNP_TYPE_FTS426) return vlevel * 1000; /* * Calculate ULT HF buck VSET based on range: * In case of range 0: VSET is a 7 bit value. Loading Loading @@ -201,19 +222,63 @@ static unsigned spm_regulator_vlevel_to_selector(struct spm_vreg *vreg, static int qpnp_smps_read_voltage(struct spm_vreg *vreg) { int rc; u8 reg = 0; u8 reg[2] = {0,}; rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, ®, 1); if (vreg->regulator_type == QPNP_TYPE_FTS426) { rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_VALID_LB, reg, 2); if (rc) { dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n", dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint registers, rc=%d\n", __func__, rc); return rc; } vreg->last_set_vlevel = reg; vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, reg); vreg->last_set_vlevel = (reg[1] << 8) | reg[0]; } else { rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, reg, 1); if (rc) { dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n", __func__, rc); return rc; } vreg->last_set_vlevel = reg[0]; } vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, vreg->last_set_vlevel); return rc; } static int qpnp_smps_write_voltage(struct spm_vreg *vreg, unsigned vlevel) { int rc = 0; u8 reg[2]; /* Set voltage control registers via SPMI. */ reg[0] = vlevel & 0xFF; reg[1] = (vlevel >> 8) & 0xFF; if (vreg->regulator_type == QPNP_TYPE_FTS426) { rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_LB, reg, 2); } else { rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, reg, 1); } if (rc) pr_err("%s: spmi_ext_register_writel failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } Loading Loading @@ -267,7 +332,6 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) bool spm_failed = false; int rc = 0; u32 slew_delay; u8 reg; if (likely(!vreg->bypass_spm)) { /* Set voltage control register via SPM. */ Loading @@ -280,14 +344,9 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) } if (unlikely(vreg->bypass_spm || spm_failed)) { /* Set voltage control register via SPMI. */ reg = vlevel; rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, ®, 1); rc = qpnp_smps_write_voltage(vreg, vlevel); if (rc) { pr_err("%s: spmi_ext_register_writel failed, rc=%d\n", pr_err("%s: voltage write failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } Loading Loading @@ -531,7 +590,7 @@ static int spm_regulator_avs_set_voltage(struct regulator_dev *rdev, int min_uV, return -EINVAL; } vlevel_max = (uV - range->min_uV) / range->step_uV; vlevel_max = spm_regulator_uv_to_vlevel(vreg, uV); avs_max_uV = spm_regulator_vlevel_to_uv(vreg, vlevel_max); if (avs_max_uV < min_uV) { Loading Loading @@ -636,6 +695,9 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg) } else if (type[0] == QPNP_FTS2p5_TYPE && type[1] == QPNP_FTS2p5_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_FTS2p5; } else if (type[0] == QPNP_FTS426_TYPE && type[1] == QPNP_FTS426_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_FTS426; } else if (type[0] == QPNP_ULT_HF_TYPE && type[1] == QPNP_ULT_HF_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_ULT_HF; Loading Loading @@ -776,24 +838,39 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) return rc; } /* ULT buck does not support steps */ if (vreg->regulator_type != QPNP_TYPE_ULT_HF) /* ULT and FTS426 bucks do not support steps */ if (vreg->regulator_type != QPNP_TYPE_ULT_HF && vreg->regulator_type != QPNP_TYPE_FTS426) step = (reg & QPNP_SMPS_STEP_CTRL_STEP_MASK) >> QPNP_SMPS_STEP_CTRL_STEP_SHIFT; if (vreg->regulator_type == QPNP_TYPE_FTS426) { delay = (reg & QPNP_FTS426_STEP_CTRL_DELAY_MASK) >> QPNP_FTS426_STEP_CTRL_DELAY_SHIFT; /* step_rate has units of uV/us. */ vreg->step_rate = QPNP_FTS426_CLOCK_RATE * vreg->range->step_uV; } else { delay = (reg & QPNP_SMPS_STEP_CTRL_DELAY_MASK) >> QPNP_SMPS_STEP_CTRL_DELAY_SHIFT; /* step_rate has units of uV/us. */ vreg->step_rate = QPNP_SMPS_CLOCK_RATE * vreg->range->step_uV * (1 << step); } if ((vreg->regulator_type == QPNP_TYPE_ULT_HF) || (vreg->regulator_type == QPNP_TYPE_HF)) vreg->step_rate /= 1000 * (QPNP_HF_STEP_DELAY << delay); else if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->step_rate /= 1000 * (QPNP_FTS426_STEP_DELAY << delay); else vreg->step_rate /= 1000 * (QPNP_FTS2_STEP_DELAY << delay); if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->step_rate = vreg->step_rate * QPNP_FTS426_STEP_MARGIN_NUM / QPNP_FTS426_STEP_MARGIN_DEN; else vreg->step_rate = vreg->step_rate * QPNP_FTS2_STEP_MARGIN_NUM / QPNP_FTS2_STEP_MARGIN_DEN; Loading @@ -806,7 +883,8 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) static bool spm_regulator_using_range0(struct spm_vreg *vreg) { return vreg->range == &fts2_range0 || vreg->range == &fts2p5_range0 || vreg->range == &ult_hf_range0 || vreg->range == &hf_range0; || vreg->range == &ult_hf_range0 || vreg->range == &hf_range0 || vreg->range == &fts426_range; } /* Register a regulator to enable/disable AVS and set AVS min/max limits. */ Loading Loading @@ -937,6 +1015,8 @@ static int spm_regulator_probe(struct spmi_device *spmi) rc = qpnp_smps_init_range(vreg, &fts2_range0, &fts2_range1); else if (vreg->regulator_type == QPNP_TYPE_FTS2p5) rc = qpnp_smps_init_range(vreg, &fts2p5_range0, &fts2p5_range1); else if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->range = &fts426_range; else if (vreg->regulator_type == QPNP_TYPE_HF) rc = qpnp_smps_init_range(vreg, &hf_range0, &hf_range1); else if (vreg->regulator_type == QPNP_TYPE_ULT_HF) Loading