summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2011-10-03 13:21:11 -0700
committerSimon Glass <sjg@chromium.org>2011-10-06 19:24:30 -0700
commit5605de2e1851d005c226643af2040bffca9c6c39 (patch)
tree8453e0a549f447ef76307c888b901d0703230b97 /arch
parent4a4703b398df9a3e5d29623e5e3dcf1d99336ebc (diff)
tegra: Detect the number of CPUs
This adds ap20_get_num_cpus() which returns the number of CPUs in the system, and adjusts a clock function to use it. BUG=chromium-os:19004 TEST=build and boot on Seaboard Change-Id: If7b56a2cecfb3d856308cac43dfcb32d3f1fef14 Reviewed-on: http://gerrit.chromium.org/gerrit/8688 Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/armv7/tegra-common/ap20.c39
-rw-r--r--arch/arm/cpu/armv7/tegra-common/clock.c8
-rw-r--r--arch/arm/include/asm/arch-tegra/ap20.h7
3 files changed, 47 insertions, 7 deletions
diff --git a/arch/arm/cpu/armv7/tegra-common/ap20.c b/arch/arm/cpu/armv7/tegra-common/ap20.c
index cc3afaa77a..3a7e402b0c 100644
--- a/arch/arm/cpu/armv7/tegra-common/ap20.c
+++ b/arch/arm/cpu/armv7/tegra-common/ap20.c
@@ -64,6 +64,32 @@ static struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_COUNT]
},
};
+enum tegra_family_t {
+ TEGRA_FAMILY_T2x,
+ TEGRA_FAMILY_T3x,
+};
+
+#define GP_HIDREV 0x804
+
+static enum tegra_family_t ap20_get_family(void)
+{
+ u32 reg, chip_id;
+
+ reg = readl(NV_PA_APB_MISC_BASE + GP_HIDREV);
+
+ chip_id = reg >> 8;
+ chip_id &= 0xff;
+ if (chip_id == 0x30)
+ return TEGRA_FAMILY_T3x;
+ else
+ return TEGRA_FAMILY_T2x;
+}
+
+int ap20_get_num_cpus(void)
+{
+ return ap20_get_family() == TEGRA_FAMILY_T3x ? 4 : 2;
+}
+
int ap20_cpu_is_cortexa9(void)
{
u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
@@ -239,11 +265,14 @@ static void reset_A9_cpu(int reset)
* AVP only talks to the master. The AVP does not know that there
* are multiple processors in the CPU complex.
*/
-
- /* Hold CPU 1 in reset, and CPU 0 if asked */
- reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
- reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
- reset);
+ int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug;
+ int num_cpus = ap20_get_num_cpus();
+ int cpu;
+
+ /* Hold CPUs 1 onwards in reset, and CPU 0 if asked */
+ for (cpu = 1; cpu < num_cpus; cpu++)
+ reset_cmplx_set_enable(cpu, mask, 1);
+ reset_cmplx_set_enable(0, mask, reset);
/* Enable/Disable master CPU reset */
reset_set_enable(PERIPH_ID_CPU, reset);
diff --git a/arch/arm/cpu/armv7/tegra-common/clock.c b/arch/arm/cpu/armv7/tegra-common/clock.c
index 23573b1080..0aa4ef33ec 100644
--- a/arch/arm/cpu/armv7/tegra-common/clock.c
+++ b/arch/arm/cpu/armv7/tegra-common/clock.c
@@ -22,6 +22,7 @@
/* Tegra2 Clock control functions */
#include <asm/io.h>
+#include <asm/arch-tegra/ap20.h>
#include <asm/arch-tegra/bitfield.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch/clock.h>
@@ -788,8 +789,11 @@ void reset_cmplx_set_enable(int cpu, int which, int reset)
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 mask;
- /* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */
- assert(cpu >= 0 && cpu < 2);
+ /*
+ * Form the mask, which depends on the cpu chosen. Tegra2 has 2,
+ * Tegra3 has 4.
+ */
+ assert(cpu >= 0 && cpu < ap20_get_num_cpus());
mask = which << cpu;
/* either enable or disable those reset for that CPU */
diff --git a/arch/arm/include/asm/arch-tegra/ap20.h b/arch/arm/include/asm/arch-tegra/ap20.h
index 4f7d7ce714..d2251a2902 100644
--- a/arch/arm/include/asm/arch-tegra/ap20.h
+++ b/arch/arm/include/asm/arch-tegra/ap20.h
@@ -110,3 +110,10 @@ int ap20_cpu_is_cortexa9(void);
* @param slow 1 to run in safe/slow mode, 0 to run at full speed
*/
void ap20_init_pllx(int slow);
+
+/**
+ * Returns the number of CPUs supported by the SOC
+ *
+ * @return number of CPUs (1-4)
+ */
+int ap20_get_num_cpus(void);