1 // SPDX-License-Identifier: GPL-2.0-only
3 * intel_rapl_tpmi: Intel RAPL driver via TPMI interface
5 * Copyright (c) 2023, Intel Corporation.
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/auxiliary_bus.h>
13 #include <linux/intel_tpmi.h>
14 #include <linux/intel_rapl.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
18 #define TPMI_RAPL_VERSION 1
20 /* 1 header + 10 registers + 5 reserved. 8 bytes for each. */
21 #define TPMI_RAPL_DOMAIN_SIZE 128
23 enum tpmi_rapl_domain_type
{
24 TPMI_RAPL_DOMAIN_INVALID
,
25 TPMI_RAPL_DOMAIN_SYSTEM
,
26 TPMI_RAPL_DOMAIN_PACKAGE
,
27 TPMI_RAPL_DOMAIN_RESERVED
,
28 TPMI_RAPL_DOMAIN_MEMORY
,
32 enum tpmi_rapl_register
{
39 TPMI_RAPL_REG_RESERVED
,
40 TPMI_RAPL_REG_ENERGY_STATUS
,
41 TPMI_RAPL_REG_PERF_STATUS
,
42 TPMI_RAPL_REG_POWER_INFO
,
43 TPMI_RAPL_REG_DOMAIN_INFO
,
44 TPMI_RAPL_REG_INTERRUPT
,
45 TPMI_RAPL_REG_MAX
= 15,
48 struct tpmi_rapl_package
{
49 struct rapl_if_priv priv
;
50 struct intel_tpmi_plat_info
*tpmi_info
;
51 struct rapl_package
*rp
;
53 struct list_head node
;
56 static LIST_HEAD(tpmi_rapl_packages
);
57 static DEFINE_MUTEX(tpmi_rapl_lock
);
59 static struct powercap_control_type
*tpmi_control_type
;
61 static int tpmi_rapl_read_raw(int id
, struct reg_action
*ra
)
66 ra
->value
= readq(ra
->reg
.mmio
);
68 ra
->value
&= ra
->mask
;
72 static int tpmi_rapl_write_raw(int id
, struct reg_action
*ra
)
79 val
= readq(ra
->reg
.mmio
);
84 writeq(val
, ra
->reg
.mmio
);
88 static struct tpmi_rapl_package
*trp_alloc(int pkg_id
)
90 struct tpmi_rapl_package
*trp
;
93 mutex_lock(&tpmi_rapl_lock
);
95 if (list_empty(&tpmi_rapl_packages
)) {
96 tpmi_control_type
= powercap_register_control_type(NULL
, "intel-rapl", NULL
);
97 if (IS_ERR(tpmi_control_type
)) {
98 ret
= PTR_ERR(tpmi_control_type
);
103 trp
= kzalloc(sizeof(*trp
), GFP_KERNEL
);
106 goto err_del_powercap
;
109 list_add(&trp
->node
, &tpmi_rapl_packages
);
111 mutex_unlock(&tpmi_rapl_lock
);
115 if (list_empty(&tpmi_rapl_packages
))
116 powercap_unregister_control_type(tpmi_control_type
);
118 mutex_unlock(&tpmi_rapl_lock
);
122 static void trp_release(struct tpmi_rapl_package
*trp
)
124 mutex_lock(&tpmi_rapl_lock
);
125 list_del(&trp
->node
);
127 if (list_empty(&tpmi_rapl_packages
))
128 powercap_unregister_control_type(tpmi_control_type
);
131 mutex_unlock(&tpmi_rapl_lock
);
135 * Bit 0 of TPMI_RAPL_REG_DOMAIN_INFO indicates if the current package is a domain
136 * root or not. Only domain root packages can enumerate System (Psys) Domain.
138 #define TPMI_RAPL_DOMAIN_ROOT BIT(0)
140 static int parse_one_domain(struct tpmi_rapl_package
*trp
, u32 offset
)
142 u8 tpmi_domain_version
;
143 enum rapl_domain_type domain_type
;
144 enum tpmi_rapl_domain_type tpmi_domain_type
;
145 enum tpmi_rapl_register reg_index
;
146 enum rapl_domain_reg_id reg_id
;
147 int tpmi_domain_size
, tpmi_domain_flags
;
148 u64 tpmi_domain_header
= readq(trp
->base
+ offset
);
149 u64 tpmi_domain_info
;
151 /* Domain Parent bits are ignored for now */
152 tpmi_domain_version
= tpmi_domain_header
& 0xff;
153 tpmi_domain_type
= tpmi_domain_header
>> 8 & 0xff;
154 tpmi_domain_size
= tpmi_domain_header
>> 16 & 0xff;
155 tpmi_domain_flags
= tpmi_domain_header
>> 32 & 0xffff;
157 if (tpmi_domain_version
!= TPMI_RAPL_VERSION
) {
158 pr_warn(FW_BUG
"Unsupported version:%d\n", tpmi_domain_version
);
162 /* Domain size: in unit of 128 Bytes */
163 if (tpmi_domain_size
!= 1) {
164 pr_warn(FW_BUG
"Invalid Domain size %d\n", tpmi_domain_size
);
168 /* Unit register and Energy Status register are mandatory for each domain */
169 if (!(tpmi_domain_flags
& BIT(TPMI_RAPL_REG_UNIT
)) ||
170 !(tpmi_domain_flags
& BIT(TPMI_RAPL_REG_ENERGY_STATUS
))) {
171 pr_warn(FW_BUG
"Invalid Domain flag 0x%x\n", tpmi_domain_flags
);
175 switch (tpmi_domain_type
) {
176 case TPMI_RAPL_DOMAIN_PACKAGE
:
177 domain_type
= RAPL_DOMAIN_PACKAGE
;
179 case TPMI_RAPL_DOMAIN_SYSTEM
:
180 if (!(tpmi_domain_flags
& BIT(TPMI_RAPL_REG_DOMAIN_INFO
))) {
181 pr_warn(FW_BUG
"System domain must support Domain Info register\n");
184 tpmi_domain_info
= readq(trp
->base
+ offset
+ TPMI_RAPL_REG_DOMAIN_INFO
);
185 if (!(tpmi_domain_info
& TPMI_RAPL_DOMAIN_ROOT
))
187 domain_type
= RAPL_DOMAIN_PLATFORM
;
189 case TPMI_RAPL_DOMAIN_MEMORY
:
190 domain_type
= RAPL_DOMAIN_DRAM
;
193 pr_warn(FW_BUG
"Unsupported Domain type %d\n", tpmi_domain_type
);
197 if (trp
->priv
.regs
[domain_type
][RAPL_DOMAIN_REG_UNIT
].mmio
) {
198 pr_warn(FW_BUG
"Duplicate Domain type %d\n", tpmi_domain_type
);
202 reg_index
= TPMI_RAPL_REG_HEADER
;
203 while (++reg_index
!= TPMI_RAPL_REG_MAX
) {
204 if (!(tpmi_domain_flags
& BIT(reg_index
)))
208 case TPMI_RAPL_REG_UNIT
:
209 reg_id
= RAPL_DOMAIN_REG_UNIT
;
211 case TPMI_RAPL_REG_PL1
:
212 reg_id
= RAPL_DOMAIN_REG_LIMIT
;
213 trp
->priv
.limits
[domain_type
] |= BIT(POWER_LIMIT1
);
215 case TPMI_RAPL_REG_PL2
:
216 reg_id
= RAPL_DOMAIN_REG_PL2
;
217 trp
->priv
.limits
[domain_type
] |= BIT(POWER_LIMIT2
);
219 case TPMI_RAPL_REG_PL4
:
220 reg_id
= RAPL_DOMAIN_REG_PL4
;
221 trp
->priv
.limits
[domain_type
] |= BIT(POWER_LIMIT4
);
223 case TPMI_RAPL_REG_ENERGY_STATUS
:
224 reg_id
= RAPL_DOMAIN_REG_STATUS
;
226 case TPMI_RAPL_REG_PERF_STATUS
:
227 reg_id
= RAPL_DOMAIN_REG_PERF
;
229 case TPMI_RAPL_REG_POWER_INFO
:
230 reg_id
= RAPL_DOMAIN_REG_INFO
;
235 trp
->priv
.regs
[domain_type
][reg_id
].mmio
= trp
->base
+ offset
+ reg_index
* 8;
241 static int intel_rapl_tpmi_probe(struct auxiliary_device
*auxdev
,
242 const struct auxiliary_device_id
*id
)
244 struct tpmi_rapl_package
*trp
;
245 struct intel_tpmi_plat_info
*info
;
246 struct resource
*res
;
250 info
= tpmi_get_platform_data(auxdev
);
254 trp
= trp_alloc(info
->package_id
);
258 if (tpmi_get_resource_count(auxdev
) > 1) {
259 dev_err(&auxdev
->dev
, "does not support multiple resources\n");
264 res
= tpmi_get_resource_at_index(auxdev
, 0);
266 dev_err(&auxdev
->dev
, "can't fetch device resource info\n");
271 trp
->base
= devm_ioremap_resource(&auxdev
->dev
, res
);
272 if (IS_ERR(trp
->base
)) {
273 ret
= PTR_ERR(trp
->base
);
277 for (offset
= 0; offset
< resource_size(res
); offset
+= TPMI_RAPL_DOMAIN_SIZE
) {
278 ret
= parse_one_domain(trp
, offset
);
283 trp
->tpmi_info
= info
;
284 trp
->priv
.type
= RAPL_IF_TPMI
;
285 trp
->priv
.read_raw
= tpmi_rapl_read_raw
;
286 trp
->priv
.write_raw
= tpmi_rapl_write_raw
;
287 trp
->priv
.control_type
= tpmi_control_type
;
289 /* RAPL TPMI I/F is per physical package */
290 trp
->rp
= rapl_find_package_domain(info
->package_id
, &trp
->priv
, false);
292 dev_err(&auxdev
->dev
, "Domain for Package%d already exists\n", info
->package_id
);
297 trp
->rp
= rapl_add_package(info
->package_id
, &trp
->priv
, false);
298 if (IS_ERR(trp
->rp
)) {
299 dev_err(&auxdev
->dev
, "Failed to add RAPL Domain for Package%d, %ld\n",
300 info
->package_id
, PTR_ERR(trp
->rp
));
301 ret
= PTR_ERR(trp
->rp
);
305 rapl_package_add_pmu(trp
->rp
);
307 auxiliary_set_drvdata(auxdev
, trp
);
315 static void intel_rapl_tpmi_remove(struct auxiliary_device
*auxdev
)
317 struct tpmi_rapl_package
*trp
= auxiliary_get_drvdata(auxdev
);
319 rapl_package_remove_pmu(trp
->rp
);
320 rapl_remove_package(trp
->rp
);
324 static const struct auxiliary_device_id intel_rapl_tpmi_ids
[] = {
325 {.name
= "intel_vsec.tpmi-rapl" },
329 MODULE_DEVICE_TABLE(auxiliary
, intel_rapl_tpmi_ids
);
331 static struct auxiliary_driver intel_rapl_tpmi_driver
= {
332 .probe
= intel_rapl_tpmi_probe
,
333 .remove
= intel_rapl_tpmi_remove
,
334 .id_table
= intel_rapl_tpmi_ids
,
337 module_auxiliary_driver(intel_rapl_tpmi_driver
)
339 MODULE_IMPORT_NS(INTEL_TPMI
);
341 MODULE_DESCRIPTION("Intel RAPL TPMI Driver");
342 MODULE_LICENSE("GPL");