From patchwork Wed Mar 20 02:05:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Klimov X-Patchwork-Id: 13597204 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1E2A2CD11DC for ; Wed, 20 Mar 2024 02:06:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ZNj/L/KOhloLO1rkcH5007NqAo5QNYs0K3BUQ5LdxBk=; b=Yzk10atA8tyMM7 9j2aU8UohTtM3sN1oMyMF0qsPNtc38zq8M1psADUQDiZscrUgTy271qen0EQE0/PBGK8OpNz5uge+ 2JcFZHDBoTFb/EZIk3xmCVg6sCqcLrGFx38yZ1vHvhO/i/BCwAyg7mjd8Z6TAO7niliiEyIej9siB 1W53PBuzNM7j5crSsAx5yYEFtUSo9U+TbO9jIzFQm2GUijWGYQ367T7A84Qj7c9sgu8LXp0z8aFj+ eC3BoR8DKQlEGmic/Rt+g0CykymCXuYxKGzdjHMbgy6CyywxeNnxsIgc4/Y17GRvT8HMnwkm7f9F9 jLqrTRKVV8CIo+4SD9Sg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rmlLI-0000000EzxO-11ZT; Wed, 20 Mar 2024 02:06:12 +0000 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rmlL1-0000000EzqX-13OG for linux-arm-kernel@lists.infradead.org; Wed, 20 Mar 2024 02:05:58 +0000 Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-3412f49bac7so2443475f8f.0 for ; Tue, 19 Mar 2024 19:05:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1710900353; x=1711505153; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8onlL6eaVMOKsrmQglnPXgtQA9k3jRb7PbaPmYQjRaA=; b=bpIV1ql8Edom5XFxJZENb3OtoO/VZz3xmu9NaBO50PBMBAACk5vpDByS93Epw9Ulgh XxMFfItKzL4NDDQsX2n3Nqf2EOrPkFm9KFaOyHuOeqJC0SJlhzBKFXTqoaZs3WbBKgUG tRRglQVyE0Uq1dQOOyulYx9f5JE1WyHeHxt6lbafGTQ/UL/Hq/W+aZEyjQ1viC3QkDHh SbpDosSk3ejedTYni7ID43qRZ1q95CFMwVNW3d3sCUu10LahmHd5PUIqxLpf9+Y+Su/Z elasC/TJIAOWInLzjKtHYZXH8EAejYTkeqbCdUaFTM+EVTvmaErPIJNj2tTg1RMGHZsu eoQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710900353; x=1711505153; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8onlL6eaVMOKsrmQglnPXgtQA9k3jRb7PbaPmYQjRaA=; b=knDpLNH1f3WZX8VYcGgeulK6U9O4XBYG79SHDs9+XMKWOctauCyZREW9Qc02TS+aBD VaCix2jpCJbPm/RIxOw8mjLvt2EL/mq5kZiq9bJahE2WcWMmlNwvaMWm9HNae8wR6cvf RS3ptN1MMiuAVNJmgG+1IIizYqIm0yD4KkJRStOVemKYg4fah/y+m/Mpdf5qp1Re5JwM 96+ZSJ03+IvbBuVw9jAB/hME1oigI4KPirK756delIn1n7XbLORSLVOGon+M/n7CLWDs xvqrpWxpqiiI1ohlViAlIJ1J6EnuZpe6shra+ybscvTKGo5rCVNf+9VWonThCX3KRn39 O5yw== X-Forwarded-Encrypted: i=1; AJvYcCVIj3QM1PzXCE4Zw7spT1hFuGJP1lwHtmNxRffdjRtuM86FCYfzKsgYqW64d506AZgzegMYSpEY8jheK9/PZSdo6aVxZdcunmYxYqStOaa/Z4W6A6c= X-Gm-Message-State: AOJu0YxS++c9DcaadWHJLfuqA/Ow2xFpFiM+xNGDcgrXcgiqc5oWKqoF Z51xXm6lbPsYveMoQNEUo2SEt2STLXmGbOLPtMfqR+i4YLQHG3cSU/VdIFBjLNs= X-Google-Smtp-Source: AGHT+IE68IgbQV2m5xaeAAIsPInh5pDFP6u6jfPE18/dwJApj36Y7blQSDKqq5/s9aU2fs3UkSbn8Q== X-Received: by 2002:adf:f292:0:b0:33d:1eea:4346 with SMTP id k18-20020adff292000000b0033d1eea4346mr10012461wro.37.1710900353298; Tue, 19 Mar 2024 19:05:53 -0700 (PDT) Received: from localhost.localdomain ([2a02:c7c:7213:c700:e992:6869:474c:a63f]) by smtp.gmail.com with ESMTPSA id u14-20020a056000038e00b0033e34c53354sm9209295wrf.56.2024.03.19.19.05.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Mar 2024 19:05:52 -0700 (PDT) From: Alexey Klimov To: sre@kernel.org, robh@kernel.org, krzysztof.kozlowski+dt@linaro.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, peter.griffin@linaro.org, robh+dt@kernel.org Cc: conor+dt@kernel.org, linux-samsung-soc@vger.kernel.org, semen.protsenko@linaro.org, linux-kernel@vger.kernel.org, klimov.linux@gmail.com, kernel-team@android.com, tudor.ambarus@linaro.org, andre.draszik@linaro.org, saravanak@google.com, willmcvicker@google.com, alexey.klimov@linaro.org, alim.akhtar@samsung.com, linux-arm-kernel@lists.infradead.org, elder@linaro.org Subject: [PATCH 3/3] power: reset: add new gs101-poweroff driver Date: Wed, 20 Mar 2024 02:05:49 +0000 Message-ID: <20240320020549.71810-3-alexey.klimov@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240320020549.71810-1-alexey.klimov@linaro.org> References: <20240320020549.71810-1-alexey.klimov@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240319_190555_473908_3F5B8112 X-CRM114-Status: GOOD ( 25.72 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The driver allows switching off the Google gs101 SoC (Pixel6 family of mobile phones). The syscon-poweroff cannot be used since gs101 requires smc-based regmap i.e. a write to PMU register done from EL3 is required. Additionally the power off write should be performed when power button is not pressed. When USB charging cable is connected then this leads to a reboot of a device initiated by bootloader/firmware. Signed-off-by: Alexey Klimov --- drivers/power/reset/Kconfig | 7 ++ drivers/power/reset/Makefile | 1 + drivers/power/reset/gs101-poweroff.c | 157 +++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/power/reset/gs101-poweroff.c diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index fece990af4a7..e7323b3b4a61 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -100,6 +100,13 @@ config POWER_RESET_GPIO_RESTART If your board needs a GPIO high/low to restart, say Y and create a binding in your devicetree. +config POWER_RESET_GS101_POWEROFF + tristate "GS101 power-off driver" + depends on ARCH_EXYNOS || COMPILE_TEST + help + This driver supports turning off the Google Tensor Pixel6 GS101 phones. + Select this if you're building a kernel with Google Tensor SoC support. + config POWER_RESET_HISI bool "Hisilicon power-off driver" depends on ARCH_HISI diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index a95d1bd275d1..7065b7e4ce77 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o obj-$(CONFIG_POWER_RESET_GEMINI_POWEROFF) += gemini-poweroff.o obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o +obj-$(CONFIG_POWER_RESET_GS101_POWEROFF) += gs101-poweroff.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o diff --git a/drivers/power/reset/gs101-poweroff.c b/drivers/power/reset/gs101-poweroff.c new file mode 100644 index 000000000000..2be903de16a1 --- /dev/null +++ b/drivers/power/reset/gs101-poweroff.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GS101 Poweroff Driver + * + * Copyright (c) 2024, Linaro Ltd. + * Author: Alexey Klimov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define shwork_to_poweroff(x) \ + container_of(x, struct gs101_poweroff, shutdown_work) + +#define keyboard_nb_to_poweroff(x) \ + container_of(x, struct gs101_poweroff, keyboard_nb) + +struct gs101_poweroff { + struct notifier_block keyboard_nb; + bool power_key_pressed; + struct work_struct shutdown_work; + struct regmap *map; + u32 offset; + u32 mask; +}; + +static struct gs101_poweroff *gs101_poweroff_ctx; + +static void gs101_shutdown_work_fn(struct work_struct *work) +{ + struct gs101_poweroff *gs101 = shwork_to_poweroff(work); + + while (1) { + /* wait for power button release */ + if (!gs101->power_key_pressed) { + /* Issue the poweroff */ + regmap_update_bits(gs101->map, + gs101->offset, + gs101->mask, 0); + } else { + /* + * if power button is not released, + * wait and check TA again + */ + pr_info("power key is not released.\n"); + } + mdelay(1000); + } +} + +static int gs101_keyboard_notifier_call(struct notifier_block *nb, + unsigned long code, void *_param) +{ + struct keyboard_notifier_param *param = _param; + + if (param->value == KEY_POWER) { + struct gs101_poweroff *gs101 = keyboard_nb_to_poweroff(nb); + + gs101->power_key_pressed = param->down; + } + + return NOTIFY_OK; +} + +static void gs101_poweroff(void) +{ + schedule_work(&gs101_poweroff_ctx->shutdown_work); +} + +static int gs101_poweroff_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gs101_poweroff *gs101; + int ret; + + gs101 = devm_kzalloc(dev, sizeof(*gs101), GFP_KERNEL); + if (!gs101) + return -ENOMEM; + + gs101->map = exynos_get_pmu_regmap_by_phandle(dev->of_node, + "samsung,syscon-phandle"); + if (IS_ERR(gs101->map)) + return PTR_ERR(gs101->map); + + if (of_property_read_u32(dev->of_node, "offset", &gs101->offset)) { + dev_err(dev, "unable to read 'offset' from DT\n"); + return -EINVAL; + } + + if (of_property_read_u32(dev->of_node, "mask", &gs101->mask)) { + dev_err(dev, "unable to read 'mask' from DT\n"); + return -EINVAL; + } + + gs101->keyboard_nb.notifier_call = gs101_keyboard_notifier_call; + ret = register_keyboard_notifier(&gs101->keyboard_nb); + if (ret) { + dev_err(dev, "failed to register keyboard notifier: %i\n", ret); + return ret; + } + + ret = devm_work_autocancel(dev, &gs101->shutdown_work, + gs101_shutdown_work_fn); + if (ret) { + dev_err(dev, "failed to register gs101 shutdown_work: %i\n", ret); + unregister_keyboard_notifier(&gs101->keyboard_nb); + return ret; + } + + gs101_poweroff_ctx = gs101; + platform_set_drvdata(pdev, gs101); + + /* + * At this point there is a chance that psci_sys_poweroff already + * registered as pm_power_off hook but unfortunately it cannot power + * off the gs101 SoC hence we are rewriting it here just as is. + */ + pm_power_off = gs101_poweroff; + + return 0; +} + +static void gs101_poweroff_remove(struct platform_device *pdev) +{ + struct gs101_poweroff *gs101 = platform_get_drvdata(pdev); + + if (pm_power_off == gs101_poweroff) + pm_power_off = NULL; + + unregister_keyboard_notifier(&gs101->keyboard_nb); +} + +static const struct of_device_id gs101_poweroff_of_match[] = { + { .compatible = "google,gs101-poweroff" }, + {} +}; + +static struct platform_driver gs101_poweroff_driver = { + .probe = gs101_poweroff_probe, + .remove_new = gs101_poweroff_remove, + .driver = { + .name = "gs101-poweroff", + .of_match_table = gs101_poweroff_of_match, + }, +}; + +module_platform_driver(gs101_poweroff_driver); +MODULE_AUTHOR("Alexey Klimov "); +MODULE_DESCRIPTION("Google GS101 poweroff driver"); +MODULE_LICENSE("GPL v2");