Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: samsung: Add Exynos Adaptive Supply Voltage driver

The Adaptive Supply Voltage (ASV) driver adjusts CPU cluster operating
points depending on exact revision of an SoC retrieved from the CHIPID
block or the OTP memory. This allows for some power saving as for some
CPU clock frequencies we can lower CPU cluster's supply voltage comparing
to safe values common to all the SoC revisions.

This patch adds support for Exynos5422/5800 SoC, it is partially based
on code from https://github.com/hardkernel/linux repository,
branch odroidxu4-4.14.y, files: arch/arm/mach-exynos/exynos5422-asv.[ch].

Tested on Odroid XU3, XU4, XU3 Lite.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

authored by

Sylwester Nawrocki and committed by
Krzysztof Kozlowski
5ea42859 477f842f

+797
+10
drivers/soc/samsung/Kconfig
··· 7 7 8 8 if SOC_SAMSUNG 9 9 10 + config EXYNOS_ASV 11 + bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST 12 + depends on (ARCH_EXYNOS && EXYNOS_CHIPID) || COMPILE_TEST 13 + select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS 14 + 15 + # There is no need to enable these drivers for ARMv8 16 + config EXYNOS_ASV_ARM 17 + bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST 18 + depends on EXYNOS_ASV 19 + 10 20 config EXYNOS_CHIPID 11 21 bool "Exynos Chipid controller driver" if COMPILE_TEST 12 22 depends on ARCH_EXYNOS || COMPILE_TEST
+3
drivers/soc/samsung/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 + obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o 4 + obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o 5 + 3 6 obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o 4 7 obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o 5 8
+177
drivers/soc/samsung/exynos-asv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 + * http://www.samsung.com/ 5 + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> 6 + * 7 + * Samsung Exynos SoC Adaptive Supply Voltage support 8 + */ 9 + 10 + #include <linux/cpu.h> 11 + #include <linux/device.h> 12 + #include <linux/errno.h> 13 + #include <linux/init.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/module.h> 16 + #include <linux/of.h> 17 + #include <linux/of_device.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/pm_opp.h> 20 + #include <linux/regmap.h> 21 + #include <linux/soc/samsung/exynos-chipid.h> 22 + 23 + #include "exynos-asv.h" 24 + #include "exynos5422-asv.h" 25 + 26 + #define MHZ 1000000U 27 + 28 + static int exynos_asv_update_cpu_opps(struct exynos_asv *asv, 29 + struct device *cpu) 30 + { 31 + struct exynos_asv_subsys *subsys = NULL; 32 + struct dev_pm_opp *opp; 33 + unsigned int opp_freq; 34 + int i; 35 + 36 + for (i = 0; i < ARRAY_SIZE(asv->subsys); i++) { 37 + if (of_device_is_compatible(cpu->of_node, 38 + asv->subsys[i].cpu_dt_compat)) { 39 + subsys = &asv->subsys[i]; 40 + break; 41 + } 42 + } 43 + if (!subsys) 44 + return -EINVAL; 45 + 46 + for (i = 0; i < subsys->table.num_rows; i++) { 47 + unsigned int new_volt, volt; 48 + int ret; 49 + 50 + opp_freq = exynos_asv_opp_get_frequency(subsys, i); 51 + 52 + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq * MHZ, true); 53 + if (IS_ERR(opp)) { 54 + dev_info(asv->dev, "cpu%d opp%d, freq: %u missing\n", 55 + cpu->id, i, opp_freq); 56 + 57 + continue; 58 + } 59 + 60 + volt = dev_pm_opp_get_voltage(opp); 61 + new_volt = asv->opp_get_voltage(subsys, i, volt); 62 + dev_pm_opp_put(opp); 63 + 64 + if (new_volt == volt) 65 + continue; 66 + 67 + ret = dev_pm_opp_adjust_voltage(cpu, opp_freq * MHZ, 68 + new_volt, new_volt, new_volt); 69 + if (ret < 0) 70 + dev_err(asv->dev, 71 + "Failed to adjust OPP %u Hz/%u uV for cpu%d\n", 72 + opp_freq, new_volt, cpu->id); 73 + else 74 + dev_dbg(asv->dev, 75 + "Adjusted OPP %u Hz/%u -> %u uV, cpu%d\n", 76 + opp_freq, volt, new_volt, cpu->id); 77 + } 78 + 79 + return 0; 80 + } 81 + 82 + static int exynos_asv_update_opps(struct exynos_asv *asv) 83 + { 84 + struct opp_table *last_opp_table = NULL; 85 + struct device *cpu; 86 + int ret, cpuid; 87 + 88 + for_each_possible_cpu(cpuid) { 89 + struct opp_table *opp_table; 90 + 91 + cpu = get_cpu_device(cpuid); 92 + if (!cpu) 93 + continue; 94 + 95 + opp_table = dev_pm_opp_get_opp_table(cpu); 96 + if (IS_ERR(opp_table)) 97 + continue; 98 + 99 + if (!last_opp_table || opp_table != last_opp_table) { 100 + last_opp_table = opp_table; 101 + 102 + ret = exynos_asv_update_cpu_opps(asv, cpu); 103 + if (ret < 0) 104 + dev_err(asv->dev, "Couldn't udate OPPs for cpu%d\n", 105 + cpuid); 106 + } 107 + 108 + dev_pm_opp_put_opp_table(opp_table); 109 + } 110 + 111 + return 0; 112 + } 113 + 114 + static int exynos_asv_probe(struct platform_device *pdev) 115 + { 116 + int (*probe_func)(struct exynos_asv *asv); 117 + struct exynos_asv *asv; 118 + struct device *cpu_dev; 119 + u32 product_id = 0; 120 + int ret, i; 121 + 122 + cpu_dev = get_cpu_device(0); 123 + ret = dev_pm_opp_get_opp_count(cpu_dev); 124 + if (ret < 0) 125 + return -EPROBE_DEFER; 126 + 127 + asv = devm_kzalloc(&pdev->dev, sizeof(*asv), GFP_KERNEL); 128 + if (!asv) 129 + return -ENOMEM; 130 + 131 + asv->chipid_regmap = device_node_to_regmap(pdev->dev.of_node); 132 + if (IS_ERR(asv->chipid_regmap)) { 133 + dev_err(&pdev->dev, "Could not find syscon regmap\n"); 134 + return PTR_ERR(asv->chipid_regmap); 135 + } 136 + 137 + regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id); 138 + 139 + switch (product_id & EXYNOS_MASK) { 140 + case 0xE5422000: 141 + probe_func = exynos5422_asv_init; 142 + break; 143 + default: 144 + return -ENODEV; 145 + } 146 + 147 + ret = of_property_read_u32(pdev->dev.of_node, "samsung,asv-bin", 148 + &asv->of_bin); 149 + if (ret < 0) 150 + asv->of_bin = -EINVAL; 151 + 152 + asv->dev = &pdev->dev; 153 + dev_set_drvdata(&pdev->dev, asv); 154 + 155 + for (i = 0; i < ARRAY_SIZE(asv->subsys); i++) 156 + asv->subsys[i].asv = asv; 157 + 158 + ret = probe_func(asv); 159 + if (ret < 0) 160 + return ret; 161 + 162 + return exynos_asv_update_opps(asv); 163 + } 164 + 165 + static const struct of_device_id exynos_asv_of_device_ids[] = { 166 + { .compatible = "samsung,exynos4210-chipid" }, 167 + {} 168 + }; 169 + 170 + static struct platform_driver exynos_asv_driver = { 171 + .driver = { 172 + .name = "exynos-asv", 173 + .of_match_table = exynos_asv_of_device_ids, 174 + }, 175 + .probe = exynos_asv_probe, 176 + }; 177 + module_platform_driver(exynos_asv_driver);
+71
drivers/soc/samsung/exynos-asv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 + * http://www.samsung.com/ 5 + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> 6 + * 7 + * Samsung Exynos SoC Adaptive Supply Voltage support 8 + */ 9 + #ifndef __LINUX_SOC_EXYNOS_ASV_H 10 + #define __LINUX_SOC_EXYNOS_ASV_H 11 + 12 + struct regmap; 13 + 14 + /* HPM, IDS values to select target group */ 15 + struct asv_limit_entry { 16 + unsigned int hpm; 17 + unsigned int ids; 18 + }; 19 + 20 + struct exynos_asv_table { 21 + unsigned int num_rows; 22 + unsigned int num_cols; 23 + u32 *buf; 24 + }; 25 + 26 + struct exynos_asv_subsys { 27 + struct exynos_asv *asv; 28 + const char *cpu_dt_compat; 29 + int id; 30 + struct exynos_asv_table table; 31 + 32 + unsigned int base_volt; 33 + unsigned int offset_volt_h; 34 + unsigned int offset_volt_l; 35 + }; 36 + 37 + struct exynos_asv { 38 + struct device *dev; 39 + struct regmap *chipid_regmap; 40 + struct exynos_asv_subsys subsys[2]; 41 + 42 + int (*opp_get_voltage)(const struct exynos_asv_subsys *subs, 43 + int level, unsigned int voltage); 44 + unsigned int group; 45 + unsigned int table; 46 + 47 + /* True if SG fields from PKG_ID register should be used */ 48 + bool use_sg; 49 + /* ASV bin read from DT */ 50 + int of_bin; 51 + }; 52 + 53 + static inline u32 __asv_get_table_entry(const struct exynos_asv_table *table, 54 + unsigned int row, unsigned int col) 55 + { 56 + return table->buf[row * (table->num_cols) + col]; 57 + } 58 + 59 + static inline u32 exynos_asv_opp_get_voltage(const struct exynos_asv_subsys *subsys, 60 + unsigned int level, unsigned int group) 61 + { 62 + return __asv_get_table_entry(&subsys->table, level, group + 1); 63 + } 64 + 65 + static inline u32 exynos_asv_opp_get_frequency(const struct exynos_asv_subsys *subsys, 66 + unsigned int level) 67 + { 68 + return __asv_get_table_entry(&subsys->table, level, 0); 69 + } 70 + 71 + #endif /* __LINUX_SOC_EXYNOS_ASV_H */
+505
drivers/soc/samsung/exynos5422-asv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 + * http://www.samsung.com/ 5 + * 6 + * Samsung Exynos 5422 SoC Adaptive Supply Voltage support 7 + */ 8 + 9 + #include <linux/bitrev.h> 10 + #include <linux/errno.h> 11 + #include <linux/regmap.h> 12 + #include <linux/soc/samsung/exynos-chipid.h> 13 + #include <linux/slab.h> 14 + 15 + #include "exynos-asv.h" 16 + #include "exynos5422-asv.h" 17 + 18 + #define ASV_GROUPS_NUM 14 19 + #define ASV_ARM_DVFS_NUM 20 20 + #define ASV_ARM_BIN2_DVFS_NUM 17 21 + #define ASV_KFC_DVFS_NUM 14 22 + #define ASV_KFC_BIN2_DVFS_NUM 12 23 + 24 + /* 25 + * This array is a set of 4 ASV data tables, first column of each ASV table 26 + * contains frequency value in MHz and subsequent columns contain the CPU 27 + * cluster's supply voltage values in uV. 28 + * In order to create a set of OPPs for specific SoC revision one of the voltage 29 + * columns (1...14) from one of the tables (0...3) is selected during 30 + * initialization. There are separate ASV tables for the big (ARM) and little 31 + * (KFC) CPU cluster. Only OPPs which are already defined in devicetree 32 + * will be updated. 33 + */ 34 + 35 + static const u32 asv_arm_table[][ASV_ARM_DVFS_NUM][ASV_GROUPS_NUM + 1] = { 36 + { 37 + /* ARM 0, 1 */ 38 + { 2100, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 39 + 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 }, 40 + { 2000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 41 + 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 42 + { 1900, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 43 + 1162500, 1150000, 1162500, 1150000, 1137500, 1125000, 1112500 }, 44 + { 1800, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 45 + 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 }, 46 + { 1700, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 47 + 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 }, 48 + { 1600, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 49 + 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 }, 50 + { 1500, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 51 + 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 }, 52 + { 1400, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 53 + 975000, 962500, 975000, 962500, 950000, 937500, 925000 }, 54 + { 1300, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 55 + 962500, 950000, 962500, 950000, 937500, 925000, 912500 }, 56 + { 1200, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 57 + 937500, 925000, 937500, 925000, 912500, 900000, 900000 }, 58 + { 1100, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 59 + 912500, 900000, 900000, 900000, 900000, 900000, 900000 }, 60 + { 1000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 61 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 62 + { 900, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 63 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 64 + { 800, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 65 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 66 + { 700, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 67 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 68 + { 600, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 69 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 70 + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 71 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 72 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 73 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 74 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 75 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 76 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 77 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 78 + }, { 79 + /* ARM 2 */ 80 + { 2100, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 81 + 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 }, 82 + { 2000, 1312500, 1312500, 1312500, 1300000, 1275000, 1262500, 1250000, 83 + 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 84 + { 1900, 1262500, 1250000, 1250000, 1237500, 1212500, 1200000, 1187500, 85 + 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 }, 86 + { 1800, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 87 + 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 }, 88 + { 1700, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 89 + 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 }, 90 + { 1600, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 91 + 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 }, 92 + { 1500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 93 + 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 }, 94 + { 1400, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 95 + 987500, 975000, 987500, 975000, 962500, 950000, 937500 }, 96 + { 1300, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 97 + 962500, 950000, 962500, 950000, 937500, 925000, 912500 }, 98 + { 1200, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 99 + 937500, 925000, 937500, 925000, 912500, 900000, 900000 }, 100 + { 1100, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 101 + 912500, 900000, 900000, 900000, 900000, 900000, 900000 }, 102 + { 1000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 103 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 104 + { 900, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 105 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 106 + { 800, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 107 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 108 + { 700, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 109 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 110 + { 600, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 111 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 112 + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 113 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 114 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 115 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 116 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 117 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 118 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 119 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 120 + }, { 121 + /* ARM 3 */ 122 + { 2100, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 123 + 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 }, 124 + { 2000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 125 + 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 126 + { 1900, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 127 + 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 }, 128 + { 1800, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 129 + 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 }, 130 + { 1700, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 131 + 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 }, 132 + { 1600, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 133 + 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 }, 134 + { 1500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 135 + 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 }, 136 + { 1400, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 137 + 987500, 975000, 987500, 975000, 962500, 950000, 937500 }, 138 + { 1300, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 139 + 962500, 950000, 962500, 950000, 937500, 925000, 912500 }, 140 + { 1200, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 141 + 937500, 925000, 937500, 925000, 912500, 900000, 900000 }, 142 + { 1100, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 143 + 912500, 900000, 900000, 900000, 900000, 900000, 900000 }, 144 + { 1000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 145 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 146 + { 900, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 147 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 148 + { 800, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 149 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 150 + { 700, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 151 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 152 + { 600, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 153 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 154 + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 155 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 156 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 157 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 158 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 159 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 160 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 161 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 162 + }, { 163 + /* ARM bin 2 */ 164 + { 1800, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 165 + 1150000, 1137500, 1150000, 1137500, 1125000, 1112500, 1100000 }, 166 + { 1700, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 167 + 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 }, 168 + { 1600, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 169 + 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 }, 170 + { 1500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 171 + 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 }, 172 + { 1400, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 173 + 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 }, 174 + { 1300, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 175 + 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 }, 176 + { 1200, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 177 + 975000, 962500, 975000, 962500, 950000, 937500, 925000 }, 178 + { 1100, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 179 + 950000, 937500, 950000, 937500, 925000, 912500, 900000 }, 180 + { 1000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 181 + 925000, 912500, 925000, 912500, 900000, 900000, 900000 }, 182 + { 900, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 183 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 184 + { 800, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 185 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 186 + { 700, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 187 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 188 + { 600, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 189 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 190 + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 191 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 192 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 193 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 194 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 195 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 196 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 197 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 198 + } 199 + }; 200 + 201 + static const u32 asv_kfc_table[][ASV_KFC_DVFS_NUM][ASV_GROUPS_NUM + 1] = { 202 + { 203 + /* KFC 0, 1 */ 204 + { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 205 + 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 206 + { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 207 + 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 }, 208 + { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 209 + 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 }, 210 + { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 211 + 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 }, 212 + { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 213 + 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 }, 214 + { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 215 + 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 }, 216 + { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 217 + 975000, 962500, 950000, 937500, 925000, 912500, 900000 }, 218 + { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 219 + 937500, 925000, 912500, 900000, 900000, 900000, 900000 }, 220 + { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 221 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 222 + { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 223 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 224 + { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 225 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 226 + { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 227 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 228 + { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 229 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 230 + { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 231 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 232 + }, { 233 + /* KFC 2 */ 234 + { 1500, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 235 + 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 236 + { 1400, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 237 + 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 }, 238 + { 1300, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 239 + 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 }, 240 + { 1200, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 241 + 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 }, 242 + { 1100, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 243 + 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 }, 244 + { 1000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 245 + 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 }, 246 + { 900, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 247 + 975000, 962500, 950000, 937500, 925000, 912500, 900000 }, 248 + { 800, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 249 + 937500, 925000, 912500, 900000, 900000, 900000, 900000 }, 250 + { 700, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 251 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 252 + { 600, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 253 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 254 + { 500, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 255 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 256 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 257 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 258 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 259 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 260 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 261 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 262 + }, { 263 + /* KFC 3 */ 264 + { 1500, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 265 + 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 }, 266 + { 1400, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 267 + 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 }, 268 + { 1300, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 269 + 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 }, 270 + { 1200, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 271 + 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 }, 272 + { 1100, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 273 + 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 }, 274 + { 1000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 275 + 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 }, 276 + { 900, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 277 + 975000, 962500, 950000, 937500, 925000, 912500, 900000 }, 278 + { 800, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 279 + 937500, 925000, 912500, 900000, 900000, 900000, 900000 }, 280 + { 700, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 281 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 282 + { 600, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 283 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 284 + { 500, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 285 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 286 + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 287 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 288 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 289 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 290 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 291 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 292 + }, { 293 + /* KFC bin 2 */ 294 + { 1300, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 295 + 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500 }, 296 + { 1200, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 297 + 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500 }, 298 + { 1100, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 299 + 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000 }, 300 + { 1000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 301 + 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500 }, 302 + { 900, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 303 + 1000000, 987500, 975000, 962500, 950000, 937500, 925000 }, 304 + { 800, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 305 + 962500, 950000, 937500, 925000, 912500, 900000, 900000 }, 306 + { 700, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 307 + 925000, 912500, 900000, 900000, 900000, 900000, 900000 }, 308 + { 600, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 309 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 310 + { 500, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 311 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 312 + { 400, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 313 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 314 + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 315 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 316 + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 317 + 900000, 900000, 900000, 900000, 900000, 900000, 900000 }, 318 + } 319 + }; 320 + 321 + static const struct asv_limit_entry __asv_limits[ASV_GROUPS_NUM] = { 322 + { 13, 55 }, 323 + { 21, 65 }, 324 + { 25, 69 }, 325 + { 30, 72 }, 326 + { 36, 74 }, 327 + { 43, 76 }, 328 + { 51, 78 }, 329 + { 65, 80 }, 330 + { 81, 82 }, 331 + { 98, 84 }, 332 + { 119, 87 }, 333 + { 135, 89 }, 334 + { 150, 92 }, 335 + { 999, 999 }, 336 + }; 337 + 338 + static int exynos5422_asv_get_group(struct exynos_asv *asv) 339 + { 340 + unsigned int pkgid_reg, auxi_reg; 341 + int hpm, ids, i; 342 + 343 + regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PKG_ID, &pkgid_reg); 344 + regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_AUX_INFO, &auxi_reg); 345 + 346 + if (asv->use_sg) { 347 + u32 sga = (pkgid_reg >> EXYNOS5422_SG_A_OFFSET) & 348 + EXYNOS5422_SG_A_MASK; 349 + 350 + u32 sgb = (pkgid_reg >> EXYNOS5422_SG_B_OFFSET) & 351 + EXYNOS5422_SG_B_MASK; 352 + 353 + if ((pkgid_reg >> EXYNOS5422_SG_BSIGN_OFFSET) & 354 + EXYNOS5422_SG_BSIGN_MASK) 355 + return sga + sgb; 356 + else 357 + return sga - sgb; 358 + } 359 + 360 + hpm = (auxi_reg >> EXYNOS5422_TMCB_OFFSET) & EXYNOS5422_TMCB_MASK; 361 + ids = (pkgid_reg >> EXYNOS5422_IDS_OFFSET) & EXYNOS5422_IDS_MASK; 362 + 363 + for (i = 0; i < ASV_GROUPS_NUM; i++) { 364 + if (ids <= __asv_limits[i].ids) 365 + break; 366 + if (hpm <= __asv_limits[i].hpm) 367 + break; 368 + } 369 + if (i < ASV_GROUPS_NUM) 370 + return i; 371 + 372 + return 0; 373 + } 374 + 375 + static int __asv_offset_voltage(unsigned int index) 376 + { 377 + switch (index) { 378 + case 1: 379 + return 12500; 380 + case 2: 381 + return 50000; 382 + case 3: 383 + return 25000; 384 + default: 385 + return 0; 386 + }; 387 + } 388 + 389 + static void exynos5422_asv_offset_voltage_setup(struct exynos_asv *asv) 390 + { 391 + struct exynos_asv_subsys *subsys; 392 + unsigned int reg, value; 393 + 394 + regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_AUX_INFO, &reg); 395 + 396 + /* ARM offset voltage setup */ 397 + subsys = &asv->subsys[EXYNOS_ASV_SUBSYS_ID_ARM]; 398 + 399 + subsys->base_volt = 1000000; 400 + 401 + value = (reg >> EXYNOS5422_ARM_UP_OFFSET) & EXYNOS5422_ARM_UP_MASK; 402 + subsys->offset_volt_h = __asv_offset_voltage(value); 403 + 404 + value = (reg >> EXYNOS5422_ARM_DN_OFFSET) & EXYNOS5422_ARM_DN_MASK; 405 + subsys->offset_volt_l = __asv_offset_voltage(value); 406 + 407 + /* KFC offset voltage setup */ 408 + subsys = &asv->subsys[EXYNOS_ASV_SUBSYS_ID_KFC]; 409 + 410 + subsys->base_volt = 1000000; 411 + 412 + value = (reg >> EXYNOS5422_KFC_UP_OFFSET) & EXYNOS5422_KFC_UP_MASK; 413 + subsys->offset_volt_h = __asv_offset_voltage(value); 414 + 415 + value = (reg >> EXYNOS5422_KFC_DN_OFFSET) & EXYNOS5422_KFC_DN_MASK; 416 + subsys->offset_volt_l = __asv_offset_voltage(value); 417 + } 418 + 419 + static int exynos5422_asv_opp_get_voltage(const struct exynos_asv_subsys *subsys, 420 + int level, unsigned int volt) 421 + { 422 + unsigned int asv_volt; 423 + 424 + if (level >= subsys->table.num_rows) 425 + return volt; 426 + 427 + asv_volt = exynos_asv_opp_get_voltage(subsys, level, 428 + subsys->asv->group); 429 + 430 + if (volt > subsys->base_volt) 431 + asv_volt += subsys->offset_volt_h; 432 + else 433 + asv_volt += subsys->offset_volt_l; 434 + 435 + return asv_volt; 436 + } 437 + 438 + static unsigned int exynos5422_asv_parse_table(unsigned int pkg_id) 439 + { 440 + return (pkg_id >> EXYNOS5422_TABLE_OFFSET) & EXYNOS5422_TABLE_MASK; 441 + } 442 + 443 + static bool exynos5422_asv_parse_bin2(unsigned int pkg_id) 444 + { 445 + return (pkg_id >> EXYNOS5422_BIN2_OFFSET) & EXYNOS5422_BIN2_MASK; 446 + } 447 + 448 + static bool exynos5422_asv_parse_sg(unsigned int pkg_id) 449 + { 450 + return (pkg_id >> EXYNOS5422_USESG_OFFSET) & EXYNOS5422_USESG_MASK; 451 + } 452 + 453 + int exynos5422_asv_init(struct exynos_asv *asv) 454 + { 455 + struct exynos_asv_subsys *subsys; 456 + unsigned int table_index; 457 + unsigned int pkg_id; 458 + bool bin2; 459 + 460 + regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PKG_ID, &pkg_id); 461 + 462 + if (asv->of_bin == 2) { 463 + bin2 = true; 464 + asv->use_sg = false; 465 + } else { 466 + asv->use_sg = exynos5422_asv_parse_sg(pkg_id); 467 + bin2 = exynos5422_asv_parse_bin2(pkg_id); 468 + } 469 + 470 + asv->group = exynos5422_asv_get_group(asv); 471 + asv->table = exynos5422_asv_parse_table(pkg_id); 472 + 473 + exynos5422_asv_offset_voltage_setup(asv); 474 + 475 + if (bin2) { 476 + table_index = 3; 477 + } else { 478 + if (asv->table == 2 || asv->table == 3) 479 + table_index = asv->table - 1; 480 + else 481 + table_index = 0; 482 + } 483 + 484 + subsys = &asv->subsys[EXYNOS_ASV_SUBSYS_ID_ARM]; 485 + subsys->cpu_dt_compat = "arm,cortex-a15"; 486 + if (bin2) 487 + subsys->table.num_rows = ASV_ARM_BIN2_DVFS_NUM; 488 + else 489 + subsys->table.num_rows = ASV_ARM_DVFS_NUM; 490 + subsys->table.num_cols = ASV_GROUPS_NUM + 1; 491 + subsys->table.buf = (u32 *)asv_arm_table[table_index]; 492 + 493 + subsys = &asv->subsys[EXYNOS_ASV_SUBSYS_ID_KFC]; 494 + subsys->cpu_dt_compat = "arm,cortex-a7"; 495 + if (bin2) 496 + subsys->table.num_rows = ASV_KFC_BIN2_DVFS_NUM; 497 + else 498 + subsys->table.num_rows = ASV_KFC_DVFS_NUM; 499 + subsys->table.num_cols = ASV_GROUPS_NUM + 1; 500 + subsys->table.buf = (u32 *)asv_kfc_table[table_index]; 501 + 502 + asv->opp_get_voltage = exynos5422_asv_opp_get_voltage; 503 + 504 + return 0; 505 + }
+31
drivers/soc/samsung/exynos5422-asv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 + * http://www.samsung.com/ 5 + * 6 + * Samsung Exynos 5422 SoC Adaptive Supply Voltage support 7 + */ 8 + 9 + #ifndef __LINUX_SOC_EXYNOS5422_ASV_H 10 + #define __LINUX_SOC_EXYNOS5422_ASV_H 11 + 12 + #include <linux/errno.h> 13 + 14 + enum { 15 + EXYNOS_ASV_SUBSYS_ID_ARM, 16 + EXYNOS_ASV_SUBSYS_ID_KFC, 17 + EXYNOS_ASV_SUBSYS_ID_MAX 18 + }; 19 + 20 + struct exynos_asv; 21 + 22 + #ifdef CONFIG_EXYNOS_ASV_ARM 23 + int exynos5422_asv_init(struct exynos_asv *asv); 24 + #else 25 + static inline int exynos5422_asv_init(struct exynos_asv *asv) 26 + { 27 + return -ENOTSUPP; 28 + } 29 + #endif 30 + 31 + #endif /* __LINUX_SOC_EXYNOS5422_ASV_H */