From d92092a71bcb5d214bd1e013a31b69a35e778add Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 24 Apr 2014 22:57:25 +0100 Subject: [PATCH] ARM: 8040/1: pj4: properly detect existence of iWMMXt coprocessor commit 1d4f00d6c284937842d79581bdf2d3b13c4271b3 ("ARM: 8015/1: Add cpu_is_pj4 to distinguish PJ4 because it has some differences with V7") introduced a fix for checking PJ4 cpuid to not use PJ4 specific coprocessor access on non-PJ4 platforms. Unfortunately, this in turn broke Marvell Armada 370/XP, both comprising Marvell PJ4B CPUs without iWMMXt extension. Instead of only checking for cpuid, which may not be sufficient to determine iWMMXt support, the presence of iWMMXt coprocessors can be checked by enabling and reading the Coprocessor ID register (wCID, register 0 of CP1). Therefore this adds an explicit check for the presence and correct wCID value, before enabling iWMMXt capabilities. As a bonus, also print the iWMMXt version of a detected coprocessor. This has been tested to properly detect iWMMXt presence/absence on: - PJ4, CPUID 0x560f5815, wCID 0x56052001: Marvell Dove, iWMMXt v2 - PJ4B, CPUID 0x561f5811: Marvell Armada 370, no iWMMXt - PJ4B, CPUID 0x562f5841, wCID 0x56052001: Marvell Armada 1500, iWMMXt v2 - PJ4B, CPUID 0x562f5842: Marvell Armada XP, no iWMMXt Signed-off-by: Sebastian Hesselbarth Tested-by: Thomas Petazzoni Tested-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/kernel/pj4-cp0.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c index 12352cd30ab29..8153e36b24917 100644 --- a/arch/arm/kernel/pj4-cp0.c +++ b/arch/arm/kernel/pj4-cp0.c @@ -72,6 +72,33 @@ static void __init pj4_cp_access_write(u32 value) : "=r" (temp) : "r" (value)); } +static int __init pj4_get_iwmmxt_version(void) +{ + u32 cp_access, wcid; + + cp_access = pj4_cp_access_read(); + pj4_cp_access_write(cp_access | 0xf); + + /* check if coprocessor 0 and 1 are available */ + if ((pj4_cp_access_read() & 0xf) != 0xf) { + pj4_cp_access_write(cp_access); + return -ENODEV; + } + + /* read iWMMXt coprocessor id register p1, c0 */ + __asm__ __volatile__ ("mrc p1, 0, %0, c0, c0, 0\n" : "=r" (wcid)); + + pj4_cp_access_write(cp_access); + + /* iWMMXt v1 */ + if ((wcid & 0xffffff00) == 0x56051000) + return 1; + /* iWMMXt v2 */ + if ((wcid & 0xffffff00) == 0x56052000) + return 2; + + return -EINVAL; +} /* * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy @@ -80,17 +107,22 @@ static void __init pj4_cp_access_write(u32 value) static int __init pj4_cp0_init(void) { u32 __maybe_unused cp_access; + int vers; if (!cpu_is_pj4()) return 0; + vers = pj4_get_iwmmxt_version(); + if (vers < 0) + return 0; + #ifndef CONFIG_IWMMXT pr_info("PJ4 iWMMXt coprocessor detected, but kernel support is missing.\n"); #else cp_access = pj4_cp_access_read() & ~0xf; pj4_cp_access_write(cp_access); - printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n"); + pr_info("PJ4 iWMMXt v%d coprocessor enabled.\n", vers); elf_hwcap |= HWCAP_IWMMXT; thread_register_notifier(&iwmmxt_notifier_block); #endif -- 2.39.5