From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753234AbdBHQYd (ORCPT ); Wed, 8 Feb 2017 11:24:33 -0500 Received: from mail-eopbgr30121.outbound.protection.outlook.com ([40.107.3.121]:53760 "EHLO EUR03-AM5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751906AbdBHQY2 (ORCPT ); Wed, 8 Feb 2017 11:24:28 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=peda@axentia.se; From: Peter Rosin To: CC: Peter Rosin , Wolfram Sang , "Rob Herring" , Mark Rutland , "Jonathan Cameron" , Hartmut Knaack , "Lars-Peter Clausen" , Peter Meerwald-Stadler , Jonathan Corbet , , , , , Andrew Morton Subject: [PATCH v9 08/10] i2c: i2c-mux-gpmux: new driver Date: Wed, 8 Feb 2017 16:41:55 +0100 Message-ID: <1486568517-6997-9-git-send-email-peda@axentia.se> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1486568517-6997-1-git-send-email-peda@axentia.se> References: <1486568517-6997-1-git-send-email-peda@axentia.se> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [217.210.101.82] X-ClientProxiedBy: DB5PR08CA0069.eurprd08.prod.outlook.com (10.166.166.165) To HE1PR0202MB2555.eurprd02.prod.outlook.com (10.168.184.8) X-MS-Office365-Filtering-Correlation-Id: 2a7e0bf2-c7b8-4d09-2d7e-08d450394826 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:HE1PR0202MB2555; X-Microsoft-Exchange-Diagnostics: 1;HE1PR0202MB2555;3:eqwRqkJ/i++r1JmkVzugb1kovnbQqnimh6TE/15+mXEldFU6UfagtOSNfNWQ91yzj15a3PTdoZBCXwINpNs5vgolXhe2Fu5pDTIWEeh5eXdrBsyTBc2Q7D0wliPg5T6JxZuEUZx+N69gm5DBIoU3UDQZml53VrFt2+6UvzKU5kjAKyly7lSpaI7UzuyN24m5EvyotcdX1APyHVTZQa1hLUF8xES3mmI9CDxcmh8lMz+6nchqhP7evY6/mR4O0j9sTJymp8scMNeLbRW5QfsYzw==;25:bT+SqINfGLnbCEDBs03jaC0atcaJQX0u71fmZSMDNVhN7IFUo/Z+ARviXJhtj9af5RYH/QnhHco3pXdo8Wy5TL8d2L71Vd7vRuzaTNCv0mFkkbulhlXYChTnljJhO/JxY1w3v40dn4yqKx5o16qDAyIb+DeIXtsIuzkWt8WWUvXPFMnd5aYP4svDVMpbf0eG1UIRYKDIqvE5+qIpi6rIwHhyNggeFC/QRDnYr5QHAvISGONez3c++JbNntPephq89rl8WWSoE/LUswf2ptpymLuBWqzkFtMd+plg8PQxzAAE8vmzhvDgpeOBzecAW+l/lQSgHRD0fR6lsnGRAuF6XFMfxBZdzmpd3JZSHp0s0h7guM3NxaBCaCVjdx0IKA97+UrD04cXeqZT5g9TQG/HrmGuL/5ZmbDTnQ2GQlQL8G6wU/xoXdoOFXMbZVfZO/MoCJ5t4BQyem8tiCKmH8kecQ== X-Microsoft-Exchange-Diagnostics: 1;HE1PR0202MB2555;31:0rp/2fDQ3N7mpWoyleOKmfPEDMdGLaPF9lLK6r5cRwgVvhocWA0Y5gi2k5RIk00fMl3v0dDx6NyteuyDp/DeNFqkEv+Rzh5ZjsgGThwWFWt2umW07hL7/0kSTdhbN/uQYropCbyAik2P3JtOc+PbrbhG+C2dOaERjafbDIT3tuayHoue/4nesxXdIQMQmKqxWNMY8eASZNN2sgYWNDVqzUE+dw+FrpZ/BKPIpJ3ircdyaYVO4uKCttR5Z9PTHxqw X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(5005006)(2017020702029)(8121501046)(20170203043)(3002001)(10201501046)(6041248)(2016111802025)(20161123564025)(20161123560025)(20161123558025)(20161123562025)(20161123555025)(6043046)(6072148);SRVR:HE1PR0202MB2555;BCL:0;PCL:0;RULEID:;SRVR:HE1PR0202MB2555; X-Microsoft-Exchange-Diagnostics: 1;HE1PR0202MB2555;4:OMyud8zZ8J86zR9hhQ4O3zZL5gAtFOydAigM3Ga4OP5Ok+ceFLjoHcfpoh/qbQg8BLD3vZSi6isaEqolvuxUVCQTU5SHgjAxBfRXSpE4+ClWwHJ5GYE1NAVVqLcsMtLsmGOTSsm/pslwbyOyD6uk6cfj2+YrzWMbyhCmkqAe6ISCXgvwz7+7ThfGFMXCJFeABiEeO8B9HROTXqsTL+/Mkjf91Rl8BZD6NjcffbPHq9NMzwt9ubJbhKBd17kOtw3E6QX+wZak4zrX94TlkH0dekSC3u6Y58maK/jRDgc9sQ+eMzSDuvSmashZn7mbC1OEuW+Q1nuG4mfY9A9BRmyF49EmK5XVZGDhoWA25GY7yRBtSXkK5k1yuxAbU0d1Fo6i+WEa1HpwGliAy4D3lJsrYtwnEVqwilwsTx70ZQ5QexWpkjPrMRU0L36mg+8o+MW1dDFYCYC4LBxNjrPIjlB6bKOnUqmRjN/I14iSpZl7P3Dr92jfSy9mjfKS8Xsoz9bEKJGNpd2O/CiBQwApor6nSf+mLeLRtpvwL3edNecmw+16MtvM69V0gEceRfTaY78w0AW/kmE21Jfrs1xDH9LVmTo06IANBAynTFADIKRcDrvj90j/sjyaZ9f+SjBeVvNalRFsOocrdhKUSSy+A8YnbnQKSZCeib0Gnq6ymkqqJbd/IabhGGS8zWI+8yqOPwAgq2RhQUB8gLoZU0s4On1Yqw== X-Forefront-PRVS: 0212BDE3BE X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(39840400002)(39450400003)(39410400002)(199003)(189002)(6116002)(3846002)(7736002)(50466002)(2351001)(38730400002)(74482002)(2906002)(101416001)(305945005)(97736004)(48376002)(8676002)(47776003)(110136004)(81166006)(76176999)(50986999)(81156014)(4326007)(6512007)(53936002)(6486002)(66066001)(86362001)(6506006)(33646002)(92566002)(7416002)(50226002)(6666003)(105586002)(230783001)(42186005)(36756003)(5660300001)(189998001)(6916009)(25786008)(106356001)(2950100002)(5003940100001)(8666007)(54906002)(68736007)(2004002)(42262002);DIR:OUT;SFP:1102;SCL:1;SRVR:HE1PR0202MB2555;H:localhost.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;HE1PR0202MB2555;23:hXmSWvRmf6PgPGLwEBWsIOjFVcouFBH1fvGjO9I?= =?us-ascii?Q?hYsLmtZgQGuvuZChkBy//hWrO6ZeLzuqvRRdW6bMo0pSWyQ+2epFCaCj8Ul6?= =?us-ascii?Q?gdFr39GhiovnvPbOL4nLbdSQJnm7HECZblKdqLzIh0pHrdxo7hG7W10rcx6H?= =?us-ascii?Q?UF0lPTYL3P0+2WfB4Ombl45ZAMgmKZp0HPjBaYWGhLAhXdmPhMbldVVRHLzq?= =?us-ascii?Q?PDtn6DrIaXED6Czw+vNNIkq/69uNdWL1faQuUuxBwBGdKXJVM7uNhC2FwGKd?= =?us-ascii?Q?MiZO4QdWBq3MJk0naWaR/Zw99Zk2ItWn3hX3XjYzI9zSYuyOsohzRDs6p8yD?= =?us-ascii?Q?BJVkWA7mDA6cmccHiumIfzKOnh134CeE3+c1aDf7V3GSYb6fCHNARNSU+zVI?= =?us-ascii?Q?8iN1F2bc6t4asLo5285Vicf0vFkRKTgxk8/xivFrFTpTOeOLEHWXd5jUIXHO?= =?us-ascii?Q?xsyXz+97Oy9O+UgfLnULyqyAsQPl1thv+8yMh5xrIh6HbLiGZ+yMV/9cb8it?= =?us-ascii?Q?uXAoIlBKJYonBMKrhhhoYSc3oYl28BUGZJmpnir6wHT2MNT6Y1+tcpoC6e7w?= =?us-ascii?Q?HkGZ2k4SK4H0N3BNJR8OZ7PpMYPICsjQ5kDzTa75kNqGzzJAFSbPGMPcIHQr?= =?us-ascii?Q?0RFfbzQWt+gzNgrB8w778h+cdVbDsf5gI5lQfE9OkG4YDNHCp7IAOMWp78Ec?= =?us-ascii?Q?TfYzxeVQmK7lQB2I4eBnBJDsgcYgcgUB9CRIog/70ePHxtTEGgSu+PKF0jfn?= =?us-ascii?Q?JUwib4RkQFwx4PT6fyWbbqjL0a91Xq0MIa2BMsAEh6wccsfFwzzzX/uHEqTv?= =?us-ascii?Q?UQ5Sxnz/m4ApXSVQ2YJMvbIsk+t8CeoeQe2E7ShVXNft5kT2e9uiEdmgX97Y?= =?us-ascii?Q?WBA5QCAcTSHOB4YGFL7oZwHIWQfiKVtpihUV7Gx3auanosXoYDxtl1Fd/T3L?= =?us-ascii?Q?pD5fO66AKD8v29C1fS4rsbwS0md/xAwcCg/5K9lZpvA+R8skdsHKOn3k+mSH?= =?us-ascii?Q?dNIhdBdn2T5MlWwqEMqP8HynWlXjJ/8oKV7fvPOQ/4/SLz4FakrdAXhgZgr1?= =?us-ascii?Q?yiAN3cxmhbMvTBWbuoDr0haW1+PzxQrcM7KATKGs7RrUQ7rjuPp+RnGlZwMj?= =?us-ascii?Q?4h7j9/VQn5K6kIFEyXcuEj3u3Qj+CV0RFsJkwQ4ulp0fxHwOKajDVUvRAJTK?= =?us-ascii?Q?sEZ16EPBKE/6pWkRcGseHlB22h/raMhKJqy0Y3jHJyhEYyrLMOLtxrQCH8uI?= =?us-ascii?Q?vrmM/r5bMDi7SQ7+Fvgc9FJuxGUbu07Xc8RMRxrjp4azBWbHsM90F1qw1g5A?= =?us-ascii?Q?d4/mzVNopWHSp4BY4ZqF2065+LoMm0CnzTnsXloMXgXlR?= X-Microsoft-Exchange-Diagnostics: 1;HE1PR0202MB2555;6:Ne779Nqsx+2+yeQR+KduFhIsGD4gtjXkRipk2tjz1UkdIBxnu2C+TkQmwoSOJdu7Q8zgD1kT1A3AbRJYeG64vXCuHMv+K1TUsGfghVQSDK0Dx96Ry0H809HSxmOSuUV89fjnycFGgHlFzpRyXlkYwPcy6Lst9mScPWOsuCmNRqBa8OHIoyeqiIl6SjV7i6YJdL84ABFnlpEBuNfjYjUJ8TDASJ1nVPtnzoxQFZq1rNpQtYXhuO8MKu3Aq3cvzKedaECP0T8xWZS9FuNocXUdNiEmcXtFGrBDdpZf8xPWCtUZKeoeukppTSI7Lzu+C2S93ldeIE+la44mnXzU+UOQl+lg0kMXe4ml6a9OgpbVHnGIzfE1WsXMTPQ8cQ0SQUns1ts+34cnrjdJyHWvL3fB5Q==;5:aVeKwGuplvV+S0xyhA5zeIk8Ld3j+KukSmJSNdzXb+dCj822naD3AhDnrAfF+1C1f0bM3Fuu/N+JXccmN39htZmeWV3bvMTwOfg61yZNISj5dWAOGsfjJRDudPiT7nMJ/7948/BgGPAzlh9H+ui3nw==;24:yewCWEBF72nBv1/Q7tNyat1FW6+NcpQNW8oJU/5uIBNJ00getjtcFyzwMz+sPMH2caLhlyzgZ423A2PsRp+d7UzM80xsUm9WTVUE8+mPy0w= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;HE1PR0202MB2555;7:sFKdlfZpvxz/3T/kCiX2XCnjOA96GDa9XncIV0wxVM3XNfNGXhc9tOAyfDsCVCvDcfdmNLd2tuJdJG8FAOHHWV2+uVXkPo4qKQRAHsqFcxUlllQ9fjWhmqdnotYfYCWY4YTw+cp6qY7vuRKt8DByH8Q5f/Hm5MLziEEcSX8zZQbHBoeec/3WvBPBTa3wAqXiVVdXiel/rXL65Jxr1hAbzNIu32NmpCag86hP6hfsUwiKDVJWQiHpvbzcmAKA3ubsf9WGW7L5hd/ucyzkfFaM92dtTpPgWcqXBJlAcFmDHN1wpqsWtPJ8KFlsuD6SRKb+g2QvPRDsqjh8hiixolKmLCczKUg6nSy7+IN+PSv6YtlbYtKOiCOP0vTKqoWaWi1pqDQ1Iv1poUTvu3mM+V0VY00hon2V28422CKTn+EErtXZzaPWYF75M9PeZTiUXbXoce1vXR9G6+E3IfbtwdHO3lRVn5sd3OUG56qjdH1BBSXYFpsD7j0F6IiPBg0dhde4LNqwhzcZPaN9t/DQu8FKnw== X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Feb 2017 15:43:49.7723 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0202MB2555 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is a general purpose i2c mux that uses a multiplexer controlled by the multiplexer subsystem to do the muxing. The user can select if the mux is to be mux-locked and parent-locked as described in Documentation/i2c/i2c-topology. Acked-by: Jonathan Cameron Acked-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/Kconfig | 13 +++ drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 10b3d17ae3ea..11115fb34f24 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -30,6 +30,19 @@ config I2C_MUX_GPIO This driver can also be built as a module. If so, the module will be called i2c-mux-gpio. +config I2C_MUX_GPMUX + tristate "General Purpose I2C multiplexer" + select MULTIPLEXER + depends on OF + help + If you say yes to this option, support will be included for a + general purpose I2C multiplexer. This driver provides access to + I2C busses connected through a MUX, which in turn is controlled + by a MUX-controller from the MUX subsystem. + + This driver can also be built as a module. If so, the module + will be called i2c-mux-gpmux. + config I2C_MUX_PCA9541 tristate "NXP PCA9541 I2C Master Selector" help diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 9948fa45037f..af43c6c3e861 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o obj-$(CONFIG_I2C_DEMUX_PINCTRL) += i2c-demux-pinctrl.o obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o +obj-$(CONFIG_I2C_MUX_GPMUX) += i2c-mux-gpmux.o obj-$(CONFIG_I2C_MUX_MLXCPLD) += i2c-mux-mlxcpld.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c new file mode 100644 index 000000000000..fb23b2278462 --- /dev/null +++ b/drivers/i2c/muxes/i2c-mux-gpmux.c @@ -0,0 +1,173 @@ +/* + * General Purpose I2C multiplexer + * + * Copyright (C) 2017 Axentia Technologies AB + * + * Author: Peter Rosin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +struct mux { + struct mux_control *control; + + bool do_not_deselect; +}; + +static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct mux *mux = i2c_mux_priv(muxc); + int ret; + + ret = mux_control_select(mux->control, chan); + mux->do_not_deselect = ret < 0; + + return ret; +} + +static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan) +{ + struct mux *mux = i2c_mux_priv(muxc); + + if (mux->do_not_deselect) + return 0; + + return mux_control_deselect(mux->control); +} + +static struct i2c_adapter *mux_parent_adapter(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct device_node *parent_np; + struct i2c_adapter *parent; + + parent_np = of_parse_phandle(np, "i2c-parent", 0); + if (!parent_np) { + dev_err(dev, "Cannot parse i2c-parent\n"); + return ERR_PTR(-ENODEV); + } + parent = of_find_i2c_adapter_by_node(parent_np); + of_node_put(parent_np); + if (!parent) + return ERR_PTR(-EPROBE_DEFER); + + return parent; +} + +static const struct of_device_id i2c_mux_of_match[] = { + { .compatible = "i2c-mux", }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2c_mux_of_match); + +static int i2c_mux_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + struct i2c_mux_core *muxc; + struct mux *mux; + struct i2c_adapter *parent; + int children; + int ret; + + if (!np) + return -ENODEV; + + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); + if (!mux) + return -ENOMEM; + + mux->control = devm_mux_control_get(dev, NULL); + if (IS_ERR(mux->control)) { + if (PTR_ERR(mux->control) != -EPROBE_DEFER) + dev_err(dev, "failed to get control-mux\n"); + return PTR_ERR(mux->control); + } + + parent = mux_parent_adapter(dev); + if (IS_ERR(parent)) { + if (PTR_ERR(parent) != -EPROBE_DEFER) + dev_err(dev, "failed to get i2c-parent adapter\n"); + return PTR_ERR(parent); + } + + children = of_get_child_count(np); + + muxc = i2c_mux_alloc(parent, dev, children, 0, 0, + i2c_mux_select, i2c_mux_deselect); + if (!muxc) { + ret = -ENOMEM; + goto err_parent; + } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); + + muxc->mux_locked = of_property_read_bool(np, "mux-locked"); + + for_each_child_of_node(np, child) { + u32 chan; + + ret = of_property_read_u32(child, "reg", &chan); + if (ret < 0) { + dev_err(dev, "no reg property for node '%s'\n", + child->name); + goto err_children; + } + + if (chan >= mux->control->states) { + dev_err(dev, "invalid reg %u\n", chan); + ret = -EINVAL; + goto err_children; + } + + ret = i2c_mux_add_adapter(muxc, 0, chan, 0); + if (ret) + goto err_children; + } + + dev_info(dev, "%d-port mux on %s adapter\n", children, parent->name); + + return 0; + +err_children: + i2c_mux_del_adapters(muxc); +err_parent: + i2c_put_adapter(parent); + + return ret; +} + +static int i2c_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); + + return 0; +} + +static struct platform_driver i2c_mux_driver = { + .probe = i2c_mux_probe, + .remove = i2c_mux_remove, + .driver = { + .name = "i2c-mux-gpmux", + .of_match_table = i2c_mux_of_match, + }, +}; +module_platform_driver(i2c_mux_driver); + +MODULE_DESCRIPTION("General Purpose I2C multiplexer driver"); +MODULE_AUTHOR("Peter Rosin "); +MODULE_LICENSE("GPL v2"); -- 2.1.4