xref: /openbmc/linux/drivers/powercap/intel_rapl_tpmi.c (revision 7b7fd0ac7dc1ffcaf24d9bca0f051b0168e43cd4)
19eef7f9dSZhang Rui // SPDX-License-Identifier: GPL-2.0-only
29eef7f9dSZhang Rui /*
39eef7f9dSZhang Rui  * intel_rapl_tpmi: Intel RAPL driver via TPMI interface
49eef7f9dSZhang Rui  *
59eef7f9dSZhang Rui  * Copyright (c) 2023, Intel Corporation.
69eef7f9dSZhang Rui  * All Rights Reserved.
79eef7f9dSZhang Rui  *
89eef7f9dSZhang Rui  */
99eef7f9dSZhang Rui #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
109eef7f9dSZhang Rui 
119eef7f9dSZhang Rui #include <linux/auxiliary_bus.h>
129eef7f9dSZhang Rui #include <linux/io.h>
139eef7f9dSZhang Rui #include <linux/intel_tpmi.h>
149eef7f9dSZhang Rui #include <linux/intel_rapl.h>
159eef7f9dSZhang Rui #include <linux/module.h>
169eef7f9dSZhang Rui #include <linux/slab.h>
179eef7f9dSZhang Rui 
18a91c6e11SZhang Rui #define TPMI_RAPL_MAJOR_VERSION 0
19a91c6e11SZhang Rui #define TPMI_RAPL_MINOR_VERSION 1
209eef7f9dSZhang Rui 
219eef7f9dSZhang Rui /* 1 header + 10 registers + 5 reserved. 8 bytes for each. */
229eef7f9dSZhang Rui #define TPMI_RAPL_DOMAIN_SIZE 128
239eef7f9dSZhang Rui 
249eef7f9dSZhang Rui enum tpmi_rapl_domain_type {
259eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_INVALID,
269eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_SYSTEM,
279eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_PACKAGE,
289eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_RESERVED,
299eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_MEMORY,
309eef7f9dSZhang Rui 	TPMI_RAPL_DOMAIN_MAX,
319eef7f9dSZhang Rui };
329eef7f9dSZhang Rui 
339eef7f9dSZhang Rui enum tpmi_rapl_register {
349eef7f9dSZhang Rui 	TPMI_RAPL_REG_HEADER,
359eef7f9dSZhang Rui 	TPMI_RAPL_REG_UNIT,
369eef7f9dSZhang Rui 	TPMI_RAPL_REG_PL1,
379eef7f9dSZhang Rui 	TPMI_RAPL_REG_PL2,
389eef7f9dSZhang Rui 	TPMI_RAPL_REG_PL3,
399eef7f9dSZhang Rui 	TPMI_RAPL_REG_PL4,
409eef7f9dSZhang Rui 	TPMI_RAPL_REG_RESERVED,
419eef7f9dSZhang Rui 	TPMI_RAPL_REG_ENERGY_STATUS,
429eef7f9dSZhang Rui 	TPMI_RAPL_REG_PERF_STATUS,
439eef7f9dSZhang Rui 	TPMI_RAPL_REG_POWER_INFO,
44b5cbb42fSZhang Rui 	TPMI_RAPL_REG_DOMAIN_INFO,
459eef7f9dSZhang Rui 	TPMI_RAPL_REG_INTERRUPT,
469eef7f9dSZhang Rui 	TPMI_RAPL_REG_MAX = 15,
479eef7f9dSZhang Rui };
489eef7f9dSZhang Rui 
499eef7f9dSZhang Rui struct tpmi_rapl_package {
509eef7f9dSZhang Rui 	struct rapl_if_priv priv;
519eef7f9dSZhang Rui 	struct intel_tpmi_plat_info *tpmi_info;
529eef7f9dSZhang Rui 	struct rapl_package *rp;
539eef7f9dSZhang Rui 	void __iomem *base;
549eef7f9dSZhang Rui 	struct list_head node;
559eef7f9dSZhang Rui };
569eef7f9dSZhang Rui 
579eef7f9dSZhang Rui static LIST_HEAD(tpmi_rapl_packages);
589eef7f9dSZhang Rui static DEFINE_MUTEX(tpmi_rapl_lock);
599eef7f9dSZhang Rui 
609eef7f9dSZhang Rui static struct powercap_control_type *tpmi_control_type;
619eef7f9dSZhang Rui 
tpmi_rapl_read_raw(int id,struct reg_action * ra)629eef7f9dSZhang Rui static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
639eef7f9dSZhang Rui {
6416e95a62SZhang Rui 	if (!ra->reg.mmio)
659eef7f9dSZhang Rui 		return -EINVAL;
669eef7f9dSZhang Rui 
6716e95a62SZhang Rui 	ra->value = readq(ra->reg.mmio);
689eef7f9dSZhang Rui 
699eef7f9dSZhang Rui 	ra->value &= ra->mask;
709eef7f9dSZhang Rui 	return 0;
719eef7f9dSZhang Rui }
729eef7f9dSZhang Rui 
tpmi_rapl_write_raw(int id,struct reg_action * ra)739eef7f9dSZhang Rui static int tpmi_rapl_write_raw(int id, struct reg_action *ra)
749eef7f9dSZhang Rui {
759eef7f9dSZhang Rui 	u64 val;
769eef7f9dSZhang Rui 
7716e95a62SZhang Rui 	if (!ra->reg.mmio)
789eef7f9dSZhang Rui 		return -EINVAL;
799eef7f9dSZhang Rui 
8016e95a62SZhang Rui 	val = readq(ra->reg.mmio);
819eef7f9dSZhang Rui 
829eef7f9dSZhang Rui 	val &= ~ra->mask;
839eef7f9dSZhang Rui 	val |= ra->value;
849eef7f9dSZhang Rui 
8516e95a62SZhang Rui 	writeq(val, ra->reg.mmio);
869eef7f9dSZhang Rui 	return 0;
879eef7f9dSZhang Rui }
889eef7f9dSZhang Rui 
trp_alloc(int pkg_id)899eef7f9dSZhang Rui static struct tpmi_rapl_package *trp_alloc(int pkg_id)
909eef7f9dSZhang Rui {
919eef7f9dSZhang Rui 	struct tpmi_rapl_package *trp;
929eef7f9dSZhang Rui 	int ret;
939eef7f9dSZhang Rui 
949eef7f9dSZhang Rui 	mutex_lock(&tpmi_rapl_lock);
959eef7f9dSZhang Rui 
969eef7f9dSZhang Rui 	if (list_empty(&tpmi_rapl_packages)) {
979eef7f9dSZhang Rui 		tpmi_control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
989eef7f9dSZhang Rui 		if (IS_ERR(tpmi_control_type)) {
999eef7f9dSZhang Rui 			ret = PTR_ERR(tpmi_control_type);
1009eef7f9dSZhang Rui 			goto err_unlock;
1019eef7f9dSZhang Rui 		}
1029eef7f9dSZhang Rui 	}
1039eef7f9dSZhang Rui 
1049eef7f9dSZhang Rui 	trp = kzalloc(sizeof(*trp), GFP_KERNEL);
1059eef7f9dSZhang Rui 	if (!trp) {
1069eef7f9dSZhang Rui 		ret = -ENOMEM;
1079eef7f9dSZhang Rui 		goto err_del_powercap;
1089eef7f9dSZhang Rui 	}
1099eef7f9dSZhang Rui 
1109eef7f9dSZhang Rui 	list_add(&trp->node, &tpmi_rapl_packages);
1119eef7f9dSZhang Rui 
1129eef7f9dSZhang Rui 	mutex_unlock(&tpmi_rapl_lock);
1139eef7f9dSZhang Rui 	return trp;
1149eef7f9dSZhang Rui 
1159eef7f9dSZhang Rui err_del_powercap:
1169eef7f9dSZhang Rui 	if (list_empty(&tpmi_rapl_packages))
1179eef7f9dSZhang Rui 		powercap_unregister_control_type(tpmi_control_type);
1189eef7f9dSZhang Rui err_unlock:
1199eef7f9dSZhang Rui 	mutex_unlock(&tpmi_rapl_lock);
1209eef7f9dSZhang Rui 	return ERR_PTR(ret);
1219eef7f9dSZhang Rui }
1229eef7f9dSZhang Rui 
trp_release(struct tpmi_rapl_package * trp)1239eef7f9dSZhang Rui static void trp_release(struct tpmi_rapl_package *trp)
1249eef7f9dSZhang Rui {
1259eef7f9dSZhang Rui 	mutex_lock(&tpmi_rapl_lock);
1269eef7f9dSZhang Rui 	list_del(&trp->node);
1279eef7f9dSZhang Rui 
1289eef7f9dSZhang Rui 	if (list_empty(&tpmi_rapl_packages))
1299eef7f9dSZhang Rui 		powercap_unregister_control_type(tpmi_control_type);
1309eef7f9dSZhang Rui 
1319eef7f9dSZhang Rui 	kfree(trp);
1329eef7f9dSZhang Rui 	mutex_unlock(&tpmi_rapl_lock);
1339eef7f9dSZhang Rui }
1349eef7f9dSZhang Rui 
1357f628266SZhang Rui /*
1367f628266SZhang Rui  * Bit 0 of TPMI_RAPL_REG_DOMAIN_INFO indicates if the current package is a domain
1377f628266SZhang Rui  * root or not. Only domain root packages can enumerate System (Psys) Domain.
1387f628266SZhang Rui  */
1397f628266SZhang Rui #define TPMI_RAPL_DOMAIN_ROOT	BIT(0)
1407f628266SZhang Rui 
parse_one_domain(struct tpmi_rapl_package * trp,u32 offset)1419eef7f9dSZhang Rui static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
1429eef7f9dSZhang Rui {
1439eef7f9dSZhang Rui 	u8 tpmi_domain_version;
1449eef7f9dSZhang Rui 	enum rapl_domain_type domain_type;
1459eef7f9dSZhang Rui 	enum tpmi_rapl_domain_type tpmi_domain_type;
1469eef7f9dSZhang Rui 	enum tpmi_rapl_register reg_index;
1479eef7f9dSZhang Rui 	enum rapl_domain_reg_id reg_id;
1489eef7f9dSZhang Rui 	int tpmi_domain_size, tpmi_domain_flags;
14916e95a62SZhang Rui 	u64 tpmi_domain_header = readq(trp->base + offset);
1507f628266SZhang Rui 	u64 tpmi_domain_info;
1519eef7f9dSZhang Rui 
1529eef7f9dSZhang Rui 	/* Domain Parent bits are ignored for now */
1539eef7f9dSZhang Rui 	tpmi_domain_version = tpmi_domain_header & 0xff;
1549eef7f9dSZhang Rui 	tpmi_domain_type = tpmi_domain_header >> 8 & 0xff;
1559eef7f9dSZhang Rui 	tpmi_domain_size = tpmi_domain_header >> 16 & 0xff;
1569eef7f9dSZhang Rui 	tpmi_domain_flags = tpmi_domain_header >> 32 & 0xffff;
1579eef7f9dSZhang Rui 
158a91c6e11SZhang Rui 	if (tpmi_domain_version == TPMI_VERSION_INVALID) {
159a91c6e11SZhang Rui 		pr_warn(FW_BUG "Invalid version\n");
1609eef7f9dSZhang Rui 		return -ENODEV;
1619eef7f9dSZhang Rui 	}
1629eef7f9dSZhang Rui 
163a91c6e11SZhang Rui 	if (TPMI_MAJOR_VERSION(tpmi_domain_version) != TPMI_RAPL_MAJOR_VERSION) {
164a91c6e11SZhang Rui 		pr_warn(FW_BUG "Unsupported major version:%ld\n",
165a91c6e11SZhang Rui 			TPMI_MAJOR_VERSION(tpmi_domain_version));
166a91c6e11SZhang Rui 		return -ENODEV;
167a91c6e11SZhang Rui 	}
168a91c6e11SZhang Rui 
169a91c6e11SZhang Rui 	if (TPMI_MINOR_VERSION(tpmi_domain_version) > TPMI_RAPL_MINOR_VERSION)
170a91c6e11SZhang Rui 		pr_info("Ignore: Unsupported minor version:%ld\n",
171a91c6e11SZhang Rui 			TPMI_MINOR_VERSION(tpmi_domain_version));
172a91c6e11SZhang Rui 
1739eef7f9dSZhang Rui 	/* Domain size: in unit of 128 Bytes */
1749eef7f9dSZhang Rui 	if (tpmi_domain_size != 1) {
1759eef7f9dSZhang Rui 		pr_warn(FW_BUG "Invalid Domain size %d\n", tpmi_domain_size);
1769eef7f9dSZhang Rui 		return -EINVAL;
1779eef7f9dSZhang Rui 	}
1789eef7f9dSZhang Rui 
1799eef7f9dSZhang Rui 	/* Unit register and Energy Status register are mandatory for each domain */
1809eef7f9dSZhang Rui 	if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_UNIT)) ||
1819eef7f9dSZhang Rui 	    !(tpmi_domain_flags & BIT(TPMI_RAPL_REG_ENERGY_STATUS))) {
1829eef7f9dSZhang Rui 		pr_warn(FW_BUG "Invalid Domain flag 0x%x\n", tpmi_domain_flags);
1839eef7f9dSZhang Rui 		return -EINVAL;
1849eef7f9dSZhang Rui 	}
1859eef7f9dSZhang Rui 
1869eef7f9dSZhang Rui 	switch (tpmi_domain_type) {
1879eef7f9dSZhang Rui 	case TPMI_RAPL_DOMAIN_PACKAGE:
1889eef7f9dSZhang Rui 		domain_type = RAPL_DOMAIN_PACKAGE;
1899eef7f9dSZhang Rui 		break;
1909eef7f9dSZhang Rui 	case TPMI_RAPL_DOMAIN_SYSTEM:
1917f628266SZhang Rui 		if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_DOMAIN_INFO))) {
1927f628266SZhang Rui 			pr_warn(FW_BUG "System domain must support Domain Info register\n");
1937f628266SZhang Rui 			return -ENODEV;
1947f628266SZhang Rui 		}
195*bd3222d4SZhang Rui 		tpmi_domain_info = readq(trp->base + offset + TPMI_RAPL_REG_DOMAIN_INFO * 8);
1967f628266SZhang Rui 		if (!(tpmi_domain_info & TPMI_RAPL_DOMAIN_ROOT))
1977f628266SZhang Rui 			return 0;
1989eef7f9dSZhang Rui 		domain_type = RAPL_DOMAIN_PLATFORM;
1999eef7f9dSZhang Rui 		break;
2009eef7f9dSZhang Rui 	case TPMI_RAPL_DOMAIN_MEMORY:
2019eef7f9dSZhang Rui 		domain_type = RAPL_DOMAIN_DRAM;
2029eef7f9dSZhang Rui 		break;
2039eef7f9dSZhang Rui 	default:
2049eef7f9dSZhang Rui 		pr_warn(FW_BUG "Unsupported Domain type %d\n", tpmi_domain_type);
2059eef7f9dSZhang Rui 		return -EINVAL;
2069eef7f9dSZhang Rui 	}
2079eef7f9dSZhang Rui 
20816e95a62SZhang Rui 	if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT].mmio) {
2099eef7f9dSZhang Rui 		pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type);
2109eef7f9dSZhang Rui 		return -EINVAL;
2119eef7f9dSZhang Rui 	}
2129eef7f9dSZhang Rui 
2139eef7f9dSZhang Rui 	reg_index = TPMI_RAPL_REG_HEADER;
2149eef7f9dSZhang Rui 	while (++reg_index != TPMI_RAPL_REG_MAX) {
2159eef7f9dSZhang Rui 		if (!(tpmi_domain_flags & BIT(reg_index)))
2169eef7f9dSZhang Rui 			continue;
2179eef7f9dSZhang Rui 
2189eef7f9dSZhang Rui 		switch (reg_index) {
2199eef7f9dSZhang Rui 		case TPMI_RAPL_REG_UNIT:
2209eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_UNIT;
2219eef7f9dSZhang Rui 			break;
2229eef7f9dSZhang Rui 		case TPMI_RAPL_REG_PL1:
2239eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_LIMIT;
2249eef7f9dSZhang Rui 			trp->priv.limits[domain_type] |= BIT(POWER_LIMIT1);
2259eef7f9dSZhang Rui 			break;
2269eef7f9dSZhang Rui 		case TPMI_RAPL_REG_PL2:
2279eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_PL2;
2289eef7f9dSZhang Rui 			trp->priv.limits[domain_type] |= BIT(POWER_LIMIT2);
2299eef7f9dSZhang Rui 			break;
2309eef7f9dSZhang Rui 		case TPMI_RAPL_REG_PL4:
2319eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_PL4;
2329eef7f9dSZhang Rui 			trp->priv.limits[domain_type] |= BIT(POWER_LIMIT4);
2339eef7f9dSZhang Rui 			break;
2349eef7f9dSZhang Rui 		case TPMI_RAPL_REG_ENERGY_STATUS:
2359eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_STATUS;
2369eef7f9dSZhang Rui 			break;
2379eef7f9dSZhang Rui 		case TPMI_RAPL_REG_PERF_STATUS:
2389eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_PERF;
2399eef7f9dSZhang Rui 			break;
2409eef7f9dSZhang Rui 		case TPMI_RAPL_REG_POWER_INFO:
2419eef7f9dSZhang Rui 			reg_id = RAPL_DOMAIN_REG_INFO;
2429eef7f9dSZhang Rui 			break;
2439eef7f9dSZhang Rui 		default:
2449eef7f9dSZhang Rui 			continue;
2459eef7f9dSZhang Rui 		}
24616e95a62SZhang Rui 		trp->priv.regs[domain_type][reg_id].mmio = trp->base + offset + reg_index * 8;
2479eef7f9dSZhang Rui 	}
2489eef7f9dSZhang Rui 
2499eef7f9dSZhang Rui 	return 0;
2509eef7f9dSZhang Rui }
2519eef7f9dSZhang Rui 
intel_rapl_tpmi_probe(struct auxiliary_device * auxdev,const struct auxiliary_device_id * id)2529eef7f9dSZhang Rui static int intel_rapl_tpmi_probe(struct auxiliary_device *auxdev,
2539eef7f9dSZhang Rui 				 const struct auxiliary_device_id *id)
2549eef7f9dSZhang Rui {
2559eef7f9dSZhang Rui 	struct tpmi_rapl_package *trp;
2569eef7f9dSZhang Rui 	struct intel_tpmi_plat_info *info;
2579eef7f9dSZhang Rui 	struct resource *res;
2589eef7f9dSZhang Rui 	u32 offset;
2599eef7f9dSZhang Rui 	int ret;
2609eef7f9dSZhang Rui 
2619eef7f9dSZhang Rui 	info = tpmi_get_platform_data(auxdev);
2629eef7f9dSZhang Rui 	if (!info)
2639eef7f9dSZhang Rui 		return -ENODEV;
2649eef7f9dSZhang Rui 
2659eef7f9dSZhang Rui 	trp = trp_alloc(info->package_id);
2669eef7f9dSZhang Rui 	if (IS_ERR(trp))
2679eef7f9dSZhang Rui 		return PTR_ERR(trp);
2689eef7f9dSZhang Rui 
2699eef7f9dSZhang Rui 	if (tpmi_get_resource_count(auxdev) > 1) {
2709eef7f9dSZhang Rui 		dev_err(&auxdev->dev, "does not support multiple resources\n");
2719eef7f9dSZhang Rui 		ret = -EINVAL;
2729eef7f9dSZhang Rui 		goto err;
2739eef7f9dSZhang Rui 	}
2749eef7f9dSZhang Rui 
2759eef7f9dSZhang Rui 	res = tpmi_get_resource_at_index(auxdev, 0);
2769eef7f9dSZhang Rui 	if (!res) {
2779eef7f9dSZhang Rui 		dev_err(&auxdev->dev, "can't fetch device resource info\n");
2789eef7f9dSZhang Rui 		ret = -EIO;
2799eef7f9dSZhang Rui 		goto err;
2809eef7f9dSZhang Rui 	}
2819eef7f9dSZhang Rui 
2829eef7f9dSZhang Rui 	trp->base = devm_ioremap_resource(&auxdev->dev, res);
28349776c71SDan Carpenter 	if (IS_ERR(trp->base)) {
28449776c71SDan Carpenter 		ret = PTR_ERR(trp->base);
2859eef7f9dSZhang Rui 		goto err;
2869eef7f9dSZhang Rui 	}
2879eef7f9dSZhang Rui 
2889eef7f9dSZhang Rui 	for (offset = 0; offset < resource_size(res); offset += TPMI_RAPL_DOMAIN_SIZE) {
2899eef7f9dSZhang Rui 		ret = parse_one_domain(trp, offset);
2909eef7f9dSZhang Rui 		if (ret)
2919eef7f9dSZhang Rui 			goto err;
2929eef7f9dSZhang Rui 	}
2939eef7f9dSZhang Rui 
2949eef7f9dSZhang Rui 	trp->tpmi_info = info;
2959eef7f9dSZhang Rui 	trp->priv.type = RAPL_IF_TPMI;
2969eef7f9dSZhang Rui 	trp->priv.read_raw = tpmi_rapl_read_raw;
2979eef7f9dSZhang Rui 	trp->priv.write_raw = tpmi_rapl_write_raw;
2989eef7f9dSZhang Rui 	trp->priv.control_type = tpmi_control_type;
2999eef7f9dSZhang Rui 
3009eef7f9dSZhang Rui 	/* RAPL TPMI I/F is per physical package */
3019eef7f9dSZhang Rui 	trp->rp = rapl_find_package_domain(info->package_id, &trp->priv, false);
3029eef7f9dSZhang Rui 	if (trp->rp) {
3039eef7f9dSZhang Rui 		dev_err(&auxdev->dev, "Domain for Package%d already exists\n", info->package_id);
3049eef7f9dSZhang Rui 		ret = -EEXIST;
3059eef7f9dSZhang Rui 		goto err;
3069eef7f9dSZhang Rui 	}
3079eef7f9dSZhang Rui 
3089eef7f9dSZhang Rui 	trp->rp = rapl_add_package(info->package_id, &trp->priv, false);
3099eef7f9dSZhang Rui 	if (IS_ERR(trp->rp)) {
3109eef7f9dSZhang Rui 		dev_err(&auxdev->dev, "Failed to add RAPL Domain for Package%d, %ld\n",
3119eef7f9dSZhang Rui 			info->package_id, PTR_ERR(trp->rp));
3129eef7f9dSZhang Rui 		ret = PTR_ERR(trp->rp);
3139eef7f9dSZhang Rui 		goto err;
3149eef7f9dSZhang Rui 	}
3159eef7f9dSZhang Rui 
3169eef7f9dSZhang Rui 	auxiliary_set_drvdata(auxdev, trp);
3179eef7f9dSZhang Rui 
3189eef7f9dSZhang Rui 	return 0;
3199eef7f9dSZhang Rui err:
3209eef7f9dSZhang Rui 	trp_release(trp);
3219eef7f9dSZhang Rui 	return ret;
3229eef7f9dSZhang Rui }
3239eef7f9dSZhang Rui 
intel_rapl_tpmi_remove(struct auxiliary_device * auxdev)3249eef7f9dSZhang Rui static void intel_rapl_tpmi_remove(struct auxiliary_device *auxdev)
3259eef7f9dSZhang Rui {
3269eef7f9dSZhang Rui 	struct tpmi_rapl_package *trp = auxiliary_get_drvdata(auxdev);
3279eef7f9dSZhang Rui 
3289eef7f9dSZhang Rui 	rapl_remove_package(trp->rp);
3299eef7f9dSZhang Rui 	trp_release(trp);
3309eef7f9dSZhang Rui }
3319eef7f9dSZhang Rui 
3329eef7f9dSZhang Rui static const struct auxiliary_device_id intel_rapl_tpmi_ids[] = {
3339eef7f9dSZhang Rui 	{.name = "intel_vsec.tpmi-rapl" },
3349eef7f9dSZhang Rui 	{ }
3359eef7f9dSZhang Rui };
3369eef7f9dSZhang Rui 
3379eef7f9dSZhang Rui MODULE_DEVICE_TABLE(auxiliary, intel_rapl_tpmi_ids);
3389eef7f9dSZhang Rui 
3399eef7f9dSZhang Rui static struct auxiliary_driver intel_rapl_tpmi_driver = {
3409eef7f9dSZhang Rui 	.probe = intel_rapl_tpmi_probe,
3419eef7f9dSZhang Rui 	.remove = intel_rapl_tpmi_remove,
3429eef7f9dSZhang Rui 	.id_table = intel_rapl_tpmi_ids,
3439eef7f9dSZhang Rui };
3449eef7f9dSZhang Rui 
3459eef7f9dSZhang Rui module_auxiliary_driver(intel_rapl_tpmi_driver)
3469eef7f9dSZhang Rui 
3479eef7f9dSZhang Rui MODULE_IMPORT_NS(INTEL_TPMI);
3489eef7f9dSZhang Rui 
3499eef7f9dSZhang Rui MODULE_DESCRIPTION("Intel RAPL TPMI Driver");
3509eef7f9dSZhang Rui MODULE_LICENSE("GPL");
351