/* * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg. * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
*/ #define SMN_HSMP_BASE 0x3B00000 #define SMN_HSMP_MSG_ID 0x0010534 #define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934 #define SMN_HSMP_MSG_RESP 0x0010980 #define SMN_HSMP_MSG_DATA 0x00109E0
if (id == 0 && sock_ind >= hsmp_pdev->num_sockets) return SYSFS_GROUP_INVISIBLE;
if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) return battr->attr.mode;
return 0;
}
/* * AMD supports maximum of 8 sockets in a system. * Static array of 8 + 1(for NULL) elements is created below * to create sysfs groups for sockets. * is_bin_visible function is used to show / hide the necessary groups. * * Validate the maximum number against MAX_AMD_NUM_NODES. If this changes, * then the attributes and groups below must be adjusted.
*/
static_assert(MAX_AMD_NUM_NODES == 8);
for (i = 0; i < hsmp_pdev->num_sockets; i++) {
sock = &hsmp_pdev->sock[i];
sock->sock_ind = i;
sock->dev = dev;
sock->mbinfo.base_addr = SMN_HSMP_BASE;
sock->amd_hsmp_rdwr = amd_hsmp_pci_rdwr;
/* * This is a transitional change from non-ACPI to ACPI, only * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.
*/ if (is_f1a_m0h())
sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H; else
sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID;
/* Test the hsmp interface on each socket */
ret = hsmp_test(i, 0xDEADBEEF); if (ret) {
dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
boot_cpu_data.x86, boot_cpu_data.x86_model);
dev_err(dev, "Is HSMP disabled in BIOS ?\n"); return ret;
}
ret = hsmp_cache_proto_ver(i); if (ret) {
dev_err(dev, "Failed to read HSMP protocol version\n"); return ret;
}
if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
ret = hsmp_get_tbl_dram_base(i); if (ret)
dev_err(dev, "Failed to init metric table\n");
}
/* Register with hwmon interface for reporting power */
ret = hsmp_create_sensor(dev, i); if (ret)
dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
}
return 0;
}
staticint hsmp_pltdrv_probe(struct platform_device *pdev)
{ int ret;
hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, sizeof(*hsmp_pdev->sock),
GFP_KERNEL); if (!hsmp_pdev->sock) return -ENOMEM;
ret = init_platform_device(&pdev->dev); if (ret) {
dev_err(&pdev->dev, "Failed to init HSMP mailbox\n"); return ret;
}
ret = hsmp_misc_register(&pdev->dev); if (ret) {
dev_err(&pdev->dev, "Failed to register misc device\n"); return ret;
}
dev_dbg(&pdev->dev, "AMD HSMP is probed successfully\n"); return 0;
}
amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE); if (!amd_hsmp_platdev) return -ENOMEM;
ret = platform_device_add(amd_hsmp_platdev); if (ret)
platform_device_put(amd_hsmp_platdev);
return ret;
}
/* * This check is only needed for backward compatibility of previous platforms. * All new platforms are expected to support ACPI based probing.
*/ staticbool legacy_hsmp_support(void)
{ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) returnfalse;
switch (boot_cpu_data.x86) { case 0x19: switch (boot_cpu_data.x86_model) { case 0x00 ... 0x1F: case 0x30 ... 0x3F: case 0x90 ... 0x9F: case 0xA0 ... 0xAF: returntrue; default: returnfalse;
} case 0x1A: switch (boot_cpu_data.x86_model) { case 0x00 ... 0x0F: returntrue; default: returnfalse;
} default: returnfalse;
}
returnfalse;
}
staticint __init hsmp_plt_init(void)
{ int ret = -ENODEV;
if (acpi_dev_present(ACPI_HSMP_DEVICE_HID, NULL, -1)) { if (IS_ENABLED(CONFIG_AMD_HSMP_ACPI))
pr_debug("HSMP is supported through ACPI on this platform, please use hsmp_acpi.ko\n"); else
pr_info("HSMP is supported through ACPI on this platform, please enable AMD_HSMP_ACPI config\n"); return -ENODEV;
}
if (!legacy_hsmp_support()) {
pr_info("HSMP interface is either disabled or not supported on family:%x model:%x\n",
boot_cpu_data.x86, boot_cpu_data.x86_model); return ret;
}
hsmp_pdev = get_hsmp_pdev(); if (!hsmp_pdev) return -ENOMEM;
/* * amd_num_nodes() returns number of SMN/DF interfaces present in the system * if we have N SMN/DF interfaces that ideally means N sockets
*/
hsmp_pdev->num_sockets = amd_num_nodes(); if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) {
pr_err("Wrong number of sockets\n"); return ret;
}
ret = platform_driver_register(&amd_hsmp_driver); if (ret) return ret;
ret = hsmp_plat_dev_register(); if (ret)
platform_driver_unregister(&amd_hsmp_driver);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.