From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752216AbcDTPTk (ORCPT ); Wed, 20 Apr 2016 11:19:40 -0400 Received: from mail-am1on0128.outbound.protection.outlook.com ([157.56.112.128]:6491 "EHLO emea01-am1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751254AbcDTPTf (ORCPT ); Wed, 20 Apr 2016 11:19:35 -0400 Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=none action=none header.from=axentia.se; From: Peter Rosin To: CC: Peter Rosin , Wolfram Sang , Jonathan Corbet , Peter Korsgaard , Guenter Roeck , Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald , Antti Palosaari , Mauro Carvalho Chehab , Rob Herring , Frank Rowand , Grant Likely , Andrew Morton , "David S. Miller" , Greg Kroah-Hartman , Kalle Valo , Jiri Slaby , Daniel Baluta , Lucas De Marchi , Adriana Reus , Matt Ranostay , Krzysztof Kozlowski , Hans Verkuil , Terry Heo , Arnd Bergmann , Tommi Rantala , Crestez Dan Leonard , , , , , , Peter Rosin Subject: [PATCH v7 06/24] i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core Date: Wed, 20 Apr 2016 17:17:46 +0200 Message-ID: <1461165484-2314-7-git-send-email-peda@axentia.se> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1461165484-2314-1-git-send-email-peda@axentia.se> References: <1461165484-2314-1-git-send-email-peda@axentia.se> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [217.210.101.82] X-ClientProxiedBy: DB3PR01CA0069.eurprd01.prod.exchangelabs.com (10.242.133.172) To VI1PR02MB1312.eurprd02.prod.outlook.com (10.165.231.154) X-MS-Office365-Filtering-Correlation-Id: 1d9e83c8-91e8-4562-aee9-08d3692f2b3a X-Microsoft-Exchange-Diagnostics: 1;VI1PR02MB1312;2:qfeAHgURxt5e5P3g44O0KeOcH14HMw6ULtceNyX2N6G+aLV/FKhRdmCVFF/BuPFAmKXMPNpqiQIFyDD8XIZn4RMgtKCcM1JBwXh5YBgKiSSr14E1mItBlOeOVafySYQFPLqBSo95TqDytfTxP7OK69VxAokxKBIbj8w/wB9o84aGAhPCt2xTd2kTIwghDAPz;3:8lwbvsCDzfSUEoeLkw0cutW+qBq4/r+/iYWy4Q1FV1wjhSxkcVVQWUlCsVFyxCc6xTKHuyOP52bvhxuQU4Y5GYaQ9kU3a1P44tLNMiTSFKhrQ55TL6Ek7P7Ndhr9LXdR;25:YZqvz0WBRxMC6McDT29rLsh8a3CXy8+jGL6IY61WNEC5nJL5n0R/r/4HqUxYjffU6eCadDGcfcGvTWXGVuCvel1v4BQ0nYHbYQ9zkvcS5Hovs/9kadA+WrbUg57YvyKrHX5eFDPq2Z22TEnbTLW8z5QOgcwg7+mQD06LSIcTiLS1qZvWEdVvfavosAjMmRLyMrnMcXLftWfDjSS//FcNfFKaFosnGmnbInAZKd97CG+BAnfLmrf0dz4HFbex9a6hy4RMEjIYLPiTZj84nwafPIQwYsgxr6vE+1KO+GGEST0YjpfVXavdCyJX8QfJ3X8yOHVubi4zgzHbVmYsvOp9Ow== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:VI1PR02MB1312; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(9101521026)(6040130)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6041046)(6043046);SRVR:VI1PR02MB1312;BCL:0;PCL:0;RULEID:;SRVR:VI1PR02MB1312; X-Microsoft-Exchange-Diagnostics: 1;VI1PR02MB1312;4:TIZO4B2v+kZFU6cbmfm7wWgsoWAHZMluH0sd6zS73MttihfjaVk/BIojBvZxuABJQfq1Erb0T7VJoMP1PZVi75fAQ3ukZ0dTOaYTGH7RDCYUZfjqOg2bzz4sYJoGm/NO2FS10YE/MwH5FlId9HUx+2xz7OWs+ptOaUU4x7ozhdG/fHjYvdVlPBcIdXYGwjBBbpfdmNNJSL2BVPlFE3vYO764gqyXg1lKIDyQkThLZ39J8n2b/gwDbJ14mQXRT3+HD2ouufK9tbl4uQ9A0i2KwWlGsd+tGXX6fSGduazK9DbTg4V2hAob8ybtt8lvn+flGt2nQ6gTrpGtJ+418Hlen7Z+yf9NnKa/K1u8DDtYTto98LzDeEKYlX62CoOpS3g2KQ0+gxC4yrupiNiKG/vVm4FTaIqWjSv57Ww3jEpitoaCbBXIhVZXCCZTzoYoL6l79K4el3wQYud6+e+vFdXXew== X-Forefront-PRVS: 0918748D70 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6069001)(66066001)(2906002)(19580395003)(19580405001)(110136002)(92566002)(189998001)(230783001)(5008740100001)(47776003)(42186005)(33646002)(6116002)(3846002)(5003940100001)(586003)(81166005)(48376002)(2950100001)(4326007)(50466002)(76176999)(1096002)(50226001)(77096005)(50986999)(36756003)(86362001)(2351001)(229853001)(74482002)(5004730100002)(7059030)(42262002);DIR:OUT;SFP:1102;SCL:1;SRVR:VI1PR02MB1312;H:localhost.localdomain;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;VI1PR02MB1312;23:mm37Q09ie4t1IOD24UkkVA94fGMqpu8EbtAVTogm/?= =?us-ascii?Q?iV5EdQzdDReOU1pvlctaZ6U3lUQOw0MwjP3HwFcI9OZ+2WSmAXUO3L2n2Cqn?= =?us-ascii?Q?kvZCVLZfBy7Cz44cdYNlNELiS/laAX1clwMkBXI5tk7ylh1Wq0O6idFlrWQt?= =?us-ascii?Q?xn7Muvb7XacZ530cNAfnjKYw+VSajKKWGVujow2KQ6tOeWlMDXPb89Kr8yL1?= =?us-ascii?Q?1Dr+GLfQXpJepmHjpQPXVm9g8rSrY5+6/KWvnleWjEXx3+BofVYK/no1FzXQ?= =?us-ascii?Q?70Dn1dtbEV+bRbHZe8crnK36c8yBFXPMig3rC05OI/Mo5G6nM/HauGBdC5Vt?= =?us-ascii?Q?O7NuD+UYur5iNR8LKTlA8Mxx3D97SiVXE22fzlWfZCrakUMbN6YryFnY3G0F?= =?us-ascii?Q?ed9ZnNgaEiDDCKd2RmPTbKo5zeWT79wGc9FOr75OwvlRcRX+kmojb8IRW5uW?= =?us-ascii?Q?nUGvKxVxyniF+Af7Q7/KMS6EQ2MFZSCe/RDUjhjZB0pM0XErV3+hVFbmtBq3?= =?us-ascii?Q?7LgEV13T92WcmcCt1v32N27caZg+A0OzC+93WYNlJy5U439p5CthMMuENtCk?= =?us-ascii?Q?181RCcANgrQltL8z1jyYhZS0yjUm0/+PElY6Ss0IPl7r4bQ06oH6wh3lyAGp?= =?us-ascii?Q?z29OD6BxBiPpu/YFge+qttzbJfExNwRlBQpvwINBLjbu9EBTmhOob+HAz42G?= =?us-ascii?Q?X7FM5nMJf/WfzMH7ossmHSzRSJWjef4Un93Pld83up3bF4ZRNzPQXKfdlvMN?= =?us-ascii?Q?FFJ+cv4jIF4j6/q0QvaX8tWxlTebZCZYAm01ZgSHNXSbDEHsptj9t1PvGSca?= =?us-ascii?Q?Ywjh8lRoh3QkK8roMZ/LNge21R/7RPYoW7MqG9Qvi+uk64VW9jQTckVsL+bP?= =?us-ascii?Q?my8ZVKRdKYA+yle6oe6GpW17IAbRxa8yJceK6Vz+HxIaPgCAqrUVT7mLaQck?= =?us-ascii?Q?jCc0k77f78xbmkhWpgEXQtSQR6nEHVqN8aSaPnxdgRJ1mwg8+zl3GvXweuFe?= =?us-ascii?Q?qw=3D?= X-Microsoft-Exchange-Diagnostics: 1;VI1PR02MB1312;5:kZyVf5+LQ727/SQ7g9FxDUZGvf5VUDmNyG71EjtxPVgNr0npP6jkp8qwT5JkHn2yxz37ei15krJZbvBJWALmHof+kNYZLtSa+kqyR6qBBJjjqsoxD/a5HqYMKQdx7IQUoHkYTJbDCyqxFqeOGe0GlaT8sK2p2DBgbBv3xViQMzy07W4oR/T4u/uq2ySXb9Oq;24:Gv9rcSYwt6BSeUYBX4JjIq25Ya8zT5ZcLmGmzHcPZN+ZjoNGm7R7IwLFWK/tVeJwwtnsQB3luWDm/snmY9MFYz5POWLgVlTNQ1iKYbYDGP0=;7:CuE6QuSMaV4DV+laGMtDsFH84m0cKUxDEsLFLfVZQLwP9MQM2NBqRwrhKcRln8ZrssdgqKcPxazwrI6KOpNmUpywVRgqTHL/ntqmxPOC4Et1RVK+uJ+QPcCagecV4EfIvZfkvCzMor1wRzsqrsB8acp1QtTOB7NHS3A3THx45uKHUWezwpQdnTSag/GdG7Btk/HYLQxai6M2Bv+Y3nDjcJjb+ztDNt8M7DnmfT/b678= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Apr 2016 15:19:24.9172 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR02MB1312 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Add a mask to handle the case where not all child adapters should cause a mux deselect to happen, now that there is a common deselect op for all child adapters. Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca954x.c | 61 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index acfcef3d4068..528e755c468f 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -60,9 +60,10 @@ enum pca_type { struct pca954x { enum pca_type type; - struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; }; struct chip_desc { @@ -146,10 +147,10 @@ static int pca954x_reg_write(struct i2c_adapter *adap, return ret; } -static int pca954x_select_chan(struct i2c_adapter *adap, - void *client, u32 chan) +static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) { - struct pca954x *data = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; const struct chip_desc *chip = &chips[data->type]; u8 regval; int ret = 0; @@ -162,21 +163,24 @@ static int pca954x_select_chan(struct i2c_adapter *adap, /* Only select the channel if its different from the last channel */ if (data->last_chan != regval) { - ret = pca954x_reg_write(adap, client, regval); + ret = pca954x_reg_write(muxc->parent, client, regval); data->last_chan = regval; } return ret; } -static int pca954x_deselect_mux(struct i2c_adapter *adap, - void *client, u32 chan) +static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) { - struct pca954x *data = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + if (!(data->deselect & (1 << chan))) + return 0; /* Deselect active channel */ data->last_chan = 0; - return pca954x_reg_write(adap, client, data->last_chan); + return pca954x_reg_write(muxc->parent, client, data->last_chan); } /* @@ -191,17 +195,22 @@ static int pca954x_probe(struct i2c_client *client, bool idle_disconnect_dt; struct gpio_desc *gpio; int num, force, class; + struct i2c_mux_core *muxc; struct pca954x *data; int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) return -ENODEV; - data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL); - if (!data) + muxc = i2c_mux_alloc(adap, &client->dev, + PCA954X_MAX_NCHANS, sizeof(*data), 0, + pca954x_select_chan, pca954x_deselect_mux); + if (!muxc) return -ENOMEM; + data = i2c_mux_priv(muxc); - i2c_set_clientdata(client, data); + i2c_set_clientdata(client, muxc); + data->client = client; /* Get the mux out of reset if a reset GPIO is specified. */ gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); @@ -238,16 +247,13 @@ static int pca954x_probe(struct i2c_client *client, /* discard unconfigured channels */ break; idle_disconnect_pd = pdata->modes[num].deselect_on_exit; + data->deselect |= (idle_disconnect_pd + || idle_disconnect_dt) << num; } - data->virt_adaps[num] = - i2c_add_mux_adapter(adap, &client->dev, client, - force, num, class, pca954x_select_chan, - (idle_disconnect_pd || idle_disconnect_dt) - ? pca954x_deselect_mux : NULL); + ret = i2c_mux_add_adapter(muxc, force, num, class); - if (data->virt_adaps[num] == NULL) { - ret = -ENODEV; + if (ret) { dev_err(&client->dev, "failed to register multiplexed adapter" " %d as bus %d\n", num, force); @@ -263,23 +269,15 @@ static int pca954x_probe(struct i2c_client *client, return 0; virt_reg_failed: - for (num--; num >= 0; num--) - i2c_del_mux_adapter(data->virt_adaps[num]); + i2c_mux_del_adapters(muxc); return ret; } static int pca954x_remove(struct i2c_client *client) { - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - int i; - - for (i = 0; i < chip->nchans; ++i) - if (data->virt_adaps[i]) { - i2c_del_mux_adapter(data->virt_adaps[i]); - data->virt_adaps[i] = NULL; - } + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + i2c_mux_del_adapters(muxc); return 0; } @@ -287,7 +285,8 @@ static int pca954x_remove(struct i2c_client *client) static int pca954x_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct pca954x *data = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); data->last_chan = 0; return i2c_smbus_write_byte(client, 0); -- 2.1.4