linux/drivers/platform/surface/surface3_power.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Supports for the power IC on the Surface 3 tablet.
 *
 * (C) Copyright 2016-2018 Red Hat, Inc
 * (C) Copyright 2016-2018 Benjamin Tissoires <[email protected]>
 * (C) Copyright 2016 Stephen Just <[email protected]>
 *
 * This driver has been reverse-engineered by parsing the DSDT of the Surface 3
 * and looking at the registers of the chips.
 *
 * The DSDT allowed to find out that:
 * - the driver is required for the ACPI BAT0 device to communicate to the chip
 *   through an operation region.
 * - the various defines for the operation region functions to communicate with
 *   this driver
 * - the DSM 3f99e367-6220-4955-8b0f-06ef2ae79412 allows to trigger ACPI
 *   events to BAT0 (the code is all available in the DSDT).
 *
 * Further findings regarding the 2 chips declared in the MSHW0011 are:
 * - there are 2 chips declared:
 *   . 0x22 seems to control the ADP1 line status (and probably the charger)
 *   . 0x55 controls the battery directly
 * - the battery chip uses a SMBus protocol (using plain SMBus allows non
 *   destructive commands):
 *   . the commands/registers used are in the range 0x00..0x7F
 *   . if bit 8 (0x80) is set in the SMBus command, the returned value is the
 *     same as when it is not set. There is a high chance this bit is the
 *     read/write
 *   . the various registers semantic as been deduced by observing the register
 *     dumps.
 */

#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/freezer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uuid.h>
#include <linux/unaligned.h>

#define SURFACE_3_POLL_INTERVAL
#define SURFACE_3_STRLEN

struct mshw0011_data {};

struct mshw0011_handler_data {};

struct bix {} __packed;

struct bst {} __packed;

struct gsb_command {} __packed;

struct gsb_buffer {} __packed;

#define ACPI_BATTERY_STATE_DISCHARGING
#define ACPI_BATTERY_STATE_CHARGING
#define ACPI_BATTERY_STATE_CRITICAL

#define MSHW0011_CMD_DEST_BAT0
#define MSHW0011_CMD_DEST_ADP1

#define MSHW0011_CMD_BAT0_STA
#define MSHW0011_CMD_BAT0_BIX
#define MSHW0011_CMD_BAT0_BCT
#define MSHW0011_CMD_BAT0_BTM
#define MSHW0011_CMD_BAT0_BST
#define MSHW0011_CMD_BAT0_BTP
#define MSHW0011_CMD_ADP1_PSR
#define MSHW0011_CMD_BAT0_PSOC
#define MSHW0011_CMD_BAT0_PMAX
#define MSHW0011_CMD_BAT0_PSRC
#define MSHW0011_CMD_BAT0_CHGI
#define MSHW0011_CMD_BAT0_ARTG

#define MSHW0011_NOTIFY_GET_VERSION
#define MSHW0011_NOTIFY_ADP1
#define MSHW0011_NOTIFY_BAT0_BST
#define MSHW0011_NOTIFY_BAT0_BIX

#define MSHW0011_ADP1_REG_PSR

#define MSHW0011_BAT0_REG_CAPACITY
#define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY
#define MSHW0011_BAT0_REG_DESIGN_CAPACITY
#define MSHW0011_BAT0_REG_VOLTAGE
#define MSHW0011_BAT0_REG_RATE
#define MSHW0011_BAT0_REG_OEM
#define MSHW0011_BAT0_REG_TYPE
#define MSHW0011_BAT0_REG_SERIAL_NO
#define MSHW0011_BAT0_REG_CYCLE_CNT

#define MSHW0011_EV_2_5_MASK

/* 3f99e367-6220-4955-8b0f-06ef2ae79412 */
static const guid_t mshw0011_guid =;

static int
mshw0011_notify(struct mshw0011_data *cdata, u8 arg1, u8 arg2,
		unsigned int *ret_value)
{}

static const struct bix default_bix =;

static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
{}

static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
{}

static int mshw0011_adp_psr(struct mshw0011_data *cdata)
{}

static int mshw0011_isr(struct mshw0011_data *cdata)
{}

static int mshw0011_poll_task(void *data)
{}

static acpi_status
mshw0011_space_handler(u32 function, acpi_physical_address command,
			u32 bits, u64 *value64,
			void *handler_context, void *region_context)
{}

static int mshw0011_install_space_handler(struct i2c_client *client)
{}

static void mshw0011_remove_space_handler(struct i2c_client *client)
{}

static int mshw0011_probe(struct i2c_client *client)
{}

static void mshw0011_remove(struct i2c_client *client)
{}

static const struct acpi_device_id mshw0011_acpi_match[] =;
MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);

static struct i2c_driver mshw0011_driver =;
module_i2c_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();