cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

surface3_power.c (14604B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Supports for the power IC on the Surface 3 tablet.
      4 *
      5 * (C) Copyright 2016-2018 Red Hat, Inc
      6 * (C) Copyright 2016-2018 Benjamin Tissoires <benjamin.tissoires@gmail.com>
      7 * (C) Copyright 2016 Stephen Just <stephenjust@gmail.com>
      8 *
      9 * This driver has been reverse-engineered by parsing the DSDT of the Surface 3
     10 * and looking at the registers of the chips.
     11 *
     12 * The DSDT allowed to find out that:
     13 * - the driver is required for the ACPI BAT0 device to communicate to the chip
     14 *   through an operation region.
     15 * - the various defines for the operation region functions to communicate with
     16 *   this driver
     17 * - the DSM 3f99e367-6220-4955-8b0f-06ef2ae79412 allows to trigger ACPI
     18 *   events to BAT0 (the code is all available in the DSDT).
     19 *
     20 * Further findings regarding the 2 chips declared in the MSHW0011 are:
     21 * - there are 2 chips declared:
     22 *   . 0x22 seems to control the ADP1 line status (and probably the charger)
     23 *   . 0x55 controls the battery directly
     24 * - the battery chip uses a SMBus protocol (using plain SMBus allows non
     25 *   destructive commands):
     26 *   . the commands/registers used are in the range 0x00..0x7F
     27 *   . if bit 8 (0x80) is set in the SMBus command, the returned value is the
     28 *     same as when it is not set. There is a high chance this bit is the
     29 *     read/write
     30 *   . the various registers semantic as been deduced by observing the register
     31 *     dumps.
     32 */
     33
     34#include <linux/acpi.h>
     35#include <linux/bits.h>
     36#include <linux/freezer.h>
     37#include <linux/i2c.h>
     38#include <linux/kernel.h>
     39#include <linux/kthread.h>
     40#include <linux/slab.h>
     41#include <linux/types.h>
     42#include <linux/uuid.h>
     43#include <asm/unaligned.h>
     44
     45#define SURFACE_3_POLL_INTERVAL		(2 * HZ)
     46#define SURFACE_3_STRLEN		10
     47
     48struct mshw0011_data {
     49	struct i2c_client	*adp1;
     50	struct i2c_client	*bat0;
     51	unsigned short		notify_mask;
     52	struct task_struct	*poll_task;
     53	bool			kthread_running;
     54
     55	bool			charging;
     56	bool			bat_charging;
     57	u8			trip_point;
     58	s32			full_capacity;
     59};
     60
     61struct mshw0011_handler_data {
     62	struct acpi_connection_info	info;
     63	struct i2c_client		*client;
     64};
     65
     66struct bix {
     67	u32	revision;
     68	u32	power_unit;
     69	u32	design_capacity;
     70	u32	last_full_charg_capacity;
     71	u32	battery_technology;
     72	u32	design_voltage;
     73	u32	design_capacity_of_warning;
     74	u32	design_capacity_of_low;
     75	u32	cycle_count;
     76	u32	measurement_accuracy;
     77	u32	max_sampling_time;
     78	u32	min_sampling_time;
     79	u32	max_average_interval;
     80	u32	min_average_interval;
     81	u32	battery_capacity_granularity_1;
     82	u32	battery_capacity_granularity_2;
     83	char	model[SURFACE_3_STRLEN];
     84	char	serial[SURFACE_3_STRLEN];
     85	char	type[SURFACE_3_STRLEN];
     86	char	OEM[SURFACE_3_STRLEN];
     87} __packed;
     88
     89struct bst {
     90	u32	battery_state;
     91	s32	battery_present_rate;
     92	u32	battery_remaining_capacity;
     93	u32	battery_present_voltage;
     94} __packed;
     95
     96struct gsb_command {
     97	u8	arg0;
     98	u8	arg1;
     99	u8	arg2;
    100} __packed;
    101
    102struct gsb_buffer {
    103	u8	status;
    104	u8	len;
    105	u8	ret;
    106	union {
    107		struct gsb_command	cmd;
    108		struct bst		bst;
    109		struct bix		bix;
    110	} __packed;
    111} __packed;
    112
    113#define ACPI_BATTERY_STATE_DISCHARGING	BIT(0)
    114#define ACPI_BATTERY_STATE_CHARGING	BIT(1)
    115#define ACPI_BATTERY_STATE_CRITICAL	BIT(2)
    116
    117#define MSHW0011_CMD_DEST_BAT0		0x01
    118#define MSHW0011_CMD_DEST_ADP1		0x03
    119
    120#define MSHW0011_CMD_BAT0_STA		0x01
    121#define MSHW0011_CMD_BAT0_BIX		0x02
    122#define MSHW0011_CMD_BAT0_BCT		0x03
    123#define MSHW0011_CMD_BAT0_BTM		0x04
    124#define MSHW0011_CMD_BAT0_BST		0x05
    125#define MSHW0011_CMD_BAT0_BTP		0x06
    126#define MSHW0011_CMD_ADP1_PSR		0x07
    127#define MSHW0011_CMD_BAT0_PSOC		0x09
    128#define MSHW0011_CMD_BAT0_PMAX		0x0a
    129#define MSHW0011_CMD_BAT0_PSRC		0x0b
    130#define MSHW0011_CMD_BAT0_CHGI		0x0c
    131#define MSHW0011_CMD_BAT0_ARTG		0x0d
    132
    133#define MSHW0011_NOTIFY_GET_VERSION	0x00
    134#define MSHW0011_NOTIFY_ADP1		0x01
    135#define MSHW0011_NOTIFY_BAT0_BST	0x02
    136#define MSHW0011_NOTIFY_BAT0_BIX	0x05
    137
    138#define MSHW0011_ADP1_REG_PSR		0x04
    139
    140#define MSHW0011_BAT0_REG_CAPACITY		0x0c
    141#define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY	0x0e
    142#define MSHW0011_BAT0_REG_DESIGN_CAPACITY	0x40
    143#define MSHW0011_BAT0_REG_VOLTAGE	0x08
    144#define MSHW0011_BAT0_REG_RATE		0x14
    145#define MSHW0011_BAT0_REG_OEM		0x45
    146#define MSHW0011_BAT0_REG_TYPE		0x4e
    147#define MSHW0011_BAT0_REG_SERIAL_NO	0x56
    148#define MSHW0011_BAT0_REG_CYCLE_CNT	0x6e
    149
    150#define MSHW0011_EV_2_5_MASK		GENMASK(8, 0)
    151
    152/* 3f99e367-6220-4955-8b0f-06ef2ae79412 */
    153static const guid_t mshw0011_guid =
    154	GUID_INIT(0x3F99E367, 0x6220, 0x4955, 0x8B, 0x0F, 0x06, 0xEF,
    155		  0x2A, 0xE7, 0x94, 0x12);
    156
    157static int
    158mshw0011_notify(struct mshw0011_data *cdata, u8 arg1, u8 arg2,
    159		unsigned int *ret_value)
    160{
    161	union acpi_object *obj;
    162	acpi_handle handle;
    163	unsigned int i;
    164
    165	handle = ACPI_HANDLE(&cdata->adp1->dev);
    166	if (!handle)
    167		return -ENODEV;
    168
    169	obj = acpi_evaluate_dsm_typed(handle, &mshw0011_guid, arg1, arg2, NULL,
    170				      ACPI_TYPE_BUFFER);
    171	if (!obj) {
    172		dev_err(&cdata->adp1->dev, "device _DSM execution failed\n");
    173		return -ENODEV;
    174	}
    175
    176	*ret_value = 0;
    177	for (i = 0; i < obj->buffer.length; i++)
    178		*ret_value |= obj->buffer.pointer[i] << (i * 8);
    179
    180	ACPI_FREE(obj);
    181	return 0;
    182}
    183
    184static const struct bix default_bix = {
    185	.revision = 0x00,
    186	.power_unit = 0x01,
    187	.design_capacity = 0x1dca,
    188	.last_full_charg_capacity = 0x1dca,
    189	.battery_technology = 0x01,
    190	.design_voltage = 0x10df,
    191	.design_capacity_of_warning = 0x8f,
    192	.design_capacity_of_low = 0x47,
    193	.cycle_count = 0xffffffff,
    194	.measurement_accuracy = 0x00015f90,
    195	.max_sampling_time = 0x03e8,
    196	.min_sampling_time = 0x03e8,
    197	.max_average_interval = 0x03e8,
    198	.min_average_interval = 0x03e8,
    199	.battery_capacity_granularity_1 = 0x45,
    200	.battery_capacity_granularity_2 = 0x11,
    201	.model = "P11G8M",
    202	.serial = "",
    203	.type = "LION",
    204	.OEM = "",
    205};
    206
    207static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
    208{
    209	struct i2c_client *client = cdata->bat0;
    210	char buf[SURFACE_3_STRLEN];
    211	int ret;
    212
    213	*bix = default_bix;
    214
    215	/* get design capacity */
    216	ret = i2c_smbus_read_word_data(client,
    217				       MSHW0011_BAT0_REG_DESIGN_CAPACITY);
    218	if (ret < 0) {
    219		dev_err(&client->dev, "Error reading design capacity: %d\n",
    220			ret);
    221		return ret;
    222	}
    223	bix->design_capacity = ret;
    224
    225	/* get last full charge capacity */
    226	ret = i2c_smbus_read_word_data(client,
    227				       MSHW0011_BAT0_REG_FULL_CHG_CAPACITY);
    228	if (ret < 0) {
    229		dev_err(&client->dev,
    230			"Error reading last full charge capacity: %d\n", ret);
    231		return ret;
    232	}
    233	bix->last_full_charg_capacity = ret;
    234
    235	/*
    236	 * Get serial number, on some devices (with unofficial replacement
    237	 * battery?) reading any of the serial number range addresses gets
    238	 * nacked in this case just leave the serial number empty.
    239	 */
    240	ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO,
    241					    sizeof(buf), buf);
    242	if (ret == -EREMOTEIO) {
    243		/* no serial number available */
    244	} else if (ret != sizeof(buf)) {
    245		dev_err(&client->dev, "Error reading serial no: %d\n", ret);
    246		return ret;
    247	} else {
    248		snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf);
    249	}
    250
    251	/* get cycle count */
    252	ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT);
    253	if (ret < 0) {
    254		dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
    255		return ret;
    256	}
    257	bix->cycle_count = ret;
    258
    259	/* get OEM name */
    260	ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_OEM,
    261					    4, buf);
    262	if (ret != 4) {
    263		dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
    264		return ret;
    265	}
    266	snprintf(bix->OEM, ARRAY_SIZE(bix->OEM), "%3pE", buf);
    267
    268	return 0;
    269}
    270
    271static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
    272{
    273	struct i2c_client *client = cdata->bat0;
    274	int rate, capacity, voltage, state;
    275	s16 tmp;
    276
    277	rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE);
    278	if (rate < 0)
    279		return rate;
    280
    281	capacity = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CAPACITY);
    282	if (capacity < 0)
    283		return capacity;
    284
    285	voltage = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_VOLTAGE);
    286	if (voltage < 0)
    287		return voltage;
    288
    289	tmp = rate;
    290	bst->battery_present_rate = abs((s32)tmp);
    291
    292	state = 0;
    293	if ((s32) tmp > 0)
    294		state |= ACPI_BATTERY_STATE_CHARGING;
    295	else if ((s32) tmp < 0)
    296		state |= ACPI_BATTERY_STATE_DISCHARGING;
    297	bst->battery_state = state;
    298
    299	bst->battery_remaining_capacity = capacity;
    300	bst->battery_present_voltage = voltage;
    301
    302	return 0;
    303}
    304
    305static int mshw0011_adp_psr(struct mshw0011_data *cdata)
    306{
    307	return i2c_smbus_read_byte_data(cdata->adp1, MSHW0011_ADP1_REG_PSR);
    308}
    309
    310static int mshw0011_isr(struct mshw0011_data *cdata)
    311{
    312	struct bst bst;
    313	struct bix bix;
    314	int ret;
    315	bool status, bat_status;
    316
    317	ret = mshw0011_adp_psr(cdata);
    318	if (ret < 0)
    319		return ret;
    320
    321	status = ret;
    322	if (status != cdata->charging)
    323		mshw0011_notify(cdata, cdata->notify_mask,
    324				MSHW0011_NOTIFY_ADP1, &ret);
    325
    326	cdata->charging = status;
    327
    328	ret = mshw0011_bst(cdata, &bst);
    329	if (ret < 0)
    330		return ret;
    331
    332	bat_status = bst.battery_state;
    333	if (bat_status != cdata->bat_charging)
    334		mshw0011_notify(cdata, cdata->notify_mask,
    335				MSHW0011_NOTIFY_BAT0_BST, &ret);
    336
    337	cdata->bat_charging = bat_status;
    338
    339	ret = mshw0011_bix(cdata, &bix);
    340	if (ret < 0)
    341		return ret;
    342
    343	if (bix.last_full_charg_capacity != cdata->full_capacity)
    344		mshw0011_notify(cdata, cdata->notify_mask,
    345				MSHW0011_NOTIFY_BAT0_BIX, &ret);
    346
    347	cdata->full_capacity = bix.last_full_charg_capacity;
    348
    349	return 0;
    350}
    351
    352static int mshw0011_poll_task(void *data)
    353{
    354	struct mshw0011_data *cdata = data;
    355	int ret = 0;
    356
    357	cdata->kthread_running = true;
    358
    359	set_freezable();
    360
    361	while (!kthread_should_stop()) {
    362		schedule_timeout_interruptible(SURFACE_3_POLL_INTERVAL);
    363		try_to_freeze();
    364		ret = mshw0011_isr(data);
    365		if (ret)
    366			break;
    367	}
    368
    369	cdata->kthread_running = false;
    370	return ret;
    371}
    372
    373static acpi_status
    374mshw0011_space_handler(u32 function, acpi_physical_address command,
    375			u32 bits, u64 *value64,
    376			void *handler_context, void *region_context)
    377{
    378	struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
    379	struct mshw0011_handler_data *data = handler_context;
    380	struct acpi_connection_info *info = &data->info;
    381	struct acpi_resource_i2c_serialbus *sb;
    382	struct i2c_client *client = data->client;
    383	struct mshw0011_data *cdata = i2c_get_clientdata(client);
    384	struct acpi_resource *ares;
    385	u32 accessor_type = function >> 16;
    386	acpi_status ret;
    387	int status = 1;
    388
    389	ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
    390	if (ACPI_FAILURE(ret))
    391		return ret;
    392
    393	if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
    394		ret = AE_BAD_PARAMETER;
    395		goto err;
    396	}
    397
    398	if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
    399		ret = AE_BAD_PARAMETER;
    400		goto err;
    401	}
    402
    403	if (gsb->cmd.arg0 == MSHW0011_CMD_DEST_ADP1 &&
    404	    gsb->cmd.arg1 == MSHW0011_CMD_ADP1_PSR) {
    405		status = mshw0011_adp_psr(cdata);
    406		if (status >= 0) {
    407			ret = AE_OK;
    408			goto out;
    409		} else {
    410			ret = AE_ERROR;
    411			goto err;
    412		}
    413	}
    414
    415	if (gsb->cmd.arg0 != MSHW0011_CMD_DEST_BAT0) {
    416		ret = AE_BAD_PARAMETER;
    417		goto err;
    418	}
    419
    420	switch (gsb->cmd.arg1) {
    421	case MSHW0011_CMD_BAT0_STA:
    422		break;
    423	case MSHW0011_CMD_BAT0_BIX:
    424		ret = mshw0011_bix(cdata, &gsb->bix);
    425		break;
    426	case MSHW0011_CMD_BAT0_BTP:
    427		cdata->trip_point = gsb->cmd.arg2;
    428		break;
    429	case MSHW0011_CMD_BAT0_BST:
    430		ret = mshw0011_bst(cdata, &gsb->bst);
    431		break;
    432	default:
    433		dev_info(&cdata->bat0->dev, "command(0x%02x) is not supported.\n", gsb->cmd.arg1);
    434		ret = AE_BAD_PARAMETER;
    435		goto err;
    436	}
    437
    438 out:
    439	gsb->ret = status;
    440	gsb->status = 0;
    441
    442 err:
    443	ACPI_FREE(ares);
    444	return ret;
    445}
    446
    447static int mshw0011_install_space_handler(struct i2c_client *client)
    448{
    449	struct acpi_device *adev;
    450	struct mshw0011_handler_data *data;
    451	acpi_status status;
    452
    453	adev = ACPI_COMPANION(&client->dev);
    454	if (!adev)
    455		return -ENODEV;
    456
    457	data = kzalloc(sizeof(struct mshw0011_handler_data),
    458			    GFP_KERNEL);
    459	if (!data)
    460		return -ENOMEM;
    461
    462	data->client = client;
    463	status = acpi_bus_attach_private_data(adev->handle, (void *)data);
    464	if (ACPI_FAILURE(status)) {
    465		kfree(data);
    466		return -ENOMEM;
    467	}
    468
    469	status = acpi_install_address_space_handler(adev->handle,
    470						    ACPI_ADR_SPACE_GSBUS,
    471						    &mshw0011_space_handler,
    472						    NULL,
    473						    data);
    474	if (ACPI_FAILURE(status)) {
    475		dev_err(&client->dev, "Error installing i2c space handler\n");
    476		acpi_bus_detach_private_data(adev->handle);
    477		kfree(data);
    478		return -ENOMEM;
    479	}
    480
    481	acpi_dev_clear_dependencies(adev);
    482	return 0;
    483}
    484
    485static void mshw0011_remove_space_handler(struct i2c_client *client)
    486{
    487	struct mshw0011_handler_data *data;
    488	acpi_handle handle;
    489	acpi_status status;
    490
    491	handle = ACPI_HANDLE(&client->dev);
    492	if (!handle)
    493		return;
    494
    495	acpi_remove_address_space_handler(handle,
    496				ACPI_ADR_SPACE_GSBUS,
    497				&mshw0011_space_handler);
    498
    499	status = acpi_bus_get_private_data(handle, (void **)&data);
    500	if (ACPI_SUCCESS(status))
    501		kfree(data);
    502
    503	acpi_bus_detach_private_data(handle);
    504}
    505
    506static int mshw0011_probe(struct i2c_client *client)
    507{
    508	struct i2c_board_info board_info;
    509	struct device *dev = &client->dev;
    510	struct i2c_client *bat0;
    511	struct mshw0011_data *data;
    512	int error, mask;
    513
    514	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    515	if (!data)
    516		return -ENOMEM;
    517
    518	data->adp1 = client;
    519	i2c_set_clientdata(client, data);
    520
    521	memset(&board_info, 0, sizeof(board_info));
    522	strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE);
    523
    524	bat0 = i2c_acpi_new_device(dev, 1, &board_info);
    525	if (IS_ERR(bat0))
    526		return PTR_ERR(bat0);
    527
    528	data->bat0 = bat0;
    529	i2c_set_clientdata(bat0, data);
    530
    531	error = mshw0011_notify(data, 1, MSHW0011_NOTIFY_GET_VERSION, &mask);
    532	if (error)
    533		goto out_err;
    534
    535	data->notify_mask = mask == MSHW0011_EV_2_5_MASK;
    536
    537	data->poll_task = kthread_run(mshw0011_poll_task, data, "mshw0011_adp");
    538	if (IS_ERR(data->poll_task)) {
    539		error = PTR_ERR(data->poll_task);
    540		dev_err(&client->dev, "Unable to run kthread err %d\n", error);
    541		goto out_err;
    542	}
    543
    544	error = mshw0011_install_space_handler(client);
    545	if (error)
    546		goto out_err;
    547
    548	return 0;
    549
    550out_err:
    551	if (data->kthread_running)
    552		kthread_stop(data->poll_task);
    553	i2c_unregister_device(data->bat0);
    554	return error;
    555}
    556
    557static int mshw0011_remove(struct i2c_client *client)
    558{
    559	struct mshw0011_data *cdata = i2c_get_clientdata(client);
    560
    561	mshw0011_remove_space_handler(client);
    562
    563	if (cdata->kthread_running)
    564		kthread_stop(cdata->poll_task);
    565
    566	i2c_unregister_device(cdata->bat0);
    567
    568	return 0;
    569}
    570
    571static const struct acpi_device_id mshw0011_acpi_match[] = {
    572	{ "MSHW0011", 0 },
    573	{ }
    574};
    575MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);
    576
    577static struct i2c_driver mshw0011_driver = {
    578	.probe_new = mshw0011_probe,
    579	.remove = mshw0011_remove,
    580	.driver = {
    581		.name = "mshw0011",
    582		.acpi_match_table = mshw0011_acpi_match,
    583	},
    584};
    585module_i2c_driver(mshw0011_driver);
    586
    587MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
    588MODULE_DESCRIPTION("mshw0011 driver");
    589MODULE_LICENSE("GPL v2");