Loading Documentation/devicetree/bindings/regulator/cpr-regulator.txt +57 −32 Original line number Diff line number Diff line Loading @@ -22,10 +22,6 @@ Required properties: should be 1 for SVS corner - regulator-max-microvolt: Maximum corner value as max constraint, which should be 4 for SUPER_TURBO or 3 for TURBO - qcom,pvs-voltage-table: Array of triples in which each triple indicates the initial voltage of the PVS bin in SVS, NOM and Turbo corner in microvolts. The location or 0-based index of an triple in the list corresponds to the bin number. - qcom,cpr-voltage-ceiling: Ceiling voltages of SVS, NOM and TURBO corners respectively - qcom,cpr-voltage-floor: Floor voltages of SVS, NOM and TURBO corners respectively The ceiling voltages for each of above two Loading @@ -52,33 +48,6 @@ Required properties: - qcom,cpr-idle-clocks: Idle clock cycles RO can be in. - qcom,cpr-gcnt-time: The time for gate count in microseconds. - qcom,cpr-apc-volt-step: The voltage in microvolt per CPR step, such as 5000uV. - qcom,pvs-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant PVS fuse bits would be used instead of the original bits and method to read fuse row, reading register through SCM or directly. The 5 elements with index [0..4] are: [0] => the fuse row number of the selector [1] => LSB bit position of the bits [2] => number of bits [3] => the value to indicate redundant selection [4] => fuse reading method, 0 for direct reading or 1 for SCM reading When the value of the fuse bits specified by first 3 elements equals to the value in 4th element, redundant PVS fuse bits should be selected. Otherwise, the original PVS bits should be selected. If the 5th element is 0, read the fuse row from register directly. Otherwise, read it through SCM. - qcom,pvs-fuse: Array of 4 elements to indicate the bits for PVS fuse and read method. The array should have index and value like this: [0] => the PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading - qcom,pvs-fuse-redun: Array of 4 elements to indicate the bits for redundant PVS fuse. The array should have index and value like this: [0] => the redundant PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading - qcom,cpr-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant CPR fuse bits would be used instead of the original bits and method to read fuse row, using SCM Loading Loading @@ -146,6 +115,41 @@ Optional properties: [1] => voltage to set for vdd-mx when VDD_APC is running at NOM corner [2] => voltage to set for vdd-mx when VDD_APC is running at TURBO corner This is required when the qcom,vdd-mx-vmin-method property has a value of 4. - qcom,pvs-voltage-table: Array of triples in which each triple indicates the initial voltage of the PVS bin in SVS, NOM and Turbo corner in microvolts. The location or 0-based index of an triple in the list corresponds to the bin number. A given cpr-regulator device must have either qcom,pvs-voltage-table specified or qcom,cpr-fuse-init-voltage (and its associated properties). - qcom,pvs-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant PVS fuse bits would be used instead of the original bits and method to read fuse row, reading register through SCM or directly. The 5 elements with index [0..4] are: [0] => the fuse row number of the selector [1] => LSB bit position of the bits [2] => number of bits [3] => the value to indicate redundant selection [4] => fuse reading method, 0 for direct reading or 1 for SCM reading When the value of the fuse bits specified by first 3 elements equals to the value in 4th element, redundant PVS fuse bits should be selected. Otherwise, the original PVS bits should be selected. If the 5th element is 0, read the fuse row from register directly. Otherwise, read it through SCM. This property is required if qcom,pvs-voltage-table is present. - qcom,pvs-fuse: Array of 4 elements to indicate the bits for PVS fuse and read method. The array should have index and value like this: [0] => the PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading This property is required if qcom,pvs-voltage-table is present. - qcom,pvs-fuse-redun: Array of 4 elements to indicate the bits for redundant PVS fuse. The array should have index and value like this: [0] => the redundant PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading This property is required if qcom,pvs-voltage-table is present. - qcom,cpr-fuse-redun-bp-cpr-disable: Redundant bit position of the bit to indicate if CPR should be disable - qcom,cpr-fuse-redun-bp-scheme: Redundant bit position of the bit to indicate if it's a global/local scheme This property is required if cpr-fuse-redun-bp-cpr-disable Loading Loading @@ -251,7 +255,23 @@ Optional properties: corresponds to 'scaling' in this equation: quot_adjust = (freq_turbo - freq_corner) * scaling / 1000. This property is required if qcom,cpr-speed-bin-max-corners is present. - qcom,cpr-fuse-init-voltage: Array of quadruples in which each quadruple specifies a fuse location to read in order to get an initial voltage for the SVS, NORMAL, or TURBO fuse corner. The fuse values are encoded as voltage steps higher or lower than the voltages defined in qcom,cpr-voltage-ceiling. Each step corresponds to the voltage defined by the qcom,cpr-init-voltage-step property. The 4 elements in one quadruple are: [0]: => the fuse row number of the bits [1]: => LSB bit position of the bits [2]: => number of the bits [3]: => fuse reading method, 0 for direct reading or 1 for SCM reading The quadruples are ordered from the lowest voltage fuse corner to the highest voltage fuse corner. A given cpr-regulator device must have either qcom,cpr-fuse-init-voltage specified or qcom,pvs-voltage-table (and its associated properties). - qcom,cpr-init-voltage-step: The voltage step size in microvolts of the CPR initial voltage fuses described by the qcom,cpr-fuse-init-voltage property. This property is required if qcom,cpr-fuse-init-voltage is present. Example: apc_vreg_corner: regulator@f9018000 { status = "okay"; Loading Loading @@ -360,5 +380,10 @@ Example: <2 1 2 4 10>, <5 1 2 4 14>; qcom,cpr-quot-adjust-scaling-factor-max = <650>; qcom,cpr-fuse-init-voltage = <27 36 6 0>, <27 18 6 0>, <27 0 6 0>; qcom,cpr-init-voltage-step = <10000>; }; drivers/regulator/cpr-regulator.c +136 −17 Original line number Diff line number Diff line Loading @@ -1093,13 +1093,100 @@ static int cpr_voltage_uplift_wa_inc_volt(struct cpr_regulator *cpr_vreg, return rc; } static int cpr_pvs_init(struct platform_device *pdev, /* * Property qcom,cpr-fuse-init-voltage specifies the fuse position of the * initial voltage for each fuse corner. MSB of the fuse value is a sign * bit, and the remaining bits define the steps of the offset. Each step has * units of microvolts defined in the qcom,cpr-fuse-init-voltage-step property. * The initial voltages can be calculated using the formula: * pvs_corner_v[corner] = ceiling_volt[corner] + (sign * steps * step_size_uv) */ static int cpr_pvs_per_corner_init(struct device_node *of_node, struct cpr_regulator *cpr_vreg) { u64 efuse_bits; int i, size, sign, steps, step_size_uv, rc; u32 *fuse_sel, *tmp; struct property *prop; prop = of_find_property(of_node, "qcom,cpr-fuse-init-voltage", NULL); if (!prop) { pr_err("qcom,cpr-fuse-init-voltage is missing\n"); return -EINVAL; } size = prop->length / sizeof(u32); if (size != (CPR_FUSE_CORNER_MAX - 1) * 4) { pr_err("fuse position for init voltages is invalid\n"); return -EINVAL; } fuse_sel = kzalloc(sizeof(u32) * size, GFP_KERNEL); if (!fuse_sel) { pr_err("memory alloc failed.\n"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-init-voltage", fuse_sel, size); if (rc < 0) { pr_err("read cpr-fuse-init-voltage failed, rc = %d\n", rc); kfree(fuse_sel); return rc; } rc = of_property_read_u32(of_node, "qcom,cpr-init-voltage-step", &step_size_uv); if (rc < 0) { pr_err("read cpr-init-voltage-step failed, rc = %d\n", rc); kfree(fuse_sel); return rc; } tmp = fuse_sel; for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) { efuse_bits = cpr_read_efuse_row(cpr_vreg, fuse_sel[0], fuse_sel[3]); sign = (efuse_bits >> fuse_sel[1]) & (1 << (fuse_sel[2] - 1)); sign = ((sign == 0) ? 1 : -1); steps = (efuse_bits >> fuse_sel[1]) & ((1 << (fuse_sel[2] - 1)) - 1); pr_debug("corner %d: sign = %d, steps = %d\n", i, sign, steps); cpr_vreg->pvs_corner_v[i] = cpr_vreg->ceiling_volt[i] + sign * steps * step_size_uv; cpr_vreg->pvs_corner_v[i] = DIV_ROUND_UP( cpr_vreg->pvs_corner_v[i], cpr_vreg->step_volt) * cpr_vreg->step_volt; if (cpr_vreg->pvs_corner_v[i] > cpr_vreg->ceiling_volt[i]) { pr_info("Warning: initial voltage[%d] %d above ceiling %d\n", i, cpr_vreg->pvs_corner_v[i], cpr_vreg->ceiling_volt[i]); cpr_vreg->pvs_corner_v[i] = cpr_vreg->ceiling_volt[i]; } else if (cpr_vreg->pvs_corner_v[i] < cpr_vreg->floor_volt[i]) { pr_info("Warning: initial voltage[%d] %d below floor %d\n", i, cpr_vreg->pvs_corner_v[i], cpr_vreg->floor_volt[i]); cpr_vreg->pvs_corner_v[i] = cpr_vreg->floor_volt[i]; } fuse_sel += 4; } kfree(tmp); return 0; } /* * A single PVS bin is stored in a fuse that's position is defined either * in the qcom,pvs-fuse-redun property or in the qcom,pvs-fuse property. * The fuse value defined in the qcom,pvs-fuse-redun-sel property is used * to pick between the primary or redudant PVS fuse position. * After the PVS bin value is read out successfully, it is used as the row * index to get initial voltages for each fuse corner from the voltage table * defined in the qcom,pvs-voltage-table property. */ static int cpr_pvs_single_bin_init(struct device_node *of_node, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; u64 efuse_bits; int rc, i, stripe_size; u32 pvs_fuse[4], pvs_fuse_redun_sel[5]; int rc, i, stripe_size; bool redundant; size_t pvs_bins; u32 *tmp; Loading @@ -1112,7 +1199,6 @@ static int cpr_pvs_init(struct platform_device *pdev, } redundant = cpr_fuse_is_setting_expected(cpr_vreg, pvs_fuse_redun_sel); if (redundant) { rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun", pvs_fuse, 4); Loading @@ -1130,13 +1216,10 @@ static int cpr_pvs_init(struct platform_device *pdev, } /* Construct PVS process # from the efuse bits */ efuse_bits = cpr_read_efuse_row(cpr_vreg, pvs_fuse[0], pvs_fuse[3]); cpr_vreg->pvs_bin = (efuse_bits >> pvs_fuse[1]) & ((1 << pvs_fuse[2]) - 1); pvs_bins = 1 << pvs_fuse[2]; stripe_size = CPR_FUSE_CORNER_MAX - 1; tmp = kzalloc(sizeof(u32) * pvs_bins * stripe_size, GFP_KERNEL); if (!tmp) { Loading @@ -1157,6 +1240,46 @@ static int cpr_pvs_init(struct platform_device *pdev, stripe_size + i - 1]; kfree(tmp); return 0; } /* * The initial voltage for each fuse corner may be determined by one of two * possible styles of fuse. If qcom,cpr-fuse-init-voltage is present, then * the initial voltages are encoded in a fuse for each fuse corner. If it is * not present, then the initial voltages are all determined using a single * PVS bin fuse value. */ static int cpr_pvs_init(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; int i, rc; rc = of_property_read_u32(of_node, "qcom,cpr-apc-volt-step", &cpr_vreg->step_volt); if (rc < 0) { pr_err("read cpr-apc-volt-step failed, rc = %d\n", rc); return rc; } else if (cpr_vreg->step_volt == 0) { pr_err("apc voltage step size can't be set to 0.\n"); return -EINVAL; } if (of_find_property(of_node, "qcom,cpr-fuse-init-voltage", NULL)) { rc = cpr_pvs_per_corner_init(of_node, cpr_vreg); if (rc < 0) { pr_err("get pvs per corner failed, rc = %d", rc); return rc; } } else { rc = cpr_pvs_single_bin_init(of_node, cpr_vreg); if (rc < 0) { pr_err("get pvs from single bin failed, rc = %d", rc); return rc; } } if (cpr_vreg->flags & FLAGS_UPLIFT_QUOT_VOLT) { rc = cpr_voltage_uplift_wa_inc_volt(cpr_vreg, of_node); if (rc < 0) { Loading Loading @@ -1784,10 +1907,6 @@ static int cpr_init_cpr_parameters(struct platform_device *pdev, &cpr_vreg->vdd_apc_step_down_limit, rc); if (rc) return rc; CPR_PROP_READ_U32(of_node, "cpr-apc-volt-step", &cpr_vreg->step_volt, rc); if (rc) return rc; /* Init module parameter with the DT value */ cpr_vreg->enable = of_property_read_bool(of_node, "qcom,cpr-enable"); Loading Loading
Documentation/devicetree/bindings/regulator/cpr-regulator.txt +57 −32 Original line number Diff line number Diff line Loading @@ -22,10 +22,6 @@ Required properties: should be 1 for SVS corner - regulator-max-microvolt: Maximum corner value as max constraint, which should be 4 for SUPER_TURBO or 3 for TURBO - qcom,pvs-voltage-table: Array of triples in which each triple indicates the initial voltage of the PVS bin in SVS, NOM and Turbo corner in microvolts. The location or 0-based index of an triple in the list corresponds to the bin number. - qcom,cpr-voltage-ceiling: Ceiling voltages of SVS, NOM and TURBO corners respectively - qcom,cpr-voltage-floor: Floor voltages of SVS, NOM and TURBO corners respectively The ceiling voltages for each of above two Loading @@ -52,33 +48,6 @@ Required properties: - qcom,cpr-idle-clocks: Idle clock cycles RO can be in. - qcom,cpr-gcnt-time: The time for gate count in microseconds. - qcom,cpr-apc-volt-step: The voltage in microvolt per CPR step, such as 5000uV. - qcom,pvs-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant PVS fuse bits would be used instead of the original bits and method to read fuse row, reading register through SCM or directly. The 5 elements with index [0..4] are: [0] => the fuse row number of the selector [1] => LSB bit position of the bits [2] => number of bits [3] => the value to indicate redundant selection [4] => fuse reading method, 0 for direct reading or 1 for SCM reading When the value of the fuse bits specified by first 3 elements equals to the value in 4th element, redundant PVS fuse bits should be selected. Otherwise, the original PVS bits should be selected. If the 5th element is 0, read the fuse row from register directly. Otherwise, read it through SCM. - qcom,pvs-fuse: Array of 4 elements to indicate the bits for PVS fuse and read method. The array should have index and value like this: [0] => the PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading - qcom,pvs-fuse-redun: Array of 4 elements to indicate the bits for redundant PVS fuse. The array should have index and value like this: [0] => the redundant PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading - qcom,cpr-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant CPR fuse bits would be used instead of the original bits and method to read fuse row, using SCM Loading Loading @@ -146,6 +115,41 @@ Optional properties: [1] => voltage to set for vdd-mx when VDD_APC is running at NOM corner [2] => voltage to set for vdd-mx when VDD_APC is running at TURBO corner This is required when the qcom,vdd-mx-vmin-method property has a value of 4. - qcom,pvs-voltage-table: Array of triples in which each triple indicates the initial voltage of the PVS bin in SVS, NOM and Turbo corner in microvolts. The location or 0-based index of an triple in the list corresponds to the bin number. A given cpr-regulator device must have either qcom,pvs-voltage-table specified or qcom,cpr-fuse-init-voltage (and its associated properties). - qcom,pvs-fuse-redun-sel: Array of 5 elements to indicate where to read the bits, what value to compare with in order to decide if the redundant PVS fuse bits would be used instead of the original bits and method to read fuse row, reading register through SCM or directly. The 5 elements with index [0..4] are: [0] => the fuse row number of the selector [1] => LSB bit position of the bits [2] => number of bits [3] => the value to indicate redundant selection [4] => fuse reading method, 0 for direct reading or 1 for SCM reading When the value of the fuse bits specified by first 3 elements equals to the value in 4th element, redundant PVS fuse bits should be selected. Otherwise, the original PVS bits should be selected. If the 5th element is 0, read the fuse row from register directly. Otherwise, read it through SCM. This property is required if qcom,pvs-voltage-table is present. - qcom,pvs-fuse: Array of 4 elements to indicate the bits for PVS fuse and read method. The array should have index and value like this: [0] => the PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading This property is required if qcom,pvs-voltage-table is present. - qcom,pvs-fuse-redun: Array of 4 elements to indicate the bits for redundant PVS fuse. The array should have index and value like this: [0] => the redundant PVS fuse row number [1] => LSB bit position of the bits [2] => number of bits [3] => fuse reading method, 0 for direct reading or 1 for SCM reading This property is required if qcom,pvs-voltage-table is present. - qcom,cpr-fuse-redun-bp-cpr-disable: Redundant bit position of the bit to indicate if CPR should be disable - qcom,cpr-fuse-redun-bp-scheme: Redundant bit position of the bit to indicate if it's a global/local scheme This property is required if cpr-fuse-redun-bp-cpr-disable Loading Loading @@ -251,7 +255,23 @@ Optional properties: corresponds to 'scaling' in this equation: quot_adjust = (freq_turbo - freq_corner) * scaling / 1000. This property is required if qcom,cpr-speed-bin-max-corners is present. - qcom,cpr-fuse-init-voltage: Array of quadruples in which each quadruple specifies a fuse location to read in order to get an initial voltage for the SVS, NORMAL, or TURBO fuse corner. The fuse values are encoded as voltage steps higher or lower than the voltages defined in qcom,cpr-voltage-ceiling. Each step corresponds to the voltage defined by the qcom,cpr-init-voltage-step property. The 4 elements in one quadruple are: [0]: => the fuse row number of the bits [1]: => LSB bit position of the bits [2]: => number of the bits [3]: => fuse reading method, 0 for direct reading or 1 for SCM reading The quadruples are ordered from the lowest voltage fuse corner to the highest voltage fuse corner. A given cpr-regulator device must have either qcom,cpr-fuse-init-voltage specified or qcom,pvs-voltage-table (and its associated properties). - qcom,cpr-init-voltage-step: The voltage step size in microvolts of the CPR initial voltage fuses described by the qcom,cpr-fuse-init-voltage property. This property is required if qcom,cpr-fuse-init-voltage is present. Example: apc_vreg_corner: regulator@f9018000 { status = "okay"; Loading Loading @@ -360,5 +380,10 @@ Example: <2 1 2 4 10>, <5 1 2 4 14>; qcom,cpr-quot-adjust-scaling-factor-max = <650>; qcom,cpr-fuse-init-voltage = <27 36 6 0>, <27 18 6 0>, <27 0 6 0>; qcom,cpr-init-voltage-step = <10000>; };
drivers/regulator/cpr-regulator.c +136 −17 Original line number Diff line number Diff line Loading @@ -1093,13 +1093,100 @@ static int cpr_voltage_uplift_wa_inc_volt(struct cpr_regulator *cpr_vreg, return rc; } static int cpr_pvs_init(struct platform_device *pdev, /* * Property qcom,cpr-fuse-init-voltage specifies the fuse position of the * initial voltage for each fuse corner. MSB of the fuse value is a sign * bit, and the remaining bits define the steps of the offset. Each step has * units of microvolts defined in the qcom,cpr-fuse-init-voltage-step property. * The initial voltages can be calculated using the formula: * pvs_corner_v[corner] = ceiling_volt[corner] + (sign * steps * step_size_uv) */ static int cpr_pvs_per_corner_init(struct device_node *of_node, struct cpr_regulator *cpr_vreg) { u64 efuse_bits; int i, size, sign, steps, step_size_uv, rc; u32 *fuse_sel, *tmp; struct property *prop; prop = of_find_property(of_node, "qcom,cpr-fuse-init-voltage", NULL); if (!prop) { pr_err("qcom,cpr-fuse-init-voltage is missing\n"); return -EINVAL; } size = prop->length / sizeof(u32); if (size != (CPR_FUSE_CORNER_MAX - 1) * 4) { pr_err("fuse position for init voltages is invalid\n"); return -EINVAL; } fuse_sel = kzalloc(sizeof(u32) * size, GFP_KERNEL); if (!fuse_sel) { pr_err("memory alloc failed.\n"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-init-voltage", fuse_sel, size); if (rc < 0) { pr_err("read cpr-fuse-init-voltage failed, rc = %d\n", rc); kfree(fuse_sel); return rc; } rc = of_property_read_u32(of_node, "qcom,cpr-init-voltage-step", &step_size_uv); if (rc < 0) { pr_err("read cpr-init-voltage-step failed, rc = %d\n", rc); kfree(fuse_sel); return rc; } tmp = fuse_sel; for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) { efuse_bits = cpr_read_efuse_row(cpr_vreg, fuse_sel[0], fuse_sel[3]); sign = (efuse_bits >> fuse_sel[1]) & (1 << (fuse_sel[2] - 1)); sign = ((sign == 0) ? 1 : -1); steps = (efuse_bits >> fuse_sel[1]) & ((1 << (fuse_sel[2] - 1)) - 1); pr_debug("corner %d: sign = %d, steps = %d\n", i, sign, steps); cpr_vreg->pvs_corner_v[i] = cpr_vreg->ceiling_volt[i] + sign * steps * step_size_uv; cpr_vreg->pvs_corner_v[i] = DIV_ROUND_UP( cpr_vreg->pvs_corner_v[i], cpr_vreg->step_volt) * cpr_vreg->step_volt; if (cpr_vreg->pvs_corner_v[i] > cpr_vreg->ceiling_volt[i]) { pr_info("Warning: initial voltage[%d] %d above ceiling %d\n", i, cpr_vreg->pvs_corner_v[i], cpr_vreg->ceiling_volt[i]); cpr_vreg->pvs_corner_v[i] = cpr_vreg->ceiling_volt[i]; } else if (cpr_vreg->pvs_corner_v[i] < cpr_vreg->floor_volt[i]) { pr_info("Warning: initial voltage[%d] %d below floor %d\n", i, cpr_vreg->pvs_corner_v[i], cpr_vreg->floor_volt[i]); cpr_vreg->pvs_corner_v[i] = cpr_vreg->floor_volt[i]; } fuse_sel += 4; } kfree(tmp); return 0; } /* * A single PVS bin is stored in a fuse that's position is defined either * in the qcom,pvs-fuse-redun property or in the qcom,pvs-fuse property. * The fuse value defined in the qcom,pvs-fuse-redun-sel property is used * to pick between the primary or redudant PVS fuse position. * After the PVS bin value is read out successfully, it is used as the row * index to get initial voltages for each fuse corner from the voltage table * defined in the qcom,pvs-voltage-table property. */ static int cpr_pvs_single_bin_init(struct device_node *of_node, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; u64 efuse_bits; int rc, i, stripe_size; u32 pvs_fuse[4], pvs_fuse_redun_sel[5]; int rc, i, stripe_size; bool redundant; size_t pvs_bins; u32 *tmp; Loading @@ -1112,7 +1199,6 @@ static int cpr_pvs_init(struct platform_device *pdev, } redundant = cpr_fuse_is_setting_expected(cpr_vreg, pvs_fuse_redun_sel); if (redundant) { rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun", pvs_fuse, 4); Loading @@ -1130,13 +1216,10 @@ static int cpr_pvs_init(struct platform_device *pdev, } /* Construct PVS process # from the efuse bits */ efuse_bits = cpr_read_efuse_row(cpr_vreg, pvs_fuse[0], pvs_fuse[3]); cpr_vreg->pvs_bin = (efuse_bits >> pvs_fuse[1]) & ((1 << pvs_fuse[2]) - 1); pvs_bins = 1 << pvs_fuse[2]; stripe_size = CPR_FUSE_CORNER_MAX - 1; tmp = kzalloc(sizeof(u32) * pvs_bins * stripe_size, GFP_KERNEL); if (!tmp) { Loading @@ -1157,6 +1240,46 @@ static int cpr_pvs_init(struct platform_device *pdev, stripe_size + i - 1]; kfree(tmp); return 0; } /* * The initial voltage for each fuse corner may be determined by one of two * possible styles of fuse. If qcom,cpr-fuse-init-voltage is present, then * the initial voltages are encoded in a fuse for each fuse corner. If it is * not present, then the initial voltages are all determined using a single * PVS bin fuse value. */ static int cpr_pvs_init(struct platform_device *pdev, struct cpr_regulator *cpr_vreg) { struct device_node *of_node = pdev->dev.of_node; int i, rc; rc = of_property_read_u32(of_node, "qcom,cpr-apc-volt-step", &cpr_vreg->step_volt); if (rc < 0) { pr_err("read cpr-apc-volt-step failed, rc = %d\n", rc); return rc; } else if (cpr_vreg->step_volt == 0) { pr_err("apc voltage step size can't be set to 0.\n"); return -EINVAL; } if (of_find_property(of_node, "qcom,cpr-fuse-init-voltage", NULL)) { rc = cpr_pvs_per_corner_init(of_node, cpr_vreg); if (rc < 0) { pr_err("get pvs per corner failed, rc = %d", rc); return rc; } } else { rc = cpr_pvs_single_bin_init(of_node, cpr_vreg); if (rc < 0) { pr_err("get pvs from single bin failed, rc = %d", rc); return rc; } } if (cpr_vreg->flags & FLAGS_UPLIFT_QUOT_VOLT) { rc = cpr_voltage_uplift_wa_inc_volt(cpr_vreg, of_node); if (rc < 0) { Loading Loading @@ -1784,10 +1907,6 @@ static int cpr_init_cpr_parameters(struct platform_device *pdev, &cpr_vreg->vdd_apc_step_down_limit, rc); if (rc) return rc; CPR_PROP_READ_U32(of_node, "cpr-apc-volt-step", &cpr_vreg->step_volt, rc); if (rc) return rc; /* Init module parameter with the DT value */ cpr_vreg->enable = of_property_read_bool(of_node, "qcom,cpr-enable"); Loading