From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E02635FF73 for ; Mon, 23 Feb 2026 10:06:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771841216; cv=none; b=POFuzUSu3Fdp0KgTthyJ/tZw7oOO1A3Ebl7VXHe3xzDUCdx+5eoeNaHDpm1+KmxKyOqBdtDu3Cc5e9AVQKuFYLWwXdaHa8icE7E+tuBiOkhycI9PJ+ma0I5F+i1JTgVhIG1jGuGDfvv+ZPZ7pJ6Ryo/HUU6X3czvDvpMTvFTXfA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771841216; c=relaxed/simple; bh=jum6Qho+wp9sD55zthJFwhWw/JVxWHj7gRydsVtAeno=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KPUawfQ43RzCEyTwEkO6L9vvi7+ZO/Br6qEaFpLlEgJKde1AYjWosn9wTFCju0+8HLcTql/h0nD0SUQdJSvCbB9gHdJ/oNNJe6K+A1/d/tsj7tFV2DdO5o0LOc4Ua0CS5J5JDAwwJ3kc/GxbDyNP9l3w6IlEGq/YlaxgNumWGso= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=kouCVdFY; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=c0Jav1vU; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="kouCVdFY"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="c0Jav1vU" Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61N8csZ01857015 for ; Mon, 23 Feb 2026 10:06:53 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 9CYcjONxBsNvTa+zYyCl8Cx7PqH2W10kWCvU/1Yb+a8=; b=kouCVdFY+cXOR+zm iHn3h3CpCONYnU11I8X/CS+X+4dTqGzNR1Ta7080oNpnZEKPW425c2obCYUNcmHQ X/KuqAsHcBu5Qw2XwzKLGBY8OojY7G1foWOq+sftA2Oc8yH2JLR87/pOu2R1MiVq Oho3uqLkLUIwHBS3BTaH20zlEOM0Ro5ONwMPnhh7R+YSrhYCzalM+LU5PsPXR3/L p7toUhhCLUvYuf2xgpmsKqirNkYHLhqgEim6G/jThWOjpKuu2mps9DYfl+0UCRKD ZF03l7TWbSgwnM0O+ZLsR6zr8rgCUKeBQZpJ295qPt9GKwxvxcEJVvECFYkMoWHy 2yCBYw== Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cf5vgvba1-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 23 Feb 2026 10:06:53 +0000 (GMT) Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-8cb37db8b79so1409131485a.3 for ; Mon, 23 Feb 2026 02:06:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771841212; x=1772446012; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=9CYcjONxBsNvTa+zYyCl8Cx7PqH2W10kWCvU/1Yb+a8=; b=c0Jav1vUYWPN1jmMJ7eKXcQCVC9WKdlLxK7ddjeHoyGu5Mi2jzE2mD6iw59mHrBPbh dsSyvrs9DqKapR26Ur3ZF4wogrfs+bP4wrtMTSqqC+gryFUyDjDr0y7oqkIEW7C7Aalv mJh7ZmEXxSFKGQ6JlPReiV9IoY6CPOy+6qCS7lAlzDmEjCFcjfyJDwd3QG2LNDE3v9ep v8RuU4fF67JvKn30PnfxuTJLPhgdbvIU0KdNUzDwOJ0UoNVf8fIhb21rU8isS0U2gdS+ QXnpBnRRmrfbRzV2MHDINnZNYSqc+wMjstieaS5wMt2A5fObeQeXE+nJe8nHbWG3hkL0 7M0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771841212; x=1772446012; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=9CYcjONxBsNvTa+zYyCl8Cx7PqH2W10kWCvU/1Yb+a8=; b=bf+iqsEK5YjjzcA8SZSZKt5UwOvd7Ib4X71qEc5e7IrxET1gaTsXmVqyF3y0eJ0olq u3mL96QZ2g0eaqfc+M7rFmhFHwR1a5lN6N/0/SHMPQMPwV2ugwK6e8HgYKYxGpRv9BrZ 4I3GfW1TiOFVh8F6Wf0kvBGEVaxG0UN3B+JE0EdKS5Mi/nsvINfHwA0ClVmVHy1JCz1e 4edNrUJCU7dg6//zhp+tcuBZLXJRXKtskMIbSpR+mkjYtHPg/lmME1TQnjy2tToN8wuJ YBkD84bM05MHuMz7vJlUoGAXyqOJh/pRIhHNXU7dSYelP6fzeCWA7GOxG4AoCQc45Q6+ 4pCQ== X-Gm-Message-State: AOJu0YxptRx+luPd2kqnvx9+Aw6sll8twjr13VamJKAjzIY5T5UENuNi yyIo/6WWgWOi+8X7p0uGLmXolyiJ8pR6QuZdC4JutukjkUeeMv2dyGQSKo2ucYdNbNZpHLbu1Nz QaV02Bn/ghRm0ZgeWIYjFTHyOp8SO3xNUOQlkemMLvkfzmHjTCZq2SQEXpSeGXTJVW2k= X-Gm-Gg: AZuq6aJyK5tH8YGp8jM+KK2XAOsWRQLVzsPrCVDr316QJ5ZOJkLWKnfntyUnFzYStud yl/Yl3KA6uu/zuIAPcMsatVi4etQRsyNJvRxHkP/mLTITsxlqarravG01dQzjVxl8XvZKrPzPiZ tl7J2IuMmiS3fYwPQbzyw3havuBr5rpLskPfqY0mLRJM7j57qlRx00uasbPWbzQw0+38B/iy3bv /9+tJdKyzQ7xViUey651HP/SrIv8J35VMjm6sWpjyBCD2ZLBV8hcHSFyi4vWeZqJAdw8jz3RZjU yce95nMB+lCQH6RVNIGut+mi9T/TpK8+4w3RePrpSdc8G77tKqqVVKAeW0otdOy3jlvShydbW2v v+7MZqkf+aelKd6sVpzAyq/m+5PvMrPvFUepsGISPlStTW+ej1FyI X-Received: by 2002:a05:620a:1927:b0:8c6:a8a6:e164 with SMTP id af79cd13be357-8cb8ca64fc7mr1018058785a.45.1771841212095; Mon, 23 Feb 2026 02:06:52 -0800 (PST) X-Received: by 2002:a05:620a:1927:b0:8c6:a8a6:e164 with SMTP id af79cd13be357-8cb8ca64fc7mr1018056085a.45.1771841211641; Mon, 23 Feb 2026 02:06:51 -0800 (PST) Received: from brgl-qcom.local ([2a01:cb1d:dc:7e00:bd71:422c:5e83:8b37]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43970d54760sm18288885f8f.35.2026.02.23.02.06.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Feb 2026 02:06:51 -0800 (PST) From: Bartosz Golaszewski Date: Mon, 23 Feb 2026 11:06:26 +0100 Subject: [PATCH v2 13/14] reset: convert reset core to using firmware nodes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260223-reset-core-refactor-v2-13-5e5a7289190c@oss.qualcomm.com> References: <20260223-reset-core-refactor-v2-0-5e5a7289190c@oss.qualcomm.com> In-Reply-To: <20260223-reset-core-refactor-v2-0-5e5a7289190c@oss.qualcomm.com> To: Krzysztof Kozlowski , Philipp Zabel Cc: linux-kernel@vger.kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15369; i=bartosz.golaszewski@oss.qualcomm.com; h=from:subject:message-id; bh=jum6Qho+wp9sD55zthJFwhWw/JVxWHj7gRydsVtAeno=; b=owEBbQKS/ZANAwAKAQWdLsv/NoTDAcsmYgBpnCarjvUpx2ZGaFo9jppQnyJsivuBQn76AuAEf feBXACKCAaJAjMEAAEKAB0WIQSR5RMt5bVGHXuiZfwFnS7L/zaEwwUCaZwmqwAKCRAFnS7L/zaE wzEDEACrENyyjBwtziDj1aynCfR/M9H2eiaTxB+GXK/Lw7eDKcnB3bYAQz2DgxDBOvS4EkwyHsZ xtbo762U23WuhRsWVSxT/NVi++7WLvuzgXOGqTnLHvoCbuwQVvB8tDc/Q/ymWrFFcGs1zBn/JdX uIoYpE3kPQSTf5pZdozuqlBO63+sc5cYlo+x8Px1n+HPcJBzNsHUCjYJ9JdbJkwXDdlCjjszY9b Jw86wJBb5Qt4LN3sZgCdCVgb5gTK4+KZUdQSDoNKza8G42HaWKw/qCPxzkMtiqToucNDBfGtrDP MTEIu+GR+YNnq9fLwzf2tjNiJf2fqleNF/AgapjlIml41KiGUK5FLHaKkP2WwXUVyU7sMoWs6zk BAJJoFEGQlSDAqfI/Eu6nvJLTLZ3Gz2lWCtCvhoxNjuMBtOao9x5y+CDIUSYTtLOdBetdeopFeO uWrQbvKQ2kJAIAoK/NglieGnuHwhJIGgVoIjHLw9RSFqiJTdkI80LO+va3w5IptJENBdEx+Vm6O JS2hBS9IZ4tkjmX5OvOuT50FTvc0RVYDvHiQ49P6nFWHTfUP5PN50vE/KnxibI4NCLxqLnZqs2A LJuaCdxsNTzACYH0kUSaDpHW2J72DfZZr39GmZK+dWbRkYQAyTrRky4TkkxHOGDEn5ocC8DI/Bx 2uaarZs077GZ8ww== X-Developer-Key: i=bartosz.golaszewski@oss.qualcomm.com; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjIzMDA4NiBTYWx0ZWRfX6fXG39XjPxPi HrFlaS4JaAnYqHpySllmdwXyCCcp6kqo/h2nIZFF51P5uiMwLXi9nbUyVBH0/9a9Y2MUEA9SmL/ 4qIKDFn7CXLSa9KDJt8CtpHy3WQElfG1WIVma/pupryMhZ1GOtcNmUDRHR7u52VUwWf87h1Ms8s FDVCRAcuvPRBwKfjBlGCz3z4Q2nreBPsNZ+dgsM1AIzOqOKsoFY25h0qO2SzKrgSCW10rFidLuI 8m26T7shJFrCGl1bCh4wQ2mmYvFIMPOIEz2YDa524rOSRIYwZKO9YENigG8swQT6Ft9bmWux9xh tVRrSbxYzuxQrzHSFKUzJwKPnq1bJ0Ja/tQ1AsEYxcCZzJBqYjjpzWE5ZSCpuT8ZhWOQdKK3JIv +88zW1Z3ze/du4YG1NhHVrfTmK3250wT+06q6M3ilah+Yi9ntQKD6DXjfv+fKp20mS8asFA0Udy Uvy5Z/MFqaKAYtHbXJA== X-Authority-Analysis: v=2.4 cv=W+A1lBWk c=1 sm=1 tr=0 ts=699c26bd cx=c_pps a=qKBjSQ1v91RyAK45QCPf5w==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=EUspDBNiAAAA:8 a=EAxQ06SQvwH9g5cYwaQA:9 a=QEXdDO2ut3YA:10 a=NFOGd7dJGGMPyQGDc5-O:22 X-Proofpoint-GUID: zg1WVNXz-VK8tghl8uOMzBESaK68a4RY X-Proofpoint-ORIG-GUID: zg1WVNXz-VK8tghl8uOMzBESaK68a4RY X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-23_02,2026-02-20_04,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 spamscore=0 bulkscore=0 adultscore=0 priorityscore=1501 clxscore=1015 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602230086 With everything else now in place, we can convert the remaining parts of the reset subsystem to becoming fwnode-agnostic - meaning it will work with all kinds of firmware nodes, not only devicetree. To that end: extend struct reset_controller_dev with fields taking information relevant for using firmware nodes (which mirrors what we already do for OF-nodes) and limit using of_ APIs only to where it's absolutely necessary (mostly around the of_xlate callback). For backward compatibility of existing drivers we still support OF-nodes but firmware nodes become the preferred method. Signed-off-by: Bartosz Golaszewski --- drivers/reset/core.c | 154 +++++++++++++++++++++++---------------- include/linux/reset-controller.h | 14 +++- 2 files changed, 103 insertions(+), 65 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 1ac68371b77101b18db5a16c6471cfffee0dce7c..174b50eda01948bc697529a549cf38bfca7180f8 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -81,13 +81,13 @@ struct reset_control_array { /** * struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices - * @of_args: phandle to the reset controller with all the args like GPIO number + * @ref_args: Reference to the reset controller with all the args like GPIO number * @swnode: Software node containing the reference to the GPIO provider * @list: list entry for the reset_gpio_lookup_list * @adev: Auxiliary device representing the reset controller */ struct reset_gpio_lookup { - struct of_phandle_args of_args; + struct fwnode_reference_args ref_args; struct fwnode_handle *swnode; struct list_head list; struct auxiliary_device adev; @@ -98,24 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev) if (rcdev->dev) return dev_name(rcdev->dev); - if (rcdev->of_node) - return rcdev->of_node->full_name; + if (rcdev->fwnode) + return fwnode_get_name(rcdev->fwnode); return NULL; } /** - * of_reset_simple_xlate - translate reset_spec to the reset line number + * fwnode_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device - * @reset_spec: reset line specifier as found in the device tree + * @reset_spec: reset line specifier as found in firmware * - * This static translation function is used by default if of_xlate in + * This static translation function is used by default if fwnode_xlate in * :c:type:`reset_controller_dev` is not set. It is useful for all reset * controllers with 1:1 mapping, where reset lines can be indexed by number * without gaps. */ -static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, - const struct of_phandle_args *reset_spec) +static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev, + const struct fwnode_reference_args *reset_spec) { if (reset_spec->args[0] >= rcdev->nr_resets) return -EINVAL; @@ -129,9 +129,17 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { - if (!rcdev->of_xlate) { - rcdev->of_reset_n_cells = 1; - rcdev->of_xlate = of_reset_simple_xlate; + if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate)) + return -EINVAL; + + if (rcdev->of_node) { + rcdev->fwnode = of_fwnode_handle(rcdev->of_node); + rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells; + } + + if (rcdev->fwnode && !rcdev->fwnode_xlate) { + rcdev->fwnode_reset_n_cells = 1; + rcdev->fwnode_xlate = fwnode_reset_simple_xlate; } INIT_LIST_HEAD(&rcdev->reset_control_head); @@ -917,7 +925,7 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, adev->id = id; adev->name = "gpio"; adev->dev.parent = parent; - adev->dev.platform_data = &rgpio_dev->of_args; + adev->dev.platform_data = &rgpio_dev->ref_args; adev->dev.release = reset_gpio_aux_device_release; device_set_node(&adev->dev, rgpio_dev->swnode); @@ -937,18 +945,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, return 0; } -static void reset_gpio_add_devlink(struct device_node *np, +static void reset_gpio_add_devlink(struct fwnode_handle *fwnode, struct reset_gpio_lookup *rgpio_dev) { struct device *consumer; /* - * We must use get_dev_from_fwnode() and not of_find_device_by_node() + * We must use get_dev_from_fwnode() and not ref_find_device_by_node() * because the latter only considers the platform bus while we want to * get consumers of any kind that can be associated with firmware * nodes: auxiliary, soundwire, etc. */ - consumer = get_dev_from_fwnode(of_fwnode_handle(np)); + consumer = get_dev_from_fwnode(fwnode); if (consumer) { if (!device_link_add(consumer, &rgpio_dev->adev.dev, DL_FLAG_AUTOREMOVE_CONSUMER)) @@ -968,15 +976,23 @@ static void reset_gpio_add_devlink(struct device_node *np, */ } +/* TODO: move it out into drivers/base/ */ +static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left, + const struct fwnode_reference_args *right) +{ + return left->fwnode == right->fwnode && left->nargs == right->nargs && + !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs); +} + /* * @np: OF-node associated with the consumer - * @args: phandle to the GPIO provider with all the args like GPIO number + * @args: Reference to the GPIO provider with all the args like GPIO number */ -static int __reset_add_reset_gpio_device(struct device_node *np, - const struct of_phandle_args *args) +static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode, + const struct fwnode_reference_args *args) { struct property_entry properties[3] = { }; - unsigned int offset, of_flags, lflags; + unsigned int offset, flags, lflags; struct reset_gpio_lookup *rgpio_dev; struct device *parent; int ret, prop = 0; @@ -987,7 +1003,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, * args[1]: GPIO flags * TODO: Handle other cases. */ - if (args->args_count != 2) + if (args->nargs != 2) return -ENOENT; /* @@ -998,7 +1014,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, lockdep_assert_not_held(&reset_list_mutex); offset = args->args[0]; - of_flags = args->args[1]; + flags = args->args[1]; /* * Later we map GPIO flags between OF and Linux, however not all @@ -1008,33 +1024,31 @@ static int __reset_add_reset_gpio_device(struct device_node *np, * FIXME: Find a better way of translating OF flags to GPIO lookup * flags. */ - if (of_flags > GPIO_ACTIVE_LOW) { + if (flags > GPIO_ACTIVE_LOW) { pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n", - of_flags, offset); + flags, offset); return -EINVAL; } struct gpio_device *gdev __free(gpio_device_put) = - gpio_device_find_by_fwnode(of_fwnode_handle(args->np)); + gpio_device_find_by_fwnode(args->fwnode); if (!gdev) return -EPROBE_DEFER; guard(mutex)(&reset_gpio_lookup_mutex); list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { - if (args->np == rgpio_dev->of_args.np) { - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) { - /* - * Already on the list, create the device link - * and stop here. - */ - reset_gpio_add_devlink(np, rgpio_dev); - return 0; - } + if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) { + /* + * Already on the list, create the device link + * and stop here. + */ + reset_gpio_add_devlink(fwnode, rgpio_dev); + return 0; } } - lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW); + lflags = GPIO_PERSISTENT | (flags & GPIO_ACTIVE_LOW); parent = gpio_device_to_device(gdev); properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio"); properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags); @@ -1044,43 +1058,43 @@ static int __reset_add_reset_gpio_device(struct device_node *np, if (!rgpio_dev) return -ENOMEM; - rgpio_dev->of_args = *args; + rgpio_dev->ref_args = *args; /* - * We keep the device_node reference, but of_args.np is put at the end - * of __fwnode_reset_control_get(), so get it one more time. + * We keep the fwnode_handle reference, but ref_args.fwnode is put at + * the end of __fwnode_reset_control_get(), so get it one more time. * Hold reference as long as rgpio_dev memory is valid. */ - of_node_get(rgpio_dev->of_args.np); + fwnode_handle_get(rgpio_dev->ref_args.fwnode); rgpio_dev->swnode = fwnode_create_software_node(properties, NULL); if (IS_ERR(rgpio_dev->swnode)) { ret = PTR_ERR(rgpio_dev->swnode); - goto err_put_of_node; + goto err_put_fwnode; } ret = reset_create_gpio_aux_device(rgpio_dev, parent); if (ret) goto err_del_swnode; - reset_gpio_add_devlink(np, rgpio_dev); + reset_gpio_add_devlink(fwnode, rgpio_dev); list_add(&rgpio_dev->list, &reset_gpio_lookup_list); return 0; err_del_swnode: fwnode_remove_software_node(rgpio_dev->swnode); -err_put_of_node: - of_node_put(rgpio_dev->of_args.np); +err_put_fwnode: + fwnode_handle_put(rgpio_dev->ref_args.fwnode); kfree(rgpio_dev); return ret; } -static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args, - bool gpio_fallback) +static struct reset_controller_dev * +__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback) { + struct fwnode_reference_args *rc_args; struct reset_controller_dev *rcdev; - struct of_phandle_args *rc_args; lockdep_assert_held(&reset_list_mutex); @@ -1089,10 +1103,10 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a device_is_compatible(rcdev->dev, "reset-gpio")) { rc_args = dev_get_platdata(rcdev->dev); - if (of_phandle_args_equal(args, rc_args)) + if (fwnode_reference_args_equal(args, rc_args)) return rcdev; } else { - if (args->np == rcdev->of_node) + if (args->fwnode == rcdev->fwnode) return rcdev; } } @@ -1106,27 +1120,26 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; bool gpio_fallback = false; - struct device_node *node = to_of_node(fwnode); struct reset_control *rstc = ERR_PTR(-EINVAL); struct reset_controller_dev *rcdev; - struct of_phandle_args args; - int rstc_id; + struct fwnode_reference_args args; + struct of_phandle_args of_args; + int rstc_id = -EINVAL; int ret; if (!fwnode) return ERR_PTR(-EINVAL); if (id) { - index = of_property_match_string(node, - "reset-names", id); + index = fwnode_property_match_string(fwnode, "reset-names", id); if (index == -EILSEQ) return ERR_PTR(index); if (index < 0) return optional ? NULL : ERR_PTR(-ENOENT); } - ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", - index, &args); + ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells", + 0, index, &args); if (ret == -EINVAL) return ERR_PTR(ret); if (ret) { @@ -1137,16 +1150,16 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind * There can be only one reset-gpio for regular devices, so * don't bother with the "reset-gpios" phandle index. */ - ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells", - 0, &args); + ret = fwnode_property_get_reference_args(fwnode, "reset-gpios", + "#gpio-cells", 0, 0, &args); if (ret) return optional ? NULL : ERR_PTR(ret); gpio_fallback = true; - ret = __reset_add_reset_gpio_device(node, &args); + ret = __reset_add_reset_gpio_device(fwnode, &args); if (ret) { - of_node_put(args.np); + fwnode_handle_put(args.fwnode); return ERR_PTR(ret); } } @@ -1159,15 +1172,30 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind goto out_put; } - if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { + if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) { rstc = ERR_PTR(-EINVAL); goto out_put; } - rstc_id = rcdev->of_xlate(rcdev, &args); + if (rcdev->of_xlate && is_of_node(fwnode)) { + ret = of_parse_phandle_with_args(to_of_node(fwnode), + gpio_fallback ? "reset-gpios" : "resets", + gpio_fallback ? "#gpio-cells" : "#reset-cells", + gpio_fallback ? 0 : index, + &of_args); + if (ret) { + rstc = ERR_PTR(ret); + goto out_put; + } + + rstc_id = rcdev->of_xlate(rcdev, &of_args); + of_node_put(of_args.np); + } else if (rcdev->fwnode_xlate) { + rstc_id = rcdev->fwnode_xlate(rcdev, &args); + } if (rstc_id < 0) { rstc = ERR_PTR(rstc_id); - goto out_put; + goto out_put; } flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; @@ -1176,7 +1204,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind rstc = __reset_control_get_internal(rcdev, rstc_id, flags); out_put: - of_node_put(args.np); + fwnode_handle_put(args.fwnode); return rstc; } diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index 2fecb4edeba1a2b1f5f5db2b34c867362c5f9c18..2f7a1217d0ec6dba4f8831fb8c66308188f7a339 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -5,6 +5,8 @@ #include #include +struct fwnode_handle; +struct fwnode_reference_args; struct reset_controller_dev; /** @@ -38,8 +40,12 @@ struct of_phandle_args; * @of_node: corresponding device tree node as phandle target * @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, defaults - * to :c:func:`of_reset_simple_xlate`. + * device tree to id as given to the reset control ops + * @fwnode: firmware node associated with this device + * @fwnode_reset_n_cells: number of cells in reset line specifiers + * @fwnode_xlate: translation function to translate from firmware specifier to + * id as given to the reset control ops, defaults to + * :c:func:`fwnode_reset_simple_xlate` * @nr_resets: number of reset controls in this reset controller device * @lock: synchronizes concurrent access to the structure's fields */ @@ -53,6 +59,10 @@ struct reset_controller_dev { int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); + struct fwnode_handle *fwnode; + int fwnode_reset_n_cells; + int (*fwnode_xlate)(struct reset_controller_dev *rcdev, + const struct fwnode_reference_args *reset_spec); unsigned int nr_resets; struct mutex lock; }; -- 2.47.3