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