Skip to content

Commit e6b9d8e

Browse files
vlsunilpalmer-dabbelt
authored andcommitted
drivers/acpi: RISC-V: Add RHCT related code
RHCT is a new table defined for RISC-V to communicate the features of the CPU to the OS. Create a new architecture folder in drivers/acpi and add RHCT parsing code. Signed-off-by: Sunil V L <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Reviewed-by: Palmer Dabbelt <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent f995611 commit e6b9d8e

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

arch/riscv/include/asm/acpi.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,21 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { }
6262
void acpi_init_rintc_map(void);
6363
struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu);
6464
u32 get_acpi_id_for_cpu(int cpu);
65+
int acpi_get_riscv_isa(struct acpi_table_header *table,
66+
unsigned int cpu, const char **isa);
6567
#else
6668
static inline void acpi_init_rintc_map(void) { }
6769
static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
6870
{
6971
return NULL;
7072
}
7173

74+
static inline int acpi_get_riscv_isa(struct acpi_table_header *table,
75+
unsigned int cpu, const char **isa)
76+
{
77+
return -EINVAL;
78+
}
79+
7280
#endif /* CONFIG_ACPI */
7381

7482
#endif /*_ASM_ACPI_H*/

drivers/acpi/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,5 @@ obj-y += dptf/
131131
obj-$(CONFIG_ARM64) += arm64/
132132

133133
obj-$(CONFIG_ACPI_VIOT) += viot.o
134+
135+
obj-$(CONFIG_RISCV) += riscv/

drivers/acpi/riscv/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
obj-y += rhct.o

drivers/acpi/riscv/rhct.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2022-2023, Ventana Micro Systems Inc
4+
* Author: Sunil V L <[email protected]>
5+
*
6+
*/
7+
8+
#define pr_fmt(fmt) "ACPI: RHCT: " fmt
9+
10+
#include <linux/acpi.h>
11+
12+
static struct acpi_table_header *acpi_get_rhct(void)
13+
{
14+
static struct acpi_table_header *rhct;
15+
acpi_status status;
16+
17+
/*
18+
* RHCT will be used at runtime on every CPU, so we
19+
* don't need to call acpi_put_table() to release the table mapping.
20+
*/
21+
if (!rhct) {
22+
status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct);
23+
if (ACPI_FAILURE(status)) {
24+
pr_warn_once("No RHCT table found\n");
25+
return NULL;
26+
}
27+
}
28+
29+
return rhct;
30+
}
31+
32+
/*
33+
* During early boot, the caller should call acpi_get_table() and pass its pointer to
34+
* these functions(and free up later). At run time, since this table can be used
35+
* multiple times, NULL may be passed in order to use the cached table.
36+
*/
37+
int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const char **isa)
38+
{
39+
struct acpi_rhct_node_header *node, *ref_node, *end;
40+
u32 size_hdr = sizeof(struct acpi_rhct_node_header);
41+
u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info);
42+
struct acpi_rhct_hart_info *hart_info;
43+
struct acpi_rhct_isa_string *isa_node;
44+
struct acpi_table_rhct *rhct;
45+
u32 *hart_info_node_offset;
46+
u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
47+
48+
BUG_ON(acpi_disabled);
49+
50+
if (!table) {
51+
rhct = (struct acpi_table_rhct *)acpi_get_rhct();
52+
if (!rhct)
53+
return -ENOENT;
54+
} else {
55+
rhct = (struct acpi_table_rhct *)table;
56+
}
57+
58+
end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
59+
60+
for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
61+
node < end;
62+
node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
63+
if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) {
64+
hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr);
65+
hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo);
66+
if (acpi_cpu_id != hart_info->uid)
67+
continue;
68+
69+
for (int i = 0; i < hart_info->num_offsets; i++) {
70+
ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
71+
rhct, hart_info_node_offset[i]);
72+
if (ref_node->type == ACPI_RHCT_NODE_TYPE_ISA_STRING) {
73+
isa_node = ACPI_ADD_PTR(struct acpi_rhct_isa_string,
74+
ref_node, size_hdr);
75+
*isa = isa_node->isa;
76+
return 0;
77+
}
78+
}
79+
}
80+
}
81+
82+
return -1;
83+
}

0 commit comments

Comments
 (0)