Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a772daf5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: mem-acc-regulator: Add override ACC configuration support"

parents c7585e1f d8403507
Loading
Loading
Loading
Loading
+36 −6
Original line number Diff line number Diff line
@@ -64,11 +64,6 @@ Optional properties:
				configuration logic is skipped. Otherwise, the original configuration sent
				from corner map should be applied. If the 5th element is 0, read the fuse row
				from register directly. Otherwise, read it through SCM.
- qcom,skip-l2-custom-on-l1:	A boolean property which specifies the dependency of L2 ACC custom data
				configuration on L1 MEM ACC configuration. This property is applicable
				where both L1 and L2 share the same ACC_SEL configuration. If the property
				is specified in the device node, skip L2 ACC custom data configuration
				whenever the L1 MEM ACC configuration is skipped.
- qcom,l1-acc-custom-data:	Array which maps APC corner values to L1 ACC custom data values.
				The corresponding custom data is written into the custom register
				while switching between APC corners. The custom register address
@@ -79,6 +74,39 @@ Optional properties:
				while switching between APC corners. The custom register address
				is specified by "acc-l2-custom" reg-property. The length of the array
				should be equal to number of APC corners.
- qcom,override-acc-fuse-sel:	Array of 5 elements to indicate where to read the bits, what value to
				compare with in order to decide whether to
				apply override acc-map and custom data or not
				and method to read fuse row, using SCM to read or read register 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 select override ACC configuration
				  [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, overridden accelerator configuration logic is applied.
				Otherwise, the original configuration should be applied. If the 5th element is 0,
				read the fuse row from register directly. Otherwise, read it through SCM.
- qcom,override-corner-acc-map:	Array which overrides the existing acc-corner map (specified by qcom,corner-acc-map)
				with corner values specified in this property.
				[0] maps APC SVS corner (1) to accelerator SVS corner
				[1] maps APC NOMINAL corner (2) to accelerator NOMINAL corner
				[2] maps APC TURBO corner (3) to accelerator TURBO corner
- qcom,override-l1-acc-custom-data:	Array which overrides the existing l1-acc-custom data
				(specified by qcom,l1-acc-custom-data), with values specified in this property.
				The corresponding custom data is written into the custom register
				while switching between APC corners. The custom register address
				is specified by "acc-11-custom" reg-property. The length of the array
				should be equal to number of APC corners.
				This property can only be specified if the "qcom,l1-acc-custom-data" is already defined.
- qcom,override-l2-acc-custom-data:	Array which overrides the existing l2-acc-custom data
				(specified by qcom,l2-acc-custom-data) with values specified in this property.
				The corresponding custom data is written into the custom register
				while switching between APC corners. The custom register address
				is specified by "acc-l2-custom" reg-property. The length of the array
				should be equal to number of APC corners.
				This property can only be specified if the " qcom,l2-acc-custom-data" is already defined.

mem_acc_vreg_corner: regulator@fd4aa044 {
	compatible = "qcom,mem-acc-regulator";
@@ -97,6 +125,8 @@ mem_acc_vreg_corner: regulator@fd4aa044 {
	qcom,acc-sel-l2-bit-size = <2>;
	qcom,corner-acc-map = <0 1 3>;
	qcom,l1-config-skip-fuse-sel = <0 52 1 1 0>;
	qcom,skip-l2-custom-on-l1;
	qcom,l2-acc-custom-data = <0x0 0x3000 0x3000>;
	qcom,override-acc-fuse-sel = <0 52 1 1 0>;
	qcom,override-corner-acc-map = <0 0 1>;
	qcom,overide-l2-acc-custom-data = <0x0 0x0 0x3000>;
};
+94 −18
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@

/* mem-acc config flags */
#define MEM_ACC_SKIP_L1_CONFIG		BIT(0)
#define MEM_ACC_OVERRIDE_CONFIG		BIT(1)

enum {
	MEMORY_L1,
@@ -409,7 +410,8 @@ static int mem_acc_efuse_init(struct platform_device *pdev,

	pr_info("efuse_addr = %pa (len=0x%x)\n", &res->start, len);

	mem_acc_vreg->efuse_base = ioremap(mem_acc_vreg->efuse_addr, len);
	mem_acc_vreg->efuse_base = devm_ioremap(&pdev->dev,
						mem_acc_vreg->efuse_addr, len);
	if (!mem_acc_vreg->efuse_base) {
		pr_err("Unable to map efuse_addr %pa\n",
				&mem_acc_vreg->efuse_addr);
@@ -424,7 +426,7 @@ static int mem_acc_efuse_init(struct platform_device *pdev,
		if (rc < 0) {
			pr_err("Read failed - qcom,l1-config-skip-fuse-sel rc=%d\n",
					rc);
			goto err_out;
			return rc;
		}

		if (mem_acc_fuse_is_setting_expected(mem_acc_vreg,
@@ -434,10 +436,7 @@ static int mem_acc_efuse_init(struct platform_device *pdev,
		}
	}


err_out:
	iounmap(mem_acc_vreg->efuse_base);
	return rc;
	return 0;
}

static int mem_acc_custom_data_init(struct platform_device *pdev,
@@ -498,19 +497,48 @@ static int mem_acc_custom_data_init(struct platform_device *pdev,

	mem_acc_vreg->mem_acc_custom_supported[mem_type] = true;

	/*
	 * there is a possibility that L2 and L1 MEM_ACC_SEL configuration
	 * bits are shared. In such a case the L2-custom ACC configuration
	 * may not be needed for those parts which have valid skip-l1
	 * fuse
	 */
	return 0;
}

	if (mem_type == MEMORY_L2 &&
		(mem_acc_vreg->flags & MEM_ACC_SKIP_L1_CONFIG) &&
		(of_property_read_bool(mem_acc_vreg->dev->of_node,
					"qcom,skip-l2-custom-on-l1"))) {
		pr_debug("Skip L2 custom data configuration\n");
		mem_acc_vreg->mem_acc_custom_supported[mem_type] = false;
static int override_mem_acc_custom_data(struct platform_device *pdev,
				 struct mem_acc_regulator *mem_acc_vreg,
				 int mem_type)
{
	char *custom_apc_data_str;
	int len, rc = 0;

	switch (mem_type) {
	case MEMORY_L1:
		custom_apc_data_str = "qcom,override-l1-acc-custom-data";
		break;
	case MEMORY_L2:
		custom_apc_data_str = "qcom,override-l2-acc-custom-data";
		break;
	default:
		pr_err("Invalid memory type: %d\n", mem_type);
		return -EINVAL;
	}

	if (!of_find_property(mem_acc_vreg->dev->of_node,
				custom_apc_data_str, NULL)) {
		pr_debug("%s not specified\n", custom_apc_data_str);
		return 0;
	}

	/* Free old custom data */
	devm_kfree(&pdev->dev, mem_acc_vreg->acc_custom_data[mem_type]);

	/* Populate override custom data */
	rc = populate_acc_data(mem_acc_vreg, custom_apc_data_str,
				&mem_acc_vreg->acc_custom_data[mem_type], &len);
	if (rc) {
		pr_err("Unable to find %s rc=%d\n", custom_apc_data_str, rc);
		return rc;
	}

	if (mem_acc_vreg->num_corners != len) {
		pr_err("Override custom data is not present for all the corners\n");
		return -EINVAL;
	}

	return 0;
@@ -521,6 +549,7 @@ static int mem_acc_init(struct platform_device *pdev,
{
	struct resource *res;
	int len, rc, i;
	u32 override_acc_fuse_sel[5];

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acc-en");
	if (!res || !res->start) {
@@ -618,6 +647,53 @@ static int mem_acc_init(struct platform_device *pdev,
		}
	}

	if (of_find_property(mem_acc_vreg->dev->of_node,
				"qcom,override-acc-fuse-sel", NULL)) {
		rc = of_property_read_u32_array(mem_acc_vreg->dev->of_node,
					"qcom,override-acc-fuse-sel",
					override_acc_fuse_sel, 5);
		if (rc < 0) {
			pr_err("Read failed - qcom,override-acc-fuse-sel rc=%d\n",
					rc);
			return rc;
		}

		if (mem_acc_fuse_is_setting_expected(mem_acc_vreg,
						override_acc_fuse_sel)) {
			mem_acc_vreg->flags |= MEM_ACC_OVERRIDE_CONFIG;
			pr_debug("Apply ACC override configuration\n");
		}
	}

	if (mem_acc_vreg->flags & MEM_ACC_OVERRIDE_CONFIG) {
		if (of_find_property(mem_acc_vreg->dev->of_node,
				"qcom,override-corner-acc-map", NULL)) {
			/* Free old corner-acc-map */
			devm_kfree(&pdev->dev, mem_acc_vreg->corner_acc_map);

			/* Populate override corner acc map */
			rc = populate_acc_data(mem_acc_vreg,
						"qcom,override-corner-acc-map",
						&mem_acc_vreg->corner_acc_map,
						&mem_acc_vreg->num_corners);
			if (rc) {
				pr_err("Unable to find 'qcom,overrie-corner-acc-map' rc=%d\n",
					rc);
				return rc;
			}
		}

		for (i = 0; i < MEMORY_MAX; i++) {
			rc = override_mem_acc_custom_data(pdev,
							mem_acc_vreg, i);
			if (rc) {
				pr_err("Unable to override custom data for mem_type=%d rc=%d\n",
					i, rc);
				return rc;
			}
		}
	}

	return 0;
}