From patchwork Sun Sep 6 19:50:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11759707 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E3529138E for ; Sun, 6 Sep 2020 19:51:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6F9D2080A for ; Sun, 6 Sep 2020 19:51:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FjPv8tOM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726544AbgIFTvj (ORCPT ); Sun, 6 Sep 2020 15:51:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41350 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726484AbgIFTva (ORCPT ); Sun, 6 Sep 2020 15:51:30 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81E62C061573; Sun, 6 Sep 2020 12:51:26 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id b12so6427473lfp.9; Sun, 06 Sep 2020 12:51:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gyFVRrq7oNAkyBDcab1pW5QCuvDZJBB4EknZ7t3FCyQ=; b=FjPv8tOM4FBh/CLhJkVsKZdT31s0rjSmN5qV1MfwaP7Iv5UON4zmgkqEJGqViLNq3W yQtG9heHntzY/MHYNJxRvyjmXWoWDEYjMrCa3HoTqylNalhYnOiWxjVl+dq9bQgEBR6d f1sOHI9t04+jc0rlXKWieqnK8UJfHkVHtcMVW0q1FX6nxQQdVARgsmbrNSwC1dmmShFz U5vquJplAF7zWBVyAM51alG5WS8Dk4iNufN617XsMy2XOloJ6TWo0w9g1ZLryq1MxlH4 574fb4f6XMDdgcfFeJeY7RKflRmx36gcUS82WNL8J0eLngAD7Ges0sHM39wboaXvVkhO YBDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gyFVRrq7oNAkyBDcab1pW5QCuvDZJBB4EknZ7t3FCyQ=; b=gW+1ZaoWZah87VTt83K/C/VWfm0R5T9j5mM0C6r6ZCCLIDHSYQcmdMDkVlw9hsYMlo 8ycrXmMu7Q7/rYWNmDzEyV2riil+ahKUrm44c2eHYIRn8kNaxa4xReuaNbCMgtoCJ2BZ EGk14Y8T/yb5pyGg6JyUHiCpKiEBMWhryHACHg+NMiHHJw+xVK1flBsBWa2Y8Jh/pX9M +b0i2P0gBGib0Ebn9mTZMg4Qz+nBO2AUb75rsbOWWB/SpaciRii07rJhGRlUwEdZMtfz WfwofVGMSlvJXao4bg2EixB1YBpmoL7Nfiu0PVrq5iBK86wI6p5+MI3W6pDf2VTTRjT+ Br2g== X-Gm-Message-State: AOAM533OAY/Q7wEbzyLBxyWT9TaIHrglDYNZ7Qk06a6kS6GaMV2TatuL 035Kk2/A78XQ3SgaAjQ+KAY= X-Google-Smtp-Source: ABdhPJyQ4SMKxWY6kGyeKB7uBWsDjTbkL01fuiofXbrjJA1j/cifvBDot70J0IM0cDVq2ry6PzlvQA== X-Received: by 2002:a19:4ad8:: with SMTP id x207mr8509418lfa.73.1599421883105; Sun, 06 Sep 2020 12:51:23 -0700 (PDT) Received: from localhost.localdomain (109-252-170-211.dynamic.spd-mgts.ru. [109.252.170.211]) by smtp.gmail.com with ESMTPSA id b7sm4942574lfq.36.2020.09.06.12.51.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2020 12:51:22 -0700 (PDT) From: Dmitry Osipenko To: Lee Jones , Rob Herring , Thierry Reding , Jonathan Hunter , Pavel Machek , Dan Murphy , Sebastian Reichel , Lubomir Rintel Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/5] dt-bindings: mfd: Add ENE KB930 Embedded Controller binding Date: Sun, 6 Sep 2020 22:50:59 +0300 Message-Id: <20200906195103.1347-2-digetx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200906195103.1347-1-digetx@gmail.com> References: <20200906195103.1347-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Add binding document for the ENE KB930 Embedded Controller. Signed-off-by: Dmitry Osipenko Reviewed-by: Rob Herring --- .../devicetree/bindings/mfd/ene-kb930.yaml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/ene-kb930.yaml diff --git a/Documentation/devicetree/bindings/mfd/ene-kb930.yaml b/Documentation/devicetree/bindings/mfd/ene-kb930.yaml new file mode 100644 index 000000000000..635c8966ca22 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/ene-kb930.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/ene-kb930.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ENE KB930 Embedded Controller bindings + +description: | + This binding describes the ENE KB930 Embedded Controller attached to an + I2C bus. + +maintainers: + - Dmitry Osipenko + +properties: + compatible: + items: + - enum: + - acer,a500-iconia-ec # Acer A500 Iconia tablet device + - enum: + - ene,kb930 + reg: + maxItems: 1 + + monitored-battery: true + power-supplies: true + system-power-controller: true + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + battery: battery-cell { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3260000>; + energy-full-design-microwatt-hours = <24000000>; + operating-range-celsius = <0 40>; + }; + + mains: ac-adapter { + compatible = "gpio-charger"; + charger-type = "mains"; + gpios = <&gpio 125 0>; + }; + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + embedded-controller@58 { + compatible = "acer,a500-iconia-ec", "ene,kb930"; + reg = <0x58>; + + system-power-controller; + + monitored-battery = <&battery>; + power-supplies = <&mains>; + }; + }; + +... From patchwork Sun Sep 6 19:51:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11759715 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 12CBE138E for ; Sun, 6 Sep 2020 19:52:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E68FB208B3 for ; Sun, 6 Sep 2020 19:52:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tJCKAx0L" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726721AbgIFTwC (ORCPT ); Sun, 6 Sep 2020 15:52:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726220AbgIFTv0 (ORCPT ); Sun, 6 Sep 2020 15:51:26 -0400 Received: from mail-lj1-x241.google.com (mail-lj1-x241.google.com [IPv6:2a00:1450:4864:20::241]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B260DC061574; Sun, 6 Sep 2020 12:51:25 -0700 (PDT) Received: by mail-lj1-x241.google.com with SMTP id c2so13611936ljj.12; Sun, 06 Sep 2020 12:51:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5TUxA8XatXP4/Be/gKKaW1Zqc6zH5qP5Od3gWtx/EpE=; b=tJCKAx0LGXsVSpQXUIK24lHXsyZ6xDbBk0kR6OyUFrhJ119ou/kqGL2pW5YSt6irND p/fYoIc73b5aSnsrxBqkQT0siW9mBIGtysc+exKDV0mzrxLZ2y5kh5WnkRW1jiQ9ePp/ AAllXg9eXtJkl33ZF15a8LFQ3MIbBMThhGKG8JRYKndX4976vkIIszIKDV2ZqLmPGXYp P+eo1bcae/jcNzi9DOhrcZcDMxC+PbmV0WJS9yEZd1jPdjpYUAbaxGYrbAifl+UApCTh qcq8A9QqXNuQIrurL7W9tBdHAgLdthqKmve1dPE63OBMw6k0f5mdpMgSdEJwuebT24Tp kPAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5TUxA8XatXP4/Be/gKKaW1Zqc6zH5qP5Od3gWtx/EpE=; b=LodMwt8b6iWxORfi0oEFHBi4v9aDURr2BrVHzf8xjPC+IAJBeiTjc9q6s+q+fOfngE ACuNPPX5zq2yypWfEjBbvv+asKhc61HB8804rvgE+pEadmS0h4BaoaNn/beoEubz78pn 0xysKbdxSYoFFdszAbqcC8iCpUNKKbXjIkuZP61KrgPUsGomWa8XavtuYqqAxc+2UVhB tBETs73bTeHtCwCV9SWhqXcOrr8+R76UQRx75w+TuLr7AzFT7ZvkT+yUSbN7Kio4WWYp c/HRJFqZczV81lNCjWGctefyTjxJTpTyspb/vbHi33drlsTzhqr+yEuPsy/9AMC9Vpug Ye1Q== X-Gm-Message-State: AOAM530MY6vvfTiQLVs/w6QV4JQCfWbJAqcV+/f3tPhAiPke8W+P6AXV DnAlh0mdVpjQoLkHbyYc5Ys= X-Google-Smtp-Source: ABdhPJxc5o6Vlqz3HteWECIMToBeT/TMPBDjvRR3Xn6Gp34Po8WFPFKn1qoeZ8CtZXXlTjjnqwDmuA== X-Received: by 2002:a2e:91c7:: with SMTP id u7mr8311531ljg.413.1599421884063; Sun, 06 Sep 2020 12:51:24 -0700 (PDT) Received: from localhost.localdomain (109-252-170-211.dynamic.spd-mgts.ru. [109.252.170.211]) by smtp.gmail.com with ESMTPSA id b7sm4942574lfq.36.2020.09.06.12.51.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2020 12:51:23 -0700 (PDT) From: Dmitry Osipenko To: Lee Jones , Rob Herring , Thierry Reding , Jonathan Hunter , Pavel Machek , Dan Murphy , Sebastian Reichel , Lubomir Rintel Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/5] mfd: Add driver for Embedded Controller found on Acer Iconia Tab A500 Date: Sun, 6 Sep 2020 22:51:00 +0300 Message-Id: <20200906195103.1347-3-digetx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200906195103.1347-1-digetx@gmail.com> References: <20200906195103.1347-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Acer Iconia Tab A500 is an Android tablet device, it has ENE KB930 Embedded Controller which provides battery-gauge, LED, GPIO and some other functions. The EC uses firmware that is specifically customized for Acer A500. This patch adds MFD driver for the Embedded Controller which allows to power-off / reboot the A500 device, it also provides a common register read/write API that will be used by the sub-devices. Signed-off-by: Dmitry Osipenko --- drivers/mfd/Kconfig | 12 +++ drivers/mfd/Makefile | 1 + drivers/mfd/acer-ec-a500.c | 203 +++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 drivers/mfd/acer-ec-a500.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 231095933778..9b10e5895136 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2062,6 +2062,18 @@ config MFD_KHADAS_MCU additional drivers must be enabled in order to use the functionality of the device. +config MFD_ACER_A500_EC + tristate "Embedded Controller driver for Acer Iconia Tab A500" + depends on I2C + depends on ARCH_TEGRA_2x_SOC || COMPILE_TEST + select MFD_CORE + select REGMAP + help + Support for Acer Iconia Tab A500 Embedded Controller. + + The controller itself is ENE KB930, it is running firmware + customized for the specific needs of the Acer A500 hardware. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index a60e5f835283..6e3a6162ad94 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -262,5 +262,6 @@ obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX) += stmfx.o obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o +obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o diff --git a/drivers/mfd/acer-ec-a500.c b/drivers/mfd/acer-ec-a500.c new file mode 100644 index 000000000000..2785a6d9bcc4 --- /dev/null +++ b/drivers/mfd/acer-ec-a500.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MFD driver for Acer Iconia Tab A500 Embedded Controller. + * + * Copyright 2020 GRATE-driver project. + * + * Based on downstream driver from Acer Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define A500_EC_I2C_ERR_TIMEOUT 500 +#define A500_EC_POWER_CMD_TIMEOUT 1000 + +enum { + REG_CURRENT_NOW = 0x03, + REG_SHUTDOWN = 0x52, + REG_WARM_REBOOT = 0x54, + REG_COLD_REBOOT = 0x55, +}; + +static struct i2c_client *a500_ec_client_pm_off; + +static int a500_ec_read(void *context, const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_sizel) +{ + struct i2c_client *client = context; + unsigned int reg, retries = 5; + u16 *ret_val = val_buf; + s32 ret = 0; + + if (reg_size != 1 || val_sizel != 2) + return -EOPNOTSUPP; + + reg = *(u8 *)reg_buf; + + while (retries-- > 0) { + ret = i2c_smbus_read_word_data(client, reg); + if (ret >= 0) + break; + + msleep(A500_EC_I2C_ERR_TIMEOUT); + } + + if (ret < 0) { + dev_err(&client->dev, "read 0x%x failed: %d\n", reg, ret); + return ret; + } + + *ret_val = ret; + + if (reg == REG_CURRENT_NOW) + fsleep(10000); + + return 0; +} + +static int a500_ec_write(void *context, const void *data, size_t count) +{ + struct i2c_client *client = context; + unsigned int reg, val, retries = 5; + s32 ret = 0; + + if (count != 3) + return -EOPNOTSUPP; + + reg = *(u8 *)(data + 0); + val = *(u16 *)(data + 1); + + while (retries-- > 0) { + ret = i2c_smbus_write_word_data(client, reg, val); + if (ret >= 0) + break; + + msleep(A500_EC_I2C_ERR_TIMEOUT); + } + + if (ret < 0) { + dev_err(&client->dev, "write 0x%x failed: %d\n", reg, ret); + return ret; + } + + return 0; +} + +static const struct regmap_config a500_ec_regmap_config = { + .name = "KB930", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0xff, +}; + +static const struct regmap_bus a500_ec_regmap_bus = { + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, + .write = a500_ec_write, + .read = a500_ec_read, + .max_raw_read = 2, +}; + +static void a500_ec_poweroff(void) +{ + i2c_smbus_write_word_data(a500_ec_client_pm_off, REG_SHUTDOWN, 0); + + mdelay(A500_EC_POWER_CMD_TIMEOUT); +} + +static int a500_ec_restart_notify(struct notifier_block *this, + unsigned long reboot_mode, void *data) +{ + if (reboot_mode == REBOOT_WARM) + i2c_smbus_write_word_data(a500_ec_client_pm_off, + REG_WARM_REBOOT, 0); + else + i2c_smbus_write_word_data(a500_ec_client_pm_off, + REG_COLD_REBOOT, 1); + + mdelay(A500_EC_POWER_CMD_TIMEOUT); + + return NOTIFY_DONE; +} + +static struct notifier_block a500_ec_restart_handler = { + .notifier_call = a500_ec_restart_notify, + .priority = 200, +}; + +static const struct mfd_cell a500_ec_cells[] = { + { .name = "acer-a500-iconia-battery", }, + { .name = "acer-a500-iconia-leds", }, +}; + +static int a500_ec_probe(struct i2c_client *client) +{ + struct regmap *rmap; + int err; + + rmap = devm_regmap_init(&client->dev, &a500_ec_regmap_bus, + client, &a500_ec_regmap_config); + if (IS_ERR(rmap)) + return PTR_ERR(rmap); + + /* register battery and LED sub-devices */ + err = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, + a500_ec_cells, ARRAY_SIZE(a500_ec_cells), + NULL, 0, NULL); + if (err) { + dev_err(&client->dev, "failed to add sub-devices: %d\n", err); + return err; + } + + /* set up power management functions */ + if (of_device_is_system_power_controller(client->dev.of_node)) { + a500_ec_client_pm_off = client; + + err = register_restart_handler(&a500_ec_restart_handler); + if (err) + return err; + + if (!pm_power_off) + pm_power_off = a500_ec_poweroff; + } + + return 0; +} + +static int a500_ec_remove(struct i2c_client *client) +{ + if (of_device_is_system_power_controller(client->dev.of_node)) { + if (pm_power_off == a500_ec_poweroff) + pm_power_off = NULL; + + unregister_restart_handler(&a500_ec_restart_handler); + } + + return 0; +} + +static const struct of_device_id a500_ec_match[] = { + { .compatible = "acer,a500-iconia-ec" }, + { } +}; +MODULE_DEVICE_TABLE(of, a500_ec_match); + +static struct i2c_driver a500_ec_driver = { + .driver = { + .name = "acer-a500-embedded-controller", + .of_match_table = a500_ec_match, + }, + .probe_new = a500_ec_probe, + .remove = a500_ec_remove, +}; +module_i2c_driver(a500_ec_driver); + +MODULE_DESCRIPTION("Acer Iconia Tab A500 Embedded Controller driver"); +MODULE_AUTHOR("Dmitry Osipenko "); +MODULE_LICENSE("GPL"); From patchwork Sun Sep 6 19:51:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11759717 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6B93B1599 for ; Sun, 6 Sep 2020 19:52:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 48EB0214DB for ; Sun, 6 Sep 2020 19:52:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="S/oBveru" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726667AbgIFTv5 (ORCPT ); Sun, 6 Sep 2020 15:51:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726482AbgIFTv1 (ORCPT ); Sun, 6 Sep 2020 15:51:27 -0400 Received: from mail-lj1-x242.google.com (mail-lj1-x242.google.com [IPv6:2a00:1450:4864:20::242]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2AA1C061575; Sun, 6 Sep 2020 12:51:26 -0700 (PDT) Received: by mail-lj1-x242.google.com with SMTP id t23so13687475ljc.3; Sun, 06 Sep 2020 12:51:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=i9kECGEmFpeu/YlzXuXIcv9eZGuOQH1eLhQ/SORGYyY=; b=S/oBveru7SpaDKNVtEI2y0DaW9Krc4+eQZaCKOM5mJOZ3FplbXP6H++vJ9d9vTNhuC H51+mhfBlWwN5/qhQCDcjS5Fpbi0Y72UilCayhK/0K6dTSqNf1SJmUVWb88E0m6bIHIT 4LQs2rte/SxpOOHkmBgIXoKORXkCp3r6v7Z6XZmDoN472CcUmfxI5Ppiq9sI/4b1ZJdx Xtyz9VBh71N0C4XDZbMldqOEt2F+6q5gDPeyKKvSOyzbJ5rbGPZi42lxKiODx0ddF1xE 1XodI3LVtwgJ1bOEkROiMjyJ/yCmr1rqXz4t6AgyOEzCtf39AWebwFMy7CyqxGau8Yn+ 8wBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=i9kECGEmFpeu/YlzXuXIcv9eZGuOQH1eLhQ/SORGYyY=; b=WeXtL1VMpN+EHc2VRtqhn2NPOdpu7JLM3w8CThUm69TbFz3UdudsDV519pCKN02k1m snPsMFjS6ov4U86umVadyKCDuf/P3SFOQFvOW83uBcGpaUDoF1S5ZMrWTH6VLtAd+ndd ppP9vtJhb6MOBeu6aPkLXYsPqOj1CdMfQPyCNG45iyzKi466Wb0Yp7czOYIq6tDLfKUX Eii/RItL2gQbQrSLXkviBJd0jcFt07hcQzorvZHOf9RPDhvUgdAmkcDc3GaV4R+iw9bR gDlx+TzrryyW3vuGT/Jz+GM/BI/0CCh+Acczrkd54krIty6lquxYrexxTEsnnkn4fXt3 worw== X-Gm-Message-State: AOAM531Yn81WojldHu+RTKStiRjFvbl62RznSAFjCcrKPGMMyHjfPj81 1x86bOh8uQUXeraPob6LyP8= X-Google-Smtp-Source: ABdhPJyJxrY1v/eSNxhu4uRp5af6bIOu5LzG1jrGW4IxNf5z3eetZrmesBTdZywW5H9z/oeXoE1EUg== X-Received: by 2002:a2e:8046:: with SMTP id p6mr8236843ljg.372.1599421885040; Sun, 06 Sep 2020 12:51:25 -0700 (PDT) Received: from localhost.localdomain (109-252-170-211.dynamic.spd-mgts.ru. [109.252.170.211]) by smtp.gmail.com with ESMTPSA id b7sm4942574lfq.36.2020.09.06.12.51.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2020 12:51:24 -0700 (PDT) From: Dmitry Osipenko To: Lee Jones , Rob Herring , Thierry Reding , Jonathan Hunter , Pavel Machek , Dan Murphy , Sebastian Reichel , Lubomir Rintel Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/5] power: supply: Add battery gauge driver for Acer Iconia Tab A500 Date: Sun, 6 Sep 2020 22:51:01 +0300 Message-Id: <20200906195103.1347-4-digetx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200906195103.1347-1-digetx@gmail.com> References: <20200906195103.1347-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org This patch adds battery gauge driver for Acer Iconia Tab A500 device. The battery gauge function is provided via the Embedded Controller, which is found on the Acer A500. Signed-off-by: Dmitry Osipenko Reviewed-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 6 + drivers/power/supply/Makefile | 1 + drivers/power/supply/acer_a500_battery.c | 297 +++++++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 drivers/power/supply/acer_a500_battery.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index a4657484f38b..21257a81b55b 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -760,4 +760,10 @@ config RN5T618_POWER This driver can also be built as a module. If so, the module will be called rn5t618_power. +config BATTERY_ACER_A500 + tristate "Acer Iconia Tab A500 battery driver" + depends on MFD_ACER_A500_EC + help + Say Y to include support for Acer Iconia Tab A500 battery fuel gauge. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 293d4a5d80d3..d0f1b77c5c49 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -97,3 +97,4 @@ obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o +obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o diff --git a/drivers/power/supply/acer_a500_battery.c b/drivers/power/supply/acer_a500_battery.c new file mode 100644 index 000000000000..93135933c8af --- /dev/null +++ b/drivers/power/supply/acer_a500_battery.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Battery driver for Acer Iconia Tab A500. + * + * Copyright 2020 GRATE-driver project. + * + * Based on downstream driver from Acer Inc. + * Based on NVIDIA Gas Gauge driver for SBS Compliant Batteries. + * + * Copyright (c) 2010, NVIDIA Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include + +enum { + REG_CAPACITY, + REG_VOLTAGE, + REG_CURRENT, + REG_DESIGN_CAPACITY, + REG_TEMPERATURE, +}; + +#define EC_DATA(_reg, _psp) { \ + .psp = POWER_SUPPLY_PROP_ ## _psp, \ + .reg = _reg, \ +} + +static const struct battery_register { + enum power_supply_property psp; + unsigned int reg; +} ec_data[] = { + [REG_CAPACITY] = EC_DATA(0x00, CAPACITY), + [REG_VOLTAGE] = EC_DATA(0x01, VOLTAGE_NOW), + [REG_CURRENT] = EC_DATA(0x03, CURRENT_NOW), + [REG_DESIGN_CAPACITY] = EC_DATA(0x08, CHARGE_FULL_DESIGN), + [REG_TEMPERATURE] = EC_DATA(0x0a, TEMP), +}; + +static const enum power_supply_property a500_battery_properties[] = { + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +struct a500_battery { + struct delayed_work poll_work; + struct power_supply *psy; + struct regmap *rmap; + unsigned int capacity; +}; + +static bool a500_battery_update_capacity(struct a500_battery *bat) +{ + unsigned int capacity; + int err; + + err = regmap_read(bat->rmap, ec_data[REG_CAPACITY].reg, &capacity); + if (err) + return false; + + /* capacity can be >100% even if max value is 100% */ + capacity = min(capacity, 100u); + + if (bat->capacity != capacity) { + bat->capacity = capacity; + return true; + } + + return false; +} + +static int a500_battery_get_status(struct a500_battery *bat) +{ + if (bat->capacity < 100) { + if (power_supply_am_i_supplied(bat->psy)) + return POWER_SUPPLY_STATUS_CHARGING; + else + return POWER_SUPPLY_STATUS_DISCHARGING; + } + + return POWER_SUPPLY_STATUS_FULL; +} + +static void a500_battery_unit_adjustment(struct device *dev, + enum power_supply_property psp, + union power_supply_propval *val) +{ + const unsigned int base_unit_conversion = 1000; + const unsigned int temp_kelvin_to_celsius = 2731; + + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_CURRENT_NOW: + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval *= base_unit_conversion; + break; + + case POWER_SUPPLY_PROP_TEMP: + val->intval -= temp_kelvin_to_celsius; + break; + + case POWER_SUPPLY_PROP_PRESENT: + val->intval = !!val->intval; + break; + + default: + dev_dbg(dev, + "%s: no need for unit conversion %d\n", __func__, psp); + } +} + +static int a500_battery_get_ec_data_index(struct device *dev, + enum power_supply_property psp) +{ + unsigned int i; + + /* + * DESIGN_CAPACITY register always returns a non-zero value if + * battery is connected and zero if disconnected, hence we'll use + * it for judging the battery presence. + */ + if (psp == POWER_SUPPLY_PROP_PRESENT) + psp = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; + + for (i = 0; i < ARRAY_SIZE(ec_data); i++) + if (psp == ec_data[i].psp) + return i; + + dev_dbg(dev, "%s: invalid property %u\n", __func__, psp); + + return -EINVAL; +} + +static int a500_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct a500_battery *bat = power_supply_get_drvdata(psy); + struct device *dev = psy->dev.parent; + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = a500_battery_get_status(bat); + break; + + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + + case POWER_SUPPLY_PROP_CAPACITY: + a500_battery_update_capacity(bat); + val->intval = bat->capacity; + break; + + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_CURRENT_NOW: + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + case POWER_SUPPLY_PROP_PRESENT: + case POWER_SUPPLY_PROP_TEMP: + ret = a500_battery_get_ec_data_index(dev, psp); + if (ret < 0) + break; + + ret = regmap_read(bat->rmap, ec_data[ret].reg, &val->intval); + break; + + default: + dev_err(dev, "%s: invalid property %u\n", __func__, psp); + return -EINVAL; + } + + if (!ret) { + /* convert units to match requirements of power supply class */ + a500_battery_unit_adjustment(dev, psp, val); + } + + dev_dbg(dev, "%s: property = %d, value = %x\n", + __func__, psp, val->intval); + + /* return NODATA for properties if battery not presents */ + if (ret) + return -ENODATA; + + return 0; +} + +static void a500_battery_poll_work(struct work_struct *work) +{ + struct a500_battery *bat; + bool capacity_changed; + + bat = container_of(work, struct a500_battery, poll_work.work); + capacity_changed = a500_battery_update_capacity(bat); + + if (capacity_changed) + power_supply_changed(bat->psy); + + /* continuously send uevent notification */ + schedule_delayed_work(&bat->poll_work, 30 * HZ); +} + +static const struct power_supply_desc a500_battery_desc = { + .name = "ec-battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = a500_battery_properties, + .get_property = a500_battery_get_property, + .num_properties = ARRAY_SIZE(a500_battery_properties), + .external_power_changed = power_supply_changed, +}; + +static int a500_battery_probe(struct platform_device *pdev) +{ + struct power_supply_config psy_cfg = {}; + struct a500_battery *bat; + + bat = devm_kzalloc(&pdev->dev, sizeof(*bat), GFP_KERNEL); + if (!bat) + return -ENOMEM; + + platform_set_drvdata(pdev, bat); + + psy_cfg.of_node = pdev->dev.parent->of_node; + psy_cfg.drv_data = bat; + + bat->rmap = dev_get_regmap(pdev->dev.parent, "KB930"); + if (!bat->rmap) + return -EINVAL; + + bat->psy = devm_power_supply_register_no_ws(&pdev->dev, + &a500_battery_desc, + &psy_cfg); + if (IS_ERR(bat->psy)) + return dev_err_probe(&pdev->dev, PTR_ERR(bat->psy), + "failed to register battery\n"); + + INIT_DELAYED_WORK(&bat->poll_work, a500_battery_poll_work); + schedule_delayed_work(&bat->poll_work, HZ); + + return 0; +} + +static int a500_battery_remove(struct platform_device *pdev) +{ + struct a500_battery *bat = dev_get_drvdata(&pdev->dev); + + cancel_delayed_work_sync(&bat->poll_work); + + return 0; +} + +static int __maybe_unused a500_battery_suspend(struct device *dev) +{ + struct a500_battery *bat = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&bat->poll_work); + + return 0; +} + +static int __maybe_unused a500_battery_resume(struct device *dev) +{ + struct a500_battery *bat = dev_get_drvdata(dev); + + schedule_delayed_work(&bat->poll_work, HZ); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(a500_battery_pm_ops, + a500_battery_suspend, a500_battery_resume); + +static struct platform_driver a500_battery_driver = { + .driver = { + .name = "acer-a500-iconia-battery", + .pm = &a500_battery_pm_ops, + }, + .probe = a500_battery_probe, + .remove = a500_battery_remove, +}; +module_platform_driver(a500_battery_driver); + +MODULE_DESCRIPTION("Battery gauge driver for Acer Iconia Tab A500"); +MODULE_AUTHOR("Dmitry Osipenko "); +MODULE_ALIAS("platform:acer-a500-iconia-battery"); +MODULE_LICENSE("GPL"); From patchwork Sun Sep 6 19:51:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11759713 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1326B1599 for ; Sun, 6 Sep 2020 19:52:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3B9B20C09 for ; Sun, 6 Sep 2020 19:52:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WzGqMuiz" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726692AbgIFTv6 (ORCPT ); Sun, 6 Sep 2020 15:51:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41364 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726490AbgIFTva (ORCPT ); Sun, 6 Sep 2020 15:51:30 -0400 Received: from mail-lf1-x142.google.com (mail-lf1-x142.google.com [IPv6:2a00:1450:4864:20::142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB277C061755; Sun, 6 Sep 2020 12:51:27 -0700 (PDT) Received: by mail-lf1-x142.google.com with SMTP id x69so762947lff.3; Sun, 06 Sep 2020 12:51:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hPl0RuRyAddcYtgA2PYbH+dGQ9rcZfnkqx62zbHZNDs=; b=WzGqMuizkdqv3LcT5H63qtHW6T+SWVN5iMJYSnKfpGJKHZ6JFdbUlE4pithhF9HeDW 2+fDs80rbAlpi+NTZ2EMlAAxI5ftTiHKhYKBgc/if6aCKKn9qz/EJfqa3SkKtWxjBPW9 3uO80FLONaltAFu9LMZbqrSNa3zTifRV+1L5vhe++y5E+C5rY41sWTNRsLqlV/dcEQfA 4DaX26o7OJknIUW4UXcf0rK4PEt4cu8rriqdxEgcK0K7zzrMPNrjSOCz+FOkjIKhPLtJ 7FJyDHMynhxSFTdCb0rm9GuKeJBy1zMZwf14d8vvJH4MCKp30WOtm6INubpcHKiYVNBn saLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hPl0RuRyAddcYtgA2PYbH+dGQ9rcZfnkqx62zbHZNDs=; b=oNZS+pC66MIfUAVRxkvUwTSV/Z4ZhmbKsLng0aDRa/do+kXaD4OHf4L9kgQSOLXiHF iieQ1FJmWAsd63bHrc42VR6j0X0pSjVDpKfuPGNrPehAH78HLGxoxnzSWLaEg8eqy8mv mvFQmc3X40GUUX1RXTcHqYxIvAxye9beDlaVmuAhIVCjwb2nIp199+jrA9zJ+MeYyB+U iJyRtEJ96iQyBNOX2U5pFb4ExqLCKCbpd/yvF6BDM7M4qa2Ps9g0r85qmefs0/pn13FB z8LljYVqDgFBLBCf22L3MlksWwdoyZYNSIQFzdBoudefV24lekESA6M5ns68xQBuYb0w rUPw== X-Gm-Message-State: AOAM532RTAYXlOivzmuLjCY9B1e9TTq23OWuV9UydVkJL5j1Ic5JONR0 CzMnQ9M+EZvDw9LF/mlfh+w= X-Google-Smtp-Source: ABdhPJwlcl+hj+WdN2P9rse3UxNapsut1UgP1VUvsdjpVIHzLYNPmHLImAIpWUZ2Wyzeu+YVorEOMw== X-Received: by 2002:a19:f513:: with SMTP id j19mr8572603lfb.174.1599421886018; Sun, 06 Sep 2020 12:51:26 -0700 (PDT) Received: from localhost.localdomain (109-252-170-211.dynamic.spd-mgts.ru. [109.252.170.211]) by smtp.gmail.com with ESMTPSA id b7sm4942574lfq.36.2020.09.06.12.51.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2020 12:51:25 -0700 (PDT) From: Dmitry Osipenko To: Lee Jones , Rob Herring , Thierry Reding , Jonathan Hunter , Pavel Machek , Dan Murphy , Sebastian Reichel , Lubomir Rintel Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/5] leds: Add driver for Acer Iconia Tab A500 Date: Sun, 6 Sep 2020 22:51:02 +0300 Message-Id: <20200906195103.1347-5-digetx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200906195103.1347-1-digetx@gmail.com> References: <20200906195103.1347-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Acer Iconia Tab A500 is an Android tablet device which has two LEDs embedded into the Power Button. Orange LED indicates "battery charging" status and white LED indicates "wake-up/charge-done" status. The new LED driver provides control over both LEDs to userspace. Signed-off-by: Dmitry Osipenko --- drivers/leds/Kconfig | 7 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-acer-a500.c | 129 ++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/leds/leds-acer-a500.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 4f6464a169d5..4c39b53bcf1f 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -921,6 +921,13 @@ config LEDS_SGM3140 This option enables support for the SGM3140 500mA Buck/Boost Charge Pump LED Driver. +config LEDS_ACER_A500 + tristate "Power button LED support for Acer Iconia Tab A500" + depends on LEDS_CLASS && MFD_ACER_A500_EC + help + This option enables support for the Power Button LED of + Acer Iconia Tab A500. + comment "LED Triggers" source "drivers/leds/trigger/Kconfig" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 778cb4bb8c52..73e603e1727e 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o # LED Platform Drivers (keep this sorted, M-| sort) obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o +obj-$(CONFIG_LEDS_ACER_A500) += leds-acer-a500.o obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o obj-$(CONFIG_LEDS_APU) += leds-apu.o diff --git a/drivers/leds/leds-acer-a500.c b/drivers/leds/leds-acer-a500.c new file mode 100644 index 000000000000..8cf0b11f4390 --- /dev/null +++ b/drivers/leds/leds-acer-a500.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include + +#define A500_EC_LED_DELAY_USEC (100 * 1000) + +enum { + REG_RESET_LEDS = 0x40, + REG_POWER_LED_ON = 0x42, + REG_CHARGE_LED_ON = 0x43, + REG_ANDROID_LEDS_OFF = 0x5a, +}; + +struct a500_led { + struct led_classdev cdev; + const struct reg_sequence *enable_seq; + struct a500_led *other; + struct regmap *rmap; +}; + +static const struct reg_sequence a500_ec_leds_reset_seq[] = { + REG_SEQ(REG_RESET_LEDS, 0x0, A500_EC_LED_DELAY_USEC), + REG_SEQ(REG_ANDROID_LEDS_OFF, 0x0, A500_EC_LED_DELAY_USEC), +}; + +static const struct reg_sequence a500_ec_white_led_enable_seq[] = { + REG_SEQ(REG_POWER_LED_ON, 0x0, A500_EC_LED_DELAY_USEC), +}; + +static const struct reg_sequence a500_ec_orange_led_enable_seq[] = { + REG_SEQ(REG_CHARGE_LED_ON, 0x0, A500_EC_LED_DELAY_USEC), +}; + +static int a500_ec_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct a500_led *led = container_of(led_cdev, struct a500_led, cdev); + struct reg_sequence control_seq[2]; + unsigned int num_regs = 1; + + if (value) { + control_seq[0] = led->enable_seq[0]; + } else { + /* + * There is no separate controls which can disable LEDs + * individually, there is only RESET_LEDS command that turns + * off both LEDs. + * + * RESET_LEDS turns off both LEDs, thus restore other LED if + * it's turned ON. + */ + if (led->other->cdev.brightness) + num_regs = 2; + + control_seq[0] = a500_ec_leds_reset_seq[0]; + control_seq[1] = led->other->enable_seq[0]; + } + + return regmap_multi_reg_write(led->rmap, control_seq, num_regs); +} + +static int a500_ec_leds_probe(struct platform_device *pdev) +{ + struct a500_led *white_led, *orange_led; + struct regmap *rmap; + int err; + + rmap = dev_get_regmap(pdev->dev.parent, "KB930"); + if (!rmap) + return -EINVAL; + + /* reset and turn off LEDs */ + regmap_multi_reg_write(rmap, a500_ec_leds_reset_seq, 2); + + white_led = devm_kzalloc(&pdev->dev, sizeof(*white_led), GFP_KERNEL); + if (!white_led) + return -ENOMEM; + + white_led->cdev.name = "power:white"; + white_led->cdev.brightness_set_blocking = a500_ec_led_brightness_set; + white_led->cdev.flags = LED_CORE_SUSPENDRESUME; + white_led->cdev.max_brightness = 1; + white_led->enable_seq = a500_ec_white_led_enable_seq; + white_led->rmap = rmap; + + orange_led = devm_kzalloc(&pdev->dev, sizeof(*orange_led), GFP_KERNEL); + if (!orange_led) + return -ENOMEM; + + orange_led->cdev.name = "power:orange"; + orange_led->cdev.brightness_set_blocking = a500_ec_led_brightness_set; + orange_led->cdev.flags = LED_CORE_SUSPENDRESUME; + orange_led->cdev.max_brightness = 1; + orange_led->enable_seq = a500_ec_orange_led_enable_seq; + orange_led->rmap = rmap; + + white_led->other = orange_led; + orange_led->other = white_led; + + err = devm_led_classdev_register(&pdev->dev, &white_led->cdev); + if (err) { + dev_err(&pdev->dev, "failed to register white LED\n"); + return err; + } + + err = devm_led_classdev_register(&pdev->dev, &orange_led->cdev); + if (err) { + dev_err(&pdev->dev, "failed to register orange LED\n"); + return err; + } + + return 0; +} + +static struct platform_driver a500_ec_leds_driver = { + .driver = { + .name = "acer-a500-iconia-leds", + }, + .probe = a500_ec_leds_probe, +}; +module_platform_driver(a500_ec_leds_driver); + +MODULE_DESCRIPTION("LED driver for Acer Iconia Tab A500 Power Button"); +MODULE_AUTHOR("Dmitry Osipenko "); +MODULE_ALIAS("platform:acer-a500-iconia-leds"); +MODULE_LICENSE("GPL"); From patchwork Sun Sep 6 19:51:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11759711 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B2E2C1599 for ; Sun, 6 Sep 2020 19:52:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9533F20C09 for ; Sun, 6 Sep 2020 19:52:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Oobg5koT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726564AbgIFTv5 (ORCPT ); Sun, 6 Sep 2020 15:51:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726493AbgIFTva (ORCPT ); Sun, 6 Sep 2020 15:51:30 -0400 Received: from mail-lf1-x144.google.com (mail-lf1-x144.google.com [IPv6:2a00:1450:4864:20::144]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9ADC5C061756; Sun, 6 Sep 2020 12:51:28 -0700 (PDT) Received: by mail-lf1-x144.google.com with SMTP id d15so5546574lfq.11; Sun, 06 Sep 2020 12:51:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=35wLUHHiL0jcYl7dr+ydbL6W/M+IENF1DgF9AQYM8t8=; b=Oobg5koT9Ox8v79M5WhWmKiVhX59pyNIUp9/wkzJHs3WGEBM3+96r9IBtOQktr1S/d QnHjBaLyyhA2oWdyy1KBBJULvt16SxQxcsaE/iUac+Eb1nPlamVSUD5vhGuXl5SSbe11 TZKFDHVz7icmCrmH3fnIR4gwjbADsDpZhue2J8nRWMnKk8GLaxP9CRFnZYkgrqdS7emM hsUN+OmSZnxiSEnQaxJ+UBuYxlYjDMDKm9VHwRcoo8aogoVFWVLxtpwEftu4ChkP2XVe QejLkAIFhFCu6RS0q1Y+Qg1F1176Dk+blJNhugmazRt/Rm/1qHBqUZCSvCRB7YYCXLLq 2B1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=35wLUHHiL0jcYl7dr+ydbL6W/M+IENF1DgF9AQYM8t8=; b=c9xP2TlLGJoyHP4mb33u8AzR/THQCw4x4tEMJSQ/ohg4NAjWzasJ2ijBPg3sVZLEnS M3PrpEo0UFft78XjG2ibAVh69kUhI3eQRk9+ynYf8uBvLawASxOHm8MefOpDWzJSdeYD T1XkaZRU4JGwiCshBwKNjKO+03KSSh8YpA1Fz6PBn57JhSKVHyXIrPfB7XSd8OYPeitf 3fklXST9RCehisA72W8qHUIs8zAMC0ZRQzrlHih8SvY5XMb6mhsqH6Un0zF42WoEl+ZW YO/XUT1PH1t9G1sufBIL8RVsoXDjrJfEw1IaHlMzLod8LWMjWli3MWmiVrABcnFl2Hyp vOOQ== X-Gm-Message-State: AOAM533ciFEBd13uEkkpUafX5Y45NdVI6JqWXdIf4Xf7Y4XuL6ZIE3gE KrSpBSZOjX8r5qDU4hFBqyg= X-Google-Smtp-Source: ABdhPJz1lqvoiCo/WdRrNpCNNEaDozq2pMzlNdc8l1vYlS76MU5hhy2Z1yaXF0kfHPjprP58FS8jTw== X-Received: by 2002:a19:6411:: with SMTP id y17mr8719678lfb.199.1599421887058; Sun, 06 Sep 2020 12:51:27 -0700 (PDT) Received: from localhost.localdomain (109-252-170-211.dynamic.spd-mgts.ru. [109.252.170.211]) by smtp.gmail.com with ESMTPSA id b7sm4942574lfq.36.2020.09.06.12.51.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2020 12:51:26 -0700 (PDT) From: Dmitry Osipenko To: Lee Jones , Rob Herring , Thierry Reding , Jonathan Hunter , Pavel Machek , Dan Murphy , Sebastian Reichel , Lubomir Rintel Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 5/5] ARM: tegra: acer-a500: Add Embedded Controller Date: Sun, 6 Sep 2020 22:51:03 +0300 Message-Id: <20200906195103.1347-6-digetx@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200906195103.1347-1-digetx@gmail.com> References: <20200906195103.1347-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org This patch adds device-tree node for the Embedded Controller which is found on the Picasso board. The Embedded Controller itself is ENE KB930, it provides functions like battery-gauge/LED/GPIO/etc and it uses firmware that is specifically customized for the Acer A500 device. Signed-off-by: Dmitry Osipenko --- arch/arm/boot/dts/tegra20-acer-a500-picasso.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts index 2d683c9a1a5d..f92712e4bd34 100644 --- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts +++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts @@ -502,6 +502,16 @@ panel_ddc: i2c@1 { reg = <1>; #address-cells = <1>; #size-cells = <0>; + + embedded-controller@58 { + compatible = "acer,a500-iconia-ec", "ene,kb930"; + reg = <0x58>; + + system-power-controller; + + monitored-battery = <&bat1010>; + power-supplies = <&mains>; + }; }; }; @@ -780,6 +790,13 @@ backlight: backlight { default-brightness-level = <20>; }; + bat1010: battery-2s1p { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3260000>; + energy-full-design-microwatt-hours = <24000000>; + operating-range-celsius = <0 40>; + }; + /* PMIC has a built-in 32KHz oscillator which is used by PMC */ clk32k_in: clock@0 { compatible = "fixed-clock";