xref: /linux/drivers/platform/x86/amd/hsmp/plat.c (revision e47c018a0ee6962fe3dd895407e2c49538cc066d)
1*e47c018aSSuma Hegde // SPDX-License-Identifier: GPL-2.0
2*e47c018aSSuma Hegde /*
3*e47c018aSSuma Hegde  * AMD HSMP Platform Driver
4*e47c018aSSuma Hegde  * Copyright (c) 2024, AMD.
5*e47c018aSSuma Hegde  * All Rights Reserved.
6*e47c018aSSuma Hegde  *
7*e47c018aSSuma Hegde  * This file provides platform device implementations.
8*e47c018aSSuma Hegde  */
9*e47c018aSSuma Hegde 
10*e47c018aSSuma Hegde #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11*e47c018aSSuma Hegde 
12*e47c018aSSuma Hegde #include <asm/amd_nb.h>
13*e47c018aSSuma Hegde 
14*e47c018aSSuma Hegde #include <linux/device.h>
15*e47c018aSSuma Hegde #include <linux/pci.h>
16*e47c018aSSuma Hegde #include <linux/sysfs.h>
17*e47c018aSSuma Hegde 
18*e47c018aSSuma Hegde #include "hsmp.h"
19*e47c018aSSuma Hegde 
20*e47c018aSSuma Hegde /*
21*e47c018aSSuma Hegde  * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
22*e47c018aSSuma Hegde  * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
23*e47c018aSSuma Hegde  * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
24*e47c018aSSuma Hegde  */
25*e47c018aSSuma Hegde #define SMN_HSMP_BASE		0x3B00000
26*e47c018aSSuma Hegde #define SMN_HSMP_MSG_ID		0x0010534
27*e47c018aSSuma Hegde #define SMN_HSMP_MSG_ID_F1A_M0H	0x0010934
28*e47c018aSSuma Hegde #define SMN_HSMP_MSG_RESP	0x0010980
29*e47c018aSSuma Hegde #define SMN_HSMP_MSG_DATA	0x00109E0
30*e47c018aSSuma Hegde 
31*e47c018aSSuma Hegde #define HSMP_INDEX_REG		0xc4
32*e47c018aSSuma Hegde #define HSMP_DATA_REG		0xc8
33*e47c018aSSuma Hegde 
34*e47c018aSSuma Hegde static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
35*e47c018aSSuma Hegde 			     u32 *value, bool write)
36*e47c018aSSuma Hegde {
37*e47c018aSSuma Hegde 	int ret;
38*e47c018aSSuma Hegde 
39*e47c018aSSuma Hegde 	if (!sock->root)
40*e47c018aSSuma Hegde 		return -ENODEV;
41*e47c018aSSuma Hegde 
42*e47c018aSSuma Hegde 	ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
43*e47c018aSSuma Hegde 				     sock->mbinfo.base_addr + offset);
44*e47c018aSSuma Hegde 	if (ret)
45*e47c018aSSuma Hegde 		return ret;
46*e47c018aSSuma Hegde 
47*e47c018aSSuma Hegde 	ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)
48*e47c018aSSuma Hegde 		     : pci_read_config_dword(sock->root, HSMP_DATA_REG, value));
49*e47c018aSSuma Hegde 
50*e47c018aSSuma Hegde 	return ret;
51*e47c018aSSuma Hegde }
52*e47c018aSSuma Hegde 
53*e47c018aSSuma Hegde int hsmp_create_non_acpi_sysfs_if(struct device *dev)
54*e47c018aSSuma Hegde {
55*e47c018aSSuma Hegde 	const struct attribute_group **hsmp_attr_grps;
56*e47c018aSSuma Hegde 	struct attribute_group *attr_grp;
57*e47c018aSSuma Hegde 	u16 i;
58*e47c018aSSuma Hegde 
59*e47c018aSSuma Hegde 	hsmp_attr_grps = devm_kcalloc(dev, plat_dev.num_sockets + 1,
60*e47c018aSSuma Hegde 				      sizeof(*hsmp_attr_grps),
61*e47c018aSSuma Hegde 				      GFP_KERNEL);
62*e47c018aSSuma Hegde 	if (!hsmp_attr_grps)
63*e47c018aSSuma Hegde 		return -ENOMEM;
64*e47c018aSSuma Hegde 
65*e47c018aSSuma Hegde 	/* Create a sysfs directory for each socket */
66*e47c018aSSuma Hegde 	for (i = 0; i < plat_dev.num_sockets; i++) {
67*e47c018aSSuma Hegde 		attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group),
68*e47c018aSSuma Hegde 					GFP_KERNEL);
69*e47c018aSSuma Hegde 		if (!attr_grp)
70*e47c018aSSuma Hegde 			return -ENOMEM;
71*e47c018aSSuma Hegde 
72*e47c018aSSuma Hegde 		snprintf(plat_dev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i);
73*e47c018aSSuma Hegde 		attr_grp->name			= plat_dev.sock[i].name;
74*e47c018aSSuma Hegde 		attr_grp->is_bin_visible	= hsmp_is_sock_attr_visible;
75*e47c018aSSuma Hegde 		hsmp_attr_grps[i]		= attr_grp;
76*e47c018aSSuma Hegde 
77*e47c018aSSuma Hegde 		hsmp_create_attr_list(attr_grp, dev, i);
78*e47c018aSSuma Hegde 	}
79*e47c018aSSuma Hegde 
80*e47c018aSSuma Hegde 	return device_add_groups(dev, hsmp_attr_grps);
81*e47c018aSSuma Hegde }
82*e47c018aSSuma Hegde 
83*e47c018aSSuma Hegde static inline bool is_f1a_m0h(void)
84*e47c018aSSuma Hegde {
85*e47c018aSSuma Hegde 	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
86*e47c018aSSuma Hegde 		return true;
87*e47c018aSSuma Hegde 
88*e47c018aSSuma Hegde 	return false;
89*e47c018aSSuma Hegde }
90*e47c018aSSuma Hegde 
91*e47c018aSSuma Hegde int init_platform_device(struct device *dev)
92*e47c018aSSuma Hegde {
93*e47c018aSSuma Hegde 	struct hsmp_socket *sock;
94*e47c018aSSuma Hegde 	int ret, i;
95*e47c018aSSuma Hegde 
96*e47c018aSSuma Hegde 	for (i = 0; i < plat_dev.num_sockets; i++) {
97*e47c018aSSuma Hegde 		if (!node_to_amd_nb(i))
98*e47c018aSSuma Hegde 			return -ENODEV;
99*e47c018aSSuma Hegde 		sock = &plat_dev.sock[i];
100*e47c018aSSuma Hegde 		sock->root			= node_to_amd_nb(i)->root;
101*e47c018aSSuma Hegde 		sock->sock_ind			= i;
102*e47c018aSSuma Hegde 		sock->dev			= dev;
103*e47c018aSSuma Hegde 		sock->mbinfo.base_addr		= SMN_HSMP_BASE;
104*e47c018aSSuma Hegde 		sock->amd_hsmp_rdwr		= amd_hsmp_pci_rdwr;
105*e47c018aSSuma Hegde 
106*e47c018aSSuma Hegde 		/*
107*e47c018aSSuma Hegde 		 * This is a transitional change from non-ACPI to ACPI, only
108*e47c018aSSuma Hegde 		 * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.
109*e47c018aSSuma Hegde 		 */
110*e47c018aSSuma Hegde 		if (is_f1a_m0h())
111*e47c018aSSuma Hegde 			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID_F1A_M0H;
112*e47c018aSSuma Hegde 		else
113*e47c018aSSuma Hegde 			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID;
114*e47c018aSSuma Hegde 
115*e47c018aSSuma Hegde 		sock->mbinfo.msg_resp_off	= SMN_HSMP_MSG_RESP;
116*e47c018aSSuma Hegde 		sock->mbinfo.msg_arg_off	= SMN_HSMP_MSG_DATA;
117*e47c018aSSuma Hegde 		sema_init(&sock->hsmp_sem, 1);
118*e47c018aSSuma Hegde 
119*e47c018aSSuma Hegde 		/* Test the hsmp interface on each socket */
120*e47c018aSSuma Hegde 		ret = hsmp_test(i, 0xDEADBEEF);
121*e47c018aSSuma Hegde 		if (ret) {
122*e47c018aSSuma Hegde 			dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
123*e47c018aSSuma Hegde 				boot_cpu_data.x86, boot_cpu_data.x86_model);
124*e47c018aSSuma Hegde 			dev_err(dev, "Is HSMP disabled in BIOS ?\n");
125*e47c018aSSuma Hegde 			return ret;
126*e47c018aSSuma Hegde 		}
127*e47c018aSSuma Hegde 
128*e47c018aSSuma Hegde 		ret = hsmp_cache_proto_ver(i);
129*e47c018aSSuma Hegde 		if (ret) {
130*e47c018aSSuma Hegde 			dev_err(dev, "Failed to read HSMP protocol version\n");
131*e47c018aSSuma Hegde 			return ret;
132*e47c018aSSuma Hegde 		}
133*e47c018aSSuma Hegde 	}
134*e47c018aSSuma Hegde 
135*e47c018aSSuma Hegde 	return 0;
136*e47c018aSSuma Hegde }
137