Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2196888/?format=api
{ "id": 2196888, "url": "http://patchwork.ozlabs.org/api/patches/2196888/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-i2c/patch/20260216-i2c-mux-v6-2-9be28ecfd7e3@gmail.com/", "project": { "id": 35, "url": "http://patchwork.ozlabs.org/api/projects/35/?format=api", "name": "Linux I2C development", "link_name": "linux-i2c", "list_id": "linux-i2c.vger.kernel.org", "list_email": "linux-i2c@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260216-i2c-mux-v6-2-9be28ecfd7e3@gmail.com>", "list_archive_url": null, "date": "2026-02-16T12:38:14", "name": "[v6,2/5] i2c: mux: add support for per channel bus frequency", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "53daf97bba79da53fb407c3c36950a39664ff80f", "submitter": { "id": 46679, "url": "http://patchwork.ozlabs.org/api/people/46679/?format=api", "name": "Marcus Folkesson", "email": "marcus.folkesson@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-i2c/patch/20260216-i2c-mux-v6-2-9be28ecfd7e3@gmail.com/mbox/", "series": [ { "id": 492305, "url": "http://patchwork.ozlabs.org/api/series/492305/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-i2c/list/?series=492305", "date": "2026-02-16T12:38:13", "name": "I2C Mux per channel bus speed", "version": 6, "mbox": "http://patchwork.ozlabs.org/series/492305/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2196888/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2196888/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-i2c+bounces-16012-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-i2c@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=QpuvhoMk;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=linux-i2c+bounces-16012-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"QpuvhoMk\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.167.52", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com" ], "Received": [ "from sto.lore.kernel.org (sto.lore.kernel.org\n [IPv6:2600:3c09:e001:a7::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fF2Q551gNz1xpY\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 16 Feb 2026 23:38:53 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id 5D2F6300A333\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 16 Feb 2026 12:38:43 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id B15DC1DF27F;\n\tMon, 16 Feb 2026 12:38:37 +0000 (UTC)", "from mail-lf1-f52.google.com (mail-lf1-f52.google.com\n [209.85.167.52])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id D017922B584\n\tfor <linux-i2c@vger.kernel.org>; Mon, 16 Feb 2026 12:38:35 +0000 (UTC)", "by mail-lf1-f52.google.com with SMTP id\n 2adb3069b0e04-59e5eaa491cso3695771e87.0\n for <linux-i2c@vger.kernel.org>; Mon, 16 Feb 2026 04:38:35 -0800 (PST)", "from [192.168.1.135] (83-233-6-197.cust.bredband2.com.\n [83.233.6.197])\n by smtp.gmail.com with ESMTPSA id\n 2adb3069b0e04-59e5f5b0577sm3175920e87.71.2026.02.16.04.38.32\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 16 Feb 2026 04:38:33 -0800 (PST)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1771245517; cv=none;\n b=fFS2U8xmKuiXLxPzTpUCu7HAHMjKIhTTr3O/nNyAsdq4gQkTawGLvsvI0G7KJKsW5S/nK1gRTLS1ikwByvewoQcp6iHGIGXOPcflKIbT/+Q59Ubql/0laaqnzponsWqMGliDOfc1T9R3SPejyQ/MZUok0rRK0a/846UF1QC6u/8=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1771245517; c=relaxed/simple;\n\tbh=/bBzf2R/gDr+xFsEvUjSSz9V/1X475MKmehIdfO82S0=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=aztjxQfFI0RrKsJa3PLo4ZVjH2VCAz/lYLCCZtkbV24jgJFwcGDxsZ609VMHoJRSgHBGAGZOcLC+u2vc0hZSWViwkTwRF/+gEJrFkhKl4szwyN9cLP/zMfFehQHKk2sKg0+U+UvZCSn2iXg1P+s60I3FepQa1tF2K9wAd++CyRA=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=QpuvhoMk; arc=none smtp.client-ip=209.85.167.52", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1771245514; x=1771850314;\n darn=vger.kernel.org;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to;\n bh=KaNXPqSzXRni0/7DZfH0pXrm0ku9rx2g9K/sQobHHbo=;\n b=QpuvhoMkb2B+RqoayeEDpjilHlYjPWF7ut7ct3iY+Lc6Wx90egN//aTXjzF5rFujSs\n JPSDKBeTskqaa30Nu10q/jfv+741zBx8gVSaVQwouMzZjeUDw8TtgG0K+vrKAucl7R/r\n eQqfs0sQKpCgGXaOvfVtYZtkLDmN4ZO5oE7XYaBtDqpbjnmHveU4b79KmoM6mFg7SxhM\n 4wL4JSYhRlMfjqk0kmlBVGb5yHcB0Am5/C4z5Kodfvcg8/ycaWR/82D3hPGvLvqai8dh\n +V5z8M5BbZErntIyMwoZZfo0I2xUtYSa4nun6YHUqRqMfobmoHsCDZOOQGawldx2mbEY\n kyRw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771245514; x=1771850314;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=KaNXPqSzXRni0/7DZfH0pXrm0ku9rx2g9K/sQobHHbo=;\n b=GmHDCsp+X7N3uQdhOX+V1bfbl9uW/n9UI6yA4DBeLHqSt4IAE3xmAEyjcmUMqMPAra\n ZcORYrM5mwxsRAxa+gFUU5J7gGW/ULzjCtr6Hn4UrRxaatxQxAfQt+Gf9bpvLcNaVb25\n jbT4lfpCnezJfMa+MHr2sOc5cgsV1un7ZwR3K2T30q+8NMM431UdtiAGX9YneCPn04Z2\n vG1/lL30+iVj7Tt5ntGfYY39pekKF/o1rylPkXC10Jv1H2QAbxBmwKCAOieiErzonAEs\n MGZstODo57hdKoWzBPoTaOUhpVZ+3hQ8hNurqHNDDtyaf9DT8uZhBajxnDQmQiZMo+NB\n 2fVA==", "X-Gm-Message-State": "AOJu0YxK+FpHnRrshYFaVv20ADDYcMqx9zH+EUJnL2O3LHldbzdZFiNc\n\tBsXDiuuYcIQ8VmHHYvURFStq6N9ZXMOTtLTSTECb6Xc7GSsB4LAk1y50", "X-Gm-Gg": "AZuq6aIFkdaWTBSdVxCoXY3od1mJvWbASNRLlBKV7iDpUzrDgAXg0HT3JkqtToOujQi\n\tGMLyVbWnn0cFegUYu7rrn+tlKf4i/WYVSN+VjQWuBB3gLo4DcIIeCI8Po0xl+gYE1dZFbFhSFPX\n\tEeXOWtEg1ZnoPbLmptCFah6wwQmcwpAfEGZ0mjg30jiNegS7Z+QmNU32vrkZ6tUfxK5cw91gCq2\n\t8nOwsMEju5Q10ERyyATdNXQOOomc2nMY3JwSt61aRNzCQP2MzJirfpZKDw2fgKW73G73xquqZKP\n\tZbDfq1+TbfmZ9WTAlgtxt5pA45JI3+RkUb25I4sDa2agQNyYG5oH7JzW2cz8R4C7Pz5hXJZUZpm\n\tbyldEiQsx39Uu+F1H/hasIiSR4KpacqDOwF/jdC8kH+CXEC+42EOR8atLdzUHggonlD9EmAjCDV\n\tbjGt55UXywcYPA/kkVj/TNtVQKkp/sdysPR6uJwZRel6LBeQkRNtQ+bB/pte3M7zgk+uzS", "X-Received": "by 2002:ac2:4f04:0:b0:59e:459c:15f7 with SMTP id\n 2adb3069b0e04-59f69c23b4fmr2689862e87.14.1771245513793;\n Mon, 16 Feb 2026 04:38:33 -0800 (PST)", "From": "Marcus Folkesson <marcus.folkesson@gmail.com>", "Date": "Mon, 16 Feb 2026 13:38:14 +0100", "Subject": "[PATCH v6 2/5] i2c: mux: add support for per channel bus frequency", "Precedence": "bulk", "X-Mailing-List": "linux-i2c@vger.kernel.org", "List-Id": "<linux-i2c.vger.kernel.org>", "List-Subscribe": "<mailto:linux-i2c+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-i2c+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "7bit", "Message-Id": "<20260216-i2c-mux-v6-2-9be28ecfd7e3@gmail.com>", "References": "<20260216-i2c-mux-v6-0-9be28ecfd7e3@gmail.com>", "In-Reply-To": "<20260216-i2c-mux-v6-0-9be28ecfd7e3@gmail.com>", "To": "Wolfram Sang <wsa+renesas@sang-engineering.com>,\n Peter Rosin <peda@axentia.se>,\n Michael Hennerich <michael.hennerich@analog.com>,\n Bartosz Golaszewski <brgl@bgdev.pl>, Andi Shyti <andi.shyti@kernel.org>,\n Andy Shevchenko <andriy.shevchenko@intel.com>,\n Bartosz Golaszewski <brgl@kernel.org>", "Cc": "linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,\n linux-arm-kernel@lists.infradead.org,\n Marcus Folkesson <marcus.folkesson@gmail.com>", "X-Mailer": "b4 0.14.3", "X-Developer-Signature": "v=1; a=openpgp-sha256; l=8944;\n i=marcus.folkesson@gmail.com; h=from:subject:message-id;\n bh=/bBzf2R/gDr+xFsEvUjSSz9V/1X475MKmehIdfO82S0=;\n b=owEBbQKS/ZANAwAKAYiATm9ZXVIyAcsmYgBpkw/IPz4xzOf0GygzsdQUR9jYSoA8MYUX8kYSp\n CwhsOUu8/KJAjMEAAEKAB0WIQQFUaLotmy1TWTBLGWIgE5vWV1SMgUCaZMPyAAKCRCIgE5vWV1S\n MhlBEACRSkI9YUbj+XI6UXMYW3BF06vIgS/RBysjCddJxOIXqoFXdLXo+HvGzpMSfsebQ662nor\n yMP/mDH/4JANEiwR/QgPu2K8FanwF9u4vhC9lyc810zQPOjtIvvh/2DWQCXuPJsjbY0ktw2I80Y\n vApTtlcrnhdGPyF0I7rUe8cCPqjz8Ghwk/Esf1zc2xGlglsGXK+9TyeUOqffP/BwnJ3SB1p1L/p\n rALCgYGrvki5sK1Ep/AZ/f4dj5PnIpN1COZtWuoD22KgYFq665psaZeTteuxHeDKKV5U3GMLwaV\n 9ONe5HrK4g0CXpfsv7Y19cS+N93MMzRbE+sF/X0jXbgfJaLz0KQwACwJdJTCAQaIdIJ7k4rkCHu\n cAgOyyuR25Mx1uh501QQaheYBAFAc5n2iKtC3tAbgumsd5oDNuWRsa4UmneGTTjDGUGkzVO4SGG\n 99k76a4jH4G8XRr1lPYjjiaimtzZ1EsJlcyilUzBIZpcWwRzcoQa9q5iBIcKdzaYeHWGJNblt7l\n 4vxpPEAFn2ZvwtniWSPzofj8iWOf2rGE4hq585/6tRMKt0e0ni0bFRkFxbeG9S2JGOkx5alYp//\n 6dOUIoZeXUmk3K9yVNUbObftrCg0J+ifKpkfbQ6sFohpuZHCO/zwxt0M2d4lgYhRBj5WkH8fLb6\n n6/Z9zCHfqQ9SUQ==", "X-Developer-Key": "i=marcus.folkesson@gmail.com; a=openpgp;\n fpr=AB91D46C7E0F6E6FB2AB640EC0FE25D598F6C127" }, "content": "There may be several reasons why you may need to use a certain speed\non an I2C bus. E.g.\n\n- When several devices are attached to the bus, the speed must be\n selected according to the slowest device.\n\n- Electrical conditions may limit the usuable speed on the bus for\n different reasons.\n\nWith an I2C multiplexer, it is possible to group the attached devices\nafter their preferred speed by e.g. put all \"slow\" devices on a separate\nchannel on the multiplexer.\n\nConsider the following topology:\n\n .----------. 100kHz .--------.\n .--------. 400kHz | |--------| dev D1 |\n | root |--+-----| I2C MUX | '--------'\n '--------' | | |--. 400kHz .--------.\n | '----------' '-------| dev D2 |\n | .--------. '--------'\n '--| dev D3 |\n '--------'\n\nOne requirement with this design is that a multiplexer may only use the\nsame or lower bus speed as its parent.\nOtherwise, if the multiplexer would have to increase the bus frequency,\nthen all siblings (D3 in this case) would run into a clock speed it may\nnot support.\n\nThe bus frequency for each channel is set in the devicetree. As the\ni2c-mux bindings import the i2c-controller schema, the clock-frequency\nproperty is already allowed.\nIf no clock-frequency property is set, the channel inherit their parent\nbus speed.\n\nThe following example uses dt bindings to illustrate the topology above:\n\n i2c {\n\tclock-frequency = <400000>;\n\n i2c-mux {\n i2c@0 {\n clock-frequency = <100000>;\n\n D1 {\n ...\n };\n };\n\n i2c@1 {\n D2 {\n ...\n };\n };\n };\n\n D3 {\n ...\n }\n };\n\nSigned-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>\n---\n drivers/i2c/i2c-mux.c | 145 +++++++++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 133 insertions(+), 12 deletions(-)", "diff": "diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c\nindex d59644e50f14..f125b4b8ae58 100644\n--- a/drivers/i2c/i2c-mux.c\n+++ b/drivers/i2c/i2c-mux.c\n@@ -36,21 +36,113 @@ struct i2c_mux_priv {\n \tu32 chan_id;\n };\n \n+static struct i2c_mux_core *i2c_mux_first_mux_locked(struct i2c_adapter *adap)\n+{\n+\tstruct i2c_adapter *parent;\n+\n+\twhile ((parent = i2c_parent_is_i2c_adapter(adap)) != NULL) {\n+\t\tstruct i2c_mux_priv *priv = adap->algo_data;\n+\n+\t\tif (priv && priv->muxc && priv->muxc->mux_locked)\n+\t\t\treturn priv->muxc;\n+\n+\t\tadap = parent;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int i2c_mux_select_chan(struct i2c_adapter *adap, u32 chan_id, u32 *oldclock)\n+{\n+\tstruct i2c_adapter *root = i2c_root_adapter(&adap->dev);\n+\tstruct i2c_mux_priv *priv = adap->algo_data;\n+\tstruct i2c_mux_core *muxc = priv->muxc;\n+\tstruct i2c_mux_core *mux_locked_ancestor;\n+\tint ret;\n+\n+\tif (priv->adap.clock_hz && priv->adap.clock_hz < root->clock_hz) {\n+\t\tmux_locked_ancestor = i2c_mux_first_mux_locked(adap);\n+\t\t*oldclock = root->clock_hz;\n+\n+\t\t/*\n+\t\t * If there's a mux-locked mux in our ancestry, lock the parent\n+\t\t * of the first one. When locked with I2C_LOCK_ROOT_ADAPTER,\n+\t\t * this will recurse through all intermediate muxes (both mux-locked\n+\t\t * and parent-locked) up to the root adapter, ensuring the entire\n+\t\t * chain is locked.\n+\t\t */\n+\t\tif (mux_locked_ancestor)\n+\t\t\ti2c_lock_bus(mux_locked_ancestor->parent, I2C_LOCK_ROOT_ADAPTER);\n+\n+\t\tret = i2c_adapter_set_clk_freq(root, priv->adap.clock_hz);\n+\n+\t\tif (mux_locked_ancestor)\n+\t\t\ti2c_unlock_bus(mux_locked_ancestor->parent, I2C_LOCK_ROOT_ADAPTER);\n+\n+\t\tif (ret)\n+\t\t\tdev_err(&adap->dev,\n+\t\t\t\t\"Failed to set clock frequency %dHz on root adapter %s: %d\\n\",\n+\t\t\t\tpriv->adap.clock_hz, root->name, ret);\n+\t}\n+\n+\treturn muxc->select(muxc, priv->chan_id);\n+}\n+\n+static void i2c_mux_deselect_chan(struct i2c_adapter *adap, u32 chan_id, u32 oldclock)\n+{\n+\tstruct i2c_mux_priv *priv = adap->algo_data;\n+\tstruct i2c_mux_core *mux_locked_ancestor;\n+\tstruct i2c_mux_core *muxc = priv->muxc;\n+\tstruct i2c_adapter *parent = muxc->parent;\n+\tstruct i2c_adapter *root;\n+\tint ret;\n+\n+\tif (muxc->deselect)\n+\t\tmuxc->deselect(muxc, priv->chan_id);\n+\n+\tif (oldclock && oldclock != priv->adap.clock_hz) {\n+\t\tmux_locked_ancestor = i2c_mux_first_mux_locked(adap);\n+\t\troot = i2c_root_adapter(&parent->dev);\n+\n+\t\t/*\n+\t\t * If there's a mux-locked mux in our ancestry, lock the parent\n+\t\t * of the first one. When locked with I2C_LOCK_ROOT_ADAPTER,\n+\t\t * this will recurse through all intermediate muxes (both mux-locked\n+\t\t * and parent-locked) up to the root adapter, ensuring the entire\n+\t\t * chain is locked.\n+\t\t */\n+\t\tif (mux_locked_ancestor)\n+\t\t\ti2c_lock_bus(mux_locked_ancestor->parent, I2C_LOCK_ROOT_ADAPTER);\n+\n+\t\tret = i2c_adapter_set_clk_freq(root, oldclock);\n+\n+\t\tif (mux_locked_ancestor)\n+\t\t\ti2c_unlock_bus(mux_locked_ancestor->parent, I2C_LOCK_ROOT_ADAPTER);\n+\n+\t\tif (ret)\n+\t\t\tdev_err(&adap->dev,\n+\t\t\t\t\"Failed to set clock frequency %dHz on root adapter %s: %d\\n\",\n+\t\t\t\toldclock, root->name, ret);\n+\n+\t}\n+}\n+\n static int __i2c_mux_master_xfer(struct i2c_adapter *adap,\n \t\t\t\t struct i2c_msg msgs[], int num)\n {\n \tstruct i2c_mux_priv *priv = adap->algo_data;\n \tstruct i2c_mux_core *muxc = priv->muxc;\n \tstruct i2c_adapter *parent = muxc->parent;\n+\tu32 oldclock = 0;\n \tint ret;\n \n \t/* Switch to the right mux port and perform the transfer. */\n \n-\tret = muxc->select(muxc, priv->chan_id);\n+\tret = i2c_mux_select_chan(adap, priv->chan_id, &oldclock);\n \tif (ret >= 0)\n \t\tret = __i2c_transfer(parent, msgs, num);\n-\tif (muxc->deselect)\n-\t\tmuxc->deselect(muxc, priv->chan_id);\n+\n+\ti2c_mux_deselect_chan(adap, priv->chan_id, oldclock);\n \n \treturn ret;\n }\n@@ -61,15 +153,16 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,\n \tstruct i2c_mux_priv *priv = adap->algo_data;\n \tstruct i2c_mux_core *muxc = priv->muxc;\n \tstruct i2c_adapter *parent = muxc->parent;\n+\tu32 oldclock = 0;\n \tint ret;\n \n \t/* Switch to the right mux port and perform the transfer. */\n \n-\tret = muxc->select(muxc, priv->chan_id);\n+\tret = i2c_mux_select_chan(adap, priv->chan_id, &oldclock);\n \tif (ret >= 0)\n \t\tret = i2c_transfer(parent, msgs, num);\n-\tif (muxc->deselect)\n-\t\tmuxc->deselect(muxc, priv->chan_id);\n+\n+\ti2c_mux_deselect_chan(adap, priv->chan_id, oldclock);\n \n \treturn ret;\n }\n@@ -82,16 +175,17 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,\n \tstruct i2c_mux_priv *priv = adap->algo_data;\n \tstruct i2c_mux_core *muxc = priv->muxc;\n \tstruct i2c_adapter *parent = muxc->parent;\n+\tu32 oldclock = 0;\n \tint ret;\n \n \t/* Select the right mux port and perform the transfer. */\n \n-\tret = muxc->select(muxc, priv->chan_id);\n+\tret = i2c_mux_select_chan(adap, priv->chan_id, &oldclock);\n \tif (ret >= 0)\n \t\tret = __i2c_smbus_xfer(parent, addr, flags,\n \t\t\t\t read_write, command, size, data);\n-\tif (muxc->deselect)\n-\t\tmuxc->deselect(muxc, priv->chan_id);\n+\n+\ti2c_mux_deselect_chan(adap, priv->chan_id, oldclock);\n \n \treturn ret;\n }\n@@ -104,16 +198,17 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,\n \tstruct i2c_mux_priv *priv = adap->algo_data;\n \tstruct i2c_mux_core *muxc = priv->muxc;\n \tstruct i2c_adapter *parent = muxc->parent;\n+\tu32 oldclock = 0;\n \tint ret;\n \n \t/* Select the right mux port and perform the transfer. */\n \n-\tret = muxc->select(muxc, priv->chan_id);\n+\tret = i2c_mux_select_chan(adap, priv->chan_id, &oldclock);\n \tif (ret >= 0)\n \t\tret = i2c_smbus_xfer(parent, addr, flags,\n \t\t\t\t read_write, command, size, data);\n-\tif (muxc->deselect)\n-\t\tmuxc->deselect(muxc, priv->chan_id);\n+\n+\ti2c_mux_deselect_chan(adap, priv->chan_id, oldclock);\n \n \treturn ret;\n }\n@@ -362,6 +457,32 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,\n \t\t\t}\n \t\t}\n \n+\t\tof_property_read_u32(child, \"clock-frequency\", &priv->adap.clock_hz);\n+\n+\t\t/* If the mux adapter has no clock-frequency property, inherit from parent */\n+\t\tif (!priv->adap.clock_hz)\n+\t\t\tpriv->adap.clock_hz = parent->clock_hz;\n+\n+\t\t/*\n+\t\t * Warn if the mux adapter is not parent-locked as\n+\t\t * this may cause issues for some hardware topologies.\n+\t\t */\n+\t\tif ((priv->adap.clock_hz < parent->clock_hz) && muxc->mux_locked)\n+\t\t\tdev_warn(muxc->dev,\n+\t\t\t\t \"channel %u is slower than parent on a non parent-locked mux\\n\",\n+\t\t\t\t chan_id);\n+\n+\t\t/* We don't support mux adapters faster than their parent */\n+\t\tif (priv->adap.clock_hz > parent->clock_hz) {\n+\t\t\tdev_err(muxc->dev,\n+\t\t\t\t\"channel (%u) is faster (%u) than parent (%u)\\n\",\n+\t\t\t\tchan_id, priv->adap.clock_hz, parent->clock_hz);\n+\n+\t\t\tof_node_put(mux_node);\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto err_free_priv;\n+\t\t}\n+\n \t\tpriv->adap.dev.of_node = child;\n \t\tof_node_put(mux_node);\n \t}\n", "prefixes": [ "v6", "2/5" ] }