From patchwork Fri Oct 23 19:27:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: York Sun X-Patchwork-Id: 535231 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 214D514171D for ; Sat, 24 Oct 2015 06:28:29 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753229AbbJWT1d (ORCPT ); Fri, 23 Oct 2015 15:27:33 -0400 Received: from mail-bn1bon0140.outbound.protection.outlook.com ([157.56.111.140]:20657 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753160AbbJWT10 (ORCPT ); Fri, 23 Oct 2015 15:27:26 -0400 Received: from BN3PR0301CA0042.namprd03.prod.outlook.com (10.160.180.180) by BN3PR03MB1464.namprd03.prod.outlook.com (10.163.35.14) with Microsoft SMTP Server (TLS) id 15.1.306.13; Fri, 23 Oct 2015 19:27:24 +0000 Received: from BL2FFO11OLC014.protection.gbl (2a01:111:f400:7c09::187) by BN3PR0301CA0042.outlook.office365.com (2a01:111:e400:4000::52) with Microsoft SMTP Server (TLS) id 15.1.306.13 via Frontend Transport; Fri, 23 Oct 2015 19:27:24 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; freescale.mail.onmicrosoft.com; dmarc=none action=none header.from=freescale.com; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11OLC014.mail.protection.outlook.com (10.173.160.144) with Microsoft SMTP Server (TLS) id 15.1.306.13 via Frontend Transport; Fri, 23 Oct 2015 19:27:24 +0000 Received: from oslab-l1.am.freescale.net ([10.214.84.99]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id t9NJRLf9012960; Fri, 23 Oct 2015 12:27:22 -0700 From: York Sun To: , CC: , , York Sun Subject: [PATCH] driver/i2c: Add API to add new I2C device without registering Date: Fri, 23 Oct 2015 12:27:09 -0700 Message-ID: <1445628429-12993-1-git-send-email-yorksun@freescale.com> X-Mailer: git-send-email 1.7.9.5 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11OLC014; 1:l1/LqNYfUkc+U2uouspS/0JGn4ZDHHYVzrhL3oECuOr374Zvg5+GASHBIKsbFuV1Mircr4LysY9VfXKwEqe2WiwJXKf0ionenTiHlbgsmVhKFgtfpcYG623eM/GwBJtluULW0eMI8StlQVjmQQzN4jVy/+aDk7dE7PlrPY5f8wN+BSAYzIkvnOH7M9t4z+solYyiftOP1uTEQV1v9k28niF3niSgRYfDJOSbCOrPCj0EV4k9TLsggk9yWNY9/Lty7u6YYGRb4D9NHC/BwL4qrilyX1HZ7sH69gPnw8tLrVZcrSOEixfM+RpocS4/ZZb2ep5hBjbTSA/Cmsl6VwQ+7Qem4KaIjb3mjQh2fzJ5w5VDFmMJvOZ+CFUmK+QuuBdbSEmn7aHTO9EuuaJG717IRA== X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(2980300002)(1109001)(1110001)(339900001)(199003)(189002)(77096005)(97736004)(5007970100001)(11100500001)(50986999)(33646002)(36756003)(5001770100001)(189998001)(47776003)(19580395003)(48376002)(107886002)(50466002)(6806005)(81156007)(5001960100002)(50226001)(104016004)(5008740100001)(105606002)(87936001)(229853001)(92566002)(106466001)(86362001)(19580405001)(5003940100001)(85426001)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:BN3PR03MB1464; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB1464; 2:FuRldin511zQJ/obr3Ts5XzY1c8zgqSlDNJLFuNusQHNxPdJxQ2qJFDJNnBjbtOHiGBjhmwdAWNWeOBhcyr+fl+4pfIC8jR2lXwMxS7cfIeQfn1+vW0NFTL1jJudRaqhG9EpIg/6Pt2FezhW81Nto8ckwrzNmeAG730apjq5W6g=; 3:mUa2YHM/tMqzaqMEzfiB5+GeOg3zq2Kqn1kFhPPUFo4ylsBlZJxmvtCFCZ5QjMiwVUWVvaTPJuWl6bqA4XxmLEjK4Dlzo7J3vTfUYpq1SaKUz6rh2/PHVX3mXAPnzsP6YS65nwHZvXjS7EIhgZeBwIcfFQ14zQl0X9wJWPjzJ7xUAbcsBXFsX9PeYyAe+4ZQ8Py0MR/rld2zo4+Yxp0+zCMqBVappQUQm2WkAS2FOeI=; 25:IfKCRhBU0IBg+rvfGe7ULPdqrJWV6mBuBhqeAm8qGeiDic/5BE93nss+udcVan8stbDMOoZhKOQkELzWh1lr0uxPTdPddUhLYgFtAz3RzEk2EmSPvlAhWs4yvWUM3ANURHzCvJVD+cn6UvVwIYowMpmNMOx89W7z9RLdobq85a56EJlGCZ2BgIJI9NdabDAAbap3qYw+SqN42JztgcFLQv3hFZRCaHyrGywwXjfliIoOjUhr0BK1hfVMXJJg6g5M4G2IPbCwrpdOWI4USQwGtQ== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1464; X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB1464; 20:xovBjd3NeqbEeDfLZ32JUu6V7ZPQdc+G1A6tJTwMPdln76dUxPP587ufZf8kzqP9nwsAAIHPQDwBBQwT53IJ298mnbe4gRt67OdHt2MVk9fD0L5xWL0orRlfJBma1ve+iEDcmcszrDwL4hSo7/7535y/NTPhs4zURZWXWCHvgLU4b5fYxG5OT8AZxX7rYnbHnFa473ilUrS7I33sYKtnHq+lddzEJD2eEz7FvpfvjkWVA0cJBdtI3KniGb3Z8VF0WUDwAe4972vA1BQrvX2oHXwiGEQUN11GZGRsuEUFt+HySYEUDg8zlNEs9ERtlKuiKALVBoGgOHBKioOk5teSvxzoGVZUD4I7g7Sk5n7cW/o=; 4:EZWVDvYSOAdppg0zT/pZ1zSRGrjDpy9WWtDe3vUbl2YocwnmdrNeGmKZ7yOHXXF7h6uTCyAAHUlsCp5zrzFpQ9JCHrTM8slkI2lpd6AmWkPxEyh//Fc0uP55qffy8SZEotfoHpgGcUs3Pczui51dE++JHiR30hHZzvfzDStpDmYfdSI5BwcxV3qkS0AlFJgFrMpVHzqBG9thJhPXnlN2KbZuMWAN6EMaWw8egBi2AjAod17QTK5cyGm29JPNwdHOvbGmdjtV6Emvhd3TWuVSiDgqIdbZGOgDYUx6GEE2nieu1lWGt8QH3i20N+0MKvO2Q/qiXgLLVKblMIXQaF7al8ZlusY+OtwtIdjLC4LkU03DmzZfkjF+X872uYBEFlzL X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(520078)(5005006)(8121501046)(3002001)(102215026); SRVR:BN3PR03MB1464; BCL:0; PCL:0; RULEID:; SRVR:BN3PR03MB1464; X-Forefront-PRVS: 0738AF4208 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN3PR03MB1464; 23:aqqsZ9xDRjvS4Htq4awbWhcJhObP2NVHd+lyCwJAx?= =?us-ascii?Q?++fCcNKGvTKpkTomULib/H8zYDpLItLx4gzO/qZkKtR4GlEaaH25s9XorSPJ?= =?us-ascii?Q?c62IWQ8GbDAdLxjGlLVOtElrZWjF6uK/r7vpbXotNoLVZW/ST/GgIj5CZe9X?= =?us-ascii?Q?9g/UipYcQ3fqWxaeHvsDxdbEsBjH15cTmmN7GMcDFNDrksmiKOVQPUw91ezz?= =?us-ascii?Q?SapdTesCjTSCPKTBT8Bgz7SDCXRFeZxpFGO1IlsxDo/zqNRApQ6k+XLU4n4q?= =?us-ascii?Q?4vQR+lDFJjo+N8PfNKg+n4K+YTbTo3frKnNIqW3gYRSH9qnqcnR5+BOcokdi?= =?us-ascii?Q?TMXfAvbfLbY7FOkI4SQod7c/2yAkNKwmmdk8hWWSfQOs9FfLwjHG3C+8zGQQ?= =?us-ascii?Q?F9BnvJneqV8lxq2o9xDU//ne9YErVKpd8qHPi8nrjof461Y+JyyK9UsU7aL1?= =?us-ascii?Q?keje8FHxrsPUg7EnuUsCXDLcvb8xv+jNf5E/RCgt+u/ImABG/sOBpdwMhWQM?= =?us-ascii?Q?xMGotU/aSdvzUWinu+TvyVLGnCOuD6mqu5az2QMIZ59ywBUDvazTPtTyNEsv?= =?us-ascii?Q?VmM7E8yXPlENRiKNDUbBzzZ1E5arKTXHEltjPSWCUIK5RgeMLpYPKSMuYLcy?= =?us-ascii?Q?WNkd5ev++Q6Vy294OH4BLzgcpHcu+TrvHPUN3twweTzdLoGAJO0B1Vo32bNY?= =?us-ascii?Q?cLHxPRfhBQacuDvoVFmBnLO9s0qChNZh8wdIL+p0LbCA1kPvCwGUj06qChKw?= =?us-ascii?Q?Ib2Ezs0eDQW1wC6ks8Ne2ByoSSPOs9MAMvSTRDZhAi6uq/0uhF6DvaPWYsbH?= =?us-ascii?Q?7KxJBNDiZVLlwMwQ3gLlQckOhoNwSDm9R/G7tUlxbZk3OaeVfwyN8HD8+9LD?= =?us-ascii?Q?V7luZ3tM1XXITAkYPhwc/nKKF0lwfCJCD0/94VTzZ9+roFBOQrcCa2PgOOsy?= =?us-ascii?Q?17phno066yvsyqOdy1CM6lNmeXbG61JTu9hKzxvTfa/PvvANSI9otTlZo8JH?= =?us-ascii?Q?Ddp8mF581cShea0n3O0zJtKrPkhyIqfZEWSwrgYvy86Jg=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB1464; 5:nMyI/+zJU99wCKmhH5mB3Yx6yCtgBZlhup34Twfu6SLdzdCiWIKWBuh8R3efPazB836K2j6Q2UMu2p7dwBmI6UEHJfQqPnJCHzIIa/Di6cGeE8JBZHwExqf+TjgQvZwfqN/Tp3pLmeJ3PPIaNuhyTQ==; 24:ob3QArSaD0FR7Xf4wxcgB1vTW7Jbko6KnMkUp0ZdqmP1V7v+t5KBmM5WiGPTAIwawp+/uZN2+m1uDMj+dx35kYCeuifZuFSsLV8GCgEI+QM=; 20:7AokVZcdvsITa9ZJGk9+vJb4dMp1cCYzX9YoazM2MzHH6MoC5i+Sh+tCrpW43kc4JwALjr9HB2/UWmUn0F1YkA== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Oct 2015 19:27:24.3181 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB1464 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Split existing API i2c_new_device(), i2c_new_probed_device() into two halves. The first half creates new i2c devices and the second half calls device_register(). It allows additional work to be done before registering the device. Signed-off-by: York Sun CC: Wolfram Sang CC: Stephen Boyd Suggested-by: Stephen Boyd --- drivers/i2c/i2c-core.c | 96 ++++++++++++++++++++++++++++++++++++++---------- include/linux/i2c.h | 8 ++++ 2 files changed, 85 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 5f89f1e..ff941b8 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -980,23 +980,19 @@ static void i2c_dev_set_name(struct i2c_adapter *adap, } /** - * i2c_new_device - instantiate an i2c device + * i2c_new_device_unregistered -- instantiate an i2c device unregistered * @adap: the adapter managing the device * @info: describes one I2C device; bus_num is ignored * Context: can sleep * - * Create an i2c device. Binding is handled through driver model - * probe()/remove() methods. A driver may be bound to this device when we - * return from this function, or any later moment (e.g. maybe hotplugging will - * load the driver module). This call is not appropriate for use by mainboard - * initialization logic, which usually runs during an arch_initcall() long - * before any i2c_adapter could exist. + * Create an i2c device but leave it unregistered. * * This returns the new i2c client, which may be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. + * device_register() or i2c_unregister_device(); or NULL to indicate an error. */ struct i2c_client * -i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) +i2c_new_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info const *info) { struct i2c_client *client; int status; @@ -1022,13 +1018,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) if (status) { dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); - goto out_err_silent; + goto out_err; } /* Check for address business */ status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client)); - if (status) + if (status) { + dev_err(&adap->dev, "i2c client %s at 0x%02x busy\n", + client->name, client->addr); goto out_err; + } client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; @@ -1037,6 +1036,41 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.fwnode = info->fwnode; i2c_dev_set_name(adap, client); + + return client; + +out_err: + kfree(client); + return NULL; +} +EXPORT_SYMBOL_GPL(i2c_new_device_unregistered); + +/** + * i2c_new_device - instantiate an i2c device + * @adap: the adapter managing the device + * @info: describes one I2C device; bus_num is ignored + * Context: can sleep + * + * Create an i2c device. Binding is handled through driver model + * probe()/remove() methods. A driver may be bound to this device when we + * return from this function, or any later moment (e.g. maybe hotplugging will + * load the driver module). This call is not appropriate for use by mainboard + * initialization logic, which usually runs during an arch_initcall() long + * before any i2c_adapter could exist. + * + * This returns the new i2c client, which may be saved for later use with + * i2c_unregister_device(); or NULL to indicate an error. + */ +struct i2c_client * +i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) +{ + struct i2c_client *client; + int status; + + client = i2c_new_device_unregistered(adap, info); + if (!client) + goto out_err_silent; + status = device_register(&client->dev); if (status) goto out_err; @@ -1050,7 +1084,6 @@ out_err: dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, status); out_err_silent: - kfree(client); return NULL; } EXPORT_SYMBOL_GPL(i2c_new_device); @@ -2455,11 +2488,9 @@ int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) } EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); -struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *, unsigned short addr)) +static unsigned short address_probe(struct i2c_adapter *adap, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) { int i; @@ -2486,12 +2517,39 @@ i2c_new_probed_device(struct i2c_adapter *adap, break; } - if (addr_list[i] == I2C_CLIENT_END) { + return addr_list[i]; +} + +struct i2c_client * +i2c_new_probed_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) +{ + info->addr = address_probe(adap, addr_list, probe); + + if (info->addr == I2C_CLIENT_END) { + dev_dbg(&adap->dev, "Probing failed, no device found\n"); + return NULL; + } + + return i2c_new_device_unregistered(adap, info); +} +EXPORT_SYMBOL_GPL(i2c_new_probed_device_unregistered); + +struct i2c_client * +i2c_new_probed_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) +{ + info->addr = address_probe(adap, addr_list, probe); + + if (info->addr == I2C_CLIENT_END) { dev_dbg(&adap->dev, "Probing failed, no device found\n"); return NULL; } - info->addr = addr_list[i]; return i2c_new_device(adap, info); } EXPORT_SYMBOL_GPL(i2c_new_probed_device); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 768063b..85068ae 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -327,6 +327,9 @@ struct i2c_board_info { */ extern struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); +extern struct i2c_client * +i2c_new_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info const *info); /* If you don't know the exact address of an I2C device, use this variant * instead, which can probe for device presence in a list of possible @@ -339,6 +342,11 @@ i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, unsigned short const *addr_list, int (*probe)(struct i2c_adapter *, unsigned short addr)); +extern struct i2c_client * +i2c_new_probed_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)); /* Common custom probe functions */ extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr);