Received: by 10.213.65.68 with SMTP id h4csp163624imn; Mon, 19 Mar 2018 23:37:22 -0700 (PDT) X-Google-Smtp-Source: AG47ELsuAvoVywdEL/EG5h/sWhxS6QyOjd/hEPQVZDpH2ikdTP/XvKrGAGLAXVoOD2emN2YJigbv X-Received: by 10.98.20.143 with SMTP id 137mr1064802pfu.78.1521527842625; Mon, 19 Mar 2018 23:37:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521527842; cv=none; d=google.com; s=arc-20160816; b=XfISwjogXnJrj+LRwlU392kLzA4+1pv1GsmmhgNmSFllwDi4vcNjwlpkbWeLXmEMX1 Ts9vG8fIGYybp3c7f2EIVefWo7mBxrX8KMJp6J9H1ywddKQ50c4IYAincfUYPtSnLN+6 4llyDhAbKbA29KGkEbkYs7jJaz0/AQIJHGSAtgnFFIMW5QxhJFfww7habhUiOIF24rJu pabmNo8VGXWWKyKyWej4yZK/edfdz5m4+L1WA43Ux6USU8vEIv2oLXtLYJWba/MzTmnP k6rohSZIIlCVVeU/ZWd6O/TDTWKA2kRSqBB8HuoyvS3TyRy19m7iKr7eJvWhdQpKc3Hc /WbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature:dkim-signature :arc-authentication-results; bh=SujSvET5iBUOFpoEmWsw0kELDaTbkytBZqsxkL+L1l4=; b=sJmLtKBYkG5NzYV8XuYvDKlpsz3znT/UC4XSl+EjFoqWKW5iia4t+rZE5ixvW4kA68 7WLCn3JISiI1t/OQzbA2e8ChxWJUBVlLWZq/0dvOmOTwKJ4y1gqm1zbfsJVjsNp7cXSL TQhZfibwH1wqSFjV9M7H+FZQ/rKXfVMkfYqG9Z61G/nYgyIX4GnqCVgI8bCPODbnaWJk cjf3w5s/UWZ2gAWrCtHTsgoWRD+VOlK35uRuixYWp1Cge3AmP5Wq9F8ypbfZclS4I+Vf pYu2ucPswIORuRFW6+OddnVrkcZqqbOeA11KdEZ5jtmGSuwmJUiaX+MfCNDfmmlErY32 KpGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=Tb1H4lVr; dkim=fail header.i=@jms.id.au header.s=google header.b=FT0I4v8b; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h11-v6si962813plk.720.2018.03.19.23.37.08; Mon, 19 Mar 2018 23:37:22 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=Tb1H4lVr; dkim=fail header.i=@jms.id.au header.s=google header.b=FT0I4v8b; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752242AbeCTGfp (ORCPT + 99 others); Tue, 20 Mar 2018 02:35:45 -0400 Received: from mail-qt0-f195.google.com ([209.85.216.195]:43378 "EHLO mail-qt0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751778AbeCTGfS (ORCPT ); Tue, 20 Mar 2018 02:35:18 -0400 Received: by mail-qt0-f195.google.com with SMTP id s48so485219qtb.10; Mon, 19 Mar 2018 23:35:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=SujSvET5iBUOFpoEmWsw0kELDaTbkytBZqsxkL+L1l4=; b=Tb1H4lVr2gSBrL9zxPVMmzGkMg2BTtmmYWVfaJenvnIwmMxxY0FpNrkHCILPuA09X8 0L637tYNvRsRjcGZ3rTJZnsnOIe2iV/DLwaiiTkDsAjSxfo0TZdoxB2eDsCsdxlYgMdT hj0wZ6QMI+FCi3k9un9izl8G6rTBKKTamPv+WGxr1l4exsdirUw0kDnTHUrdIIrKNV3e BfOWyQ1OsikZS5x+JkEeXZPZTIHQ36Md07ufbYRHR1AEwbXzT7kQDNqItITZzZHpmKNc bBzkH0K13OJmsSkrkYFPUVXCukPwNIKRJwcNi+fybjO+1a2Iug9UKy4Y98nvGlo/N1ac HXFA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jms.id.au; s=google; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=SujSvET5iBUOFpoEmWsw0kELDaTbkytBZqsxkL+L1l4=; b=FT0I4v8bhtpXF7fqiHGD0r4YbkMErEReeUDST0rNDDmctQSGt18BCGX0TCt4T60ghI pJrIHoFNHDMQZgGLXP6CQzKqU18z9Lssg4VzB1Y2wYjQcx4A24GjPDP2cdepQdiRWqFK GCesqI8RiJf5KDLjsz26olkplN7nK8XJ4/EqU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc; bh=SujSvET5iBUOFpoEmWsw0kELDaTbkytBZqsxkL+L1l4=; b=hcj1u0d/E7EbFIE5HkSovRWb6k5imgBBBYvfKRBMtKEwiAKDZLe8INEx+P5B9ntuMG YN1RVOlkM6RwAOwonkmp+KLLB3gF5daYA8fQDAI96bATU69t3b2qQKyR3Pf74R+kLliq Va9hRp3xKfk3qd71OLSnXaat3XgkOHibxmuKut/LgfevZ2uumYxG9wlUo52gOuhngipi kHeDPTCB7OlfWhL9r3X45qDBoed3cN1vMLdjpjE+ZCuUBmS5CnUxbbv773PRCrzqN0hs wGe6gquzFlUxzXi/2zWPprZeDZhLVKN9ZJNBUVEgjfzl33pwBqDTPDbMmq9a1Ob3m2+Q WgsA== X-Gm-Message-State: AElRT7HmsPJsq2y0SvSclBItWcE7TWs96DOi7Bp5ZOEMLMFQ5e5sVlyD I7PIOpdA4IaZUWBMczUaPAT3Cf0Q03yXbx+MeomuXXY3 X-Received: by 10.237.36.74 with SMTP id s10mr22318792qtc.23.1521527717275; Mon, 19 Mar 2018 23:35:17 -0700 (PDT) MIME-Version: 1.0 Received: by 10.200.63.197 with HTTP; Mon, 19 Mar 2018 23:34:56 -0700 (PDT) In-Reply-To: <20180320061909.5775-1-chen.kenyy@inventec.com> References: <20180320061909.5775-1-chen.kenyy@inventec.com> From: Joel Stanley Date: Tue, 20 Mar 2018 17:04:56 +1030 X-Google-Sender-Auth: Ud7uLPEOz9-FoYJqGwFpviZmc4k Message-ID: Subject: Re: [PATCH linux dev-4.16 v2] i2c: muxes: pca9641: new driver To: Ken Chen Cc: Guenter Roeck , Wolfram Sang , Peter Rosin , linux-i2c@vger.kernel.org, Linux Kernel Mailing List Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Ken, A note on your subject line: we use the "linux dev-4.16" style tags in OpenBMC to indicate which branch you're targetting, but in upstream Linux we always target the next release, so you don't need to use --subject-prefix at all. On Tue, Mar 20, 2018 at 4:49 PM, Ken Chen wrote: > Signed-off-by: Ken Chen Try to add some words to the commit message describing why you're making the change. I'll leave it to Peter and Guneter to review the implementation. Cheers, Joel > > --- > v1->v2 > - Merged PCA9641 code into i2c-mux-pca9541.c > - Modified title > - Add PCA9641 detect function > --- > drivers/i2c/muxes/i2c-mux-pca9541.c | 184 ++++++++++++++++++++++++++++++++++-- > 1 file changed, 174 insertions(+), 10 deletions(-) > > diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c > index 6a39ada..493f947 100644 > --- a/drivers/i2c/muxes/i2c-mux-pca9541.c > +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c > @@ -1,5 +1,5 @@ > /* > - * I2C multiplexer driver for PCA9541 bus master selector > + * I2C multiplexer driver for PCA9541/PCA9641 bus master selector > * > * Copyright (c) 2010 Ericsson AB. > * > @@ -26,8 +26,8 @@ > #include > > /* > - * The PCA9541 is a bus master selector. It supports two I2C masters connected > - * to a single slave bus. > + * The PCA9541/PCA9641 is a bus master selector. It supports two I2C masters > + * connected to a single slave bus. > * > * Before each bus transaction, a master has to acquire bus ownership. After the > * transaction is complete, bus ownership has to be released. This fits well > @@ -58,11 +58,43 @@ > #define PCA9541_ISTAT_MYTEST (1 << 6) > #define PCA9541_ISTAT_NMYTEST (1 << 7) > > +#define PCA9641_ID 0x00 > +#define PCA9641_ID_MAGIC 0x38 > + > +#define PCA9641_CONTROL 0x01 > +#define PCA9641_STATUS 0x02 > +#define PCA9641_TIME 0x03 > + > +#define PCA9641_CTL_LOCK_REQ BIT(0) > +#define PCA9641_CTL_LOCK_GRANT BIT(1) > +#define PCA9641_CTL_BUS_CONNECT BIT(2) > +#define PCA9641_CTL_BUS_INIT BIT(3) > +#define PCA9641_CTL_SMBUS_SWRST BIT(4) > +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) > +#define PCA9641_CTL_SMBUS_DIS BIT(6) > +#define PCA9641_CTL_PRIORITY BIT(7) > + > +#define PCA9641_STS_OTHER_LOCK BIT(0) > +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) > +#define PCA9641_STS_BUS_HUNG BIT(2) > +#define PCA9641_STS_MBOX_EMPTY BIT(3) > +#define PCA9641_STS_MBOX_FULL BIT(4) > +#define PCA9641_STS_TEST_INT BIT(5) > +#define PCA9641_STS_SCL_IO BIT(6) > +#define PCA9641_STS_SDA_IO BIT(7) > + > +#define PCA9641_RES_TIME 0x03 > + > #define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) > #define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) > #define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) > #define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) > > +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ > + !((y) & PCA9641_STS_OTHER_LOCK)) > +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) > +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) > + > /* arbitration timeouts, in jiffies */ > #define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ > #define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ > @@ -79,6 +111,7 @@ struct pca9541 { > > static const struct i2c_device_id pca9541_id[] = { > {"pca9541", 0}, > + {"pca9641", 1}, > {} > }; > > @@ -87,6 +120,7 @@ MODULE_DEVICE_TABLE(i2c, pca9541_id); > #ifdef CONFIG_OF > static const struct of_device_id pca9541_of_match[] = { > { .compatible = "nxp,pca9541" }, > + { .compatible = "nxp,pca9641" }, > {} > }; > MODULE_DEVICE_TABLE(of, pca9541_of_match); > @@ -328,6 +362,125 @@ static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) > } > > /* > + * Arbitration management functions > + */ > +static void pca9641_release_bus(struct i2c_client *client) > +{ > + pca9541_reg_write(client, PCA9641_CONTROL, 0); > +} > + > +/* > + * Channel arbitration > + * > + * Return values: > + * <0: error > + * 0 : bus not acquired > + * 1 : bus acquired > + */ > +static int pca9641_arbitrate(struct i2c_client *client) > +{ > + struct i2c_mux_core *muxc = i2c_get_clientdata(client); > + struct pca9541 *data = i2c_mux_priv(muxc); > + int reg_ctl, reg_sts; > + > + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); > + if (reg_ctl < 0) > + return reg_ctl; > + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); > + > + if (BUSOFF(reg_ctl, reg_sts)) { > + /* > + * Bus is off. Request ownership or turn it on unless > + * other master requested ownership. > + */ > + reg_ctl |= PCA9641_CTL_LOCK_REQ; > + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); > + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); > + > + if (lock_grant(reg_ctl)) { > + /* > + * Other master did not request ownership, > + * or arbitration timeout expired. Take the bus. > + */ > + reg_ctl |= PCA9641_CTL_BUS_CONNECT > + | PCA9641_CTL_LOCK_REQ; > + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); > + data->select_timeout = SELECT_DELAY_SHORT; > + > + return 1; > + } else { > + /* > + * Other master requested ownership. > + * Set extra long timeout to give it time to acquire it. > + */ > + data->select_timeout = SELECT_DELAY_LONG * 2; > + } > + } else if (lock_grant(reg_ctl)) { > + /* > + * Bus is on, and we own it. We are done with acquisition. > + */ > + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; > + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); > + > + return 1; > + } else if (other_lock(reg_sts)) { > + /* > + * Other master owns the bus. > + * If arbitration timeout has expired, force ownership. > + * Otherwise request it. > + */ > + data->select_timeout = SELECT_DELAY_LONG; > + reg_ctl |= PCA9641_CTL_LOCK_REQ; > + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); > + } > + return 0; > +} > + > +static int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) > +{ > + struct pca9541 *data = i2c_mux_priv(muxc); > + struct i2c_client *client = data->client; > + int ret; > + unsigned long timeout = jiffies + ARB2_TIMEOUT; > + /* give up after this time */ > + > + data->arb_timeout = jiffies + ARB_TIMEOUT; > + /* force bus ownership after this time */ > + > + do { > + ret = pca9641_arbitrate(client); > + if (ret) > + return ret < 0 ? ret : 0; > + > + if (data->select_timeout == SELECT_DELAY_SHORT) > + udelay(data->select_timeout); > + else > + msleep(data->select_timeout / 1000); > + } while (time_is_after_eq_jiffies(timeout)); > + > + return -ETIMEDOUT; > +} > + > +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) > +{ > + struct pca9541 *data = i2c_mux_priv(muxc); > + struct i2c_client *client = data->client; > + > + pca9641_release_bus(client); > + return 0; > +} > + > +static int pca9641_detect_id(struct i2c_client *client) > +{ > + int reg; > + > + reg = pca9541_reg_read(client, PCA9641_ID); > + if (reg == PCA9641_ID_MAGIC) > + return 1; > + else > + return 0; > +} > +/* > * I2C init/probing/exit functions > */ > static int pca9541_probe(struct i2c_client *client, > @@ -339,34 +492,45 @@ static int pca9541_probe(struct i2c_client *client, > struct pca9541 *data; > int force; > int ret; > + int detect_id; > > if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) > return -ENODEV; > > + detect_id = pca9641_detect_id(client); > /* > * I2C accesses are unprotected here. > * We have to lock the adapter before releasing the bus. > */ > - i2c_lock_adapter(adap); > - pca9541_release_bus(client); > - i2c_unlock_adapter(adap); > - > + if (detect_id == 0) { > + i2c_lock_adapter(adap); > + pca9541_release_bus(client); > + i2c_unlock_adapter(adap); > + } else { > + i2c_lock_adapter(adap); > + pca9641_release_bus(client); > + i2c_unlock_adapter(adap); > + } > /* Create mux adapter */ > > force = 0; > if (pdata) > force = pdata->modes[0].adap_id; > - muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), > + if (detect_id == 0) { > + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), > I2C_MUX_ARBITRATOR, > pca9541_select_chan, pca9541_release_chan); > + } else { > + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), > + I2C_MUX_ARBITRATOR, > + pca9641_select_chan, pca9641_release_chan); > + } > if (!muxc) > return -ENOMEM; > > data = i2c_mux_priv(muxc); > data->client = client; > - > i2c_set_clientdata(client, muxc); > - You can leave the whitespace as it is here. > ret = i2c_mux_add_adapter(muxc, force, 0, 0); > if (ret) > return ret; > -- > 2.9.3 >