From patchwork Mon Jun 24 15:08:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13709693 Received: from mail-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78E0D1DFD2 for ; Mon, 24 Jun 2024 15:08:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719241723; cv=none; b=NBEZBzN9Ji513Dv5Wacr3HbV6pX8e34aCUm8ooqJuvCoVKkflGrx6DnUATZTr/0sdtfYoR2Bz2wAY9XAR9Tzz1S5PgKc9giXaOyU1P9B7tvpPocfW/xTf7/Wo80wWETB8Oty+bCRq5vs5aSyw/es5wTl5L1xNI7L9m7hykn0QRM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719241723; c=relaxed/simple; bh=8tKzwExQBw5uGrVk6EJMh5rj1XlrJN3GYv6ujg5VdWo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bad81sTgxsWcOf4cKf91A0Kr9pZWPwZFEsrAj4LR/9AdbsNG8cz1zGHcewPq0SVYLLnoYsNtH15m1eJrZiVHi0uvRfBei+ilLPKFacOp+ezvXm2cumKf8lNJHcif+qcl7TDHA4SJilAQScaUWl+dL0pIdoasnFS9HsDkU565i4w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=VbkMOSAC; arc=none smtp.client-ip=209.85.167.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="VbkMOSAC" Received: by mail-lf1-f52.google.com with SMTP id 2adb3069b0e04-52bbf73f334so3395744e87.2 for ; Mon, 24 Jun 2024 08:08:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1719241720; x=1719846520; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=5yftIHZLp8eHXmdT76tLth9/O15e8LEzT136xzEFdkw=; b=VbkMOSACxfpY/8axgh+Mtj+KNZPTQm7zG/lBCQGGTEjtpMtP6G5TLhN8KPD34lumHt cAMm/IARm+GfyYhbDQ0z1TCHr6B/gYbaxU6va2zPQE9UQhiqkrS4rPqH+6x5SWJXHR8g j3wMnr6MLc3AOy2NaIEVvW8RNzCoD3PPdVtWNmg6Kth4yfOXlnOZjwQz5pZs0ESE4Hyb 2K/UG/WhTfjI6SW8okHZ7wvyzsEO5eZ9friwIlFUgwAh3Iii46ll5XnNwNmby0tE2JtV bhZJUdThU6s6Mw4vNhER4oQPI8BNFQG2YqZdkdfXJrWMszWL3DbCmwJDk4yjcKFmK1Ir OJCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719241720; x=1719846520; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5yftIHZLp8eHXmdT76tLth9/O15e8LEzT136xzEFdkw=; b=dnP8d94VJcDEItlZg/TIc8cjc/nvaM5m3MnE06KrCKv7/xG31WgwvH4FURzr2aRtg4 pB41IaESxBoLs68E3/mFjiZuoKszu5cBxbprpiehn0YMRsNsSJBbsy1VBi2wj6DgV5eK fi71xNdku5Ymsi5nS1dSgvSo4paeFzUL/QviHfMvlyj/ApG/Sv1cHT/noNVbdaDQ+s3k VaqTHzyGvZqtgrgesnNfrhDQUs/mM4WNgbicePv1xktZ76pTI/tVH8aAdlKmospJ/nYb NNgG1EHjgB032gwlc2EcdQGZDm8huBQBXPHJatXrhBGB3nHy0TyRnS4qfVVzI6qtfnyL 4ihQ== X-Forwarded-Encrypted: i=1; AJvYcCV5/mJnlrtJFdfjKSOEfwh2vUwBnoGwWrDCRdBbQ1glbaFFuk2XSV68PaTWpTY80NBYkMrjCSDTpPkL5miLrT8PIjWKhD54Yesv X-Gm-Message-State: AOJu0Yxm5YEt1/IhFsgRrdRZidFzwMBSmAs20Aq4lDmEO22aDLRHANJH BRuLrXl109wjJyeUoWI/5Ecx+1i0+SgRXTy32QFrBNnKHTiYJwYt5eLk6JGq+ko= X-Google-Smtp-Source: AGHT+IELVkPKwVNxN4A8tjYiAj1+PNkuEIcPj1BT6h+vBIKPf78ibBEW/oj4NhDWMyCQQAB4BI1qfA== X-Received: by 2002:a05:6512:3e0a:b0:52c:8b03:99d6 with SMTP id 2adb3069b0e04-52cdf7e671cmr4534542e87.6.1719241719587; Mon, 24 Jun 2024 08:08:39 -0700 (PDT) Received: from umbar.lan ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-52cdbe1bcefsm840571e87.159.2024.06.24.08.08.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:08:39 -0700 (PDT) From: Dmitry Baryshkov Date: Mon, 24 Jun 2024 18:08:12 +0300 Subject: [PATCH v9 1/2] platform/arm64: build drivers even on non-ARM64 platforms Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240624-ucsi-yoga-ec-driver-v9-1-53af411a9bd6@linaro.org> References: <20240624-ucsi-yoga-ec-driver-v9-0-53af411a9bd6@linaro.org> In-Reply-To: <20240624-ucsi-yoga-ec-driver-v9-0-53af411a9bd6@linaro.org> To: Bjorn Andersson , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Bryan O'Donoghue , Heikki Krogerus , Greg Kroah-Hartman , Konrad Dybcio Cc: linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org, Nikita Travkin X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1049; i=dmitry.baryshkov@linaro.org; h=from:subject:message-id; bh=8tKzwExQBw5uGrVk6EJMh5rj1XlrJN3GYv6ujg5VdWo=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBmeYvdCXewCSCLSdXZcWMlvqcJCP+gz8j/wucKY S9JOcrMdKCJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCZnmL3QAKCRCLPIo+Aiko 1SdLB/0YqnLB7JfF1aiZDS5x+Xb1N0rQq37UM2WWrB83zLSI+OgOmiMTBVzi+jU8MRm6LXmrDNG Ld35FLuCVkZ2Mo6xirDXm54gJ2IF1a2YcjDVhHFEEfCoPV6P90XMnTlmABibiHowQB95UNDkbOQ G+kAfll8P/solgJg0IsU90kkJnX7ltAg0+T7uc5fyIOGeQqkWNnpfRoaG87v0JxWFIFmCQBGu+n 2WKIpVdFL3+7z6JOnjMng54qkQdo7IgjY4YRLkV9zN4hrFnIK4nmkt/JMFQMtNPjR19VuvnqXSd U1JE40KQzJUh1X7GpY41fQOjdjuIK9CXn2DzEJZH7aH2BFyi X-Developer-Key: i=dmitry.baryshkov@linaro.org; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A The Kconfig for platforms/arm64 has 'depends on ARM64 || COMPILE_TEST'. However due to Makefile having just obj-$(CONFIG_ARM64) the subdir will not be descended for !ARM64 platforms and thus the drivers won't get built. This breaks modular builds of other driver drivers which depend on arm64 platform drivers. Reported-by: Greg Kroah-Hartman Fixes: 363c8aea2572 ("platform: Add ARM64 platform directory") Signed-off-by: Dmitry Baryshkov --- drivers/platform/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index fbbe4f77aa5d..837202842a6f 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -11,4 +11,4 @@ obj-$(CONFIG_OLPC_EC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ -obj-$(CONFIG_ARM64) += arm64/ +obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/ From patchwork Mon Jun 24 15:08:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13709694 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26E2F19ADB3 for ; Mon, 24 Jun 2024 15:08:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719241725; cv=none; b=tyRk6KrGQN1S0GzuBGkLOr1jEf1NwfJ51viago+sY4mtc2xwmNbPT7yvlyB5FIHl3yhPwRjempWdBa8bqtbQfa43by0mUryBLTtzky9vJ4mDbzjQHdKheDZq1NUKNND+WkwMaw5l1UYzPAa061OhIOaXKZFGH0VYJIp4lrpUOJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719241725; c=relaxed/simple; bh=6OYh9GVmCFzlYYtPr1/rlWFN2LdtNayCv9r+cMa7gHA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rzoT0iYuTkb8QF5EHgMOmZTzg88fhSbJ9ikKVRw5Dm+0Gr3l7iMvR10ZTmxUeNUn1WZJLzPq1i8SyeKHadjV3DcbocstA3Cdg5h856hNOrgdAbxLqN/iqVgtKpxhOkAAiQgPG2SOGJ5crpPNjlQwHjllziQAiV3YRTTS2lVswh4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=OqYK+KWA; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="OqYK+KWA" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-52cc671f170so4704967e87.1 for ; Mon, 24 Jun 2024 08:08:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1719241720; x=1719846520; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=4fNkTYJPvQWZmgLjYfNjuf35JHpZNSgZEp1wXGwNUwU=; b=OqYK+KWAOXHOKr9k0qfN19HHR8t4/aTmSIDdJvVrQBYqZzFr622ZyE9hu9/VV5wgoL TkjeFTxmH4NAQNKIPnEUeeknA3Nft9fjTbYRK7h8kzlAeYlXgaL9lN4bDb7Q8WdgTIAz B81lAQzW9bcboIva3sgg1Vu5gZfmPM2KTCQLd3HDK3ywcrHPNriNk7fbP+H6r09vtio3 Kd9epPLHwAW1hAnFJO0q3cNg/8njlO9z78QWTY4lKxSeC/3T3u3+U3lcWW7+cfAI7FhJ MlBOObh5ZRG0QnJf5BjBf/NRjlkcvlhCBS8r9oBIGsulXiHI7WI4JXG+z5bnNwVC2JAR foDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719241720; x=1719846520; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4fNkTYJPvQWZmgLjYfNjuf35JHpZNSgZEp1wXGwNUwU=; b=JOkvvcqYEd1mYyB2RMA9lP9mCTSTF+9/ZzQcWQ39rH5FACVRTXHfTenoFiPb/LhOl7 CvQmGW2UWn++QVR3TDUNl00oh+lXKeUMgXPrHmId34hfqe44ffsMDVfe2JePYOd43jmk SlA37w5VM4ikXpOGdMDmO6hC+gWg3wWQ+/Npz6u21KlpYvCO8ljUa7TakgkS3l+nnx/B aHRwOgVP0fGWSiJKCInV9CzZumyfMGMBodZcNOM8tOYTsbJfwfOR2V+jHAF0GgkRIA3V CKewwQnN9/usYgGW4jpWtFN0wyBv2NNH8V9S3CHDleIcYKfoElmvr/tdBl+QnSB1fkuH WDGQ== X-Forwarded-Encrypted: i=1; AJvYcCVKuNzWOT2MfIhz1RgCKnFK442aBy83HtxM3zmW8KUGnTqzg5stZcZtsQuazLwk1ZDewKJZyypt1kDkaiqPJKSEZGWIT0OWfaaY X-Gm-Message-State: AOJu0YwENWniV3D02GwopWb6azHW6sO2LtRFRqAzaVre5MqXFPpeMy5W 3dLZkFBbl2U0dbGemASD7/AUn8QwqWspObzMaz5bcVXHuf8cQCp9dNZgmdUl6SQ= X-Google-Smtp-Source: AGHT+IGJJOO7DBibqLwx6Hc8BeWlnHSDRWgoKB3loXQyx2zDHel9Sd6tYg2Sfa480VSb8XhuJWknJg== X-Received: by 2002:a05:6512:2398:b0:52c:df4c:92d8 with SMTP id 2adb3069b0e04-52cdf4c93b3mr2306668e87.1.1719241720366; Mon, 24 Jun 2024 08:08:40 -0700 (PDT) Received: from umbar.lan ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-52cdbe1bcefsm840571e87.159.2024.06.24.08.08.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:08:40 -0700 (PDT) From: Dmitry Baryshkov Date: Mon, 24 Jun 2024 18:08:13 +0300 Subject: [PATCH v9 2/2] usb: typec: ucsi: add Lenovo Yoga C630 glue driver Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240624-ucsi-yoga-ec-driver-v9-2-53af411a9bd6@linaro.org> References: <20240624-ucsi-yoga-ec-driver-v9-0-53af411a9bd6@linaro.org> In-Reply-To: <20240624-ucsi-yoga-ec-driver-v9-0-53af411a9bd6@linaro.org> To: Bjorn Andersson , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Bryan O'Donoghue , Heikki Krogerus , Greg Kroah-Hartman , Konrad Dybcio Cc: linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org, Nikita Travkin X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7349; i=dmitry.baryshkov@linaro.org; h=from:subject:message-id; bh=6OYh9GVmCFzlYYtPr1/rlWFN2LdtNayCv9r+cMa7gHA=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBmeYvdhrwcwKivuj6eDm/PHIBmAdcmYYZD4QMUH a5KA5pWtSKJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCZnmL3QAKCRCLPIo+Aiko 1WVPB/4zVzvlBpnvJAp+CJkVqEfu6jHS41VDf/RmAalcN9mnGq/ANCXrNP2Gy3q+IIU9bw5tN1Z 4zBdimIovfPhlIa5w5UXyJM7GFoyGXvYLNyBcLXNziSSFoJeVjtNHZr+5YEZAHKXGGGZPnd5N6x 8ZoFUuyYa5x1ZC815FDAE6m6hWZu/wk9TfQkAeClbJqeyB2ZB+vOEy7MPeMwdSI/HFJvcH0M34S nsrKRaZ18/Vuk9Q+WqhudJRi99c2kvpyR4JGuWlpPw2g2ke0KwW6RBBdECjK3EEyHBMeYQc1mKZ TZbs1ZmZAWFcZzdxeMcxBizCA8dJJspDwQCBrgYwBMTvdjUi X-Developer-Key: i=dmitry.baryshkov@linaro.org; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A The Lenovo Yoga C630 WOS laptop provides implements UCSI interface in the onboard EC. Add glue driver to interface the platform's UCSI implementation. Reviewed-by: Bryan O'Donoghue Reviewed-by: Heikki Krogerus Reviewed-by: Ilpo Järvinen Signed-off-by: Dmitry Baryshkov --- drivers/usb/typec/ucsi/Kconfig | 9 ++ drivers/usb/typec/ucsi/Makefile | 1 + drivers/usb/typec/ucsi/ucsi_yoga_c630.c | 204 ++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig index bdcb1764cfae..680e1b87b152 100644 --- a/drivers/usb/typec/ucsi/Kconfig +++ b/drivers/usb/typec/ucsi/Kconfig @@ -69,4 +69,13 @@ config UCSI_PMIC_GLINK To compile the driver as a module, choose M here: the module will be called ucsi_glink. +config UCSI_LENOVO_YOGA_C630 + tristate "UCSI Interface Driver for Lenovo Yoga C630" + depends on EC_LENOVO_YOGA_C630 + help + This driver enables UCSI support on the Lenovo Yoga C630 laptop. + + To compile the driver as a module, choose M here: the module will be + called ucsi_yoga_c630. + endif diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index b4679f94696b..aed41d23887b 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o obj-$(CONFIG_UCSI_STM32G0) += ucsi_stm32g0.o obj-$(CONFIG_UCSI_PMIC_GLINK) += ucsi_glink.o +obj-$(CONFIG_UCSI_LENOVO_YOGA_C630) += ucsi_yoga_c630.o diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c new file mode 100644 index 000000000000..8bee0b469041 --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024, Linaro Ltd + * Authors: + * Bjorn Andersson + * Dmitry Baryshkov + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ucsi.h" + +struct yoga_c630_ucsi { + struct yoga_c630_ec *ec; + struct ucsi *ucsi; + struct notifier_block nb; + struct completion complete; + unsigned long flags; +#define UCSI_C630_COMMAND_PENDING 0 +#define UCSI_C630_ACK_PENDING 1 + u16 version; +}; + +static int yoga_c630_ucsi_read(struct ucsi *ucsi, unsigned int offset, + void *val, size_t val_len) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + u8 buf[YOGA_C630_UCSI_READ_SIZE]; + int ret; + + ret = yoga_c630_ec_ucsi_read(uec->ec, buf); + if (ret) + return ret; + + if (offset == UCSI_VERSION) { + memcpy(val, &uec->version, min(val_len, sizeof(uec->version))); + return 0; + } + + switch (offset) { + case UCSI_CCI: + memcpy(val, buf, min(val_len, YOGA_C630_UCSI_CCI_SIZE)); + return 0; + case UCSI_MESSAGE_IN: + memcpy(val, buf + YOGA_C630_UCSI_CCI_SIZE, + min(val_len, YOGA_C630_UCSI_DATA_SIZE)); + return 0; + default: + return -EINVAL; + } +} + +static int yoga_c630_ucsi_async_write(struct ucsi *ucsi, unsigned int offset, + const void *val, size_t val_len) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + + if (offset != UCSI_CONTROL || + val_len != YOGA_C630_UCSI_WRITE_SIZE) + return -EINVAL; + + return yoga_c630_ec_ucsi_write(uec->ec, val); +} + +static int yoga_c630_ucsi_sync_write(struct ucsi *ucsi, unsigned int offset, + const void *val, size_t val_len) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; + int ret; + + if (ack) + set_bit(UCSI_C630_ACK_PENDING, &uec->flags); + else + set_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); + + reinit_completion(&uec->complete); + + ret = yoga_c630_ucsi_async_write(ucsi, offset, val, val_len); + if (ret) + goto out_clear_bit; + + if (!wait_for_completion_timeout(&uec->complete, 5 * HZ)) + ret = -ETIMEDOUT; + +out_clear_bit: + if (ack) + clear_bit(UCSI_C630_ACK_PENDING, &uec->flags); + else + clear_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); + + return ret; +} + +const struct ucsi_operations yoga_c630_ucsi_ops = { + .read = yoga_c630_ucsi_read, + .sync_write = yoga_c630_ucsi_sync_write, + .async_write = yoga_c630_ucsi_async_write, +}; + +static void yoga_c630_ucsi_notify_ucsi(struct yoga_c630_ucsi *uec, u32 cci) +{ + if (UCSI_CCI_CONNECTOR(cci)) + ucsi_connector_change(uec->ucsi, UCSI_CCI_CONNECTOR(cci)); + + if (cci & UCSI_CCI_ACK_COMPLETE && + test_bit(UCSI_C630_ACK_PENDING, &uec->flags)) + complete(&uec->complete); + + if (cci & UCSI_CCI_COMMAND_COMPLETE && + test_bit(UCSI_C630_COMMAND_PENDING, &uec->flags)) + complete(&uec->complete); +} + +static int yoga_c630_ucsi_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct yoga_c630_ucsi *uec = container_of(nb, struct yoga_c630_ucsi, nb); + u32 cci; + int ret; + + switch (action) { + case LENOVO_EC_EVENT_USB: + case LENOVO_EC_EVENT_HPD: + ucsi_connector_change(uec->ucsi, 1); + return NOTIFY_OK; + + case LENOVO_EC_EVENT_UCSI: + ret = uec->ucsi->ops->read(uec->ucsi, UCSI_CCI, &cci, sizeof(cci)); + if (ret) + return NOTIFY_DONE; + + yoga_c630_ucsi_notify_ucsi(uec, cci); + + return NOTIFY_OK; + + default: + return NOTIFY_DONE; + } +} + +static int yoga_c630_ucsi_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct yoga_c630_ec *ec = adev->dev.platform_data; + struct yoga_c630_ucsi *uec; + int ret; + + uec = devm_kzalloc(&adev->dev, sizeof(*uec), GFP_KERNEL); + if (!uec) + return -ENOMEM; + + uec->ec = ec; + init_completion(&uec->complete); + uec->nb.notifier_call = yoga_c630_ucsi_notify; + + uec->ucsi = ucsi_create(&adev->dev, &yoga_c630_ucsi_ops); + if (IS_ERR(uec->ucsi)) + return PTR_ERR(uec->ucsi); + + ucsi_set_drvdata(uec->ucsi, uec); + + uec->version = yoga_c630_ec_ucsi_get_version(uec->ec); + + auxiliary_set_drvdata(adev, uec); + + ret = yoga_c630_ec_register_notify(ec, &uec->nb); + if (ret) + return ret; + + return ucsi_register(uec->ucsi); +} + +static void yoga_c630_ucsi_remove(struct auxiliary_device *adev) +{ + struct yoga_c630_ucsi *uec = auxiliary_get_drvdata(adev); + + yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); + ucsi_unregister(uec->ucsi); +} + +static const struct auxiliary_device_id yoga_c630_ucsi_id_table[] = { + { .name = YOGA_C630_MOD_NAME "." YOGA_C630_DEV_UCSI, }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, yoga_c630_ucsi_id_table); + +static struct auxiliary_driver yoga_c630_ucsi_driver = { + .name = YOGA_C630_DEV_UCSI, + .id_table = yoga_c630_ucsi_id_table, + .probe = yoga_c630_ucsi_probe, + .remove = yoga_c630_ucsi_remove, +}; + +module_auxiliary_driver(yoga_c630_ucsi_driver); + +MODULE_DESCRIPTION("Lenovo Yoga C630 UCSI"); +MODULE_LICENSE("GPL");