Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753561AbdIDLT2 (ORCPT ); Mon, 4 Sep 2017 07:19:28 -0400 Received: from mail-eopbgr20123.outbound.protection.outlook.com ([40.107.2.123]:47488 "EHLO EUR02-VE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753380AbdIDLTY (ORCPT ); Mon, 4 Sep 2017 07:19:24 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=peda@axentia.se; Subject: Re: [PATCH 02/11] mux: core: Add support for getting a mux controller on a non DT platform To: Hans de Goede , MyungJoo Ham , Chanwoo Choi , Guenter Roeck , Heikki Krogerus , Darren Hart , Andy Shevchenko , Mathias Nyman Cc: platform-driver-x86@vger.kernel.org, devel@driverdev.osuosl.org, Kuppuswamy Sathyanarayanan , Sathyanarayanan Kuppuswamy Natarajan , linux-kernel@vger.kernel.org, Greg Kroah-Hartman , linux-usb@vger.kernel.org References: <20170901214845.7153-1-hdegoede@redhat.com> <20170901214845.7153-3-hdegoede@redhat.com> From: Peter Rosin Organization: Axentia Technologies AB Message-ID: <0c882d23-d008-3d61-27be-3fa22bf59521@axentia.se> Date: Mon, 4 Sep 2017 13:19:14 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: <20170901214845.7153-3-hdegoede@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [81.224.168.30] X-ClientProxiedBy: HE1PR0301CA0015.eurprd03.prod.outlook.com (2603:10a6:3:76::25) To VI1PR0202MB2557.eurprd02.prod.outlook.com (2603:10a6:801:6::8) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4a8bbefc-46da-486a-0d27-08d4f386ca11 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(2017082002075)(300000503095)(300135400095)(201703131423075)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095);SRVR:VI1PR0202MB2557; X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2557;3:6lzWvwUnu90jiq8tsAJxDZ9i2yiuYHsyJo3zAnOZA2LQKuij8lW7ykIs6/D0trgBdi7orNzbN2LprdKLpyRh2LITafhkGFkUOGihQviPJbE8B7EN4xMX5jwTx4Cp+EJ18Ic51XGI3UIsIn8TKHkzNIqaq2eg8nUgS74fpdTZwEAr8lSMpFcGXnyyScf/lFxRsSdrS01zWWLMUTMBZXaCsJGmRXTNEC+LNAZ4Lmd00nQU595+f7RutSaNB3HeIrhn;25:wxxihkI1w+m7Uo3zvSuTxYP8d0aoupqy0wwtw7uQiADbpzXJsEgRi05b1iHcFJs10x4+J5B27XYp9q+Ps7mKSQhudxw9aT4sinOi3PjBkNb3A79iRYsZCoBxXYT4Z85mFAo//u9DosFa6cgq806vSRkSU60nnn0yBUnJ3Azz121YMnKPBApWSk99F3KE6kfAWuA9EOPdIQGmdG9ljbFQwLBTUDnIfImNeztgXYwvQImQjcZAO49m36jkZrozOHqhu5odeAlEusudE+74xvTIOC77sLNGge3/y8sOVB+lW+ttGdIVzdhtdRQRvT3BFkIT+mlziUemCWBe5YCB+5cWBg==;31:RwG2Al78AqxbJ6D2cOzo7FpUp8rlwATQba1IXZJT/UiJwZVSgQmtvqKNZibCafD6wD4MK/+EWNe1Hf5z/C8RxS/UG+m6ZInIwcnn2Ox7ZrZOWCBTlPDDXiyi06UcPjnnro9AFZc1Y7RmRr2/mWOclbHTJ6YU84LBMK3i2uJP9YZx77+THlHNT26gyRhtOZ3kyb5wbVXBOBM2y7Smzul9MHmDzDUJCUgBIfokPQuGMFo= X-MS-TrafficTypeDiagnostic: VI1PR0202MB2557: X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(10201501046)(100000703101)(100105400095)(6041248)(2016111802025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123560025)(20161123564025)(20161123555025)(20161123558100)(6072148)(6043046)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:VI1PR0202MB2557;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:VI1PR0202MB2557; X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2557;4:9kigPXA8dUPDzUBW0OgqfPymweGZ1PAjya+CwuVUx4CZk2Yvew7OTmSQBkO2se4ZKEwGrrbOpkM66UbttmJT6VQeFfiBAJkbjTPqGtdnVDNKJCV84NseSW/PN1rU91T65DuUKSQQJN7Q32AsSh6rXu3FvufHOzAjeLUpaPC8TSNwet0SiEZaU28MB0g/c6zYkSofE+1ASXf6HHAwO3gl2jPG92KzkUbuDliRK1eBvg3BKBiywUlEIc5pGS3tISVC X-Forefront-PRVS: 0420213CCD X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(7370300001)(6009001)(6049001)(39830400002)(24454002)(189002)(377424004)(199003)(101416001)(65826007)(7416002)(5660300001)(64126003)(83506001)(50466002)(53546010)(54906002)(74482002)(53936002)(33646002)(65956001)(189998001)(47776003)(65806001)(66066001)(4001350100001)(97736004)(31696002)(6116002)(3846002)(86362001)(4326008)(31686004)(68736007)(23676002)(6246003)(106356001)(36756003)(6666003)(230700001)(2950100002)(105586002)(2906002)(7350300001)(478600001)(42186005)(305945005)(77096006)(6486002)(7736002)(81166006)(8676002)(81156014)(117156002)(229853002)(3260700006)(25786009)(76176999)(50986999)(54356999)(42262002);DIR:OUT;SFP:1102;SCL:1;SRVR:VI1PR0202MB2557;H:[192.168.13.3];FPR:;SPF:None;PTR:InfoNoRecords;MX:3;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtWSTFQUjAyMDJNQjI1NTc7MjM6VlpLU0toMU9lY3hzNWJ1a2ZLWE5kKzhW?= =?utf-8?B?bktxNWgwYUVibm13UTQyL2UzVjBBay9wT25ONStzdkVuOGFhODRheUt3djZh?= =?utf-8?B?NVE0RjQyNUtmQTVzWGo1bUJHRmt4TVo1a2VaOWo4eTlPYmJteDdERDNVSE9n?= =?utf-8?B?ZG0rVG1yL3EvcUphVjJMZmcyQVV4RHMxcTd1SlhYVk1oaXU2WCt5eWZVc3ZF?= =?utf-8?B?a2dpZ2VvbTlaZDJ1aHExeGRrOHV3SFExUkdIZTFsd1NpWTRJOWlSM3B3dzJ4?= =?utf-8?B?bjM5QlhYU1ZWZnpkRHcwQXMwTmtKcmZNNDdnZm80MjRmeEFxM3UwYkxrV3U2?= =?utf-8?B?NU02NU04My9IUlFPZVhIYTIwb3pRbmx2K3VTeGJmcTJDS1NIOXZtdWpFeC9C?= =?utf-8?B?ajJEU0JxNVpBZXBZQVlkSkZrYmhBYWZuelgwckxzb01LaWJqa3Znbkw2Ky8r?= =?utf-8?B?dTdKTk5CQUZJQWswNEZPM21KNDV1SDN6S3J1NFFHWS9tcDV5Zk42WVBLcnNV?= =?utf-8?B?ekEwUnNrWjgyYzljbzBFWGdnWWxId0lHbk90YnlwdWhNR0tCelRLOE1pbXNl?= =?utf-8?B?ck5rKzdtdjNuajZTaU9FYmtORnRCMnB2Nk5pZ2VFZkFKS3dDSk5hNnVZbWtk?= =?utf-8?B?Zm5XSDBRUDJCbGd2bGdpblZnUlo2alMxWkpCeUcwSU1kbmZpaWJKTWZwd2JU?= =?utf-8?B?ZkEzdGxuYXVja0hNbm82K3lvSy9sa1NVUDkvWVlzaUFPdm9idklsRnNlcWMx?= =?utf-8?B?OEJUVUR4QU9Tell3WFZWcytwQTIyWTdwaDNLM1JmVDN6dFo4VGtQdkxna0F0?= =?utf-8?B?b3hVS1dzNzEyblRqK2pWTE0yL0p1Y0JuTmtZREllSnZ0N1VHOHFta2F0NFZY?= =?utf-8?B?dVZITmVsYUNTWE1UeXE2Vmc4SU9wdEkxNWluMGIyOGk1WkdTaUJDcUdYeC83?= =?utf-8?B?eFNBdUU3M1dXdDFqYnFJMmNkNW4wc0JCYUloVWl2MWRZVjBrMmJEejJlZlJQ?= =?utf-8?B?dlgrOU5vVWFDVU53bFpLbENpRzFjVVVYQWxmcDZWK2h3b2QvL01SL2pxVk5k?= =?utf-8?B?VDkrMkRrTmRqb3RmeHFFU3Fid1JiUkVHVmpndll3Nmd0dUlweW9nam54RElM?= =?utf-8?B?ZEpNa3krYS9WVnQ0RjJROThZKzVaMEQyZFBrMEt4SjVSMkxHSE1uN2xUa0w3?= =?utf-8?B?RTk0WDNXUEc1MzduMzVYU0gxMTIyN09QWDBFcnJhblV6L2RMT3BMTXFKOURG?= =?utf-8?B?WmFTNGtIYk5BMkJqSGtPY0p2bkl0VklremtLMmc3Qm9NcXAxM3FIVVgzM3RT?= =?utf-8?B?Z21DUE1qaEh6UzVoUHg2N0hNYW9Xdmt1TFViSElZaVJKV3p5MW5GYzRvWTcx?= =?utf-8?B?Vm9wb1UxaXlBcE0rVXc4emRuNHFXYU5PS0F6dE91V3dHUlNpcENaYjVUcENW?= =?utf-8?B?cmRCeTVYYU84Z1g4VHJiL29VUjA2OXJyUkUwa1NOaVd3R3JiK2JqZEc0L3pT?= =?utf-8?B?a2tNQ2pVcVd0Wmw2R3hoRWQrUnZUSzVHNXQ5U2xyNnZmVkZ5aTZMWkJFaGR0?= =?utf-8?B?SDB5aEFhVjU1Vm01WVdTNDZIUWJKUXN1dVRhTXlZVFgyYkVIWTg2MGhaOWIz?= =?utf-8?B?WU5peEdHUjR6SG4ySENLRkRrK3RSMStpUm9LeHMvTDZVZmQ1aHYxTERTT1Yr?= =?utf-8?B?Qm9SK2ZsTzBnNDduQk5Jam5qRmo0UFVHeGdROHdmUWV3MHlaOXE5NHkrZG5S?= =?utf-8?B?dWFZMDNlK0haM3NHNFZvRUhPcC9aM1Q3QTJxU21WODk4VUYvQ2dQL3RMRm4v?= =?utf-8?B?a2I4NjZmbHJpZzhIUVNCSi9yeVA1d0prRm9FalFORG9scE9zQ0R0aEhWRk5X?= =?utf-8?B?N3FrcGw1TElGK0JBckJRa3RRa0JQejFMVll3SU5KblNUc092Y2NJZkJXeFlE?= =?utf-8?B?OVNPSDFZcERDNVNKTE11N2UxTFJVS1RjZzZmaDVrMkl3OHN2TXdBSlEzWnMv?= =?utf-8?B?SmFmaC9NeG5VeVNCM3poZ3kvZzl4NkRnMXNHTDZ3PT0=?= X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2557;6:eWf1BNmzsOZRcnGKKo6yhi2pYy459JoD+xZA4J6wZ7rfVClpaNIJbAXlT0EV/daYNXKhnfGLBQ3273WkCDNeM/aNdv5WYGGkRgklX6PBFiQ6Ua4JXdZj6yUGAthA4BcJdLBfIQZo/VwHAA8k6P1E/VWhXtiKtr4ai3R1p+SMy2e4iAFioDRd3UpzP19d9xazy1WKawSQzL4F/9PdvfMCmax7ldB8Y2EUzeyD9XZEKk0xyKbnhQnwMXftd6DLw9ASSyYTbIZxpiz2xcDW4GSNsHQySi/jVY7XCKd9ujPuqZIQMmf+cnV0PimezYZgpkNw2nCOito56chnbUVWvjUb7g==;5:FH/kUAGCCDSV0ixAznerfLBkxsqCljDSlp/N8FEuVXn3kCyaCbAXAPWrRhJlyS02NPoZ7kFAVX9RPbpWJ9nIUT9Dxv/rPIpxL/iKj0WDxCwaI0K2ke20wKFgx5Ci9frb98Nw/nLN6MXCWn12ndi44g==;24:4V8fM005VxwFIqKMkf1OXjgso60gfdWqibY6hfgPhS1Vf1VPAwo9q6VLoBtaH2RoIFauz/LQ11KGZSqk95Y9VcjbKw7yhOCvFL9DTedcJpw=;7:6SVZwUfpXn4PPkGOvjlNVruzm/izsnpa92N4ZgZ6ViWxbtKu/DVi23GpNs+2pzlYA8iZZvEMeOu/kSy3rloQzEnGtb9NKn/bsgRfQynONLtKSSzK0QRl6b80Ri1CsyelaLRl5Le7sJ53RC0zrByWX0rSj1iCSSOCT7ISlhgiD+wTK26Jc+o8lcMDVgDMIibOxEDyhYzjLv/OS1jSbX2lsVXgKGPBu4mBTANg44mmThk= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Sep 2017 11:19:18.7519 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0202MB2557 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6149 Lines: 217 Hi! Some comments inline... On 2017-09-01 23:48, Hans de Goede wrote: > On non DT platforms we cannot get the mux_chip by pnode. Other subsystems > (regulator, clock, pwm) have the same problem and solve this by allowing > platform / board-setup code to add entries to a lookup table and then use > this table to look things up. > > This commit adds support for getting a mux controller on a non DT platform > following this pattern. It is based on a simplified version of the pwm > subsys lookup code, the dev_id and mux_name parts of a lookup table entry > are mandatory in the mux-core implementation. > > Signed-off-by: Hans de Goede > --- > drivers/mux/core.c | 96 +++++++++++++++++++++++++++++++++++++++++++- > include/linux/mux/consumer.h | 11 +++++ > 2 files changed, 106 insertions(+), 1 deletion(-) > > diff --git a/drivers/mux/core.c b/drivers/mux/core.c > index 6142493c327b..8864cc745506 100644 > --- a/drivers/mux/core.c > +++ b/drivers/mux/core.c > @@ -24,6 +24,9 @@ > #include > #include > > +static DEFINE_MUTEX(mux_lookup_lock); > +static LIST_HEAD(mux_lookup_list); > + > /* > * The idle-as-is "state" is not an actual state that may be selected, it > * only implies that the state should not be changed. So, use that state > @@ -408,6 +411,23 @@ int mux_control_deselect(struct mux_control *mux) > } > EXPORT_SYMBOL_GPL(mux_control_deselect); > > +static int parent_name_match(struct device *dev, const void *data) > +{ > + const char *parent_name = dev_name(dev->parent); > + const char *name = data; > + > + return strcmp(parent_name, name) == 0; > +} > + > +static struct mux_chip *mux_chip_get_by_name(const char *name) > +{ > + struct device *dev; > + > + dev = class_find_device(&mux_class, NULL, name, parent_name_match); > + > + return dev ? to_mux_chip(dev) : NULL; > +} > + > static int of_dev_node_match(struct device *dev, const void *data) > { > return dev->of_node == data; > @@ -479,6 +499,42 @@ static struct mux_control *of_mux_control_get(struct device *dev, > } > > /** > + * mux_add_table() - register PWM device consumers register mux controllers (because you are not registering consumers, right? someone is registering controllers so that they can be found by consumers?) > + * @table: array of consumers to register > + * @num: number of consumers in table controllers? > + */ > +void mux_add_table(struct mux_lookup *table, size_t num) > +{ > + mutex_lock(&mux_lookup_lock); > + > + while (num--) { > + list_add_tail(&table->list, &mux_lookup_list); > + table++; > + } I prefer for (; num--; table++) list_add_tail(&table->list, &mux_lookup_list); > + > + mutex_unlock(&mux_lookup_lock); > +} > +EXPORT_SYMBOL_GPL(mux_add_table); > + > +/** > + * mux_remove_table() - unregister PWM device consumers unregister mux controllers(?) > + * @table: array of consumers to unregister > + * @num: number of consumers in table controllers? > + */ > +void mux_remove_table(struct mux_lookup *table, size_t num) > +{ > + mutex_lock(&mux_lookup_lock); > + > + while (num--) { > + list_del(&table->list); > + table++; > + } for() loop here as well. > + > + mutex_unlock(&mux_lookup_lock); > +} > +EXPORT_SYMBOL_GPL(mux_remove_table); > + > +/** > * mux_control_get() - Get the mux-control for a device. > * @dev: The device that needs a mux-control. > * @mux_name: The name identifying the mux-control. > @@ -487,11 +543,49 @@ static struct mux_control *of_mux_control_get(struct device *dev, > */ > struct mux_control *mux_control_get(struct device *dev, const char *mux_name) > { > + struct mux_lookup *m, *chosen = NULL; > + const char *dev_id = dev_name(dev); > + struct mux_chip *mux_chip; > + > /* look up via DT first */ > if (IS_ENABLED(CONFIG_OF) && dev->of_node) > return of_mux_control_get(dev, mux_name); > > - return ERR_PTR(-ENODEV); > + /* > + * For non DT we look up the provider in the static table typically > + * provided by board setup code. > + * > + * If a match is found, the provider mux chip is looked up by name > + * and a mux-control is requested using the table provided index. > + */ > + mutex_lock(&mux_lookup_lock); > + list_for_each_entry(m, &mux_lookup_list, list) { > + if (WARN_ON(!m->dev_id || !m->mux_name || !m->provider)) > + continue; > + > + if (strcmp(m->dev_id, dev_id) == 0 && > + strcmp(m->mux_name, mux_name) == 0) { I want the below format (with ! instead of == 0 and the brace on the next line when the condition has a line break): if (!strcmp(m->dev_id, dev_id) && !strcmp(m->mux_name, mux_name)) { > + chosen = m; > + break; > + } > + } > + mutex_unlock(&mux_lookup_lock); > + > + if (!chosen) > + return ERR_PTR(-ENODEV); > + > + mux_chip = mux_chip_get_by_name(chosen->provider); > + if (!mux_chip) > + return ERR_PTR(-EPROBE_DEFER); > + > + if (chosen->index >= mux_chip->controllers) { > + dev_err(dev, "Mux lookup table index out of bounds %u >= %u\n", > + chosen->index, mux_chip->controllers); > + put_device(&mux_chip->dev); > + return ERR_PTR(-EINVAL); > + } > + > + return &mux_chip->mux[chosen->index]; > } > EXPORT_SYMBOL_GPL(mux_control_get); > > diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h > index ea96d4c82be7..912dd48a3a5d 100644 > --- a/include/linux/mux/consumer.h > +++ b/include/linux/mux/consumer.h > @@ -18,6 +18,17 @@ > struct device; > struct mux_control; > I want a kernel-doc comment here, describing the structure. > +struct mux_lookup { > + struct list_head list; > + const char *provider; > + unsigned int index; > + const char *dev_id; > + const char *mux_name; > +}; > + > +void mux_add_table(struct mux_lookup *table, size_t num); > +void mux_remove_table(struct mux_lookup *table, size_t num); > + I'm not sure if consumer.h is the right place for this, but it can be moved when I think of something better. Which I can't for the moment... > unsigned int mux_control_states(struct mux_control *mux); > int __must_check mux_control_select(struct mux_control *mux, > unsigned int state); > Cheers, Peter