// SPDX-License-Identifier: GPL-2.0 #include "pr.h" #include #include #include #include #include #include #include #include "ec.h" #include "wmi.h" /* submodules */ #include "pdev.h" #include "events.h" #include "hwmon.h" #include "battery.h" /* ========================================================================== */ #define SUBMODULE_ENTRY(_name, _req) { .name = #_name, .init = ac71_ ## _name ## _setup, .cleanup = ac71_ ## _name ## _cleanup, .required = _req } static struct ac71_submodule { const char *name; bool required : 1, initialized : 1; int (*init)(void); void (*cleanup)(void); } ac71_submodules[] __refdata = { SUBMODULE_ENTRY(pdev, true), /* must be first */ SUBMODULE_ENTRY(wmi_events, false), SUBMODULE_ENTRY(hwmon, false), SUBMODULE_ENTRY(battery, false), }; #undef SUBMODULE_ENTRY static void do_cleanup(void) { int i; for (i = ARRAY_SIZE(ac71_submodules) - 1; i >= 0; i--) { const struct ac71_submodule *sm = &ac71_submodules[i]; if (sm->initialized) sm->cleanup(); } } static const struct dmi_system_id ac71_dmi_table[] __initconst = { { .matches = { DMI_MATCH(DMI_BOARD_NAME, "LAPAC71H"), { } } } }; static int __init ac71_module_init(void) { int err = 0, i; if (!wmi_has_guid(AC71_WMI_WMBC_GUID)) { pr_err("WMI GUID not found\n"); err = -ENODEV; goto out; } if (!dmi_check_system(ac71_dmi_table)) { pr_err("no DMI match\n"); err = -ENODEV; goto out; } err = ec_read_byte(PROJ_ID_ADDR); if (err < 0) { pr_err("failed to query project id: %d\n", err); goto out; } pr_info("project id: %d\n", err); err = ec_read_byte(PLATFORM_ID_ADDR); if (err < 0) { pr_err("failed to query platform id: %d\n", err); goto out; } pr_info("platform id: %d\n", err); for (i = 0; i < ARRAY_SIZE(ac71_submodules); i++) { struct ac71_submodule *sm = &ac71_submodules[i]; err = sm->init(); if (err) { pr_warn("failed to initialize %s submodule: %d\n", sm->name, err); if (sm->required) goto out; } else { sm->initialized = true; } } err = 0; out: if (err) do_cleanup(); else pr_info("module loaded\n"); return err; } static void __exit ac71_module_cleanup(void) { do_cleanup(); pr_info("module unloaded\n"); } /* ========================================================================== */ module_init(ac71_module_init); module_exit(ac71_module_cleanup); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AC71 laptop platform driver"); MODULE_ALIAS("wmi:" AC71_WMI_WMBC_GUID);