Loading Documentation/devicetree/bindings/regulator/spm-regulator.txt +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ Optional properties: be managed by an SPM. Instead, the voltage should be controlled via SPMI. - qcom,max-voltage-step: Maximum single voltage step size in microvolts. - qcom,recal-mask: Bit mask of the APSS clusters to recalibrate after each voltage change. Bit 0 corresponds to the first cluster, bit 1 corresponds to the second cluster, and so on. Optional structure: - A child node may be specified within a qcom,spm-regulator node which defines Loading drivers/regulator/spm-regulator.c +28 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,12 @@ #include <linux/regulator/spm-regulator.h> #include <soc/qcom/spm.h> #if defined(CONFIG_ARM64) || (defined(CONFIG_ARM) && defined(CONFIG_ARM_PSCI)) asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); #else #define __invoke_psci_fn_smc(a, b, c, d) 0 #endif #define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator" struct voltage_range { Loading Loading @@ -136,6 +142,7 @@ struct spm_vreg { int avs_min_uV; int avs_max_uV; bool avs_enabled; u32 recal_cluster_mask; }; static inline bool spm_regulator_using_avs(struct spm_vreg *vreg) Loading Loading @@ -290,6 +297,22 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) return rc; } static int spm_regulator_recalibrate(struct spm_vreg *vreg) { int rc; if (!vreg->recal_cluster_mask) return 0; rc = __invoke_psci_fn_smc(0xC4000020, vreg->recal_cluster_mask, 2, 0); if (rc) pr_err("%s: recalibration failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } static int _spm_regulator_set_voltage(struct regulator_dev *rdev) { struct spm_vreg *vreg = rdev_get_drvdata(rdev); Loading Loading @@ -334,6 +357,8 @@ static int _spm_regulator_set_voltage(struct regulator_dev *rdev) return rc; } rc = spm_regulator_recalibrate(vreg); return rc; } Loading Loading @@ -884,6 +909,9 @@ static int spm_regulator_probe(struct spmi_device *spmi) of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,cpu-num", &vreg->cpu_num); of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,recal-mask", &vreg->recal_cluster_mask); /* * The regulator must be initialized to range 0 or range 1 during * PMIC power on sequence. Once it is set, it cannot be changed Loading Loading
Documentation/devicetree/bindings/regulator/spm-regulator.txt +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ Optional properties: be managed by an SPM. Instead, the voltage should be controlled via SPMI. - qcom,max-voltage-step: Maximum single voltage step size in microvolts. - qcom,recal-mask: Bit mask of the APSS clusters to recalibrate after each voltage change. Bit 0 corresponds to the first cluster, bit 1 corresponds to the second cluster, and so on. Optional structure: - A child node may be specified within a qcom,spm-regulator node which defines Loading
drivers/regulator/spm-regulator.c +28 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,12 @@ #include <linux/regulator/spm-regulator.h> #include <soc/qcom/spm.h> #if defined(CONFIG_ARM64) || (defined(CONFIG_ARM) && defined(CONFIG_ARM_PSCI)) asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); #else #define __invoke_psci_fn_smc(a, b, c, d) 0 #endif #define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator" struct voltage_range { Loading Loading @@ -136,6 +142,7 @@ struct spm_vreg { int avs_min_uV; int avs_max_uV; bool avs_enabled; u32 recal_cluster_mask; }; static inline bool spm_regulator_using_avs(struct spm_vreg *vreg) Loading Loading @@ -290,6 +297,22 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV) return rc; } static int spm_regulator_recalibrate(struct spm_vreg *vreg) { int rc; if (!vreg->recal_cluster_mask) return 0; rc = __invoke_psci_fn_smc(0xC4000020, vreg->recal_cluster_mask, 2, 0); if (rc) pr_err("%s: recalibration failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } static int _spm_regulator_set_voltage(struct regulator_dev *rdev) { struct spm_vreg *vreg = rdev_get_drvdata(rdev); Loading Loading @@ -334,6 +357,8 @@ static int _spm_regulator_set_voltage(struct regulator_dev *rdev) return rc; } rc = spm_regulator_recalibrate(vreg); return rc; } Loading Loading @@ -884,6 +909,9 @@ static int spm_regulator_probe(struct spmi_device *spmi) of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,cpu-num", &vreg->cpu_num); of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,recal-mask", &vreg->recal_cluster_mask); /* * The regulator must be initialized to range 0 or range 1 during * PMIC power on sequence. Once it is set, it cannot be changed Loading