brintos

brintos / linux-shallow public Read only

0
0
Text · 24.7 KiB · 8fcf38e Raw
989 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * AMD HSMP Platform Driver4 * Copyright (c) 2022, AMD.5 * All Rights Reserved.6 *7 * This file provides a device implementation for HSMP interface8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#include <asm/amd_hsmp.h>13#include <asm/amd_nb.h>14#include <linux/delay.h>15#include <linux/io.h>16#include <linux/miscdevice.h>17#include <linux/module.h>18#include <linux/pci.h>19#include <linux/platform_device.h>20#include <linux/semaphore.h>21#include <linux/acpi.h>22 23#define DRIVER_NAME		"amd_hsmp"24#define DRIVER_VERSION		"2.2"25#define ACPI_HSMP_DEVICE_HID	"AMDI0097"26 27/* HSMP Status / Error codes */28#define HSMP_STATUS_NOT_READY	0x0029#define HSMP_STATUS_OK		0x0130#define HSMP_ERR_INVALID_MSG	0xFE31#define HSMP_ERR_INVALID_INPUT	0xFF32 33/* Timeout in millsec */34#define HSMP_MSG_TIMEOUT	10035#define HSMP_SHORT_SLEEP	136 37#define HSMP_WR			true38#define HSMP_RD			false39 40/*41 * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox42 * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.43 * Below are required SMN address for HSMP Mailbox register offsets in SMU address space44 */45#define SMN_HSMP_BASE		0x3B0000046#define SMN_HSMP_MSG_ID		0x001053447#define SMN_HSMP_MSG_ID_F1A_M0H	0x001093448#define SMN_HSMP_MSG_RESP	0x001098049#define SMN_HSMP_MSG_DATA	0x00109E050 51#define HSMP_INDEX_REG		0xc452#define HSMP_DATA_REG		0xc853 54#define HSMP_CDEV_NAME		"hsmp_cdev"55#define HSMP_DEVNODE_NAME	"hsmp"56#define HSMP_METRICS_TABLE_NAME	"metrics_bin"57 58#define HSMP_ATTR_GRP_NAME_SIZE	1059 60/* These are the strings specified in ACPI table */61#define MSG_IDOFF_STR		"MsgIdOffset"62#define MSG_ARGOFF_STR		"MsgArgOffset"63#define MSG_RESPOFF_STR		"MsgRspOffset"64 65#define MAX_AMD_SOCKETS 866 67struct hsmp_mbaddr_info {68	u32 base_addr;69	u32 msg_id_off;70	u32 msg_resp_off;71	u32 msg_arg_off;72	u32 size;73};74 75struct hsmp_socket {76	struct bin_attribute hsmp_attr;77	struct hsmp_mbaddr_info mbinfo;78	void __iomem *metric_tbl_addr;79	void __iomem *virt_base_addr;80	struct semaphore hsmp_sem;81	char name[HSMP_ATTR_GRP_NAME_SIZE];82	struct pci_dev *root;83	struct device *dev;84	u16 sock_ind;85};86 87struct hsmp_plat_device {88	struct miscdevice hsmp_device;89	struct hsmp_socket *sock;90	u32 proto_ver;91	u16 num_sockets;92	bool is_acpi_device;93	bool is_probed;94};95 96static struct hsmp_plat_device plat_dev;97 98static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,99			     u32 *value, bool write)100{101	int ret;102 103	if (!sock->root)104		return -ENODEV;105 106	ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,107				     sock->mbinfo.base_addr + offset);108	if (ret)109		return ret;110 111	ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)112		     : pci_read_config_dword(sock->root, HSMP_DATA_REG, value));113 114	return ret;115}116 117static void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,118			       u32 *value, bool write)119{120	if (write)121		iowrite32(*value, sock->virt_base_addr + offset);122	else123		*value = ioread32(sock->virt_base_addr + offset);124}125 126static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 offset,127			 u32 *value, bool write)128{129	if (plat_dev.is_acpi_device)130		amd_hsmp_acpi_rdwr(sock, offset, value, write);131	else132		return amd_hsmp_pci_rdwr(sock, offset, value, write);133 134	return 0;135}136 137/*138 * Send a message to the HSMP port via PCI-e config space registers139 * or by writing to MMIO space.140 *141 * The caller is expected to zero out any unused arguments.142 * If a response is expected, the number of response words should be greater than 0.143 *144 * Returns 0 for success and populates the requested number of arguments.145 * Returns a negative error code for failure.146 */147static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg)148{149	struct hsmp_mbaddr_info *mbinfo;150	unsigned long timeout, short_sleep;151	u32 mbox_status;152	u32 index;153	int ret;154 155	mbinfo = &sock->mbinfo;156 157	/* Clear the status register */158	mbox_status = HSMP_STATUS_NOT_READY;159	ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_WR);160	if (ret) {161		pr_err("Error %d clearing mailbox status register\n", ret);162		return ret;163	}164 165	index = 0;166	/* Write any message arguments */167	while (index < msg->num_args) {168		ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),169				    &msg->args[index], HSMP_WR);170		if (ret) {171			pr_err("Error %d writing message argument %d\n", ret, index);172			return ret;173		}174		index++;175	}176 177	/* Write the message ID which starts the operation */178	ret = amd_hsmp_rdwr(sock, mbinfo->msg_id_off, &msg->msg_id, HSMP_WR);179	if (ret) {180		pr_err("Error %d writing message ID %u\n", ret, msg->msg_id);181		return ret;182	}183 184	/*185	 * Depending on when the trigger write completes relative to the SMU186	 * firmware 1 ms cycle, the operation may take from tens of us to 1 ms187	 * to complete. Some operations may take more. Therefore we will try188	 * a few short duration sleeps and switch to long sleeps if we don't189	 * succeed quickly.190	 */191	short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP);192	timeout	= jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);193 194	while (time_before(jiffies, timeout)) {195		ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD);196		if (ret) {197			pr_err("Error %d reading mailbox status\n", ret);198			return ret;199		}200 201		if (mbox_status != HSMP_STATUS_NOT_READY)202			break;203		if (time_before(jiffies, short_sleep))204			usleep_range(50, 100);205		else206			usleep_range(1000, 2000);207	}208 209	if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) {210		return -ETIMEDOUT;211	} else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) {212		return -ENOMSG;213	} else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) {214		return -EINVAL;215	} else if (unlikely(mbox_status != HSMP_STATUS_OK)) {216		pr_err("Message ID %u unknown failure (status = 0x%X)\n",217		       msg->msg_id, mbox_status);218		return -EIO;219	}220 221	/*222	 * SMU has responded OK. Read response data.223	 * SMU reads the input arguments from eight 32 bit registers starting224	 * from SMN_HSMP_MSG_DATA and writes the response data to the same225	 * SMN_HSMP_MSG_DATA address.226	 * We copy the response data if any, back to the args[].227	 */228	index = 0;229	while (index < msg->response_sz) {230		ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),231				    &msg->args[index], HSMP_RD);232		if (ret) {233			pr_err("Error %d reading response %u for message ID:%u\n",234			       ret, index, msg->msg_id);235			break;236		}237		index++;238	}239 240	return ret;241}242 243static int validate_message(struct hsmp_message *msg)244{245	/* msg_id against valid range of message IDs */246	if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX)247		return -ENOMSG;248 249	/* msg_id is a reserved message ID */250	if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD)251		return -ENOMSG;252 253	/* num_args and response_sz against the HSMP spec */254	if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args ||255	    msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)256		return -EINVAL;257 258	return 0;259}260 261int hsmp_send_message(struct hsmp_message *msg)262{263	struct hsmp_socket *sock;264	int ret;265 266	if (!msg)267		return -EINVAL;268	ret = validate_message(msg);269	if (ret)270		return ret;271 272	if (!plat_dev.sock || msg->sock_ind >= plat_dev.num_sockets)273		return -ENODEV;274	sock = &plat_dev.sock[msg->sock_ind];275 276	/*277	 * The time taken by smu operation to complete is between278	 * 10us to 1ms. Sometime it may take more time.279	 * In SMP system timeout of 100 millisecs should280	 * be enough for the previous thread to finish the operation281	 */282	ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT));283	if (ret < 0)284		return ret;285 286	ret = __hsmp_send_message(sock, msg);287 288	up(&sock->hsmp_sem);289 290	return ret;291}292EXPORT_SYMBOL_GPL(hsmp_send_message);293 294static int hsmp_test(u16 sock_ind, u32 value)295{296	struct hsmp_message msg = { 0 };297	int ret;298 299	/*300	 * Test the hsmp port by performing TEST command. The test message301	 * takes one argument and returns the value of that argument + 1.302	 */303	msg.msg_id	= HSMP_TEST;304	msg.num_args	= 1;305	msg.response_sz	= 1;306	msg.args[0]	= value;307	msg.sock_ind	= sock_ind;308 309	ret = hsmp_send_message(&msg);310	if (ret)311		return ret;312 313	/* Check the response value */314	if (msg.args[0] != (value + 1)) {315		dev_err(plat_dev.sock[sock_ind].dev,316			"Socket %d test message failed, Expected 0x%08X, received 0x%08X\n",317			sock_ind, (value + 1), msg.args[0]);318		return -EBADE;319	}320 321	return ret;322}323 324static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)325{326	int __user *arguser = (int  __user *)arg;327	struct hsmp_message msg = { 0 };328	int ret;329 330	if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message)))331		return -EFAULT;332 333	/*334	 * Check msg_id is within the range of supported msg ids335	 * i.e within the array bounds of hsmp_msg_desc_table336	 */337	if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX)338		return -ENOMSG;339 340	switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) {341	case FMODE_WRITE:342		/*343		 * Device is opened in O_WRONLY mode344		 * Execute only set/configure commands345		 */346		if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET)347			return -EINVAL;348		break;349	case FMODE_READ:350		/*351		 * Device is opened in O_RDONLY mode352		 * Execute only get/monitor commands353		 */354		if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET)355			return -EINVAL;356		break;357	case FMODE_READ | FMODE_WRITE:358		/*359		 * Device is opened in O_RDWR mode360		 * Execute both get/monitor and set/configure commands361		 */362		break;363	default:364		return -EINVAL;365	}366 367	ret = hsmp_send_message(&msg);368	if (ret)369		return ret;370 371	if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) {372		/* Copy results back to user for get/monitor commands */373		if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message)))374			return -EFAULT;375	}376 377	return 0;378}379 380static const struct file_operations hsmp_fops = {381	.owner		= THIS_MODULE,382	.unlocked_ioctl	= hsmp_ioctl,383	.compat_ioctl	= hsmp_ioctl,384};385 386/* This is the UUID used for HSMP */387static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,388						0xa6, 0x9f, 0x4e, 0xa2,389						0x87, 0x1f, 0xc2, 0xf6);390 391static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)392{393	if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)394		return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);395 396	return false;397}398 399static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)400{401	char *uid;402 403	/*404	 * UID (ID00, ID01..IDXX) is used for differentiating sockets,405	 * read it and strip the "ID" part of it and convert the remaining406	 * bytes to integer.407	 */408	uid = acpi_device_uid(ACPI_COMPANION(dev));409 410	return kstrtou16(uid + 2, 10, sock_ind);411}412 413static acpi_status hsmp_resource(struct acpi_resource *res, void *data)414{415	struct hsmp_socket *sock = data;416	struct resource r;417 418	switch (res->type) {419	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:420		if (!acpi_dev_resource_memory(res, &r))421			return AE_ERROR;422		if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))423			return AE_ERROR;424		sock->mbinfo.base_addr = r.start;425		sock->mbinfo.size = resource_size(&r);426		break;427	case ACPI_RESOURCE_TYPE_END_TAG:428		break;429	default:430		return AE_ERROR;431	}432 433	return AE_OK;434}435 436static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)437{438	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };439	union acpi_object *guid, *mailbox_package;440	union acpi_object *dsd;441	acpi_status status;442	int ret = 0;443	int j;444 445	status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,446					    &buf, ACPI_TYPE_PACKAGE);447	if (ACPI_FAILURE(status)) {448		dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",449			acpi_format_exception(status));450		return -ENODEV;451	}452 453	dsd = buf.pointer;454 455	/* HSMP _DSD property should contain 2 objects.456	 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER457	 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE458	 *    This mailbox object contains 3 more acpi objects of type459	 *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets460	 *    these packages inturn contain 2 acpi objects of type461	 *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER462	 */463	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {464		ret = -EINVAL;465		goto free_buf;466	}467 468	guid = &dsd->package.elements[0];469	mailbox_package = &dsd->package.elements[1];470	if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {471		dev_err(sock->dev, "Invalid hsmp _DSD table data\n");472		ret = -EINVAL;473		goto free_buf;474	}475 476	for (j = 0; j < mailbox_package->package.count; j++) {477		union acpi_object *msgobj, *msgstr, *msgint;478 479		msgobj	= &mailbox_package->package.elements[j];480		msgstr	= &msgobj->package.elements[0];481		msgint	= &msgobj->package.elements[1];482 483		/* package should have 1 string and 1 integer object */484		if (msgobj->type != ACPI_TYPE_PACKAGE ||485		    msgstr->type != ACPI_TYPE_STRING ||486		    msgint->type != ACPI_TYPE_INTEGER) {487			ret = -EINVAL;488			goto free_buf;489		}490 491		if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,492			     msgstr->string.length)) {493			sock->mbinfo.msg_id_off = msgint->integer.value;494		} else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,495				    msgstr->string.length)) {496			sock->mbinfo.msg_resp_off =  msgint->integer.value;497		} else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,498				    msgstr->string.length)) {499			sock->mbinfo.msg_arg_off = msgint->integer.value;500		} else {501			ret = -ENOENT;502			goto free_buf;503		}504	}505 506	if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||507	    !sock->mbinfo.msg_arg_off)508		ret = -EINVAL;509 510free_buf:511	ACPI_FREE(buf.pointer);512	return ret;513}514 515static int hsmp_read_acpi_crs(struct hsmp_socket *sock)516{517	acpi_status status;518 519	status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,520				     hsmp_resource, sock);521	if (ACPI_FAILURE(status)) {522		dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",523			acpi_format_exception(status));524		return -EINVAL;525	}526	if (!sock->mbinfo.base_addr || !sock->mbinfo.size)527		return -EINVAL;528 529	/* The mapped region should be un cached */530	sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,531					       sock->mbinfo.size);532	if (!sock->virt_base_addr) {533		dev_err(sock->dev, "Failed to ioremap MP1 base address\n");534		return -ENOMEM;535	}536 537	return 0;538}539 540/* Parse the ACPI table to read the data */541static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)542{543	struct hsmp_socket *sock = &plat_dev.sock[sock_ind];544	int ret;545 546	sock->sock_ind		= sock_ind;547	sock->dev		= dev;548	plat_dev.is_acpi_device	= true;549 550	sema_init(&sock->hsmp_sem, 1);551 552	/* Read MP1 base address from CRS method */553	ret = hsmp_read_acpi_crs(sock);554	if (ret)555		return ret;556 557	/* Read mailbox offsets from DSD table */558	return hsmp_read_acpi_dsd(sock);559}560 561static ssize_t hsmp_metric_tbl_read(struct file *filp, struct kobject *kobj,562				    struct bin_attribute *bin_attr, char *buf,563				    loff_t off, size_t count)564{565	struct hsmp_socket *sock = bin_attr->private;566	struct hsmp_message msg = { 0 };567	int ret;568 569	if (!sock)570		return -EINVAL;571 572	/* Do not support lseek(), reads entire metric table */573	if (count < bin_attr->size) {574		dev_err(sock->dev, "Wrong buffer size\n");575		return -EINVAL;576	}577 578	msg.msg_id	= HSMP_GET_METRIC_TABLE;579	msg.sock_ind	= sock->sock_ind;580 581	ret = hsmp_send_message(&msg);582	if (ret)583		return ret;584	memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size);585 586	return bin_attr->size;587}588 589static int hsmp_get_tbl_dram_base(u16 sock_ind)590{591	struct hsmp_socket *sock = &plat_dev.sock[sock_ind];592	struct hsmp_message msg = { 0 };593	phys_addr_t dram_addr;594	int ret;595 596	msg.sock_ind	= sock_ind;597	msg.response_sz	= hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz;598	msg.msg_id	= HSMP_GET_METRIC_TABLE_DRAM_ADDR;599 600	ret = hsmp_send_message(&msg);601	if (ret)602		return ret;603 604	/*605	 * calculate the metric table DRAM address from lower and upper 32 bits606	 * sent from SMU and ioremap it to virtual address.607	 */608	dram_addr = msg.args[0] | ((u64)(msg.args[1]) << 32);609	if (!dram_addr) {610		dev_err(sock->dev, "Invalid DRAM address for metric table\n");611		return -ENOMEM;612	}613	sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr,614					     sizeof(struct hsmp_metric_table));615	if (!sock->metric_tbl_addr) {616		dev_err(sock->dev, "Failed to ioremap metric table addr\n");617		return -ENOMEM;618	}619	return 0;620}621 622static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,623					 struct bin_attribute *battr, int id)624{625	if (plat_dev.proto_ver == HSMP_PROTO_VER6)626		return battr->attr.mode;627	else628		return 0;629}630 631static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind)632{633	struct bin_attribute *hattr = &plat_dev.sock[sock_ind].hsmp_attr;634 635	sysfs_bin_attr_init(hattr);636	hattr->attr.name	= HSMP_METRICS_TABLE_NAME;637	hattr->attr.mode	= 0444;638	hattr->read		= hsmp_metric_tbl_read;639	hattr->size		= sizeof(struct hsmp_metric_table);640	hattr->private		= &plat_dev.sock[sock_ind];641	hattrs[0]		= hattr;642 643	if (plat_dev.proto_ver == HSMP_PROTO_VER6)644		return hsmp_get_tbl_dram_base(sock_ind);645	else646		return 0;647}648 649/* One bin sysfs for metrics table */650#define NUM_HSMP_ATTRS		1651 652static int hsmp_create_attr_list(struct attribute_group *attr_grp,653				 struct device *dev, u16 sock_ind)654{655	struct bin_attribute **hsmp_bin_attrs;656 657	/* Null terminated list of attributes */658	hsmp_bin_attrs = devm_kcalloc(dev, NUM_HSMP_ATTRS + 1,659				      sizeof(*hsmp_bin_attrs),660				      GFP_KERNEL);661	if (!hsmp_bin_attrs)662		return -ENOMEM;663 664	attr_grp->bin_attrs = hsmp_bin_attrs;665 666	return hsmp_init_metric_tbl_bin_attr(hsmp_bin_attrs, sock_ind);667}668 669static int hsmp_create_non_acpi_sysfs_if(struct device *dev)670{671	const struct attribute_group **hsmp_attr_grps;672	struct attribute_group *attr_grp;673	u16 i;674 675	hsmp_attr_grps = devm_kcalloc(dev, plat_dev.num_sockets + 1,676				      sizeof(*hsmp_attr_grps),677				      GFP_KERNEL);678	if (!hsmp_attr_grps)679		return -ENOMEM;680 681	/* Create a sysfs directory for each socket */682	for (i = 0; i < plat_dev.num_sockets; i++) {683		attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group),684					GFP_KERNEL);685		if (!attr_grp)686			return -ENOMEM;687 688		snprintf(plat_dev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i);689		attr_grp->name			= plat_dev.sock[i].name;690		attr_grp->is_bin_visible	= hsmp_is_sock_attr_visible;691		hsmp_attr_grps[i]		= attr_grp;692 693		hsmp_create_attr_list(attr_grp, dev, i);694	}695 696	return device_add_groups(dev, hsmp_attr_grps);697}698 699static int hsmp_create_acpi_sysfs_if(struct device *dev)700{701	struct attribute_group *attr_grp;702	u16 sock_ind;703	int ret;704 705	attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group), GFP_KERNEL);706	if (!attr_grp)707		return -ENOMEM;708 709	attr_grp->is_bin_visible = hsmp_is_sock_attr_visible;710 711	ret = hsmp_get_uid(dev, &sock_ind);712	if (ret)713		return ret;714 715	ret = hsmp_create_attr_list(attr_grp, dev, sock_ind);716	if (ret)717		return ret;718 719	return devm_device_add_group(dev, attr_grp);720}721 722static int hsmp_cache_proto_ver(u16 sock_ind)723{724	struct hsmp_message msg = { 0 };725	int ret;726 727	msg.msg_id	= HSMP_GET_PROTO_VER;728	msg.sock_ind	= sock_ind;729	msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;730 731	ret = hsmp_send_message(&msg);732	if (!ret)733		plat_dev.proto_ver = msg.args[0];734 735	return ret;736}737 738static inline bool is_f1a_m0h(void)739{740	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)741		return true;742 743	return false;744}745 746static int init_platform_device(struct device *dev)747{748	struct hsmp_socket *sock;749	int ret, i;750 751	for (i = 0; i < plat_dev.num_sockets; i++) {752		if (!node_to_amd_nb(i))753			return -ENODEV;754		sock = &plat_dev.sock[i];755		sock->root			= node_to_amd_nb(i)->root;756		sock->sock_ind			= i;757		sock->dev			= dev;758		sock->mbinfo.base_addr		= SMN_HSMP_BASE;759 760		/*761		 * This is a transitional change from non-ACPI to ACPI, only762		 * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.763		 */764		if (is_f1a_m0h())765			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID_F1A_M0H;766		else767			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID;768 769		sock->mbinfo.msg_resp_off	= SMN_HSMP_MSG_RESP;770		sock->mbinfo.msg_arg_off	= SMN_HSMP_MSG_DATA;771		sema_init(&sock->hsmp_sem, 1);772 773		/* Test the hsmp interface on each socket */774		ret = hsmp_test(i, 0xDEADBEEF);775		if (ret) {776			dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",777				boot_cpu_data.x86, boot_cpu_data.x86_model);778			dev_err(dev, "Is HSMP disabled in BIOS ?\n");779			return ret;780		}781	}782 783	return 0;784}785 786static const struct acpi_device_id amd_hsmp_acpi_ids[] = {787	{ACPI_HSMP_DEVICE_HID, 0},788	{}789};790MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);791 792static int hsmp_pltdrv_probe(struct platform_device *pdev)793{794	struct acpi_device *adev;795	u16 sock_ind = 0;796	int ret;797 798	/*799	 * On ACPI supported BIOS, there is an ACPI HSMP device added for800	 * each socket, so the per socket probing, but the memory allocated for801	 * sockets should be contiguous to access it as an array,802	 * Hence allocate memory for all the sockets at once instead of allocating803	 * on each probe.804	 */805	if (!plat_dev.is_probed) {806		plat_dev.sock = devm_kcalloc(&pdev->dev, plat_dev.num_sockets,807					     sizeof(*plat_dev.sock),808					     GFP_KERNEL);809		if (!plat_dev.sock)810			return -ENOMEM;811	}812	adev = ACPI_COMPANION(&pdev->dev);813	if (adev && !acpi_match_device_ids(adev, amd_hsmp_acpi_ids)) {814		ret = hsmp_get_uid(&pdev->dev, &sock_ind);815		if (ret)816			return ret;817		if (sock_ind >= plat_dev.num_sockets)818			return -EINVAL;819		ret = hsmp_parse_acpi_table(&pdev->dev, sock_ind);820		if (ret) {821			dev_err(&pdev->dev, "Failed to parse ACPI table\n");822			return ret;823		}824		/* Test the hsmp interface */825		ret = hsmp_test(sock_ind, 0xDEADBEEF);826		if (ret) {827			dev_err(&pdev->dev, "HSMP test message failed on Fam:%x model:%x\n",828				boot_cpu_data.x86, boot_cpu_data.x86_model);829			dev_err(&pdev->dev, "Is HSMP disabled in BIOS ?\n");830			return ret;831		}832	} else {833		ret = init_platform_device(&pdev->dev);834		if (ret) {835			dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");836			return ret;837		}838	}839 840	ret = hsmp_cache_proto_ver(sock_ind);841	if (ret) {842		dev_err(&pdev->dev, "Failed to read HSMP protocol version\n");843		return ret;844	}845 846	if (plat_dev.is_acpi_device)847		ret = hsmp_create_acpi_sysfs_if(&pdev->dev);848	else849		ret = hsmp_create_non_acpi_sysfs_if(&pdev->dev);850	if (ret)851		dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");852 853	if (!plat_dev.is_probed) {854		plat_dev.hsmp_device.name	= HSMP_CDEV_NAME;855		plat_dev.hsmp_device.minor	= MISC_DYNAMIC_MINOR;856		plat_dev.hsmp_device.fops	= &hsmp_fops;857		plat_dev.hsmp_device.parent	= &pdev->dev;858		plat_dev.hsmp_device.nodename	= HSMP_DEVNODE_NAME;859		plat_dev.hsmp_device.mode	= 0644;860 861		ret = misc_register(&plat_dev.hsmp_device);862		if (ret)863			return ret;864 865		plat_dev.is_probed = true;866	}867 868	return 0;869 870}871 872static void hsmp_pltdrv_remove(struct platform_device *pdev)873{874	/*875	 * We register only one misc_device even on multi socket system.876	 * So, deregister should happen only once.877	 */878	if (plat_dev.is_probed) {879		misc_deregister(&plat_dev.hsmp_device);880		plat_dev.is_probed = false;881	}882}883 884static struct platform_driver amd_hsmp_driver = {885	.probe		= hsmp_pltdrv_probe,886	.remove_new	= hsmp_pltdrv_remove,887	.driver		= {888		.name	= DRIVER_NAME,889		.acpi_match_table = amd_hsmp_acpi_ids,890	},891};892 893static struct platform_device *amd_hsmp_platdev;894 895static int hsmp_plat_dev_register(void)896{897	int ret;898 899	amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE);900	if (!amd_hsmp_platdev)901		return -ENOMEM;902 903	ret = platform_device_add(amd_hsmp_platdev);904	if (ret)905		platform_device_put(amd_hsmp_platdev);906 907	return ret;908}909 910/*911 * This check is only needed for backward compatibility of previous platforms.912 * All new platforms are expected to support ACPI based probing.913 */914static bool legacy_hsmp_support(void)915{916	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)917		return false;918 919	switch (boot_cpu_data.x86) {920	case 0x19:921		switch (boot_cpu_data.x86_model) {922		case 0x00 ... 0x1F:923		case 0x30 ... 0x3F:924		case 0x90 ... 0x9F:925		case 0xA0 ... 0xAF:926			return true;927		default:928			return false;929		}930	case 0x1A:931		switch (boot_cpu_data.x86_model) {932		case 0x00 ... 0x1F:933			return true;934		default:935			return false;936		}937	default:938		return false;939	}940 941	return false;942}943 944static int __init hsmp_plt_init(void)945{946	int ret = -ENODEV;947 948	/*949	 * amd_nb_num() returns number of SMN/DF interfaces present in the system950	 * if we have N SMN/DF interfaces that ideally means N sockets951	 */952	plat_dev.num_sockets = amd_nb_num();953	if (plat_dev.num_sockets == 0 || plat_dev.num_sockets > MAX_AMD_SOCKETS)954		return ret;955 956	ret = platform_driver_register(&amd_hsmp_driver);957	if (ret)958		return ret;959 960	if (!plat_dev.is_acpi_device) {961		if (legacy_hsmp_support()) {962			/* Not ACPI device, but supports HSMP, register a plat_dev */963			ret = hsmp_plat_dev_register();964		} else {965			/* Not ACPI, Does not support HSMP */966			pr_info("HSMP is not supported on Family:%x model:%x\n",967				boot_cpu_data.x86, boot_cpu_data.x86_model);968			ret = -ENODEV;969		}970		if (ret)971			platform_driver_unregister(&amd_hsmp_driver);972	}973 974	return ret;975}976 977static void __exit hsmp_plt_exit(void)978{979	platform_device_unregister(amd_hsmp_platdev);980	platform_driver_unregister(&amd_hsmp_driver);981}982 983device_initcall(hsmp_plt_init);984module_exit(hsmp_plt_exit);985 986MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");987MODULE_VERSION(DRIVER_VERSION);988MODULE_LICENSE("GPL v2");989