linux/drivers/platform/surface/surface3_power.c
<<
>>
Prefs
   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        struct acpi_device *adev;
 163        acpi_handle handle;
 164        unsigned int i;
 165
 166        handle = ACPI_HANDLE(&cdata->adp1->dev);
 167        if (!handle || acpi_bus_get_device(handle, &adev))
 168                return -ENODEV;
 169
 170        obj = acpi_evaluate_dsm_typed(handle, &mshw0011_guid, arg1, arg2, NULL,
 171                                      ACPI_TYPE_BUFFER);
 172        if (!obj) {
 173                dev_err(&cdata->adp1->dev, "device _DSM execution failed\n");
 174                return -ENODEV;
 175        }
 176
 177        *ret_value = 0;
 178        for (i = 0; i < obj->buffer.length; i++)
 179                *ret_value |= obj->buffer.pointer[i] << (i * 8);
 180
 181        ACPI_FREE(obj);
 182        return 0;
 183}
 184
 185static const struct bix default_bix = {
 186        .revision = 0x00,
 187        .power_unit = 0x01,
 188        .design_capacity = 0x1dca,
 189        .last_full_charg_capacity = 0x1dca,
 190        .battery_technology = 0x01,
 191        .design_voltage = 0x10df,
 192        .design_capacity_of_warning = 0x8f,
 193        .design_capacity_of_low = 0x47,
 194        .cycle_count = 0xffffffff,
 195        .measurement_accuracy = 0x00015f90,
 196        .max_sampling_time = 0x03e8,
 197        .min_sampling_time = 0x03e8,
 198        .max_average_interval = 0x03e8,
 199        .min_average_interval = 0x03e8,
 200        .battery_capacity_granularity_1 = 0x45,
 201        .battery_capacity_granularity_2 = 0x11,
 202        .model = "P11G8M",
 203        .serial = "",
 204        .type = "LION",
 205        .OEM = "",
 206};
 207
 208static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix)
 209{
 210        struct i2c_client *client = cdata->bat0;
 211        char buf[SURFACE_3_STRLEN];
 212        int ret;
 213
 214        *bix = default_bix;
 215
 216        /* get design capacity */
 217        ret = i2c_smbus_read_word_data(client,
 218                                       MSHW0011_BAT0_REG_DESIGN_CAPACITY);
 219        if (ret < 0) {
 220                dev_err(&client->dev, "Error reading design capacity: %d\n",
 221                        ret);
 222                return ret;
 223        }
 224        bix->design_capacity = ret;
 225
 226        /* get last full charge capacity */
 227        ret = i2c_smbus_read_word_data(client,
 228                                       MSHW0011_BAT0_REG_FULL_CHG_CAPACITY);
 229        if (ret < 0) {
 230                dev_err(&client->dev,
 231                        "Error reading last full charge capacity: %d\n", ret);
 232                return ret;
 233        }
 234        bix->last_full_charg_capacity = ret;
 235
 236        /* get serial number */
 237        ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO,
 238                                            sizeof(buf), buf);
 239        if (ret != sizeof(buf)) {
 240                dev_err(&client->dev, "Error reading serial no: %d\n", ret);
 241                return ret;
 242        }
 243        snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf);
 244
 245        /* get cycle count */
 246        ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT);
 247        if (ret < 0) {
 248                dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
 249                return ret;
 250        }
 251        bix->cycle_count = ret;
 252
 253        /* get OEM name */
 254        ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_OEM,
 255                                            4, buf);
 256        if (ret != 4) {
 257                dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
 258                return ret;
 259        }
 260        snprintf(bix->OEM, ARRAY_SIZE(bix->OEM), "%3pE", buf);
 261
 262        return 0;
 263}
 264
 265static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst)
 266{
 267        struct i2c_client *client = cdata->bat0;
 268        int rate, capacity, voltage, state;
 269        s16 tmp;
 270
 271        rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE);
 272        if (rate < 0)
 273                return rate;
 274
 275        capacity = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CAPACITY);
 276        if (capacity < 0)
 277                return capacity;
 278
 279        voltage = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_VOLTAGE);
 280        if (voltage < 0)
 281                return voltage;
 282
 283        tmp = rate;
 284        bst->battery_present_rate = abs((s32)tmp);
 285
 286        state = 0;
 287        if ((s32) tmp > 0)
 288                state |= ACPI_BATTERY_STATE_CHARGING;
 289        else if ((s32) tmp < 0)
 290                state |= ACPI_BATTERY_STATE_DISCHARGING;
 291        bst->battery_state = state;
 292
 293        bst->battery_remaining_capacity = capacity;
 294        bst->battery_present_voltage = voltage;
 295
 296        return 0;
 297}
 298
 299static int mshw0011_adp_psr(struct mshw0011_data *cdata)
 300{
 301        return i2c_smbus_read_byte_data(cdata->adp1, MSHW0011_ADP1_REG_PSR);
 302}
 303
 304static int mshw0011_isr(struct mshw0011_data *cdata)
 305{
 306        struct bst bst;
 307        struct bix bix;
 308        int ret;
 309        bool status, bat_status;
 310
 311        ret = mshw0011_adp_psr(cdata);
 312        if (ret < 0)
 313                return ret;
 314
 315        status = ret;
 316        if (status != cdata->charging)
 317                mshw0011_notify(cdata, cdata->notify_mask,
 318                                MSHW0011_NOTIFY_ADP1, &ret);
 319
 320        cdata->charging = status;
 321
 322        ret = mshw0011_bst(cdata, &bst);
 323        if (ret < 0)
 324                return ret;
 325
 326        bat_status = bst.battery_state;
 327        if (bat_status != cdata->bat_charging)
 328                mshw0011_notify(cdata, cdata->notify_mask,
 329                                MSHW0011_NOTIFY_BAT0_BST, &ret);
 330
 331        cdata->bat_charging = bat_status;
 332
 333        ret = mshw0011_bix(cdata, &bix);
 334        if (ret < 0)
 335                return ret;
 336
 337        if (bix.last_full_charg_capacity != cdata->full_capacity)
 338                mshw0011_notify(cdata, cdata->notify_mask,
 339                                MSHW0011_NOTIFY_BAT0_BIX, &ret);
 340
 341        cdata->full_capacity = bix.last_full_charg_capacity;
 342
 343        return 0;
 344}
 345
 346static int mshw0011_poll_task(void *data)
 347{
 348        struct mshw0011_data *cdata = data;
 349        int ret = 0;
 350
 351        cdata->kthread_running = true;
 352
 353        set_freezable();
 354
 355        while (!kthread_should_stop()) {
 356                schedule_timeout_interruptible(SURFACE_3_POLL_INTERVAL);
 357                try_to_freeze();
 358                ret = mshw0011_isr(data);
 359                if (ret)
 360                        break;
 361        }
 362
 363        cdata->kthread_running = false;
 364        return ret;
 365}
 366
 367static acpi_status
 368mshw0011_space_handler(u32 function, acpi_physical_address command,
 369                        u32 bits, u64 *value64,
 370                        void *handler_context, void *region_context)
 371{
 372        struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
 373        struct mshw0011_handler_data *data = handler_context;
 374        struct acpi_connection_info *info = &data->info;
 375        struct acpi_resource_i2c_serialbus *sb;
 376        struct i2c_client *client = data->client;
 377        struct mshw0011_data *cdata = i2c_get_clientdata(client);
 378        struct acpi_resource *ares;
 379        u32 accessor_type = function >> 16;
 380        acpi_status ret;
 381        int status = 1;
 382
 383        ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
 384        if (ACPI_FAILURE(ret))
 385                return ret;
 386
 387        if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
 388                ret = AE_BAD_PARAMETER;
 389                goto err;
 390        }
 391
 392        if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
 393                ret = AE_BAD_PARAMETER;
 394                goto err;
 395        }
 396
 397        if (gsb->cmd.arg0 == MSHW0011_CMD_DEST_ADP1 &&
 398            gsb->cmd.arg1 == MSHW0011_CMD_ADP1_PSR) {
 399                status = mshw0011_adp_psr(cdata);
 400                if (status >= 0) {
 401                        ret = AE_OK;
 402                        goto out;
 403                } else {
 404                        ret = AE_ERROR;
 405                        goto err;
 406                }
 407        }
 408
 409        if (gsb->cmd.arg0 != MSHW0011_CMD_DEST_BAT0) {
 410                ret = AE_BAD_PARAMETER;
 411                goto err;
 412        }
 413
 414        switch (gsb->cmd.arg1) {
 415        case MSHW0011_CMD_BAT0_STA:
 416                break;
 417        case MSHW0011_CMD_BAT0_BIX:
 418                ret = mshw0011_bix(cdata, &gsb->bix);
 419                break;
 420        case MSHW0011_CMD_BAT0_BTP:
 421                cdata->trip_point = gsb->cmd.arg2;
 422                break;
 423        case MSHW0011_CMD_BAT0_BST:
 424                ret = mshw0011_bst(cdata, &gsb->bst);
 425                break;
 426        default:
 427                dev_info(&cdata->bat0->dev, "command(0x%02x) is not supported.\n", gsb->cmd.arg1);
 428                ret = AE_BAD_PARAMETER;
 429                goto err;
 430        }
 431
 432 out:
 433        gsb->ret = status;
 434        gsb->status = 0;
 435
 436 err:
 437        ACPI_FREE(ares);
 438        return ret;
 439}
 440
 441static int mshw0011_install_space_handler(struct i2c_client *client)
 442{
 443        struct acpi_device *adev;
 444        struct mshw0011_handler_data *data;
 445        acpi_status status;
 446
 447        adev = ACPI_COMPANION(&client->dev);
 448        if (!adev)
 449                return -ENODEV;
 450
 451        data = kzalloc(sizeof(struct mshw0011_handler_data),
 452                            GFP_KERNEL);
 453        if (!data)
 454                return -ENOMEM;
 455
 456        data->client = client;
 457        status = acpi_bus_attach_private_data(adev->handle, (void *)data);
 458        if (ACPI_FAILURE(status)) {
 459                kfree(data);
 460                return -ENOMEM;
 461        }
 462
 463        status = acpi_install_address_space_handler(adev->handle,
 464                                                    ACPI_ADR_SPACE_GSBUS,
 465                                                    &mshw0011_space_handler,
 466                                                    NULL,
 467                                                    data);
 468        if (ACPI_FAILURE(status)) {
 469                dev_err(&client->dev, "Error installing i2c space handler\n");
 470                acpi_bus_detach_private_data(adev->handle);
 471                kfree(data);
 472                return -ENOMEM;
 473        }
 474
 475        acpi_dev_clear_dependencies(adev);
 476        return 0;
 477}
 478
 479static void mshw0011_remove_space_handler(struct i2c_client *client)
 480{
 481        struct mshw0011_handler_data *data;
 482        acpi_handle handle;
 483        acpi_status status;
 484
 485        handle = ACPI_HANDLE(&client->dev);
 486        if (!handle)
 487                return;
 488
 489        acpi_remove_address_space_handler(handle,
 490                                ACPI_ADR_SPACE_GSBUS,
 491                                &mshw0011_space_handler);
 492
 493        status = acpi_bus_get_private_data(handle, (void **)&data);
 494        if (ACPI_SUCCESS(status))
 495                kfree(data);
 496
 497        acpi_bus_detach_private_data(handle);
 498}
 499
 500static int mshw0011_probe(struct i2c_client *client)
 501{
 502        struct i2c_board_info board_info;
 503        struct device *dev = &client->dev;
 504        struct i2c_client *bat0;
 505        struct mshw0011_data *data;
 506        int error, mask;
 507
 508        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 509        if (!data)
 510                return -ENOMEM;
 511
 512        data->adp1 = client;
 513        i2c_set_clientdata(client, data);
 514
 515        memset(&board_info, 0, sizeof(board_info));
 516        strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE);
 517
 518        bat0 = i2c_acpi_new_device(dev, 1, &board_info);
 519        if (IS_ERR(bat0))
 520                return PTR_ERR(bat0);
 521
 522        data->bat0 = bat0;
 523        i2c_set_clientdata(bat0, data);
 524
 525        error = mshw0011_notify(data, 1, MSHW0011_NOTIFY_GET_VERSION, &mask);
 526        if (error)
 527                goto out_err;
 528
 529        data->notify_mask = mask == MSHW0011_EV_2_5_MASK;
 530
 531        data->poll_task = kthread_run(mshw0011_poll_task, data, "mshw0011_adp");
 532        if (IS_ERR(data->poll_task)) {
 533                error = PTR_ERR(data->poll_task);
 534                dev_err(&client->dev, "Unable to run kthread err %d\n", error);
 535                goto out_err;
 536        }
 537
 538        error = mshw0011_install_space_handler(client);
 539        if (error)
 540                goto out_err;
 541
 542        return 0;
 543
 544out_err:
 545        if (data->kthread_running)
 546                kthread_stop(data->poll_task);
 547        i2c_unregister_device(data->bat0);
 548        return error;
 549}
 550
 551static int mshw0011_remove(struct i2c_client *client)
 552{
 553        struct mshw0011_data *cdata = i2c_get_clientdata(client);
 554
 555        mshw0011_remove_space_handler(client);
 556
 557        if (cdata->kthread_running)
 558                kthread_stop(cdata->poll_task);
 559
 560        i2c_unregister_device(cdata->bat0);
 561
 562        return 0;
 563}
 564
 565static const struct acpi_device_id mshw0011_acpi_match[] = {
 566        { "MSHW0011", 0 },
 567        { }
 568};
 569MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);
 570
 571static struct i2c_driver mshw0011_driver = {
 572        .probe_new = mshw0011_probe,
 573        .remove = mshw0011_remove,
 574        .driver = {
 575                .name = "mshw0011",
 576                .acpi_match_table = mshw0011_acpi_match,
 577        },
 578};
 579module_i2c_driver(mshw0011_driver);
 580
 581MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
 582MODULE_DESCRIPTION("mshw0011 driver");
 583MODULE_LICENSE("GPL v2");
 584