Received: by 10.223.185.116 with SMTP id b49csp3978084wrg; Mon, 19 Feb 2018 09:00:07 -0800 (PST) X-Google-Smtp-Source: AH8x226VruW6nueBCTx/agCzf4RG0/j60N1yNq04Z/RUb8kDbCUvm3pTBWmoeasu4cJd7O/JQAno X-Received: by 2002:a17:902:2702:: with SMTP id c2-v6mr14840549plb.342.1519059607880; Mon, 19 Feb 2018 09:00:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519059607; cv=none; d=google.com; s=arc-20160816; b=s9WNTbMkRPLDxV+vu0yicJ6XkFS3+/OkoDA6vXaGvxxuMNkFqm44xfD7SkYKRrWnsy Lw0M/ZuYXEwDcDQTmIdjghLZMy1OtWDr/Tz10vXb3X6Ck9vyooDFSCtZuvzifDG7RMQk 9DT8S0jvqkgXCY28sORIb1ffKbvrk4mRrw1S0K0Aig+iG7lZIRxjbnz2TsbnfLsPtHAd H2/OHxOrWplb2OGOUX+ldEdF236nCk+CAUU6ED/ulV32XaPhvCDQWon02S5UFVwR6hYf ZX1R2olGxHJeJOLQugOVnGzyGQYcZEyjysD6STdn6W4u2Zavfn/EHZqI5Ws7AukrnUg7 IyJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=UiDUkNpIHpYQg1fkerc1W2qbNhbgw0ZMjGH6wdYPVwY=; b=Aa3V/ruOj0KrKllDcBEq50DIH6jxWydKbTt/dQE0xhd8kofOdGrjjmtrAjkqU85URr L57/+/+8Nli6nH6djYUpaZZtNPGNY/DG2ZM/BO2DQBHXXr/fiL9k3Da45FEUxCzQbqnG VZ6DoqejZx+I1SJtSjnzyQo9M8kpegusaoIJPb7fA+C5TH+5ok6v7nbDacLCesh52WS6 gmbw9ZFnGpmJBvnvZGqsm8A0W1OGmFJAqz0xhvdKiHTmcesC8M0q7gdDDZ5AOoYNYkx8 +UbtlBZgOo4HIoc+EuKdiFHUHy43bxMHSNDTTxVn9NhZyKKTVz7VV3ItrPzJZjBctJT8 7E8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=hxtLK1Go; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 97-v6si133613pld.599.2018.02.19.08.59.53; Mon, 19 Feb 2018 09:00:07 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=hxtLK1Go; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753452AbeBSQ6p (ORCPT + 99 others); Mon, 19 Feb 2018 11:58:45 -0500 Received: from mail-wr0-f193.google.com ([209.85.128.193]:32812 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753346AbeBSQ6l (ORCPT ); Mon, 19 Feb 2018 11:58:41 -0500 Received: by mail-wr0-f193.google.com with SMTP id s5so10369510wra.0 for ; Mon, 19 Feb 2018 08:58:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=UiDUkNpIHpYQg1fkerc1W2qbNhbgw0ZMjGH6wdYPVwY=; b=hxtLK1GoptyCa6R6O3JBAU2ZVJXJlRr3pVF454w5LI0fk85hVXzm/HHf5JID8PGLP8 Zvua3cY/niL4VbxOyR1CwWK0EgEsTgnpEEBCz2dqphjF2qpXnMN1yF37tHyXay8G+7Wl wzY+exKaHf2lFqqcZ7h/NYVRIxBdgpGcZs9seErDcHG81YFtzxn/ttKqwYQIZe+Rlo62 l1GGVSS2vLSkfGHeY4R+8mIq9wC1XM54LVhANPSDVU4NjeAqvy7XlZ6Yt9dKop30RJBh 6I19mmEmV2WXaRdkRKxIw4vY5U+tU0KxYV4FeUnNK58U25M6JtnHrnVJupjrvvh1zBpg GtCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=UiDUkNpIHpYQg1fkerc1W2qbNhbgw0ZMjGH6wdYPVwY=; b=uKzynUI1TDDOuixqaWBWcJU4Bv2eniVZD6oa+YpkDeu6HttgVcnUSKgWs24cen/nr6 Gs2PfpMr0Jgr7+8t2gXJPBSXW1G+Bd2q++tf29jKMPmpDOFmXWPbb2FqZQ9VamZvy5dk Svj+mOvt/1mhofluzn7Zu864Cm4Ci46BvEtLyRtud+CKiRHjMzobxCGxqMS6ad+0rTaf kuA8oDyRAycTimSJQZli2kyiVoMUeJZS2TjaAOmtf3uJ1dMMjJ5AalsegC+BjdiTb9fI RpeFVUEC0imIGLmMx5pCskhCi+hP5voJMNLAUKc3bmAyO9PckiXRpu2CDyZstcyp6pyQ I1Ew== X-Gm-Message-State: APf1xPDy4VIDzvEiV/mw6nFv7+64NHncbRFNpeTePemGQhf4xC/MJAUN rtzcTuzIagXlME3u4hN6wtV7tVwQEMc= X-Received: by 10.223.130.206 with SMTP id 72mr14569104wrc.45.1519059520051; Mon, 19 Feb 2018 08:58:40 -0800 (PST) Received: from brgl-bgdev.baylibre.local ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id a82sm10249566wme.20.2018.02.19.08.58.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Feb 2018 08:58:39 -0800 (PST) From: Bartosz Golaszewski To: Philipp Zabel Cc: linux-kernel@vger.kernel.org, Bartosz Golaszewski , Sekhar Nori , Kevin Hilman , David Lechner Subject: [PATCH v4] reset: add support for non-DT systems Date: Mon, 19 Feb 2018 17:58:37 +0100 Message-Id: <20180219165837.28913-1-brgl@bgdev.pl> X-Mailer: git-send-email 2.16.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bartosz Golaszewski The reset framework only supports device-tree. There are some platforms however, which need to use it even in legacy, board-file based mode. An example of such architecture is the DaVinci family of SoCs which supports both device tree and legacy boot modes and we don't want to introduce any regressions. We're currently working on converting the platform from its hand-crafted clock API to using the common clock framework. Part of the overhaul will be representing the chip's power sleep controller's reset lines using the reset framework. This changeset extends the core reset code with new reset lookup structures. Each lookup table contains a set of lookup entries which allow the reset core to associate reset lines with devices (by comparing the dev_id and con_id strings). Machine code can register a set of reset lines using this lookup table and concerned devices can access them using the regular reset_control API. The new lookup function is only called as a fallback in case the of_node field is NULL and doesn't change anything for current users. Tested with a dummy reset driver with several lookup entries. An example lookup table can be found below: static struct platform_device foobar_reset_dev = { .name = "foobar-reset", }; static struct reset_lookup_entry foobar_reset_lookup_entries[] = { { .con_id = "foo", id = 15 }, { .con_id = "bar", id = 5 }, }; static struct reset_lookup_table foobar_reset_lookup_table = { .dev_id = "foobar-device", .entries = foobar_reset_lookup_entries, .num_entries = ARRAY_SIZE(foobar_reset_lookup_entries), .dev = &foobar_reset_dev.dev, }; Cc: Sekhar Nori Cc: Kevin Hilman Cc: David Lechner Signed-off-by: Bartosz Golaszewski --- v1 -> v2: - renamed the new function to __reset_control_get_from_lookup() - added a missing break; when a matching entry is found - rearranged the code in __reset_control_get() - we can no longer get to the return at the bottom, so remove it and return from __reset_control_get_from_lookup() if __of_reset_control_get() fails - return -ENOENT from reset_contol_get() if we can't find a matching entry, prevously returned -EINVAL referred to the fact that we passed a device without the of_node which is no longer an error condition - add a comment about needing a sentinel in the lookup table v2 -> v3: - added the reset id number field to the lookup struct so that we don't need to rely on the array index v3 -> v4: - separated the driver and lookup table registration logic by adding a function meant to be called by machine-specific code that adds a lookup table to the internal list - the correct reset controller is now found by first finding the lookup table associated with it, then finding the actual reset controller by the associated device drivers/reset/core.c | 75 +++++++++++++++++++++++++++++++++++++++- include/linux/reset-controller.h | 32 +++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index da4292e9de97..fc6abdaf44f2 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -23,6 +23,9 @@ static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); +static DEFINE_MUTEX(reset_lookup_mutex); +static LIST_HEAD(reset_lookup_list); + /** * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device @@ -493,6 +496,76 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } EXPORT_SYMBOL_GPL(__of_reset_control_get); +/** + * reset_add_lookup_table - add a new reset lookup table + * @table: new reset lookup table + */ +void reset_add_lookup_table(struct reset_lookup_table *table) +{ + mutex_lock(&reset_lookup_mutex); + list_add_tail(&table->list, &reset_lookup_list); + mutex_unlock(&reset_lookup_mutex); +} +EXPORT_SYMBOL_GPL(reset_add_lookup_table); + +static struct reset_control * +reset_control_find_device(struct device *dev, unsigned int id, bool shared) +{ + struct reset_controller_dev *rcdev; + struct reset_control *rstc = NULL; + + mutex_lock(&reset_list_mutex); + + list_for_each_entry(rcdev, &reset_controller_list, list) { + if (rcdev->dev == dev) { + rstc = __reset_control_get_internal(rcdev, id, shared); + break; + } + } + + mutex_unlock(&reset_list_mutex); + + return rstc; +} + +static struct reset_control * +__reset_control_get_from_lookup(struct device *dev, const char *con_id, + bool shared, bool optional) +{ + const struct reset_lookup_entry *entry; + const char *dev_id = dev_name(dev); + struct reset_control *rstc = NULL; + struct reset_lookup_table *table; + int i; + + mutex_lock(&reset_lookup_mutex); + + list_for_each_entry(table, &reset_lookup_list, list) { + if (strcmp(table->dev_id, dev_id)) + continue; + + for (i = 0; i < table->num_entries; i++) { + entry = &table->entries[i]; + + if ((!con_id && !entry->con_id) || + !strcmp(con_id, entry->con_id)) { + rstc = reset_control_find_device(table->dev, + entry->id, + shared); + goto out; + } + } + } + +out: + mutex_unlock(&reset_lookup_mutex); + + if (!rstc) + return optional ? NULL : ERR_PTR(-ENOENT); + + return rstc; +} + struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) { @@ -500,7 +573,7 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, return __of_reset_control_get(dev->of_node, id, index, shared, optional); - return optional ? NULL : ERR_PTR(-EINVAL); + return __reset_control_get_from_lookup(dev, id, shared, optional); } EXPORT_SYMBOL_GPL(__reset_control_get); diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index adb88f8cefbc..b92090b177b7 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -22,6 +22,36 @@ struct reset_control_ops { int (*status)(struct reset_controller_dev *rcdev, unsigned long id); }; +/** + * struct reset_lookup_entry - a single entry in a reset lookup table + * + * @con_id: name of the reset line (can be NULL) + * @id: ID of the reset controller in the reset controller device + */ +struct reset_lookup_entry { + const char *con_id; + unsigned long id; +}; + +/** + * struct reset_lookup_table - reset controller lookup table + * + * @list: internal list of lookup tables + * @dev: reset controller device associated with this table + * @dev_id: name of the device associated with the resets in this table + * @entries: list of reset lookup entries + * @num_entries: number of reset lookup entries + */ +struct reset_lookup_table { + struct list_head list; + struct device *dev; + const char *dev_id; + struct reset_lookup_entry *entries; + size_t num_entries; +}; + +void reset_add_lookup_table(struct reset_lookup_table *table); + struct module; struct device_node; struct of_phandle_args; @@ -34,6 +64,7 @@ struct of_phandle_args; * @list: internal list of reset controller devices * @reset_control_head: head of internal list of requested reset controls * @of_node: corresponding device tree node as phandle target + * @dev: corresponding device (as fallback when not using OF) * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the * device tree to id as given to the reset control ops @@ -45,6 +76,7 @@ struct reset_controller_dev { struct list_head list; struct list_head reset_control_head; struct device_node *of_node; + struct device *dev; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); -- 2.16.1