From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Edward Blair <edward.blair@gmail.com>
Cc: linux-acpi@vger.kernel.org, linux-usb@vger.kernel.org,
rafael@kernel.org, lenb@kernel.org,
mika.westerberg@linux.intel.com, gregkh@linuxfoundation.org,
W_Armin@gmx.de, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 2/2] usb: typec: ucsi: add ITE885x I2C transport driver
Date: Mon, 7 Sep 2026 14:05:26 +0200 [thread overview]
Message-ID: <ap6ohv5oM4Ze9dzz@black.igk.intel.com> (raw)
In-Reply-To: <CAJDQNgjq-oxQkdYK+fTSd5AHMjM-qTcSPo+s2-+W=Pcn7jYr-g@mail.gmail.com>
On Tue, Sep 01, 2026 at 01:03:50PM +0100, Edward Blair wrote:
> Thanks,
>
> I will add the explicit includes and use guard(mutex) for event_lock.
>
> I kept the explicit IRQ handling because ucsi_resume() queues work which
> issues UCSI commands. If the callbacks are moved to the noirq phase,
> that work can run before the parent I2C controller's resume_early or
> resume callback, while the controller may still be unavailable.
Okay, got it.
> The current ordering disables the device IRQ before quiescing UCSI, then
> re-enables it during normal resumption after the I2C bus has resumed. Does
> that address your concern, or would it be preferable the IRQ and UCSI
> handling to be split across separate PM phases?
I'm sure it's fine as it is now.
Thanks,
> Thanks,
> Edward
>
> On Tue, 1 Sept 2026 at 11:57, Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> >
> > On Sat, Aug 29, 2026 at 03:55:16PM +0100, Edward Blair wrote:
> > > Add a UCSI transport driver for ITE8853 and ITE8800 through ITE8805
> > > USB Type-C controllers found on desktop motherboards.
> > >
> > > These controllers expose CCI, MESSAGE_IN and CONTROL at ITE-specific I2C
> > > offsets and signal UCSI and vendor events through a shared interrupt
> > > status register. Read and cache each complete UCSI event before
> > > acknowledging it so command data remains coherent between the interrupt
> > > handler and UCSI core.
> > >
> > > The interface does not expose a VERSION register and does not accept
> > > PPM_RESET over I2C. Report UCSI 1.0, limit MESSAGE_IN to its 16-byte
> > > window and handle PPM_RESET locally, matching the vendor driver's
> > > behavior.
> > >
> > > Signed-off-by: Edward Blair <edward.blair@gmail.com>
> > > ---
> > > drivers/usb/typec/ucsi/Kconfig | 11 +
> > > drivers/usb/typec/ucsi/Makefile | 1 +
> > > drivers/usb/typec/ucsi/ucsi_ite.c | 395 ++++++++++++++++++++++++++++++
> > > 3 files changed, 407 insertions(+)
> > > create mode 100644 drivers/usb/typec/ucsi/ucsi_ite.c
> > >
> > > diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
> > > index 87dd992a4..3819c4f73 100644
> > > --- a/drivers/usb/typec/ucsi/Kconfig
> > > +++ b/drivers/usb/typec/ucsi/Kconfig
> > > @@ -104,4 +104,15 @@ config UCSI_HUAWEI_GAOKUN
> > > To compile the driver as a module, choose M here: the module will be
> > > called ucsi_huawei_gaokun.
> > >
> > > +config UCSI_ITE
> > > + tristate "UCSI Interface Driver for ITE885x"
> > > + depends on ACPI && I2C
> > > + help
> > > + This driver enables UCSI support on platforms that expose an ITE8853
> > > + or ITE8800-ITE8805 USB Type-C controller over I2C, commonly found
> > > + on ASUS Z690/Z790/X670E motherboards.
> > > +
> > > + To compile the driver as a module, choose M here: the module will be
> > > + called ucsi_ite.
> > > +
> > > endif
> > > diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
> > > index c7e38bf01..9bc1d6bbb 100644
> > > --- a/drivers/usb/typec/ucsi/Makefile
> > > +++ b/drivers/usb/typec/ucsi/Makefile
> > > @@ -28,3 +28,4 @@ obj-$(CONFIG_UCSI_PMIC_GLINK) += ucsi_glink.o
> > > obj-$(CONFIG_CROS_EC_UCSI) += cros_ec_ucsi.o
> > > obj-$(CONFIG_UCSI_LENOVO_YOGA_C630) += ucsi_yoga_c630.o
> > > obj-$(CONFIG_UCSI_HUAWEI_GAOKUN) += ucsi_huawei_gaokun.o
> > > +obj-$(CONFIG_UCSI_ITE) += ucsi_ite.o
> > > diff --git a/drivers/usb/typec/ucsi/ucsi_ite.c b/drivers/usb/typec/ucsi/ucsi_ite.c
> > > new file mode 100644
> > > index 000000000..16b22c77f
> > > --- /dev/null
> > > +++ b/drivers/usb/typec/ucsi/ucsi_ite.c
> > > @@ -0,0 +1,395 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * UCSI I2C transport driver for ITE885x USB-C controllers
> > > + *
> > > + * ITE8853/ITE8800-ITE8805 are UCSI-compliant USB-C controllers found on
> > > + * desktop motherboards. They communicate over I2C using UCSI registers at
> > > + * ITE-specific offsets and signal events through a vendor interrupt register.
> > > + */
> > > +
> > > +#include <linux/acpi.h>
> > > +#include <linux/i2c.h>
> > > +#include <linux/interrupt.h>
> > > +#include <linux/module.h>
> > > +#include <linux/mutex.h>
> >
> > We need to include everything instead of relying on nested headers
> > nowadays.
> >
> > linux/device.h
> > linux/device/devres.h
> > linux/dev_printk.h
> > linux/pm.h
> > linux/string.h
> >
> > > +static int ucsi_ite_process_event(struct ucsi_ite *ite, u32 *cci)
> > > +{
> > > + u8 message_in[ITE_MESSAGE_IN_MAX_LEN] = {};
> > > + __le32 raw_cci;
> > > + u8 status;
> > > + u8 len = 0;
> > > + int event;
> > > + int err = 0;
> > > + int ret;
> > > +
> > > + mutex_lock(&ite->event_lock);
> >
> > guard(mutex)(@ite->event_lock);
> >
> > > + ret = ucsi_ite_read(ite, ITE_REG_INT_STATUS, &status, sizeof(status));
> > > + if (ret)
> > > + goto out_unlock;
> > > +
> > > + status &= ITE_INT_MASK;
> > > + if (!status) {
> > > + mutex_lock(&ite->received_lock);
> > > + *cci = ite->cci;
> > > + mutex_unlock(&ite->received_lock);
> > > + ret = ITE_EVENT_NONE;
> > > + goto out_unlock;
> > > + }
> > > +
> > > + if (status & ITE_INT_CCI) {
> > > + err = ucsi_ite_read(ite, ITE_REG_CCI, &raw_cci,
> > > + sizeof(raw_cci));
> > > + if (!err) {
> > > + *cci = le32_to_cpu(raw_cci);
> > > + len = UCSI_CCI_LENGTH(*cci);
> > > +
> > > + if (len > sizeof(message_in)) {
> > > + len = sizeof(message_in);
> > > + *cci &= ~GENMASK(15, 8);
> > > + *cci |= UCSI_SET_CCI_LENGTH(len);
> > > + }
> > > + if (len) {
> > > + err = ucsi_ite_read(ite, ITE_REG_MESSAGE_IN,
> > > + message_in, len);
> > > + }
> > > + }
> > > + }
> > > +
> > > + /* Acknowledge each latched event with the value expected by the PPM. */
> > > + if (status & ITE_INT_VENDOR_ALERT) {
> > > + u8 ack = ITE_INT_VENDOR_ALERT;
> > > +
> > > + ret = ucsi_ite_write(ite, ITE_REG_INT_ACK, &ack, sizeof(ack));
> > > + if (ret)
> > > + goto out_unlock;
> > > + }
> > > +
> > > + if ((status & ITE_INT_CCI) && !err) {
> > > + u8 ack = ITE_INT_CCI;
> > > +
> > > + ret = ucsi_ite_write(ite, ITE_REG_INT_ACK, &ack, sizeof(ack));
> > > + if (ret)
> > > + goto out_unlock;
> > > + }
> > > +
> > > + if (err) {
> > > + ret = err;
> > > + goto out_unlock;
> > > + }
> > > +
> > > + if (status & ITE_INT_CCI) {
> > > + mutex_lock(&ite->received_lock);
> > > + ite->cci = *cci;
> > > + memset(ite->message_in, 0, sizeof(ite->message_in));
> > > + memcpy(ite->message_in, message_in, len);
> > > + mutex_unlock(&ite->received_lock);
> > > + event = ITE_EVENT_CCI;
> > > + } else {
> > > + mutex_lock(&ite->received_lock);
> > > + *cci = ite->cci;
> > > + mutex_unlock(&ite->received_lock);
> > > + event = ITE_EVENT_VENDOR;
> > > + }
> > > +
> > > + ret = event;
> > > +
> > > +out_unlock:
> > > + mutex_unlock(&ite->event_lock);
> > > + return ret;
> > > +}
> >
> > > +static int ucsi_ite_suspend(struct device *dev)
> > > +{
> > > + struct ucsi_ite *ite = dev_get_drvdata(dev);
> > > + int ret;
> > > +
> > > + disable_irq(ite->client->irq);
> > > + ret = ucsi_suspend(ite->ucsi);
> > > + if (ret)
> > > + enable_irq(ite->client->irq);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static int ucsi_ite_resume(struct device *dev)
> > > +{
> > > + struct ucsi_ite *ite = dev_get_drvdata(dev);
> > > +
> > > + enable_irq(ite->client->irq);
> > > + return ucsi_resume(ite->ucsi);
> > > +}
> > > +
> > > +static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_ite_pm, ucsi_ite_suspend,
> > > + ucsi_ite_resume);
> >
> > Is the enable/disable_irq really necessary - couldn't you just use
> > NOIRQ version of the PM operations (DEFINE_NOIRQ_DEV_PM_OPS)?
> >
> > Thanks,
> >
> > --
> > heikki
--
heikki
prev parent reply other threads:[~2026-09-07 12:05 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-29 14:55 [PATCH v3 0/2] Add ITE885x UCSI I2C transport driver Edward Blair
2026-08-29 14:55 ` [PATCH v3 1/2] ACPI: scan: do not enumerate MSFT8000 as a serial bus slave Edward Blair
2026-08-29 21:00 ` Armin Wolf
2026-09-04 13:46 ` Rafael J. Wysocki (Intel)
2026-08-29 14:55 ` [PATCH v3 2/2] usb: typec: ucsi: add ITE885x I2C transport driver Edward Blair
2026-09-01 10:57 ` Heikki Krogerus
2026-09-01 12:03 ` Edward Blair
2026-09-07 12:05 ` Heikki Krogerus [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ap6ohv5oM4Ze9dzz@black.igk.intel.com \
--to=heikki.krogerus@linux.intel.com \
--cc=W_Armin@gmx.de \
--cc=edward.blair@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mika.westerberg@linux.intel.com \
--cc=rafael@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.