Loading Documentation/devicetree/bindings/regulator/cpr-regulator.txt +9 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,14 @@ Optional properties: The number of quadruples should be equal to the number of values specified in the qcom,cpr-aging-sensor-id property. This property is required if the qcom,cpr-aging-sensor-id property has been specified. - qcom,cpr-vdd-mode-map: Array of boolean values which define the mapping of the VDD operating mode for each APC virtual corner. A element value 0 indicates the VDD to be configured to AUTO mode and value 1 indicates the VDD to be configured to PWM mode for the corresponding virtual corner. The elements in the array are ordered from lowest voltage corner to highest voltage corner. Example: apc_vreg_corner: regulator@f9018000 { status = "okay"; Loading Loading @@ -727,6 +735,7 @@ Example: qcom,cpr-voltage-ceiling = <1050000 1150000 1280000>; qcom,cpr-voltage-floor = <1050000 1050000 1100000>; vdd-apc-supply = <&pm8226_s2>; qcom,cpr-vdd-mode-map = <0 0 0 0 0 0 1 1 1 1 1 1>; vdd-apc-optional-prim-supply = <&ncp6335d>; vdd-apc-optional-sec-supply = <&fan53555>; vdd-mx-supply = <&pm8226_l3_ao>; Loading drivers/regulator/cpr-regulator.c +66 −2 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ struct cpr_regulator { u32 num_corners; int *quot_adjust; int *mem_acc_corner_map; unsigned int *vdd_mode_map; int num_adj_cpus; int *adj_cpus; Loading Loading @@ -1398,6 +1399,7 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) u32 save_ctl, save_irq; cpumask_t tmp_mask; int rc = 0, i; unsigned int current_mode; save_ctl = cpr_read(cpr_vreg, REG_RBCPR_CTL); save_irq = cpr_read(cpr_vreg, REG_RBIF_IRQ_EN(cpr_vreg->irq_line)); Loading @@ -1422,6 +1424,13 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) return rc; } current_mode = regulator_get_mode(cpr_vreg->vdd_apc); if (current_mode < 0) { cpr_err(cpr_vreg, "Failed to get vdd-supply mode, error=%d\n", current_mode); return current_mode; } /* Force PWM mode */ rc = regulator_set_mode(cpr_vreg->vdd_apc, REGULATOR_MODE_NORMAL); if (rc) { Loading @@ -1447,10 +1456,10 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) put_online_cpus(); /* Set to initial mode */ rc = regulator_set_mode(cpr_vreg->vdd_apc, REGULATOR_MODE_IDLE); rc = regulator_set_mode(cpr_vreg->vdd_apc, current_mode); if (rc) { cpr_err(cpr_vreg, "unable to configure vdd-supply for mode=%u, rc=%d\n", REGULATOR_MODE_IDLE, rc); current_mode, rc); return rc; } Loading Loading @@ -1511,6 +1520,17 @@ static int cpr_regulator_set_voltage(struct regulator_dev *rdev, if (rc) return rc; if (cpr_vreg->vdd_mode_map) { rc = regulator_set_mode(cpr_vreg->vdd_apc, cpr_vreg->vdd_mode_map[corner]); if (rc) { cpr_err(cpr_vreg, "unable to configure vdd-supply for mode=%u, rc=%d\n", cpr_vreg->vdd_mode_map[corner], rc); return rc; } } if (cpr_is_allowed(cpr_vreg) && cpr_vreg->vreg_enabled) { cpr_irq_clr(cpr_vreg); if (reset_quot) Loading Loading @@ -4560,6 +4580,44 @@ static int cpr_rpm_apc_init(struct platform_device *pdev, return rc; } static int cpr_parse_vdd_mode_config(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { int rc, len = 0, i, mode; struct device_node *of_node = pdev->dev.of_node; const char *prop_str = "qcom,cpr-vdd-mode-map"; if (!of_find_property(of_node, prop_str, &len)) return 0; if (len != cpr_vreg->num_corners * sizeof(u32)) { cpr_err(cpr_vreg, "%s length=%d is invalid: required:%d\n", prop_str, len, cpr_vreg->num_corners); return -EINVAL; } cpr_vreg->vdd_mode_map = devm_kcalloc(&pdev->dev, cpr_vreg->num_corners + 1, sizeof(*cpr_vreg->vdd_mode_map), GFP_KERNEL); if (!cpr_vreg->vdd_mode_map) return -ENOMEM; for (i = 0; i < cpr_vreg->num_corners; i++) { rc = of_property_read_u32_index(of_node, prop_str, i, &mode); if (rc) { cpr_err(cpr_vreg, "read %s index %d failed, rc = %d\n", prop_str, i, rc); return rc; } cpr_vreg->vdd_mode_map[i + CPR_CORNER_MIN] = mode ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE; } return rc; } static int cpr_vsens_init(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { Loading Loading @@ -5556,6 +5614,12 @@ static int cpr_regulator_probe(struct platform_device *pdev) return rc; } rc = cpr_parse_vdd_mode_config(pdev, cpr_vreg); if (rc) { cpr_err(cpr_vreg, "vdd-mode parsing failed, rc=%d\n", rc); return rc; } if (of_property_read_bool(pdev->dev.of_node, "qcom,disable-closed-loop-in-pc")) { rc = cpr_init_pm_notification(cpr_vreg); Loading Loading
Documentation/devicetree/bindings/regulator/cpr-regulator.txt +9 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,14 @@ Optional properties: The number of quadruples should be equal to the number of values specified in the qcom,cpr-aging-sensor-id property. This property is required if the qcom,cpr-aging-sensor-id property has been specified. - qcom,cpr-vdd-mode-map: Array of boolean values which define the mapping of the VDD operating mode for each APC virtual corner. A element value 0 indicates the VDD to be configured to AUTO mode and value 1 indicates the VDD to be configured to PWM mode for the corresponding virtual corner. The elements in the array are ordered from lowest voltage corner to highest voltage corner. Example: apc_vreg_corner: regulator@f9018000 { status = "okay"; Loading Loading @@ -727,6 +735,7 @@ Example: qcom,cpr-voltage-ceiling = <1050000 1150000 1280000>; qcom,cpr-voltage-floor = <1050000 1050000 1100000>; vdd-apc-supply = <&pm8226_s2>; qcom,cpr-vdd-mode-map = <0 0 0 0 0 0 1 1 1 1 1 1>; vdd-apc-optional-prim-supply = <&ncp6335d>; vdd-apc-optional-sec-supply = <&fan53555>; vdd-mx-supply = <&pm8226_l3_ao>; Loading
drivers/regulator/cpr-regulator.c +66 −2 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ struct cpr_regulator { u32 num_corners; int *quot_adjust; int *mem_acc_corner_map; unsigned int *vdd_mode_map; int num_adj_cpus; int *adj_cpus; Loading Loading @@ -1398,6 +1399,7 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) u32 save_ctl, save_irq; cpumask_t tmp_mask; int rc = 0, i; unsigned int current_mode; save_ctl = cpr_read(cpr_vreg, REG_RBCPR_CTL); save_irq = cpr_read(cpr_vreg, REG_RBIF_IRQ_EN(cpr_vreg->irq_line)); Loading @@ -1422,6 +1424,13 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) return rc; } current_mode = regulator_get_mode(cpr_vreg->vdd_apc); if (current_mode < 0) { cpr_err(cpr_vreg, "Failed to get vdd-supply mode, error=%d\n", current_mode); return current_mode; } /* Force PWM mode */ rc = regulator_set_mode(cpr_vreg->vdd_apc, REGULATOR_MODE_NORMAL); if (rc) { Loading @@ -1447,10 +1456,10 @@ static int cpr_calculate_de_aging_margin(struct cpr_regulator *cpr_vreg) put_online_cpus(); /* Set to initial mode */ rc = regulator_set_mode(cpr_vreg->vdd_apc, REGULATOR_MODE_IDLE); rc = regulator_set_mode(cpr_vreg->vdd_apc, current_mode); if (rc) { cpr_err(cpr_vreg, "unable to configure vdd-supply for mode=%u, rc=%d\n", REGULATOR_MODE_IDLE, rc); current_mode, rc); return rc; } Loading Loading @@ -1511,6 +1520,17 @@ static int cpr_regulator_set_voltage(struct regulator_dev *rdev, if (rc) return rc; if (cpr_vreg->vdd_mode_map) { rc = regulator_set_mode(cpr_vreg->vdd_apc, cpr_vreg->vdd_mode_map[corner]); if (rc) { cpr_err(cpr_vreg, "unable to configure vdd-supply for mode=%u, rc=%d\n", cpr_vreg->vdd_mode_map[corner], rc); return rc; } } if (cpr_is_allowed(cpr_vreg) && cpr_vreg->vreg_enabled) { cpr_irq_clr(cpr_vreg); if (reset_quot) Loading Loading @@ -4560,6 +4580,44 @@ static int cpr_rpm_apc_init(struct platform_device *pdev, return rc; } static int cpr_parse_vdd_mode_config(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { int rc, len = 0, i, mode; struct device_node *of_node = pdev->dev.of_node; const char *prop_str = "qcom,cpr-vdd-mode-map"; if (!of_find_property(of_node, prop_str, &len)) return 0; if (len != cpr_vreg->num_corners * sizeof(u32)) { cpr_err(cpr_vreg, "%s length=%d is invalid: required:%d\n", prop_str, len, cpr_vreg->num_corners); return -EINVAL; } cpr_vreg->vdd_mode_map = devm_kcalloc(&pdev->dev, cpr_vreg->num_corners + 1, sizeof(*cpr_vreg->vdd_mode_map), GFP_KERNEL); if (!cpr_vreg->vdd_mode_map) return -ENOMEM; for (i = 0; i < cpr_vreg->num_corners; i++) { rc = of_property_read_u32_index(of_node, prop_str, i, &mode); if (rc) { cpr_err(cpr_vreg, "read %s index %d failed, rc = %d\n", prop_str, i, rc); return rc; } cpr_vreg->vdd_mode_map[i + CPR_CORNER_MIN] = mode ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE; } return rc; } static int cpr_vsens_init(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { Loading Loading @@ -5556,6 +5614,12 @@ static int cpr_regulator_probe(struct platform_device *pdev) return rc; } rc = cpr_parse_vdd_mode_config(pdev, cpr_vreg); if (rc) { cpr_err(cpr_vreg, "vdd-mode parsing failed, rc=%d\n", rc); return rc; } if (of_property_read_bool(pdev->dev.of_node, "qcom,disable-closed-loop-in-pc")) { rc = cpr_init_pm_notification(cpr_vreg); Loading