diff options
Diffstat (limited to 'arch/riscv/kernel/cpu.c')
| -rw-r--r-- | arch/riscv/kernel/cpu.c | 67 | 
1 files changed, 55 insertions, 12 deletions
diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index c96aa56cf1c7..a2fc952318e9 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -3,10 +3,13 @@   * Copyright (C) 2012 Regents of the University of California   */ +#include <linux/acpi.h>  #include <linux/cpu.h> +#include <linux/ctype.h>  #include <linux/init.h>  #include <linux/seq_file.h>  #include <linux/of.h> +#include <asm/acpi.h>  #include <asm/cpufeature.h>  #include <asm/csr.h>  #include <asm/hwcap.h> @@ -20,6 +23,26 @@   */  int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart)  { +	int cpu; + +	*hart = (unsigned long)of_get_cpu_hwid(node, 0); +	if (*hart == ~0UL) { +		pr_warn("Found CPU without hart ID\n"); +		return -ENODEV; +	} + +	cpu = riscv_hartid_to_cpuid(*hart); +	if (cpu < 0) +		return cpu; + +	if (!cpu_possible(cpu)) +		return -ENODEV; + +	return 0; +} + +int riscv_early_of_processor_hartid(struct device_node *node, unsigned long *hart) +{  	const char *isa;  	if (!of_device_is_compatible(node, "riscv")) { @@ -27,7 +50,7 @@ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart)  		return -ENODEV;  	} -	*hart = (unsigned long) of_get_cpu_hwid(node, 0); +	*hart = (unsigned long)of_get_cpu_hwid(node, 0);  	if (*hart == ~0UL) {  		pr_warn("Found CPU without hart ID\n");  		return -ENODEV; @@ -42,10 +65,12 @@ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart)  		pr_warn("CPU with hartid=%lu has no \"riscv,isa\" property\n", *hart);  		return -ENODEV;  	} -	if (isa[0] != 'r' || isa[1] != 'v') { -		pr_warn("CPU with hartid=%lu has an invalid ISA of \"%s\"\n", *hart, isa); + +	if (IS_ENABLED(CONFIG_32BIT) && strncasecmp(isa, "rv32ima", 7)) +		return -ENODEV; + +	if (IS_ENABLED(CONFIG_64BIT) && strncasecmp(isa, "rv64ima", 7))  		return -ENODEV; -	}  	return 0;  } @@ -183,8 +208,14 @@ arch_initcall(riscv_cpuinfo_init);  static struct riscv_isa_ext_data isa_ext_arr[] = {  	__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),  	__RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ), +	__RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR), +	__RISCV_ISA_EXT_DATA(zicsr, RISCV_ISA_EXT_ZICSR), +	__RISCV_ISA_EXT_DATA(zifencei, RISCV_ISA_EXT_ZIFENCEI),  	__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), +	__RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM), +	__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),  	__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB), +	__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),  	__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),  	__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),  	__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), @@ -283,23 +314,35 @@ static void c_stop(struct seq_file *m, void *v)  static int c_show(struct seq_file *m, void *v)  {  	unsigned long cpu_id = (unsigned long)v - 1; -	struct device_node *node = of_get_cpu_node(cpu_id, NULL);  	struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); +	struct device_node *node;  	const char *compat, *isa;  	seq_printf(m, "processor\t: %lu\n", cpu_id);  	seq_printf(m, "hart\t\t: %lu\n", cpuid_to_hartid_map(cpu_id)); -	if (!of_property_read_string(node, "riscv,isa", &isa)) -		print_isa(m, isa); -	print_mmu(m); -	if (!of_property_read_string(node, "compatible", &compat) -	    && strcmp(compat, "riscv")) -		seq_printf(m, "uarch\t\t: %s\n", compat); + +	if (acpi_disabled) { +		node = of_get_cpu_node(cpu_id, NULL); +		if (!of_property_read_string(node, "riscv,isa", &isa)) +			print_isa(m, isa); + +		print_mmu(m); +		if (!of_property_read_string(node, "compatible", &compat) && +		    strcmp(compat, "riscv")) +			seq_printf(m, "uarch\t\t: %s\n", compat); + +		of_node_put(node); +	} else { +		if (!acpi_get_riscv_isa(NULL, cpu_id, &isa)) +			print_isa(m, isa); + +		print_mmu(m); +	} +  	seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid);  	seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid);  	seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid);  	seq_puts(m, "\n"); -	of_node_put(node);  	return 0;  }  |