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