From patchwork Wed Mar 6 23:15:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Rosin X-Patchwork-Id: 1052563 X-Patchwork-Delegate: patchwork@peda.user.lysator.liu.se Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=axentia.se Authentication-Results: ozlabs.org; dkim=fail reason="key not found in DNS" (0-bit key; unprotected) header.d=axentia.se header.i=@axentia.se header.b="Z6WIb6Kk"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F8lf60jlz9sCJ for ; Thu, 7 Mar 2019 10:16:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726094AbfCFXQY (ORCPT ); Wed, 6 Mar 2019 18:16:24 -0500 Received: from mail-eopbgr80112.outbound.protection.outlook.com ([40.107.8.112]:32096 "EHLO EUR04-VI1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726342AbfCFXQX (ORCPT ); Wed, 6 Mar 2019 18:16:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axentia.se; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=EkezuVihIiF/SGNm0FgndOUpv8T1hma6KrgXxfNDKJY=; b=Z6WIb6Kk36I6V5qeA7TZjbP8bA0ZzrH7vukDUzka/MHmAuyJ5Ul1+XpWsZPrTS6DhA5Sd/31CSM4Xt9El6bvLylLHPlZ2oQtiL9dVv8xTamuSqCPoUa2ZbEA3vqr9S/1zH0fe732zJtOWy2x/iJUHRjvkjmEkCyYLaYlG9MzMx0= Received: from VI1PR02MB4542.eurprd02.prod.outlook.com (20.178.12.74) by VI1PR02MB4592.eurprd02.prod.outlook.com (20.178.12.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1665.19; Wed, 6 Mar 2019 23:15:56 +0000 Received: from VI1PR02MB4542.eurprd02.prod.outlook.com ([fe80::38db:37eb:b43e:e4c1]) by VI1PR02MB4542.eurprd02.prod.outlook.com ([fe80::38db:37eb:b43e:e4c1%6]) with mapi id 15.20.1665.020; Wed, 6 Mar 2019 23:15:56 +0000 From: Peter Rosin To: "linux-kernel@vger.kernel.org" CC: Peter Rosin , Rob Herring , Mark Rutland , Guenter Roeck , "linux-i2c@vger.kernel.org" , "devicetree@vger.kernel.org" , Ken Chen , Pradeep Srinivasan Subject: [PATCH v2 5/5] i2c: mux: pca9541: add support for PCA9641 Thread-Topic: [PATCH v2 5/5] i2c: mux: pca9541: add support for PCA9641 Thread-Index: AQHU1HKNjSK6x+/IzUatPrdqzggr/g== Date: Wed, 6 Mar 2019 23:15:56 +0000 Message-ID: <20190306231521.29367-6-peda@axentia.se> References: <20190306231521.29367-1-peda@axentia.se> In-Reply-To: <20190306231521.29367-1-peda@axentia.se> Accept-Language: en-US, sv-SE Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.11.0 x-originating-ip: [85.226.244.23] x-clientproxiedby: HE1PR1001CA0016.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:3:f7::26) To VI1PR02MB4542.eurprd02.prod.outlook.com (2603:10a6:803:b1::10) authentication-results: spf=none (sender IP is ) smtp.mailfrom=peda@axentia.se; x-ms-exchange-messagesentrepresentingtype: 1 x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 56759a6e-cab9-4598-af7b-08d6a289af8c x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(7021145)(8989299)(4534185)(7022145)(4603075)(4627221)(201702281549075)(8990200)(7048125)(7024125)(7027125)(7023125)(5600127)(711020)(4605104)(2017052603328)(7153060)(7193020); SRVR:VI1PR02MB4592; x-ms-traffictypediagnostic: VI1PR02MB4592: x-microsoft-antispam-prvs: x-forefront-prvs: 0968D37274 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(376002)(396003)(366004)(346002)(136003)(39840400004)(189003)(199004)(5640700003)(53936002)(6486002)(71200400001)(6436002)(2501003)(71190400001)(99286004)(4326008)(6916009)(476003)(102836004)(76176011)(256004)(446003)(486006)(52116002)(3846002)(86362001)(386003)(74482002)(6506007)(6512007)(26005)(6116002)(97736004)(66066001)(305945005)(7736002)(2351001)(186003)(2616005)(14444005)(11346002)(25786009)(106356001)(36756003)(8936002)(8676002)(68736007)(81156014)(81166006)(5660300002)(508600001)(2906002)(54906003)(1076003)(50226002)(316002)(14454004)(105586002)(13158425004); DIR:OUT; SFP:1102; SCL:1; SRVR:VI1PR02MB4592; H:VI1PR02MB4542.eurprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: axentia.se does not designate permitted sender hosts) x-microsoft-exchange-diagnostics: =?iso-8859-1?q?1=3BVI1PR02MB4592=3B23?= =?iso-8859-1?q?=3AbHOiRmPX8rE7fkuHVGAnr9cwtTYvRywPgJ7WR0Y+0aDezxTb?= =?iso-8859-1?q?AgbQjXBL0wMQCgaX3oHVEDzJ8AmaXbF+TA01p8LoucijVqUw4Lv?= =?iso-8859-1?q?SCk3RAUaP4cQ2bthaHH5kcV9fZLR5WYGEZ8yQBIxMrh4U34TiDt?= =?iso-8859-1?q?o4jsig3tcfLqvdtI0B1MxsweT6JnvTs19lJ/FHv5JCxdrs/efA6?= =?iso-8859-1?q?s9Vb/YSbBb/2XvOhUDawzFNkFyn1oHBfvl0QP1fFoQ4YdOvyPbG?= =?iso-8859-1?q?nnbqnWTE+uccC60qKDr6XY/OKAiUGmIlcMubBTAl6H52siaxoR8?= =?iso-8859-1?q?FiOgc3o3ztIb4oAdW+SnNbSQmX2zegIA2a9f+AMKGtVj00p0+bZ?= =?iso-8859-1?q?4kYLknGcH+SdwFOqGRH9sw54cf7C1wGYJxwP+kcpYiUzsMnMDNP?= =?iso-8859-1?q?a5OuD+nThk0xbkGg/bGWlqtDZSlFtSOzNGehzoCsUIRV/IzYWyW?= =?iso-8859-1?q?DbRplEkZpRpwqL15KFlRm8Ifd5wa20eeqJTzOElykxp0uxym1Mw?= =?iso-8859-1?q?2kRN+xfrFD7Pjm+GIaALQmWv970ft5fMslO15B6HDvDSZfCrQ7+?= =?iso-8859-1?q?hZVZY2Wl7qb1RMLj9t37VyMLsNWMxHKK42z6MiOqiuXzoqzrIhi?= =?iso-8859-1?q?gYyO5EkpkGfFZu38FLrE3t609rRMvArJ8/PTXEdiLL/m9GbpnvV?= =?iso-8859-1?q?NVg9RCac4NRESaVSRdxxA8DD5gSIbjtNMKPPmILts2vrGe3c1wJ?= =?iso-8859-1?q?Dn1Yk0z3WU861ZX2jvEGa2wyEBuZ7zYgMgywsCmzU0wGNHQ5CB3?= =?iso-8859-1?q?DPjZeJcPK04olhNXQH3Ngg5JzMBZVrS+lEtd7wNk/9fV8lGSUdx?= =?iso-8859-1?q?PsK3LwbIpt+k4CU2X6k36Qf7uMPtFRBXPUaBs9eEyAio+zzwrUq?= =?iso-8859-1?q?PqKkwAU4ioBKVE2olPyiuhqMqoGMDur4eh5QBZXO4ciKlsUOsis?= =?iso-8859-1?q?4jJQziPBraJJVc25bW4v9DABG8sjyAsD+Sh4AKrsTCPlOBdpv50?= =?iso-8859-1?q?/SKUsRoCj0WCLPbGzpFR4oEfJ37c52n2QJIOqIWAU1OKRmnMevu?= =?iso-8859-1?q?oTEGR/R1pJl9wRtPq9+45w0FUh0yH0sFU/6di2GrogqkIwuqzHa?= =?iso-8859-1?q?mSxhTQKD9BEe70p5gvjxAU9idKRjG3KbRyL9HsLtqu06+WpJdke?= =?iso-8859-1?q?4ugcJDs4eOC2Ib5ltUnz69VCuxiwZoik/w1g2HknfHNOT6y3W9r?= =?iso-8859-1?q?7DTwiGssATcmX5os1z64UN/bwJ3/a1F3cl6D6LBXt0yH7fb9Lj+?= =?iso-8859-1?q?Ydtl3dONnafmSAktBQ+xNlyz0PwQ2JZIcDB+GKXIAPcHEVgDhp+?= =?iso-8859-1?q?dGKv3FdpQeBdQH3bMuBmlUd2BXu9cFvtNVfYIEy8kineJ3YaZU0?= =?iso-8859-1?q?cHqeru+KTWpL6kLeLiYsk?= x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: ChFEKlijmToOAlVn5rSC5lQ23vfeWR5nyPDWa3As4cT66vcRI/27JNVs/lSD1vDwvwg998lHULJ3uMECTirBEVWdYsb2oLmxs1wlSF/gbxHdXS3O3QrZG7bqEQSLlwZMpaoq5QKU53KnXACchbz31J+d+zVZZbfuI2FcWKMjpV1KoW5vc+ygaNi91yj4IXdA/ZwUkVlqBC5slp8XpFXH9V8fqaWsQMw0lYpH0qhQz2dBOh24Ef9hlj8DVVdf/iom8LdG1laNXUwW8YLrMYtnsci82SvEF0BS3Cj7v/FGD6JdqOSN51SuEhnBvOBCeKwA5WFrouQDNUzLNIohOioOlQ2kpB8MzCnOwsFucxCFLbMH5B6TM07/Ob+PcmzRqFkpUNxXbBxA/hnpujRJ4rQ3m3U/BGkFvA4E3SW/PMRImbk= MIME-Version: 1.0 X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-Network-Message-Id: 56759a6e-cab9-4598-af7b-08d6a289af8c X-MS-Exchange-CrossTenant-originalarrivaltime: 06 Mar 2019 23:15:56.1387 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 4ee68585-03e1-4785-942a-df9c1871a234 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR02MB4592 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Heavily based on code from Ken Chen . Signed-off-by: Peter Rosin --- drivers/i2c/muxes/Kconfig | 6 +- drivers/i2c/muxes/i2c-mux-pca9541.c | 137 ++++++++++++++++++++++++++++++++++-- 2 files changed, 136 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 52a4a922e7e6..8532841de5db 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -55,10 +55,10 @@ config I2C_MUX_LTC4306 will be called i2c-mux-ltc4306. config I2C_MUX_PCA9541 - tristate "NXP PCA9541 I2C Master Selector" + tristate "NXP PCA9541/PCA9641 I2C Master Selectors" help - If you say yes here you get support for the NXP PCA9541 - I2C Master Selector. + If you say yes here you get support for the NXP PCA9541/PCA9641 + I2C Master Selectors. This driver can also be built as a module. If so, the module will be called i2c-mux-pca9541. diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 5eb36e3223d5..5d4e0c92e978 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 selectors * * Copyright (c) 2010 Ericsson AB. * @@ -28,8 +28,8 @@ #include /* - * The PCA9541 is a bus master selector. It supports two I2C masters connected - * to a single slave bus. + * The PCA9541 and PCA9641 are bus master selector. They support 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 @@ -63,6 +63,33 @@ #define PCA9541_BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) #define PCA9541_MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#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 + /* 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 */ @@ -73,6 +100,7 @@ enum chip_name { pca9541, + pca9641, }; struct chip_desc { @@ -102,6 +130,21 @@ static bool pca9541_busoff(int ctl) return (ctl & PCA9541_BUSON) == PCA9541_BUSON; } +static bool pca9641_lock_grant(int ctl) +{ + return !!(ctl & PCA9641_CTL_LOCK_GRANT); +} + +static bool pca9641_other_lock(int sts) +{ + return !!(sts & PCA9641_STS_OTHER_LOCK); +} + +static bool pca9641_busoff(int ctl, int sts) +{ + return !pca9641_lock_grant(ctl) && !pca9641_other_lock(sts); +} + /* * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() * as they will try to lock the adapter a second time. @@ -256,6 +299,86 @@ static int pca9541_arbitrate(struct i2c_client *client) return 0; } +/* Release bus. */ +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 (pca9641_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 (pca9641_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; + } + + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + + return 0; + } + + if (pca9641_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; + } + + if (pca9641_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 pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) { struct pca9541 *data = i2c_mux_priv(muxc); @@ -295,10 +418,15 @@ static const struct chip_desc chips[] = { .arbitrate = pca9541_arbitrate, .release_bus = pca9541_release_bus, }, + [pca9641] = { + .arbitrate = pca9641_arbitrate, + .release_bus = pca9641_release_bus, + }, }; static const struct i2c_device_id pca9541_id[] = { { "pca9541", pca9541 }, + { "pca9641", pca9641 }, {} }; @@ -307,6 +435,7 @@ MODULE_DEVICE_TABLE(i2c, pca9541_id); #ifdef CONFIG_OF static const struct of_device_id pca9541_of_match[] = { { .compatible = "nxp,pca9541", .data = &chips[pca9541] }, + { .compatible = "nxp,pca9641", .data = &chips[pca9641] }, {} }; MODULE_DEVICE_TABLE(of, pca9541_of_match); @@ -392,5 +521,5 @@ static struct i2c_driver pca9541_driver = { module_i2c_driver(pca9541_driver); MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_DESCRIPTION("PCA9541/PCA9641 I2C master selector driver"); MODULE_LICENSE("GPL v2");