131 lines
2.6 KiB
C
131 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include "pr.h"
|
|
|
|
#include <linux/dmi.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kconfig.h>
|
|
#include <linux/module.h>
|
|
#include <linux/string.h>
|
|
#include <linux/types.h>
|
|
#include <linux/wmi.h>
|
|
|
|
#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);
|