Loading Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt +36 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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"; Loading @@ -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>; }; drivers/regulator/mem-acc-regulator.c +94 −18 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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); Loading @@ -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, Loading @@ -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, Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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; } Loading Loading
Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt +36 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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"; Loading @@ -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>; };
drivers/regulator/mem-acc-regulator.c +94 −18 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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); Loading @@ -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, Loading @@ -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, Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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; } Loading