1 /*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2025 The FreeBSD Foundation
5 *
6 * This software was developed by Aymeric Wibo <obiwac@freebsd.org>
7 * under sponsorship from the FreeBSD Foundation.
8 */
9
10 #ifndef _AMDSMU_H_
11 #define _AMDSMU_H_
12
13 #include <sys/param.h>
14 #include <sys/bus.h>
15 #include <sys/eventhandler.h>
16 #include <sys/kernel.h>
17
18 #include <machine/cpu.h>
19 #include <machine/md_var.h>
20 #include <machine/cputypes.h>
21 #include <machine/specialreg.h>
22 #include <x86/cputypes.h>
23
24 #include <dev/amdsmu/amdsmu_reg.h>
25
26 #define SMU_RES_READ_PERIOD_US 50
27 #define SMU_RES_READ_MAX 20000
28
29 static const char *amdsmu_ip_blocks_names[] = {
30 "DISPLAY",
31 "CPU",
32 "GFX",
33 "VDD",
34 "ACP",
35 "VCN",
36 "ISP",
37 "NBIO",
38 "DF",
39 "USB3_0",
40 "USB3_1",
41 "LAPIC",
42 "USB3_2",
43 "USB3_3",
44 "USB3_4",
45 "USB4_0",
46 "USB4_1",
47 "MPM",
48 "JPEG",
49 "IPU",
50 "UMSCH",
51 "VPE",
52 };
53
54 static const char *amdsmu_ip_blocks_names_v2[] = {
55 "DISPLAY",
56 "CPU",
57 "GFX",
58 "VDD",
59 "VDD_CCX",
60 "ACP",
61 "VCN_0",
62 "VCN_1",
63 "ISP",
64 "NBIO",
65 "DF",
66 "USB3_0",
67 "USB3_1",
68 "LAPIC",
69 "USB3_2",
70 "USB4_RT0",
71 "USB4_RT1",
72 "USB4_0",
73 "USB4_1",
74 "MPM",
75 "JPEG_0",
76 "JPEG_1",
77 "IPU",
78 "UMSCH",
79 "VPE",
80 };
81
82 #define IP_MAX_BLOCK_NAMES 32
83
84 CTASSERT(nitems(amdsmu_ip_blocks_names) <= IP_MAX_BLOCK_NAMES);
85 CTASSERT(nitems(amdsmu_ip_blocks_names_v2) <= IP_MAX_BLOCK_NAMES);
86
87 static const struct amdsmu_product {
88 uint16_t amdsmu_vendorid;
89 uint16_t amdsmu_deviceid;
90 uint32_t model;
91 int16_t idlemask_reg;
92 size_t ip_block_count;
93 const char **ip_blocks_names;
94 uint32_t amdsmu_msg;
95 } amdsmu_products[] = {
96 { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT, 0x00,
97 SMU_REG_IDLEMASK_CEZANNE, 12 , amdsmu_ip_blocks_names,
98 SMU_REG_MSG_CEZANNE},
99 { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT, 0x00,
100 SMU_REG_IDLEMASK_PHOENIX, 12 , amdsmu_ip_blocks_names,
101 SMU_REG_MSG_CEZANNE},
102 { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT, 0x00,
103 SMU_REG_IDLEMASK_PHOENIX, 21 , amdsmu_ip_blocks_names,
104 SMU_REG_MSG_CEZANNE},
105 { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x00,
106 SMU_REG_IDLEMASK_KRACKAN, 22, amdsmu_ip_blocks_names,
107 SMU_REG_MSG_KRACKAN },
108 { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x70,
109 SMU_REG_IDLEMASK_KRACKAN, 25, amdsmu_ip_blocks_names_v2,
110 SMU_REG_MSG_KRACKAN },
111 /*
112 * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support
113 * S0i3 and thus doesn't have an idlemask. Since our driver doesn't
114 * yet understand this, don't attach to Strix Point for the time being.
115 */
116 };
117
118 struct amdsmu_softc {
119 const struct amdsmu_product *product;
120
121 struct sysctl_ctx_list *sysctlctx;
122 struct sysctl_oid *sysctlnode;
123
124 struct eventhandler_entry *eh_suspend;
125 struct eventhandler_entry *eh_resume;
126
127 struct resource *res;
128 bus_space_tag_t bus_tag;
129
130 bus_space_handle_t smu_space;
131 bus_space_handle_t reg_space;
132
133 uint8_t smu_program;
134 uint8_t smu_maj, smu_min, smu_rev;
135
136 uint32_t active_ip_blocks;
137 struct sysctl_oid *ip_blocks_sysctlnode;
138 struct sysctl_oid *ip_block_sysctlnodes[IP_MAX_BLOCK_NAMES];
139 bool ip_blocks_active[IP_MAX_BLOCK_NAMES];
140
141 bus_space_handle_t metrics_space;
142 struct amdsmu_metrics metrics;
143 uint32_t idlemask;
144 uint32_t smu_msg;
145 };
146
147 static inline uint32_t
amdsmu_read4(const struct amdsmu_softc * sc,bus_size_t reg)148 amdsmu_read4(const struct amdsmu_softc *sc, bus_size_t reg)
149 {
150 return (bus_space_read_4(sc->bus_tag, sc->reg_space, reg));
151 }
152
153 static inline void
amdsmu_write4(const struct amdsmu_softc * sc,bus_size_t reg,uint32_t val)154 amdsmu_write4(const struct amdsmu_softc *sc, bus_size_t reg, uint32_t val)
155 {
156 bus_space_write_4(sc->bus_tag, sc->reg_space, reg, val);
157 }
158
159 #endif /* _AMDSMU_H_ */
160