From fca4afe400cb68fe5a7f0a97fb1ba5cfdcb81675 Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Thu, 15 Jun 2017 10:40:58 -0400 Subject: [PATCH 1/2] sparc64: use prom interface to get %stick frequency We initialize time early, we must use prom interface instead of open firmware driver, which is not yet initialized. Also, use prom_getintdefault() instead of prom_getint() to be compatible with the code before early boot timestamps project. Signed-off-by: Pavel Tatashin Signed-off-by: David S. Miller --- arch/sparc/kernel/time_64.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index a612a91cb9cd..a62758ce9e19 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -257,7 +256,7 @@ static int stick_add_compare(unsigned long adj) static unsigned long stick_get_frequency(void) { - return prom_getint(prom_root_node, "stick-frequency"); + return prom_getintdefault(prom_root_node, "stick-frequency", 0); } static struct sparc64_tick_ops stick_operations __read_mostly = { @@ -391,9 +390,7 @@ static int hbtick_add_compare(unsigned long adj) static unsigned long hbtick_get_frequency(void) { - struct device_node *dp = of_find_node_by_path("/"); - - return of_getintprop_default(dp, "stick-frequency", 0); + return prom_getintdefault(prom_root_node, "stick-frequency", 0); } static struct sparc64_tick_ops hbtick_operations __read_mostly = { From eea9833453bd39e2f35325abb985d00486c8aa69 Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Thu, 15 Jun 2017 10:40:59 -0400 Subject: [PATCH 2/2] sparc64: broken %tick frequency on spitfire cpus After early boot time stamps project the %tick frequency is detected incorrectly on spittfire cpus. We must use cpuid of boot cpu to find corresponding cpu node in OpenBoot, and extract clock-frequency property from there. Signed-off-by: Pavel Tatashin Signed-off-by: David S. Miller --- arch/sparc/kernel/time_64.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index a62758ce9e19..f584c53e769a 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -162,9 +162,34 @@ static unsigned long tick_add_tick(unsigned long adj) return new_tick; } +/* Searches for cpu clock frequency with given cpuid in OpenBoot tree */ +static unsigned long cpuid_to_freq(phandle node, int cpuid) +{ + bool is_cpu_node = false; + unsigned long freq = 0; + char type[128]; + + if (!node) + return freq; + + if (prom_getproperty(node, "device_type", type, sizeof(type)) != -1) + is_cpu_node = (strcmp(type, "cpu") == 0); + + /* try upa-portis then cpuid to get cpuid, see prom_64.c */ + if (is_cpu_node && (prom_getint(node, "upa-portis") == cpuid || + prom_getint(node, "cpuid") == cpuid)) + freq = prom_getintdefault(node, "clock-frequency", 0); + if (!freq) + freq = cpuid_to_freq(prom_getchild(node), cpuid); + if (!freq) + freq = cpuid_to_freq(prom_getsibling(node), cpuid); + + return freq; +} + static unsigned long tick_get_frequency(void) { - return local_cpu_data().clock_tick; + return cpuid_to_freq(prom_root_node, hard_smp_processor_id()); } static struct sparc64_tick_ops tick_operations __cacheline_aligned = {