msm: acpuclock-krait: Support alternate PVS and speed bin format
msm8974 and future targets use a different eFuse register layout
than targets from previous SoC generations. Instead of hard-coding
acpuclock-krait to assume the old format, allow the format to
be decided on a per-SoC basis via function pointer assignments.
Two formats are currently supported:
- "Format A", used for 8974
- "Format B", used for older Krait-based targets
Change-Id: Id9e8a6c83e3003f2b19ac56bb7aee5dc6b1d00cf
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index 359a156..a0727b7 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -650,6 +650,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index ac29cac..405b26b 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -142,6 +142,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 40326cb..6915343 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -227,6 +227,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index 7d1ce09..9aebac9 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -203,6 +203,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930ab.c b/arch/arm/mach-msm/acpuclock-8930ab.c
index 5003862..bddac00 100644
--- a/arch/arm/mach-msm/acpuclock-8930ab.c
+++ b/arch/arm/mach-msm/acpuclock-8930ab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -257,6 +257,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index d7d3edd..317729f 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -210,6 +210,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index d2e88fb..38658a2 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -252,6 +252,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0x007000C0,
+ .get_bin_info = get_krait_bin_format_a,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 62c7cc7..acb296a 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -169,6 +169,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0xFC4B80B0,
+ .get_bin_info = get_krait_bin_format_b,
.stby_khz = 300000,
};
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 10c4d6c..bc7f20e 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1040,62 +1040,78 @@
}
}
-static int __init get_speed_bin(u32 pte_efuse)
+void __init get_krait_bin_format_a(void __iomem *base, struct bin_info *bin)
{
- uint32_t speed_bin;
+ u32 pte_efuse = readl_relaxed(base);
- speed_bin = pte_efuse & 0xF;
- if (speed_bin == 0xF)
- speed_bin = (pte_efuse >> 4) & 0xF;
+ bin->speed = pte_efuse & 0xF;
+ if (bin->speed == 0xF)
+ bin->speed = (pte_efuse >> 4) & 0xF;
+ bin->speed_valid = bin->speed != 0xF;
- if (speed_bin == 0xF) {
- speed_bin = 0;
- dev_warn(drv.dev, "SPEED BIN: Defaulting to %d\n", speed_bin);
- } else {
- dev_info(drv.dev, "SPEED BIN: %d\n", speed_bin);
- }
-
- return speed_bin;
+ bin->pvs = (pte_efuse >> 10) & 0x7;
+ if (bin->pvs == 0x7)
+ bin->pvs = (pte_efuse >> 13) & 0x7;
+ bin->pvs_valid = bin->pvs != 0x7;
}
-static int __init get_pvs_bin(u32 pte_efuse)
+void __init get_krait_bin_format_b(void __iomem *base, struct bin_info *bin)
{
- uint32_t pvs_bin;
+ u32 pte_efuse, redundant_sel;
- pvs_bin = (pte_efuse >> 10) & 0x7;
- if (pvs_bin == 0x7)
- pvs_bin = (pte_efuse >> 13) & 0x7;
+ pte_efuse = readl_relaxed(base);
+ redundant_sel = (pte_efuse >> 24) & 0x7;
+ bin->speed = pte_efuse & 0x7;
+ bin->pvs = (pte_efuse >> 6) & 0x7;
- if (pvs_bin == 0x7) {
- pvs_bin = 0;
- dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n", pvs_bin);
- } else {
- dev_info(drv.dev, "ACPU PVS: %d\n", pvs_bin);
+ switch (redundant_sel) {
+ case 1:
+ bin->speed = (pte_efuse >> 27) & 0x7;
+ break;
+ case 2:
+ bin->pvs = (pte_efuse >> 27) & 0x7;
+ break;
}
+ bin->speed_valid = true;
- return pvs_bin;
+ /* Check PVS_BLOW_STATUS */
+ pte_efuse = readl_relaxed(base + 0x4);
+ bin->pvs_valid = !!(pte_efuse & BIT(21));
}
-static struct pvs_table * __init select_freq_plan(u32 pte_efuse_phys,
- struct pvs_table (*pvs_tables)[NUM_PVS])
+static struct pvs_table * __init select_freq_plan(
+ const struct acpuclk_krait_params *params)
{
- void __iomem *pte_efuse;
- u32 pte_efuse_val;
+ void __iomem *pte_efuse_base;
+ struct bin_info bin;
- pte_efuse = ioremap(pte_efuse_phys, 4);
- if (!pte_efuse) {
- dev_err(drv.dev, "Unable to map QFPROM base\n");
+ pte_efuse_base = ioremap(params->pte_efuse_phys, 8);
+ if (!pte_efuse_base) {
+ dev_err(drv.dev, "Unable to map PTE eFuse base\n");
return NULL;
}
+ params->get_bin_info(pte_efuse_base, &bin);
+ iounmap(pte_efuse_base);
- pte_efuse_val = readl_relaxed(pte_efuse);
- iounmap(pte_efuse);
+ if (bin.speed_valid) {
+ drv.speed_bin = bin.speed;
+ dev_info(drv.dev, "SPEED BIN: %d\n", drv.speed_bin);
+ } else {
+ drv.speed_bin = 0;
+ dev_warn(drv.dev, "SPEED BIN: Defaulting to %d\n",
+ drv.speed_bin);
+ }
- /* Select frequency tables. */
- drv.speed_bin = get_speed_bin(pte_efuse_val);
- drv.pvs_bin = get_pvs_bin(pte_efuse_val);
+ if (bin.pvs_valid) {
+ drv.pvs_bin = bin.pvs;
+ dev_info(drv.dev, "ACPU PVS: %d\n", drv.pvs_bin);
+ } else {
+ drv.pvs_bin = 0;
+ dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n",
+ drv.pvs_bin);
+ }
- return &pvs_tables[drv.speed_bin][drv.pvs_bin];
+ return ¶ms->pvs_tables[drv.speed_bin][drv.pvs_bin];
}
static void __init drv_data_init(struct device *dev,
@@ -1124,7 +1140,7 @@
GFP_KERNEL);
BUG_ON(!drv.bus_scale->usecase);
- pvs = select_freq_plan(params->pte_efuse_phys, params->pvs_tables);
+ pvs = select_freq_plan(params);
BUG_ON(!pvs->table);
drv.acpu_freq_tbl = kmemdup(pvs->table, pvs->size, GFP_KERNEL);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 7947ea8..00f64fc 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -227,6 +227,20 @@
};
/**
+ * struct bin_info - Hardware speed and voltage binning info.
+ * @speed_valid: @speed field is valid
+ * @pvs_valid: @pvs field is valid
+ * @speed: Speed bin ID
+ * @pvs: PVS bin ID
+ */
+struct bin_info {
+ bool speed_valid;
+ bool pvs_valid;
+ int speed;
+ int pvs;
+};
+
+/**
* struct pvs_table - CPU performance level table and size.
* @table: CPU performance level table
* @size: sizeof(@table)
@@ -247,6 +261,7 @@
* @l2_freq_tbl: L2 frequency table.
* @l2_freq_tbl_size: Size of @l2_freq_tbl.
* @pte_efuse_phys: Physical address of PTE EFUSE.
+ * @get_bin_info: Function to populate bin_info from pte_efuse.
* @bus_scale: MSM bus driver parameters.
* @stby_khz: KHz value corresponding to an always-on clock source.
*/
@@ -258,6 +273,7 @@
struct l2_level *l2_freq_tbl;
size_t l2_freq_tbl_size;
phys_addr_t pte_efuse_phys;
+ void (*get_bin_info)(void __iomem *base, struct bin_info *bin);
struct msm_bus_scale_pdata *bus_scale;
unsigned long stby_khz;
};
@@ -297,6 +313,16 @@
};
/**
+ * get_krait_bin_format_a - Populate bin_info from a 'Format A' pte_efuse
+ */
+void __init get_krait_bin_format_a(void __iomem *base, struct bin_info *bin);
+
+/**
+ * get_krait_bin_format_b - Populate bin_info from a 'Format B' pte_efuse
+ */
+void __init get_krait_bin_format_b(void __iomem *base, struct bin_info *bin);
+
+/**
* acpuclk_krait_init - Initialize the Krait CPU clock driver give SoC params.
*/
extern int acpuclk_krait_init(struct device *dev,