18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ACPI Hardware Error Device (PNP0C33) Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010, Intel Corp. 68c2ecf20Sopenharmony_ci * Author: Huang Ying <ying.huang@intel.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * ACPI Hardware Error Device is used to report some hardware errors 98c2ecf20Sopenharmony_ci * notified via SCI, mainly the corrected errors. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/acpi.h> 168c2ecf20Sopenharmony_ci#include <acpi/hed.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic const struct acpi_device_id acpi_hed_ids[] = { 198c2ecf20Sopenharmony_ci {"PNP0C33", 0}, 208c2ecf20Sopenharmony_ci {"", 0}, 218c2ecf20Sopenharmony_ci}; 228c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, acpi_hed_ids); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic acpi_handle hed_handle; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic BLOCKING_NOTIFIER_HEAD(acpi_hed_notify_list); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciint register_acpi_hed_notifier(struct notifier_block *nb) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci return blocking_notifier_chain_register(&acpi_hed_notify_list, nb); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(register_acpi_hed_notifier); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_civoid unregister_acpi_hed_notifier(struct notifier_block *nb) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci blocking_notifier_chain_unregister(&acpi_hed_notify_list, nb); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_acpi_hed_notifier); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * SCI to report hardware error is forwarded to the listeners of HED, 428c2ecf20Sopenharmony_ci * it is used by HEST Generic Hardware Error Source with notify type 438c2ecf20Sopenharmony_ci * SCI. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_cistatic void acpi_hed_notify(struct acpi_device *device, u32 event) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int acpi_hed_add(struct acpi_device *device) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci /* Only one hardware error device */ 538c2ecf20Sopenharmony_ci if (hed_handle) 548c2ecf20Sopenharmony_ci return -EINVAL; 558c2ecf20Sopenharmony_ci hed_handle = device->handle; 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int acpi_hed_remove(struct acpi_device *device) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci hed_handle = NULL; 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic struct acpi_driver acpi_hed_driver = { 668c2ecf20Sopenharmony_ci .name = "hardware_error_device", 678c2ecf20Sopenharmony_ci .class = "hardware_error", 688c2ecf20Sopenharmony_ci .ids = acpi_hed_ids, 698c2ecf20Sopenharmony_ci .ops = { 708c2ecf20Sopenharmony_ci .add = acpi_hed_add, 718c2ecf20Sopenharmony_ci .remove = acpi_hed_remove, 728c2ecf20Sopenharmony_ci .notify = acpi_hed_notify, 738c2ecf20Sopenharmony_ci }, 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_cimodule_acpi_driver(acpi_hed_driver); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciACPI_MODULE_NAME("hed"); 788c2ecf20Sopenharmony_ciMODULE_AUTHOR("Huang Ying"); 798c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ACPI Hardware Error Device Driver"); 808c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 81