#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/irqchip.h>
#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
+#include <linux/slab.h>
-#include "exynos-chipid.h"
+#include "exynos-asv.h"
+#include "exynos5422-asv.h"
-#define EXYNOS5422_ASV_NR 14
-#define ARM_DVFS_NR 20
-#define ARM_BIN2_DVFS_NR 17
+static struct exynos_asv *exynos_asv;
-#define KFC_DVFS_NR 14
-#define KFC_BIN2_DVFS_NR 12
-
- /* HPM, IDS values to select target group */
-struct asv_limit_entry {
- unsigned int hpm;
- unsigned int ids;
-};
-
-struct asv_cluster {
- unsigned int base_volt;
- unsigned int dvfs_nr;
- unsigned int offset_volt_h;
- unsigned int offset_volt_l;
- const unsigned int (*asv_table)[EXYNOS5422_ASV_NR + 1];
-};
-
-enum {
- CLUSTER_ID_ARM,
- CLUSTER_ID_KFC,
- CLUSTER_ID_MAX
-};
-
-struct exynos_asv {
- struct asv_cluster cluster[CLUSTER_ID_MAX];
- unsigned int bin2;
- unsigned int special_lot;
- unsigned int group;
- unsigned int table;
-};
-
-static struct exynos_asv *exynos_asv = NULL;
-
-static const unsigned int arm_info_table01[ARM_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
- { 2000000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1900000, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1162500, 1150000, 1137500, 1125000, 1112500 },
- { 1800000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 },
- { 1700000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 },
- { 1600000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 },
- { 1500000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 },
- { 1400000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 975000, 962500, 950000, 937500, 925000 },
- { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
- { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
- { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int arm_info_table2[ARM_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
- { 2000000, 1312500, 1312500, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1900000, 1262500, 1250000, 1250000, 1237500, 1212500, 1200000, 1187500, 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 },
- { 1800000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 },
- { 1700000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 },
- { 1600000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 },
- { 1500000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
- { 1400000, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 987500, 975000, 962500, 950000, 937500 },
- { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
- { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
- { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int arm_info_table3[ARM_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
- { 2000000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1900000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 },
- { 1800000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 },
- { 1700000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 },
- { 1600000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 },
- { 1500000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
- { 1400000, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 987500, 975000, 962500, 950000, 937500 },
- { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
- { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
- { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int arm_info_bin2[ARM_BIN2_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 1800000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1150000, 1137500, 1125000, 1112500, 1100000 },
- { 1700000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 },
- { 1600000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 },
- { 1500000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 },
- { 1400000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
- { 1300000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 },
- { 1200000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 975000, 962500, 950000, 937500, 925000 },
- { 1100000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500, 900000 },
- { 1000000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 925000, 912500, 900000, 900000, 900000 },
- { 900000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 800000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 700000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int kfc_info_table01[KFC_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
- { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
- { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
- { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
- { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
- { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
- { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
- { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int kfc_info_table2[KFC_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
- { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
- { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
- { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
- { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
- { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
- { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
- { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int kfc_info_table3[KFC_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
- { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
- { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
- { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
- { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
- { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
- { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
- { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
- { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-};
-
-static const unsigned int kfc_info_bin2[KFC_BIN2_DVFS_NR][EXYNOS5422_ASV_NR + 1] = {
- { 1300000, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500 },
- { 1200000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500 },
- { 1100000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000 },
- { 1000000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500 },
- { 900000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000 },
- { 800000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000 },
- { 700000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000 },
- { 600000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 500000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 400000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
- { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
-
-};
-
-
-static unsigned int exynos_asv_opp_get_voltage(struct asv_cluster *cluster,
- unsigned int freq, unsigned int volt)
-{
- unsigned int i, asv_volt;
-
- for (i = 0; i < cluster->dvfs_nr; i++) {
- if (freq == cluster->asv_table[i][0])
- break;
- }
-
- if (i == cluster->dvfs_nr)
- return 0;
-
- asv_volt = cluster->asv_table[i][exynos_asv->group + 1];
-
- if (volt > cluster->base_volt)
- asv_volt += cluster->offset_volt_h;
- else
- asv_volt += cluster->offset_volt_l;
-
- return asv_volt;
-}
-
-static int exynos_asv_get_bin2(void)
-{
- unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
-
- return (reg >> EXYNOS5422_BIN2_OFFSET) & EXYNOS5422_BIN2_MASK;
-}
-
-static bool asv_special_group_check(void)
-{
- unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
-
- return (((reg >> EXYNOS5422_USESG_OFFSET) & EXYNOS5422_USESG_MASK)
- && exynos_asv->bin2 == 0);
-}
-
-static const struct asv_limit_entry exynos5422_asv_limits[EXYNOS5422_ASV_NR] = {
- { 13, 55 },
- { 21, 65 },
- { 25, 69 },
- { 30, 72 },
- { 36, 74 },
- { 43, 76 },
- { 51, 78 },
- { 65, 80 },
- { 81, 82 },
- { 98, 84 },
- { 119, 87 },
- { 135, 89 },
- { 150, 92 },
- { 999, 999 },
-};
-
-static int exynos_asv_get_group(struct exynos_asv *exynos_asv)
-{
- unsigned int pkgid_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
- unsigned int auxi_reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
- int hpm, ids, i;
-
- if (exynos_asv->special_lot) {
- u32 sga = (pkgid_reg >> EXYNOS5422_SG_A_OFFSET) &
- EXYNOS5422_SG_A_MASK;
-
- u32 sgb = (pkgid_reg >> EXYNOS5422_SG_B_OFFSET) &
- EXYNOS5422_SG_B_MASK;
-
- if ((pkgid_reg >> EXYNOS5422_SG_BSIGN_OFFSET) &
- EXYNOS5422_SG_BSIGN_MASK)
- return sga + sgb;
- else
- return sga - sgb;
- }
-
- hpm = (auxi_reg >> EXYNOS5422_TMCB_OFFSET) & EXYNOS5422_TMCB_MASK;
- ids = (pkgid_reg >> EXYNOS5422_IDS_OFFSET) & EXYNOS5422_IDS_MASK;
-
- for (i = 0; i < EXYNOS5422_ASV_NR; i++) {
- if (ids <= exynos5422_asv_limits[i].ids)
- break;
- if (hpm <= exynos5422_asv_limits[i].hpm)
- break;
- }
-
- if (i < EXYNOS5422_ASV_NR)
- return i;
- else
- return 0;
-}
-
-static int asv_table_check(void)
-{
- unsigned int pkg_id_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
-
- return (pkg_id_reg >> EXYNOS5422_TABLE_OFFSET) & EXYNOS5422_TABLE_MASK;
-}
-
-static int exynos5422_offset_voltage(unsigned int index)
-{
- static const unsigned int offset_table[] = { 12500, 50000, 25000 };
-
- if (index == 0 || index > 3)
- return 0;
-
- return offset_table[index - 1];
-}
-
-static void asv_offset_voltage_setup(void)
-{
- struct asv_cluster *cluster;
- unsigned int reg, value;
-
- if (exynos_asv->bin2) {
- exynos_asv->cluster[CLUSTER_ID_ARM].dvfs_nr = ARM_BIN2_DVFS_NR;
- exynos_asv->cluster[CLUSTER_ID_KFC].dvfs_nr = KFC_BIN2_DVFS_NR;
- } else {
- exynos_asv->cluster[CLUSTER_ID_ARM].dvfs_nr = ARM_DVFS_NR;
- exynos_asv->cluster[CLUSTER_ID_KFC].dvfs_nr = KFC_DVFS_NR;
- }
-
- reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
-
- /* ARM offset voltage setup */
- cluster = &exynos_asv->cluster[CLUSTER_ID_ARM];
-
- cluster->base_volt = 1000000;
-
- value = (reg >> EXYNOS5422_ARM_UP_OFFSET) & EXYNOS5422_ARM_UP_MASK;
- cluster->offset_volt_h = exynos5422_offset_voltage(value);
-
- value = (reg >> EXYNOS5422_ARM_DN_OFFSET) & EXYNOS5422_ARM_DN_MASK;
- cluster->offset_volt_l = exynos5422_offset_voltage(value);
-
- /* KFC offset voltage setup */
- cluster = &exynos_asv->cluster[CLUSTER_ID_KFC];
-
- cluster->base_volt = 1000000;
-
- value = (reg >> EXYNOS5422_KFC_UP_OFFSET) & EXYNOS5422_KFC_UP_MASK;
- cluster->offset_volt_h = exynos5422_offset_voltage(value);
-
- value = (reg >> EXYNOS5422_KFC_DN_OFFSET) & EXYNOS5422_KFC_DN_MASK;
- cluster->offset_volt_l = exynos5422_offset_voltage(value);
-}
-
-int exynos_asv_update_opps(struct device *cpu)
+int exynos_asv_update_cpu_opp(struct device *cpu)
{
+ struct exynos_asv_subsys *subsys = NULL;
struct dev_pm_opp *opp;
- struct asv_cluster *cluster;
unsigned int opp_freq;
int cpuid = cpu->id;
- int cluster_id = -1;
int i;
- if (of_device_is_compatible(cpu->of_node, "arm,cortex-a7"))
- cluster_id = CLUSTER_ID_KFC;
- else if (of_device_is_compatible(cpu->of_node, "arm,cortex-a15"))
- cluster_id = CLUSTER_ID_ARM;
+ if (of_device_is_compatible(cpu->of_node,
+ exynos_asv->arm.cpu_dt_compat))
+ subsys = &exynos_asv->arm;
+ else if (of_device_is_compatible(cpu->of_node,
+ exynos_asv->kfc.cpu_dt_compat))
+ subsys = &exynos_asv->kfc;
- if (cluster_id < 0)
+ if (!subsys)
return -EINVAL;
- cluster = &exynos_asv->cluster[cluster_id];
-
- for (i = 0; i < cluster->dvfs_nr; i++) {
+ for (i = 0; i < subsys->dvfs_nr; i++) {
unsigned int new_voltage;
unsigned int voltage;
int err;
- opp_freq = cluster->asv_table[i][0];
+ opp_freq = subsys->asv_table[i][0];
opp = dev_pm_opp_find_freq_exact(cpu, opp_freq * 1000, true);
if (IS_ERR(opp)) {
}
voltage = dev_pm_opp_get_voltage(opp);
- new_voltage = exynos_asv_opp_get_voltage(cluster, opp_freq,
+ new_voltage = exynos_asv->opp_get_voltage(subsys, i, opp_freq,
voltage);
dev_pm_opp_put(opp);
return 0;
}
-
-static int __init exynos_asv_init(void)
+static int exynos_asv_update_opp(void)
{
- const unsigned int (*arm_asv_table)[EXYNOS5422_ASV_NR + 1];
- const unsigned int (*kfc_asv_table)[EXYNOS5422_ASV_NR + 1];
struct opp_table *last_opp_table = NULL;
struct device *cpu;
int ret, cpuid;
- /* Currently only exynos5800 is supported */
- if (!of_machine_is_compatible("samsung,exynos5800") &&
- !of_machine_is_compatible("samsung,exynos5420"))
- return 0;
-
- exynos_asv = kmalloc(sizeof(struct exynos_asv), GFP_KERNEL);
- if (!exynos_asv)
- return -ENOMEM;
-
- exynos_asv->bin2 = exynos_asv_get_bin2();
-
- if (of_machine_is_compatible("hardkernel,odroid-xu3-lite"))
- exynos_asv->bin2 = true;
-
- exynos_asv->special_lot = asv_special_group_check();
- exynos_asv->group = exynos_asv_get_group(exynos_asv);
- exynos_asv->table = asv_table_check();
-
- asv_offset_voltage_setup();
-
- if (exynos_asv->bin2) {
- arm_asv_table = arm_info_bin2;
- kfc_asv_table = kfc_info_bin2;
- } else {
- switch(exynos_asv->table) {
- case 2:
- arm_asv_table = arm_info_table2;
- kfc_asv_table = kfc_info_table2;
- break;
- case 3:
- arm_asv_table = arm_info_table3;
- kfc_asv_table = kfc_info_table3;
- break;
- default:
- arm_asv_table = arm_info_table01;
- kfc_asv_table = kfc_info_table01;
- break;
- }
- }
-
- exynos_asv->cluster[CLUSTER_ID_ARM].asv_table = arm_asv_table;
- exynos_asv->cluster[CLUSTER_ID_KFC].asv_table = kfc_asv_table;
-
for_each_possible_cpu(cpuid) {
struct opp_table *opp_table;
if (!last_opp_table || opp_table != last_opp_table) {
last_opp_table = opp_table;
- ret = exynos_asv_update_opps(cpu);
+ ret = exynos_asv_update_cpu_opp(cpu);
if (ret < 0)
pr_err("%s: Couldn't udate OPPs for cpu%d\n",
__func__, cpuid);
return 0;
}
-late_initcall(exynos_asv_init);
+
+static int __init exynos_asv_init(void)
+{
+ int ret;
+
+ exynos_asv = kcalloc(1, sizeof(struct exynos_asv), GFP_KERNEL);
+ if (!exynos_asv)
+ return -ENOMEM;
+
+ if (of_machine_is_compatible("samsung,exynos5800") ||
+ of_machine_is_compatible("samsung,exynos5420"))
+ ret = exynos5422_asv_init(exynos_asv);
+ else
+ return 0;
+
+ if (ret < 0)
+ return ret;
+
+ return exynos_asv_update_opp();
+}
+late_initcall(exynos_asv_init)
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
+ */
+
+#include <linux/bitrev.h>
+#include <linux/cpu.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+
+#include "exynos-asv.h"
+#include "exynos-chipid.h"
+
+#define EXYNOS5422_ASV_NUM 14
+
+#define EXYNOS5422_ARM_DVFS_NUM 20
+#define EXYNOS5422_ARM_BIN2_DVFS_NUM 17
+
+#define EXYNOS5422_KFC_DVFS_NUM 14
+#define EXYNOS5422_KFC_BIN2_DVFS_NUM 12
+
+static struct exynos_asv *exynos_asv;
+
+static const unsigned int arm_info_table01[EXYNOS5422_ARM_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
+ { 2000000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1900000, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1162500, 1150000, 1137500, 1125000, 1112500 },
+ { 1800000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 },
+ { 1700000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 },
+ { 1600000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 },
+ { 1500000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 },
+ { 1400000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 975000, 962500, 950000, 937500, 925000 },
+ { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
+ { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
+ { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int arm_info_table2[EXYNOS5422_ARM_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
+ { 2000000, 1312500, 1312500, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1900000, 1262500, 1250000, 1250000, 1237500, 1212500, 1200000, 1187500, 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 },
+ { 1800000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 },
+ { 1700000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 },
+ { 1600000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 },
+ { 1500000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
+ { 1400000, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 987500, 975000, 962500, 950000, 937500 },
+ { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
+ { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
+ { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int arm_info_table3[EXYNOS5422_ARM_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 2100000, 1362500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000 },
+ { 2000000, 1312500, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1900000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1175000, 1162500, 1150000, 1137500, 1125000 },
+ { 1800000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1125000, 1112500, 1100000, 1087500, 1075000 },
+ { 1700000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1087500, 1075000, 1062500, 1050000, 1037500 },
+ { 1600000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1050000, 1037500, 1025000, 1012500, 1000000 },
+ { 1500000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
+ { 1400000, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 987500, 975000, 962500, 950000, 937500 },
+ { 1300000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 962500, 950000, 937500, 925000, 912500 },
+ { 1200000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 937500, 925000, 912500, 900000, 900000 },
+ { 1100000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 900000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 800000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 700000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int arm_info_bin2[EXYNOS5422_ARM_BIN2_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 1800000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1150000, 1137500, 1125000, 1112500, 1100000 },
+ { 1700000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1112500, 1100000, 1087500, 1075000, 1062500 },
+ { 1600000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1050000, 1037500, 1025000 },
+ { 1500000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1037500, 1025000, 1012500, 1000000, 987500 },
+ { 1400000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000, 962500 },
+ { 1300000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 1000000, 987500, 975000, 962500, 950000 },
+ { 1200000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 975000, 962500, 950000, 937500, 925000 },
+ { 1100000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500, 900000 },
+ { 1000000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 925000, 912500, 900000, 900000, 900000 },
+ { 900000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 800000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 700000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int kfc_info_table01[EXYNOS5422_KFC_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
+ { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
+ { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
+ { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
+ { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
+ { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
+ { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
+ { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int kfc_info_table2[EXYNOS5422_KFC_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
+ { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
+ { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
+ { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
+ { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
+ { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
+ { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
+ { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int kfc_info_table3[EXYNOS5422_KFC_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 1500000, 1300000, 1300000, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500 },
+ { 1400000, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500 },
+ { 1300000, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500 },
+ { 1200000, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500 },
+ { 1100000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000 },
+ { 1000000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500 },
+ { 900000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000 },
+ { 800000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000 },
+ { 700000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+};
+
+static const unsigned int kfc_info_bin2[EXYNOS5422_KFC_BIN2_DVFS_NUM][EXYNOS_ASV_MAX_NUM + 1] = {
+ { 1300000, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500 },
+ { 1200000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500 },
+ { 1100000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000 },
+ { 1000000, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500 },
+ { 900000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000 },
+ { 800000, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000 },
+ { 700000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000 },
+ { 600000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 500000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 400000, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 300000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+ { 200000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000 },
+
+};
+
+static int exynos5422_asv_opp_get_voltage(struct exynos_asv_subsys *subsys,
+ int idx, unsigned int freq, unsigned int volt)
+{
+ unsigned int i, asv_volt;
+
+ for (i = 0; i < subsys->dvfs_nr; i++) {
+ if (freq == subsys->asv_table[i][0])
+ break;
+ }
+
+ if (i == subsys->dvfs_nr)
+ return 0;
+
+ asv_volt = subsys->asv_table[i][exynos_asv->group + 1];
+
+ if (volt > subsys->base_volt)
+ asv_volt += subsys->offset_volt_h;
+ else
+ asv_volt += subsys->offset_volt_l;
+
+ return asv_volt;
+}
+
+static int exynos5422_asv_get_bin2(void)
+{
+ unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return (reg >> EXYNOS5422_BIN2_OFFSET) & EXYNOS5422_BIN2_MASK;
+}
+
+static bool exynos5422_asv_special_group_check(void)
+{
+ unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return (((reg >> EXYNOS5422_USESG_OFFSET) & EXYNOS5422_USESG_MASK)
+ && exynos_asv->bin2 == 0);
+}
+
+static const struct asv_limit_entry exynos5422_asv_limits[EXYNOS5422_ASV_NUM] = {
+ { 13, 55 },
+ { 21, 65 },
+ { 25, 69 },
+ { 30, 72 },
+ { 36, 74 },
+ { 43, 76 },
+ { 51, 78 },
+ { 65, 80 },
+ { 81, 82 },
+ { 98, 84 },
+ { 119, 87 },
+ { 135, 89 },
+ { 150, 92 },
+ { 999, 999 },
+};
+
+static int exynos5422_asv_get_group(struct exynos_asv *exynos_asv)
+{
+ unsigned int pkgid_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+ unsigned int auxi_reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
+ int hpm, ids, i;
+
+ if (exynos_asv->special_lot) {
+ u32 sga = (pkgid_reg >> EXYNOS5422_SG_A_OFFSET) &
+ EXYNOS5422_SG_A_MASK;
+
+ u32 sgb = (pkgid_reg >> EXYNOS5422_SG_B_OFFSET) &
+ EXYNOS5422_SG_B_MASK;
+
+ if ((pkgid_reg >> EXYNOS5422_SG_BSIGN_OFFSET) &
+ EXYNOS5422_SG_BSIGN_MASK)
+ return sga + sgb;
+ else
+ return sga - sgb;
+ }
+
+ hpm = (auxi_reg >> EXYNOS5422_TMCB_OFFSET) & EXYNOS5422_TMCB_MASK;
+ ids = (pkgid_reg >> EXYNOS5422_IDS_OFFSET) & EXYNOS5422_IDS_MASK;
+
+ for (i = 0; i < EXYNOS5422_ASV_NUM; i++) {
+ if (ids <= exynos5422_asv_limits[i].ids)
+ break;
+ if (hpm <= exynos5422_asv_limits[i].hpm)
+ break;
+ }
+
+ if (i < EXYNOS5422_ASV_NUM)
+ return i;
+ else
+ return 0;
+}
+
+static int exynos5422_asv_get_table(void)
+{
+ unsigned int pkg_id_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return (pkg_id_reg >> EXYNOS5422_TABLE_OFFSET) & EXYNOS5422_TABLE_MASK;
+}
+
+static int __asv_offset_voltage(unsigned int index)
+{
+ static const unsigned int offset_table[] = { 12500, 50000, 25000 };
+
+ if (index == 0 || index > 3)
+ return 0;
+
+ return offset_table[index - 1];
+}
+
+static void exynos5422_asv_offset_voltage_setup(void)
+{
+ struct exynos_asv_subsys *subsys;
+ unsigned int reg, value;
+
+ if (exynos_asv->bin2) {
+ exynos_asv->arm.dvfs_nr = EXYNOS5422_ARM_BIN2_DVFS_NUM;
+ exynos_asv->kfc.dvfs_nr = EXYNOS5422_KFC_BIN2_DVFS_NUM;
+ } else {
+ exynos_asv->arm.dvfs_nr = EXYNOS5422_ARM_DVFS_NUM;
+ exynos_asv->kfc.dvfs_nr = EXYNOS5422_KFC_DVFS_NUM;
+ }
+
+ reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
+
+ /* ARM offset voltage setup */
+ subsys = &exynos_asv->arm;
+
+ subsys->base_volt = 1000000;
+
+ value = (reg >> EXYNOS5422_ARM_UP_OFFSET) & EXYNOS5422_ARM_UP_MASK;
+ subsys->offset_volt_h = __asv_offset_voltage(value);
+
+ value = (reg >> EXYNOS5422_ARM_DN_OFFSET) & EXYNOS5422_ARM_DN_MASK;
+ subsys->offset_volt_l = __asv_offset_voltage(value);
+
+ /* KFC offset voltage setup */
+ subsys = &exynos_asv->kfc;
+
+ subsys->base_volt = 1000000;
+
+ value = (reg >> EXYNOS5422_KFC_UP_OFFSET) & EXYNOS5422_KFC_UP_MASK;
+ subsys->offset_volt_h = __asv_offset_voltage(value);
+
+ value = (reg >> EXYNOS5422_KFC_DN_OFFSET) & EXYNOS5422_KFC_DN_MASK;
+ subsys->offset_volt_l = __asv_offset_voltage(value);
+}
+
+int __init exynos5422_asv_init(struct exynos_asv *asv)
+{
+ exynos_asv = asv;
+
+ asv->bin2 = exynos5422_asv_get_bin2();
+
+ if (of_machine_is_compatible("hardkernel,odroid-xu3-lite"))
+ asv->bin2 = true;
+
+ asv->special_lot = exynos5422_asv_special_group_check();
+ asv->group = exynos5422_asv_get_group(asv);
+ asv->table = exynos5422_asv_get_table();
+
+ exynos5422_asv_offset_voltage_setup();
+
+ if (asv->bin2) {
+ asv->arm.asv_table = arm_info_bin2;
+ asv->kfc.asv_table = kfc_info_bin2;
+ } else {
+ switch(asv->table) {
+ case 2:
+ asv->arm.asv_table = arm_info_table2;
+ asv->kfc.asv_table = kfc_info_table2;
+ break;
+ case 3:
+ asv->arm.asv_table = arm_info_table3;
+ asv->kfc.asv_table = kfc_info_table3;
+ break;
+ default:
+ asv->arm.asv_table = arm_info_table01;
+ asv->kfc.asv_table = kfc_info_table01;
+ break;
+ }
+ }
+
+ asv->arm.cpu_dt_compat = "arm,cortex-a15";
+ asv->kfc.cpu_dt_compat = "arm,cortex-a7";
+
+ asv->opp_get_voltage = exynos5422_asv_opp_get_voltage;
+
+
+ return 0;
+}