From patchwork Wed Apr 5 13:44:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 13201757 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE1AC7619A for ; Wed, 5 Apr 2023 13:45:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237766AbjDENpE (ORCPT ); Wed, 5 Apr 2023 09:45:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237507AbjDENo4 (ORCPT ); Wed, 5 Apr 2023 09:44:56 -0400 Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 709D55B9D for ; Wed, 5 Apr 2023 06:44:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1680702295; x=1712238295; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=GXCV12trQehxUcs4IUml0M8hLi49IKzH7o/s92iGUbs=; b=Z+tMfcRg5XPak4S0gQhLlhhZBOeZBBBU6c0iNt0jZwwRb89cqypLpJPj gkeyQU8k2enfiA7lLAMHUnHtJgWZn8ajn+zhc6sTrC7Rl2XqCegOKoHly BZ1Cr9PMmjG/WP/JUSJPrHna48L15wzYD+BK1GHGNKZ/j2t8gUOJv3PLA gy9y5WnCxQtMu+9nVZJ73gjnjr+RGGlT0Qkh4fjeTKcUBDGf5IInGfR1n ottwne1cBOX6nV8Zh8Ns42L0dLsc/9dW0sFNFxEuhIz2mQjQ5NdrJTqCE ZAcjJPvlKoKNBdMCdNVn7CTIT+fYpnNpvrLPmj4dXz2McdPDG3fgSvn73 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10670"; a="405232564" X-IronPort-AV: E=Sophos;i="5.98,319,1673942400"; d="scan'208";a="405232564" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Apr 2023 06:44:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10670"; a="830369122" X-IronPort-AV: E=Sophos;i="5.98,319,1673942400"; d="scan'208";a="830369122" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 05 Apr 2023 06:44:53 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, =?utf-8?q?Samuel_=C4=8Cavoj?= Subject: [PATCH v2] usb: typec: ucsi: acpi: add quirk for ASUS Zenbook UM325 Date: Wed, 5 Apr 2023 16:44:56 +0300 Message-Id: <20230405134456.49607-1-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: Samuel Čavoj On some ACPI platforms (namely the ASUS Zenbook UM325) the _DSM method must not be called after a notification is received but instead the mailbox should be read immediately from RAM. This is because the ACPI interrupt handler destroys the CCI in ERAM after copying to system memory, and when _DSM is later called to perform a second copy, it retrieves a garbage value. Instead, the _DSM(read) method should only be called when necessary, i.e. for polling the state after reset and for retrieving the version. Other reads should not call _DSM and only peek into the RAM region. This adds a separate read operation for the Zenbook that syncs the ACPI mailbox only with polled commands. Link: https://lore.kernel.org/linux-usb/20210823180626.tb6m7h5tp6adhvt2@fastboi.localdomain/ Signed-off-by: Samuel Čavoj [ heikki : handling everything in ucsi_acpi.c with DMI quirk ] Signed-off-by: Heikki Krogerus --- Changed since v1 [1]: - ucsi.c is not modified anymore. The separate read_explicit callback is replaced with a dedicated read operation for the Zenbooks only. [1] https://lore.kernel.org/linux-usb/20230120233920.752245-1-samuel@cavoj.net/ --- drivers/usb/typec/ucsi/ucsi_acpi.c | 44 ++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 62206a6b8ea75..217355f1f9b94 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "ucsi.h" @@ -23,6 +24,7 @@ struct ucsi_acpi { struct completion complete; unsigned long flags; guid_t guid; + u64 cmd; }; static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) @@ -62,6 +64,7 @@ static int ucsi_acpi_async_write(struct ucsi *ucsi, unsigned int offset, struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); memcpy(ua->base + offset, val, val_len); + ua->cmd = *(u64 *)val; return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE); } @@ -93,13 +96,46 @@ static const struct ucsi_operations ucsi_acpi_ops = { .async_write = ucsi_acpi_async_write }; +static int +ucsi_zenbook_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + if (offset == UCSI_VERSION || UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + } + + memcpy(val, ua->base + offset, val_len); + + return 0; +} + +static const struct ucsi_operations ucsi_zenbook_ops = { + .read = ucsi_zenbook_read, + .sync_write = ucsi_acpi_sync_write, + .async_write = ucsi_acpi_async_write +}; + +static const struct dmi_system_id zenbook_dmi_id[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), + }, + }, + { } +}; + static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) { struct ucsi_acpi *ua = data; u32 cci; int ret; - ret = ucsi_acpi_read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ua->ucsi->ops->read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci)); if (ret) return; @@ -114,6 +150,7 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) static int ucsi_acpi_probe(struct platform_device *pdev) { struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + const struct ucsi_operations *ops = &ucsi_acpi_ops; struct ucsi_acpi *ua; struct resource *res; acpi_status status; @@ -143,7 +180,10 @@ static int ucsi_acpi_probe(struct platform_device *pdev) init_completion(&ua->complete); ua->dev = &pdev->dev; - ua->ucsi = ucsi_create(&pdev->dev, &ucsi_acpi_ops); + if (dmi_check_system(zenbook_dmi_id)) + ops = &ucsi_zenbook_ops; + + ua->ucsi = ucsi_create(&pdev->dev, ops); if (IS_ERR(ua->ucsi)) return PTR_ERR(ua->ucsi);