From patchwork Mon Dec 11 16:58:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Fiergolski X-Patchwork-Id: 847140 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; dkim=pass (1024-bit key; unprotected) header.d=cern.onmicrosoft.com header.i=@cern.onmicrosoft.com header.b="bSXN9q7Z"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywTgH11cqz9s71 for ; Tue, 12 Dec 2017 03:58:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752984AbdLKQ6d (ORCPT ); Mon, 11 Dec 2017 11:58:33 -0500 Received: from mail-eopbgr30073.outbound.protection.outlook.com ([40.107.3.73]:23936 "EHLO EUR03-AM5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752936AbdLKQ62 (ORCPT ); Mon, 11 Dec 2017 11:58:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cern.onmicrosoft.com; s=selector1-cern-ch; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=Z2Whi9c1mdKWNP26KN0gld8CJaQFgKqi4hNIniGc7hU=; b=bSXN9q7Z9lZ0N/vtnsG2w0vjRxqtxv9GqRpcj39e3dk5Rs8TwC8lvjaHTP7iHbcpQI0k1qBjZFNt66oUZjew8+n+1U1JUi8ucYlSoPc9znDcZ+cyJLFkXrQrH9RMhAnHxxYXj+Ez/KlG0fMsNMnI31DmWipX7ZYVkb+etaOwtfc= Received: from DB6PR0601CA0031.eurprd06.prod.outlook.com (2603:10a6:4:17::17) by HE1PR0601MB1913.eurprd06.prod.outlook.com (2a01:111:e400:c520::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.302.9; Mon, 11 Dec 2017 16:58:25 +0000 Received: from VE1EUR02FT050.eop-EUR02.prod.protection.outlook.com (2a01:111:f400:7e06::202) by DB6PR0601CA0031.outlook.office365.com (2603:10a6:4:17::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.302.9 via Frontend Transport; Mon, 11 Dec 2017 16:58:24 +0000 Received-SPF: Pass (protection.outlook.com: domain of cern.ch designates 188.184.36.50 as permitted sender) receiver=protection.outlook.com; client-ip=188.184.36.50; helo=cernmxgwlb4.cern.ch; Received: from cernmxgwlb4.cern.ch (188.184.36.50) by VE1EUR02FT050.mail.protection.outlook.com (10.152.13.198) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.20.302.6 via Frontend Transport; Mon, 11 Dec 2017 16:58:24 +0000 Received: from cernfe02.cern.ch (188.184.36.47) by cernmxgwlb4.cern.ch (188.184.36.50) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 11 Dec 2017 17:58:23 +0100 Received: from adrian-laptop.cern.ch (128.141.234.113) by smtp.cern.ch (188.184.36.52) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 11 Dec 2017 17:58:24 +0100 From: Adrian Fiergolski To: CC: , , , "Adrian Fiergolski" Subject: [PATCH v3] i2c: Add support for NXP PCA984x family. Date: Mon, 11 Dec 2017 17:58:11 +0100 Message-ID: <20171211165811.5806-1-adrian.fiergolski@cern.ch> X-Mailer: git-send-email 2.14.1 In-Reply-To: <8a2f6d04-f156-a877-9e82-3f760488c932@enneenne.com> References: <8a2f6d04-f156-a877-9e82-3f760488c932@enneenne.com> MIME-Version: 1.0 X-Originating-IP: [128.141.234.113] X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:188.184.36.50; IPV:NLI; CTRY:CH; EFV:NLI; SFV:NSPM; SFS:(10009020)(39860400002)(376002)(346002)(2980300002)(438002)(189003)(199004)(786003)(316002)(106466001)(72206003)(1076002)(7696005)(76176011)(5660300001)(50226002)(51416003)(66066001)(3846002)(2906002)(2351001)(74482002)(53416004)(6116002)(4326008)(7636002)(478600001)(86362001)(107886003)(575784001)(36756003)(246002)(7736002)(356003)(50466002)(305945005)(54906003)(16586007)(48376002)(2950100002)(16526018)(8936002)(6666003)(47776003)(106002)(59450400001)(8676002)(6916009); DIR:OUT; SFP:1101; SCL:1; SRVR:HE1PR0601MB1913; H:cernmxgwlb4.cern.ch; FPR:; SPF:Pass; PTR:cernmx11.cern.ch; MX:1; A:1; LANG:en; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: edaf3e97-9edc-429d-2105-08d540b86472 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4608076)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307); SRVR:HE1PR0601MB1913; X-MS-TrafficTypeDiagnostic: HE1PR0601MB1913: X-Microsoft-Exchange-Diagnostics: 1; HE1PR0601MB1913; 20:L9UAP+IwSCaDP5eeE2fgfBqTtQ6QvbOWBBCuc88Y9s/ohvt9rV69tLTxMZVv0OB5kdR7bs7rbgitsVpcnhnQXUy5opb6PLiI6HQQU1Cq0iWfQsC5vegonuvoBQmvWENhQeeVWe91XbmiZgPFW6w5CEWUrqrS5hZ4Xe687Qpmh4fZ/n23pUKgJMWS9jXwVsQWs5FFsgZcLcSfVEwpdNljb7vD6UrK6xG8zY63V7cxMW/IsKa04I3SUgRq3rvB7OaIHkRKUoh9DPzzQN9R75femgcoYoXWdtsDLuVnPHT+UYFisCLdBIpA2y6rcPFVqYZhWiKahhV5znQfvrK0fEMaRy3JinmUcUUlNxkhI9vPRa4hbJMk80mkpuvTyCYciwO4IYEH2nEfTow9nTs6yLh/U7zsC4fRuLq5A5rVIFRqOkOwz9uTZF8S/dwS+0CTBHIzPABcu/Cihhf2htZGeenykoPnXUg6Om4CboPLEsZuX5oPCa4UoIAD92xXtWM+xrJa; 4:5fRRt+ifezssqJKrcISgMhvXDJNcZR6OiFGNMbG01NKMpE88RmOx0BHuy5KoXV+4vTyDZFJzOn/z5n8Q8cGNO5mtnvXhHT3u0snaodWiWMx3fGbKr5ji28MICNXP5JjdgQQnrPj99A8RkCUlqgjGRw1cJRLLgYMey5OV+UlRAHazGiPMYOj+DPMqgWd5T5pQDZc/d1w+XpGULxlB7gVOW+I+Q84tX9k2o7xt9tdrKDazANSGIvEpZnd24kMpTY9W/OAplUDx3nhNozg/qnkXBg== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(2401047)(5005006)(8121501046)(93006095)(93004095)(3231022)(10201501046)(3002001)(6041248)(201703131423075)(201702281529075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123564025)(20161123560025)(20161123555025)(20161123558100)(6072148)(201708071742011); SRVR:HE1PR0601MB1913; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:HE1PR0601MB1913; X-Forefront-PRVS: 0518EEFB48 X-Microsoft-Exchange-Diagnostics: 1; HE1PR0601MB1913; 23:QMVUCC8OawUxfsdg9lAtUUNtjIS1ae3XCW1L/1cvfqErlPk2R3u8M1BMbpnT15Pv0DTnnvzaDl900MLF+eHHCuYkzYoppPGymOl0ZN9cUtIhfeT6nQrecRQkeWXTLqsXWX/B+IsJbFibXW6W502A5xK4WTe/8b6N97Aei3bJvon7FNKi5KmZMk9H1lxZeRUIouLxuXQ1/HJyMG0ukCgNG0Pfin9hw7G4+n/yvFvqKgqMjgpOVupJiir0QUqdNa/e/SFpgUQ4TZCi9TCzGk4VCOhAvt6lhW9TlgecOfsaoVWnrSMX8fGm4gmTWzuW8ZRHNNsVzNEiFzEzptZF1phw311TZV5LuNsu5fZC7i176t4yqVgiU1bQAtc8o6QpvCEHmG6K4f+BmJN17WrkVCElj9sE76s2jJTXOScRkmoLd9Q4pQvkxKZAZYIWQxDy6u8h0x8jYaxBmHeDijeygWBZ922Y4uCB2DPOZ7vHi0Vtf65+jvUGQDYQ5wCXKezWka0TDHkV4Q13En8HOj7mXwTqAb8EY5Yah8Rwbw4sdj/AnqXUynkhE5IjpUix4m9vxLKSPUvDFDOU8TS1l322o8aAH9M/eRwa2nLpeR51GBjj1NC3xdSCmaKo4IlIFZH9IBvGf9CEcLF14iFpULB+99e+iUzcdFzlvBnrgcK6MxeZJ7/xQFWNUv9ylpnWaXsyfOBEsg1sSCq68LJaU4IQpGR6SQKVXzliS6RoXG4t1J4zyEnZHeT15Zg/Cbgrfu2h6zc4+iFzNMzpvRoRlXfGp6tg1FlThBviCV8bKNd7CGb7Wvhv6jWDX8kZdt/OJuxlOV9jKhe24iFU8TWqcaAXDC9Ri4ERSCG8t8X44MfaYmicVBHVmOTcWkR8BsknS60GqF5QRRwtRlMoui+nA7rLitouxhI6Kpmd0P5GsXAWFwcZmT8iiPbgklMa9OdfV/iU7qGVusBaR1QpywDnS87k5TEWru2jRcJ3W7OIQA3sQKPJ7F2sEUogKwp6iEDaOAXnnuQkI2GTLZhOI8qTEQY20Q1rvs9C+dD3iOfXeZPSDQV0COaTWgQYQQ86JbEHth3b5A5OblW8QqI9tlMDLm8OUJQKcQ== X-Microsoft-Exchange-Diagnostics: 1; HE1PR0601MB1913; 6:IiKFEdJAYY06icNG+RwOCvKXt+u6Ua58JNvlLnuH3ddHfB1MrVBb7IQWkzt1YRFoQPEbYTQ3/+OfcdOMC6cSWSBiTyzmItYBIFSilmclAvU+x8e3FTQEKoWOfw8e6OdrrZzsVnOdhWx2O+kL0AELylEI+4rt+/lpS6KsJSon3z5uDsPq1cGv48ZQ1ZcwTsyk27us/sGxcthbsPGp2cxE788hiJ6gaBl+541cdgpjhwzrAVZxE0b5bFVK4d/WM2PME3sPE38v64F5NLlnwJqfCuh0gHIXxRjeRtg5Y2PmQPD2e9N2CK5pwjZf8iTLuxtHt4eZgA9f4LkFE34LYT7N6cWHwfdEGV1BIu7QbGaS9Ko=; 5:vhPWdG/kIDOkW/vfLBC6teTGbz0tjIfoq5JiCxoB6N83/0F9JSkRrsp4GJrucwjJDHNU7k81T+/8rJmusHkVM9vm+BmrS0u3gdh3HxaQhh3wMTGTWbraRf1cKrjd5VcFyGOeYvvBr9GEynsKkWIeb6whi1MCDUPmsbZVNbhM5MI=; 24:v8lhTUo6bStkwjuU/rAjFhaF2t9Z6rgrHup4bDQ+gb6ifCydDL9dSvqqreqrZxuBmvvY227NYZ/I/wx4jPYR4o7T+2uAUpTuEt2tFAZ9g5U=; 7:ixb1zIiRibtB/C9ULZ153eU7OepEt64w5Bf+OTdjdSjfPyWL6yFab+0WH58zPGKPI4NuglQgUvTmoOZuodS3LlTOybq1dhIsm8Cx4qxz/FRhJ8QUZU2ykdeenIBt6hPYMd8NcDiKG6zvwDqGJhRW7/ow/3OA6hR6kV+SPRcf9qErdIP1zPDsUU+ffU69gevCsGZs6kcO5oFfpusrRU8glgRK2L9+UY0uQsFUWMqyfaOJXjS/COelMoacs8yh7Snw SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cern.ch X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Dec 2017 16:58:24.3341 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: edaf3e97-9edc-429d-2105-08d540b86472 X-MS-Exchange-CrossTenant-Id: c80d3499-4a40-4a8c-986e-abce017d6b19 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c80d3499-4a40-4a8c-986e-abce017d6b19; Ip=[188.184.36.50]; Helo=[cernmxgwlb4.cern.ch] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0601MB1913 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This patch exetends the current i2c-mux-pca954x driver and adds suuport for a newer PCA984x family of the I2C switches and multiplexers from NXP. In probe function, the patch supports device ID function, introduced in the new family, and checks it against configuration provided by the devicetree. Moreover, it also performs software reset which is now available for the new devices. The reset of the code remains common with the legacy PCA954x devices. Signed-off-by: Adrian Fiergolski --- Apply Peter's and Rodolfo's comments. Add missing part in pca984x_family_probe which checks deviceID. Peter addressing your main comments: Quoting the PCA9848 manual: "The Software Reset Call allows all the devices in the I2C-bus to be reset to the power-up state value through a specific formatted I2C-bus command. To be performed correctly, it implies that the I2C-bus is functional and that there is no device hanging the bus." This call should reset the multiplexer and all devices which are below it in the I2C address space tree to the default state. The manufacturer ID and device ID checks in pca984x_family_probe ensures that we actually communicate with a device we intended to (according to the devicetree) and that communication with this device works properly (this device ID and manufacturer ID can be seen as a fixed pattern). .../devicetree/bindings/i2c/i2c-mux-pca954x.txt | 5 +- drivers/i2c/muxes/Kconfig | 2 +- drivers/i2c/muxes/i2c-mux-pca954x.c | 157 +++++++++++++++++++-- 3 files changed, 153 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt index aa097045a10e..b428bc0d81b1 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt @@ -1,10 +1,13 @@ * NXP PCA954x I2C bus switch +The driver supports NXP PCA954x and PCA984x I2C mux/switch devices. + Required Properties: - compatible: Must contain one of the following. "nxp,pca9540", "nxp,pca9542", "nxp,pca9543", "nxp,pca9544", - "nxp,pca9545", "nxp,pca9546", "nxp,pca9547", "nxp,pca9548" + "nxp,pca9545", "nxp,pca9546", "nxp,pca9547", "nxp,pca9548", + "nxp,pca9846", "nxp,pca9847", "nxp,pca9848", "nxp,pca9849" - reg: The I2C address of the device. diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 0f5c8fc36625..5da2e04585a9 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -68,7 +68,7 @@ config I2C_MUX_PCA954x depends on GPIOLIB || COMPILE_TEST help If you say yes here you get support for the Philips PCA954x - I2C mux/switch devices. + and PCA984x I2C mux/switch devices. This driver can also be built as a module. If so, the module will be called i2c-mux-pca954x. diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 2ca068d8b92d..6205ae52aa4d 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -1,14 +1,15 @@ /* * I2C multiplexer * + * Copyright (c) 2017 Adrian Fiergolski * Copyright (c) 2008-2009 Rodolfo Giometti * Copyright (c) 2008-2009 Eurotech S.p.A. * - * This module supports the PCA954x series of I2C multiplexer/switch chips - * made by Philips Semiconductors. + * This module supports the PCA954x and PCA954x series of I2C multiplexer/switch + * chips made by Philips Semiconductors. * This includes the: - * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 - * and PCA9548. + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547, + * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849 * * These chips are all controlled via the I2C bus itself, and all have a * single 8-bit register. The upstream "parent" bus fans out to two, @@ -54,6 +55,12 @@ #define PCA954X_IRQ_OFFSET 4 +/* PCA984x family I2C other addresses */ +#define GENERAL_CALL 0x00 +#define SOFTWARE_RESET 0x06 +#define DEVICE_ID_ADDRESS 0x7C +#define NXP_ID 0x00 + enum pca_type { pca_9540, pca_9542, @@ -63,6 +70,10 @@ enum pca_type { pca_9546, pca_9547, pca_9548, + pca_9846, + pca_9847, + pca_9848, + pca_9849, }; struct chip_desc { @@ -73,6 +84,7 @@ struct chip_desc { pca954x_ismux = 0, pca954x_isswi } muxtype; + u16 deviceID; /* used by PCA984x family only */ }; struct pca954x { @@ -129,6 +141,29 @@ static const struct chip_desc chips[] = { .nchans = 8, .muxtype = pca954x_isswi, }, + [pca_9846] = { + .nchans = 4, + .muxtype = pca954x_isswi, + .deviceID = 0x10B, + }, + + [pca_9847] = { + .nchans = 8, + .muxtype = pca954x_ismux, + .deviceID = 0x108, + }, + + [pca_9848] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .deviceID = 0x10A, + }, + + [pca_9849] = { + .nchans = 4, + .muxtype = pca954x_ismux, + .deviceID = 0x109, + }, }; static const struct i2c_device_id pca954x_id[] = { @@ -140,6 +175,10 @@ static const struct i2c_device_id pca954x_id[] = { { "pca9546", pca_9546 }, { "pca9547", pca_9547 }, { "pca9548", pca_9548 }, + { "pca9846", pca_9846 }, + { "pca9847", pca_9847 }, + { "pca9848", pca_9848 }, + { "pca9849", pca_9849 }, { } }; MODULE_DEVICE_TABLE(i2c, pca954x_id); @@ -154,6 +193,10 @@ static const struct of_device_id pca954x_of_match[] = { { .compatible = "nxp,pca9546", .data = &chips[pca_9546] }, { .compatible = "nxp,pca9547", .data = &chips[pca_9547] }, { .compatible = "nxp,pca9548", .data = &chips[pca_9548] }, + { .compatible = "nxp,pca9846", .data = &chips[pca_9846] }, + { .compatible = "nxp,pca9847", .data = &chips[pca_9847] }, + { .compatible = "nxp,pca9848", .data = &chips[pca_9848] }, + { .compatible = "nxp,pca9849", .data = &chips[pca_9849] }, {} }; MODULE_DEVICE_TABLE(of, pca954x_of_match); @@ -304,6 +347,83 @@ static void pca954x_cleanup(struct i2c_mux_core *muxc) i2c_mux_del_adapters(muxc); } +/* + * Part of probe function specific for pca954x family + */ +static int pca954x_family_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. + */ + if (i2c_smbus_write_byte(client, 0) < 0) + return -ENODEV; + + return 0; +} + +/* + * Part of probe function specific for pca984x family + */ +static int pca984x_family_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + union i2c_smbus_data device_id_raw; + u16 manufacturer_id; /* 12 bits */ + u16 device_id; /* 9 bits */ + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + dev_warn(&client->dev, "PCA9846 family: I2c adapter doesn't support I2C_FUNC_SMBUS_WRITE_BYTE_DATA"); + return -ENODEV; + } + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + dev_warn(&client->dev, "PCA9846 family: I2c adapter doesn't support I2C_FUNC_SMBUS_READ_I2C_BLOCK"); + return -ENODEV; + } + + /* Software reset */ + if (i2c_smbus_xfer(client->adapter, GENERAL_CALL, client->flags, + I2C_SMBUS_WRITE, SOFTWARE_RESET, I2C_SMBUS_BYTE, NULL) < 0) { + dev_warn(&client->dev, "PCA9846 family: Sofrware reset failed\n"); + return -ENODEV; + } + + /* Get device ID */ + device_id_raw.block[0] = 3; /* read 3 bytes */ + if (i2c_smbus_xfer(client->adapter, DEVICE_ID_ADDRESS, client->flags, + I2C_SMBUS_READ, client->addr << 1, + I2C_SMBUS_I2C_BLOCK_DATA, &device_id_raw)) { + dev_warn(&client->dev, "PCA9846 family: Get device ID failed\n"); + return -ENODEV; + } + + /* Device ID contains only 3 bytes */ + if (device_id_raw.block[0] != 3) { + dev_warn(&client->dev, "PCA9846 family: Get device ID failed\n"); + return -ENODEV; + } + + /* Check manufacturer ID (12 bits) */ + manufacturer_id = ((u16) device_id_raw.block[1] << 4) | (device_id_raw.block[2] >> 4); + if (manufacturer_id != NXP_ID) { + dev_warn(&client->dev, "PCA9846 family: Manufacturer ID does not match NXP\n"); + return -ENODEV; + } + + /* Check device ID (9 bits) */ + device_id = ((u16) device_id_raw.block[2] << 5) | (device_id_raw.block[3] >> 3); + if (device_id != chips[id->driver_data].deviceID) { + dev_warn(&client->dev, "PCA9846 family: Device ID does not match %s\n", id->name); + return -ENODEV; + } + + return 0; +} + /* * I2C init/probing/exit functions */ @@ -339,11 +459,29 @@ static int pca954x_probe(struct i2c_client *client, if (IS_ERR(gpio)) return PTR_ERR(gpio); - /* Write the mux register at addr to verify - * that the mux is in fact present. This also - * initializes the mux to disconnected state. - */ - if (i2c_smbus_write_byte(client, 0) < 0) { + switch (id->driver_data) { + case pca_9540: + case pca_9542: + case pca_9543: + case pca_9544: + case pca_9545: + case pca_9546: + case pca_9547: + case pca_9548: + ret = pca954x_family_probe(client, id); + break; + case pca_9846: + case pca_9847: + case pca_9848: + case pca_9849: + ret = pca984x_family_probe(client, id); + break; + default: /* unknown device */ + ret = -ENODEV; + break; + } + + if (ret < 0) { dev_warn(&client->dev, "probe failed\n"); return -ENODEV; } @@ -443,6 +581,7 @@ static struct i2c_driver pca954x_driver = { module_i2c_driver(pca954x_driver); +MODULE_AUTHOR("Adrian Fiergolski "); MODULE_AUTHOR("Rodolfo Giometti "); MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); MODULE_LICENSE("GPL v2");