Loading Documentation/devicetree/bindings/regulator/cpr-regulator.txt +5 −2 Original line number Diff line number Diff line Loading @@ -44,8 +44,11 @@ Required properties: - qcom,cpr-timer-cons-down: Consecutive number of timer interval (qcom,cpr-timer-delay) occurred before issuing DOWN interrupt. - qcom,cpr-irq-line: Internal interrupt route signal of RBCPR, one of 0, 1 or 2. - qcom,cpr-step-quotient: Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step to issue error_steps. - qcom,cpr-step-quotient: Defines the number of CPR quotient (i.e. Ring Oscillator(RO) count) per vdd-apc-supply output voltage step. A single integer value may be specified which is to be used for all RO's. Alternatively, 8 integer values may be specified which define the step quotients for RO0 to RO7 in order. - qcom,cpr-up-threshold: The threshold for CPR to issue interrupt when error_steps is greater than it when stepping up. - qcom,cpr-down-threshold: The threshold for CPR to issue interrupt when Loading drivers/regulator/cpr-regulator.c +73 −11 Original line number Diff line number Diff line Loading @@ -274,7 +274,7 @@ struct cpr_regulator { u32 timer_cons_up; u32 timer_cons_down; u32 irq_line; u32 step_quotient; u32 *step_quotient; u32 up_threshold; u32 down_threshold; u32 idle_clocks; Loading Loading @@ -572,13 +572,25 @@ static void cpr_corner_save(struct cpr_regulator *cpr_vreg, int corner) static void cpr_corner_restore(struct cpr_regulator *cpr_vreg, int corner) { u32 gcnt, ctl, irq, ro_sel; u32 gcnt, ctl, irq, ro_sel, step_quot; int fuse_corner = cpr_vreg->corner_map[corner]; int i; ro_sel = cpr_vreg->cpr_fuse_ro_sel[fuse_corner]; gcnt = cpr_vreg->gcnt | (cpr_vreg->cpr_fuse_target_quot[fuse_corner] - cpr_vreg->quot_adjust[corner]); /* Program the step quotient and idle clocks */ step_quot = ((cpr_vreg->idle_clocks & RBCPR_STEP_QUOT_IDLE_CLK_MASK) << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT) | (cpr_vreg->step_quotient[fuse_corner] & RBCPR_STEP_QUOT_STEPQUOT_MASK); cpr_write(cpr_vreg, REG_RBCPR_STEP_QUOT, step_quot); /* Clear the target quotient value and gate count of all ROs */ for (i = 0; i < CPR_NUM_RING_OSC; i++) cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(i), 0); cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt); ctl = cpr_vreg->save_ctl[corner]; cpr_write(cpr_vreg, REG_RBCPR_CTL, ctl); Loading Loading @@ -1150,12 +1162,6 @@ static int cpr_config(struct cpr_regulator *cpr_vreg, struct device *dev) RBCPR_GCNT_TARGET_GCNT_SHIFT; cpr_vreg->gcnt = gcnt; /* Program the step quotient and idle clocks */ val = ((cpr_vreg->idle_clocks & RBCPR_STEP_QUOT_IDLE_CLK_MASK) << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT) | (cpr_vreg->step_quotient & RBCPR_STEP_QUOT_STEPQUOT_MASK); cpr_write(cpr_vreg, REG_RBCPR_STEP_QUOT, val); /* Program the delay count for the timer */ val = (cpr_vreg->ref_clk_khz * cpr_vreg->timer_delay_us) / 1000; cpr_write(cpr_vreg, REG_RBCPR_TIMER_INTERVAL, val); Loading Loading @@ -2919,6 +2925,59 @@ static int cpr_init_ceiling_floor_override_voltages( return rc; } static int cpr_init_step_quotient(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; int len = 0; u32 step_quot[CPR_NUM_RING_OSC]; int i, rc; if (!of_find_property(of_node, "qcom,cpr-step-quotient", &len)) { cpr_err(cpr_vreg, "qcom,cpr-step-quotient property missing\n"); return -EINVAL; } if (len == sizeof(u32)) { /* Single step quotient used for all ring oscillators. */ rc = of_property_read_u32(of_node, "qcom,cpr-step-quotient", step_quot); if (rc) { cpr_err(cpr_vreg, "could not read qcom,cpr-step-quotient, rc=%d\n", rc); return rc; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_vreg->step_quotient[i] = step_quot[0]; } else if (len == sizeof(u32) * CPR_NUM_RING_OSC) { /* Unique step quotient used per ring oscillator. */ rc = of_property_read_u32_array(of_node, "qcom,cpr-step-quotient", step_quot, CPR_NUM_RING_OSC); if (rc) { cpr_err(cpr_vreg, "could not read qcom,cpr-step-quotient, rc=%d\n", rc); return rc; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_vreg->step_quotient[i] = step_quot[cpr_vreg->cpr_fuse_ro_sel[i]]; } else { cpr_err(cpr_vreg, "qcom,cpr-step-quotient has invalid length=%d\n", len); return -EINVAL; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_debug(cpr_vreg, "step_quotient[%d]=%u\n", i, cpr_vreg->step_quotient[i]); return 0; } static int cpr_init_cpr_parameters(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { Loading @@ -2945,8 +3004,8 @@ static int cpr_init_cpr_parameters(struct platform_device *pdev, &cpr_vreg->irq_line, rc); if (rc) return rc; CPR_PROP_READ_U32(cpr_vreg, of_node, "cpr-step-quotient", &cpr_vreg->step_quotient, rc); rc = cpr_init_step_quotient(pdev, cpr_vreg); if (rc) return rc; Loading Loading @@ -3333,12 +3392,15 @@ static int cpr_fuse_corner_array_alloc(struct device *dev, len * (sizeof(*cpr_vreg->fuse_ceiling_volt)), GFP_KERNEL); cpr_vreg->fuse_floor_volt = devm_kzalloc(dev, len * (sizeof(*cpr_vreg->fuse_floor_volt)), GFP_KERNEL); cpr_vreg->step_quotient = devm_kzalloc(dev, len * sizeof(*cpr_vreg->step_quotient), GFP_KERNEL); if (cpr_vreg->pvs_corner_v == NULL || cpr_vreg->cpr_fuse_ro_sel == NULL || cpr_vreg->fuse_ceiling_volt == NULL || cpr_vreg->fuse_floor_volt == NULL || cpr_vreg->vdd_mx_corner_map == NULL || cpr_vreg->cpr_fuse_target_quot == NULL) { || cpr_vreg->cpr_fuse_target_quot == NULL || cpr_vreg->step_quotient == NULL) { cpr_err(cpr_vreg, "Could not allocate memory for CPR arrays\n"); return -ENOMEM; } Loading Loading
Documentation/devicetree/bindings/regulator/cpr-regulator.txt +5 −2 Original line number Diff line number Diff line Loading @@ -44,8 +44,11 @@ Required properties: - qcom,cpr-timer-cons-down: Consecutive number of timer interval (qcom,cpr-timer-delay) occurred before issuing DOWN interrupt. - qcom,cpr-irq-line: Internal interrupt route signal of RBCPR, one of 0, 1 or 2. - qcom,cpr-step-quotient: Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step to issue error_steps. - qcom,cpr-step-quotient: Defines the number of CPR quotient (i.e. Ring Oscillator(RO) count) per vdd-apc-supply output voltage step. A single integer value may be specified which is to be used for all RO's. Alternatively, 8 integer values may be specified which define the step quotients for RO0 to RO7 in order. - qcom,cpr-up-threshold: The threshold for CPR to issue interrupt when error_steps is greater than it when stepping up. - qcom,cpr-down-threshold: The threshold for CPR to issue interrupt when Loading
drivers/regulator/cpr-regulator.c +73 −11 Original line number Diff line number Diff line Loading @@ -274,7 +274,7 @@ struct cpr_regulator { u32 timer_cons_up; u32 timer_cons_down; u32 irq_line; u32 step_quotient; u32 *step_quotient; u32 up_threshold; u32 down_threshold; u32 idle_clocks; Loading Loading @@ -572,13 +572,25 @@ static void cpr_corner_save(struct cpr_regulator *cpr_vreg, int corner) static void cpr_corner_restore(struct cpr_regulator *cpr_vreg, int corner) { u32 gcnt, ctl, irq, ro_sel; u32 gcnt, ctl, irq, ro_sel, step_quot; int fuse_corner = cpr_vreg->corner_map[corner]; int i; ro_sel = cpr_vreg->cpr_fuse_ro_sel[fuse_corner]; gcnt = cpr_vreg->gcnt | (cpr_vreg->cpr_fuse_target_quot[fuse_corner] - cpr_vreg->quot_adjust[corner]); /* Program the step quotient and idle clocks */ step_quot = ((cpr_vreg->idle_clocks & RBCPR_STEP_QUOT_IDLE_CLK_MASK) << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT) | (cpr_vreg->step_quotient[fuse_corner] & RBCPR_STEP_QUOT_STEPQUOT_MASK); cpr_write(cpr_vreg, REG_RBCPR_STEP_QUOT, step_quot); /* Clear the target quotient value and gate count of all ROs */ for (i = 0; i < CPR_NUM_RING_OSC; i++) cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(i), 0); cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt); ctl = cpr_vreg->save_ctl[corner]; cpr_write(cpr_vreg, REG_RBCPR_CTL, ctl); Loading Loading @@ -1150,12 +1162,6 @@ static int cpr_config(struct cpr_regulator *cpr_vreg, struct device *dev) RBCPR_GCNT_TARGET_GCNT_SHIFT; cpr_vreg->gcnt = gcnt; /* Program the step quotient and idle clocks */ val = ((cpr_vreg->idle_clocks & RBCPR_STEP_QUOT_IDLE_CLK_MASK) << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT) | (cpr_vreg->step_quotient & RBCPR_STEP_QUOT_STEPQUOT_MASK); cpr_write(cpr_vreg, REG_RBCPR_STEP_QUOT, val); /* Program the delay count for the timer */ val = (cpr_vreg->ref_clk_khz * cpr_vreg->timer_delay_us) / 1000; cpr_write(cpr_vreg, REG_RBCPR_TIMER_INTERVAL, val); Loading Loading @@ -2919,6 +2925,59 @@ static int cpr_init_ceiling_floor_override_voltages( return rc; } static int cpr_init_step_quotient(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; int len = 0; u32 step_quot[CPR_NUM_RING_OSC]; int i, rc; if (!of_find_property(of_node, "qcom,cpr-step-quotient", &len)) { cpr_err(cpr_vreg, "qcom,cpr-step-quotient property missing\n"); return -EINVAL; } if (len == sizeof(u32)) { /* Single step quotient used for all ring oscillators. */ rc = of_property_read_u32(of_node, "qcom,cpr-step-quotient", step_quot); if (rc) { cpr_err(cpr_vreg, "could not read qcom,cpr-step-quotient, rc=%d\n", rc); return rc; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_vreg->step_quotient[i] = step_quot[0]; } else if (len == sizeof(u32) * CPR_NUM_RING_OSC) { /* Unique step quotient used per ring oscillator. */ rc = of_property_read_u32_array(of_node, "qcom,cpr-step-quotient", step_quot, CPR_NUM_RING_OSC); if (rc) { cpr_err(cpr_vreg, "could not read qcom,cpr-step-quotient, rc=%d\n", rc); return rc; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_vreg->step_quotient[i] = step_quot[cpr_vreg->cpr_fuse_ro_sel[i]]; } else { cpr_err(cpr_vreg, "qcom,cpr-step-quotient has invalid length=%d\n", len); return -EINVAL; } for (i = CPR_FUSE_CORNER_MIN; i <= cpr_vreg->num_fuse_corners; i++) cpr_debug(cpr_vreg, "step_quotient[%d]=%u\n", i, cpr_vreg->step_quotient[i]); return 0; } static int cpr_init_cpr_parameters(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { Loading @@ -2945,8 +3004,8 @@ static int cpr_init_cpr_parameters(struct platform_device *pdev, &cpr_vreg->irq_line, rc); if (rc) return rc; CPR_PROP_READ_U32(cpr_vreg, of_node, "cpr-step-quotient", &cpr_vreg->step_quotient, rc); rc = cpr_init_step_quotient(pdev, cpr_vreg); if (rc) return rc; Loading Loading @@ -3333,12 +3392,15 @@ static int cpr_fuse_corner_array_alloc(struct device *dev, len * (sizeof(*cpr_vreg->fuse_ceiling_volt)), GFP_KERNEL); cpr_vreg->fuse_floor_volt = devm_kzalloc(dev, len * (sizeof(*cpr_vreg->fuse_floor_volt)), GFP_KERNEL); cpr_vreg->step_quotient = devm_kzalloc(dev, len * sizeof(*cpr_vreg->step_quotient), GFP_KERNEL); if (cpr_vreg->pvs_corner_v == NULL || cpr_vreg->cpr_fuse_ro_sel == NULL || cpr_vreg->fuse_ceiling_volt == NULL || cpr_vreg->fuse_floor_volt == NULL || cpr_vreg->vdd_mx_corner_map == NULL || cpr_vreg->cpr_fuse_target_quot == NULL) { || cpr_vreg->cpr_fuse_target_quot == NULL || cpr_vreg->step_quotient == NULL) { cpr_err(cpr_vreg, "Could not allocate memory for CPR arrays\n"); return -ENOMEM; } Loading