From nobody Thu Apr 9 12:08:20 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 EAFAB3B961C for ; Mon, 9 Mar 2026 12:43:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773060185; cv=none; b=Z0npJ/hF7xxO0wt8cV6wK8LIosgYjEAh0X0oAQ4aqPsxzmRBAyqN4AhtFkh1PpIg87jb83yubydmgJOIhaQHCrrOgXloUhSaWokiq8jYX0R3hyMMsnR5k6pLZZfknBCZknfvFWPwAX0EMgL/h5rsU5/uFovyYl45pTFy17SPJFs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773060185; c=relaxed/simple; bh=OUFgb8Qz0GK1/gaXT/PVQevLnAPBCQbbPDyCF7sXUFQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dP9KpFPEgssU/IkOH5WbevGaRi18zGcwyjqxssTr63FW82WTaIgrPwJo9p5w31K9C/h7LQTTRIY7/AvgYDIMKR9kpTB5Uf3EFaWbk6Pd5iuPSAN0GsYhahZu60Pkfju1CKCu1ptH+5cChM/FXaE+scPkfJIIuFaWV1QS5W7Noh8= 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=dDTyFeQe; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=DtcfYXfd; arc=none smtp.client-ip=205.220.180.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="dDTyFeQe"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="DtcfYXfd" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6298WB3s3773182 for ; Mon, 9 Mar 2026 12:43:03 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= kXfMPd1XaYmr+m0Ul6mK7sQ3BrtNsGiWSmTvc1lddOY=; b=dDTyFeQe+yLivZB+ oWYCktrl4Pg7N8S4oGzl4BGFM+dvOSA37OYEof0aGeXasiKo+GE8iTPJo44CB1EL ROYVPkt4czHhowA74QrVWKtMu+UVrBOHW1Eo5Fo9/T2YGJFJ9IM11sCiOzcZK+0Z o/yKgfc1Z9n7nsTLBgbtpsWiG5W2eCwwhWAYyTiicwf98THeev+6jGjUPuIGMaQv tf6iuXwW7+54NON/iCwyZVbTELXPEW9tGk8o214un8mDR+eTTPItvwIhxJzOaN2m wp+KOPiz4PmD6unN2tB/eVeLvby0kmSm7GTSfEVfiWZDvJXJLf0l1zg7PixB6DTA W8XL8A== 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 4cstsa8uqg-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 09 Mar 2026 12:43:02 +0000 (GMT) Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-8cb706313beso1485284285a.3 for ; Mon, 09 Mar 2026 05:43:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1773060182; x=1773664982; 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=kXfMPd1XaYmr+m0Ul6mK7sQ3BrtNsGiWSmTvc1lddOY=; b=DtcfYXfdeXBcuW/E0jHqVo5YKzjJOZwuivAwYZ/I4d8qBEhmZOSfABOheKe986vuDc TdeuIP7MVj53NSz2UF/1DHZQgvesullWhnPgbj2uV2u9O5LHaiDzT+vDYmSdkm+TfpQF n52pAIBT5l8ZIytjLBehvdUO/WjaevIGqDGpEbk1ndspxhkyprzTRXnZ4aYCJvc4airH ABSLNaatEJzKQaJH5z+rih9WVh7b1xAXzkKHnVjDfE7WItnncUXQcUcVt5ZW12o918ND LAkmCpMlysARIl6DKNmKiOCVtCKN46t7VNtbURupRFwtAnTcNik1wUFKApEuwJ+IGtrt mdrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773060182; x=1773664982; 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=kXfMPd1XaYmr+m0Ul6mK7sQ3BrtNsGiWSmTvc1lddOY=; b=DrKpFB7uoC11HdAsSJZk/5/49/3fnra6MgxlLrKtCGxyNPjikQUj/MmCfQPHarcotE AERsxVS/2YHKFELtDRx5SuovDy3heMOT9xVH3OgsGl1g+WnIKxfTdl7qef2pyrv8l+rT O9KaAC+EG/ClmygWNQRLNniCrZaQnoirsLclqyT7r+0hJPu5gv5YPEc/EpK1vUJiNh8k PugktqR+z1nMg5f/fuXALPFp22BShG+KcdpMKsJtoRCDqZRHq/m7TfDxu4Orq7SywSBH RqwLvIKgSPLyg+ndh9CL4Nyml4O50lMZnPhVBwdC0XCkmeE/h6uWYR8FpCHgvfiyasOD WUxg== X-Forwarded-Encrypted: i=1; AJvYcCWrbJd1WwVwBsvujy7P8qkQUsKcnjtJonLlP1MuyoKqNKI0iAqAnbBVAbnj3NNDTkXMcHW0N5NjYZxc2Xo=@vger.kernel.org X-Gm-Message-State: AOJu0Yzu91hDStVLrDj3GFrVmLqMNz1JcCZWyi7t2CS0C4ZCAvuNLt89 RPeSLbL9xwe1WHAd+z1hgtU67P+rq1k0oWba5QljeqgEcZfpvC70xOquuA6sQzIAo8FKJ+Qxrdt Mqj4LCN15YdCBu7fuGAY1R8jP3qX0Rv2tvCE96SgUZe5JqVIrIZ2fcliqokEZtbFWM/I= X-Gm-Gg: ATEYQzxcCgRceP6qAU3X4e0tf/wVCzs3HhMGNcM5/lElIVtDJEqjwGJfvroXQ72jA1a HoXujdAAonGTTJ5k373xak95tOlAWCtA5mVcflh7lEDi7VlDrfnAQK8w0Xo/uJe4xWXTKJAWDff C9HYs9mm6wa9Z890czxf1Uvrc70Mc0lO336a7xXRjo2oANmXVVn0YLVatfYj2c3ds3iOv5LUvX3 a3hY6UGnps0+DTifj2KrSy3pB3NCoYgraH9/fKpWBFwkLIBSBNhoDUpYDJtKvqGF/5s77ZFNPcF 13DJdA+kJ8SGlT1+IRyv4hfMoxXhA504dfine0lrOLwTNFKePritQ/gl5F16jVptNDAizuUqxS0 84e+75ZojC7rjGdEQ7+9bFuhRjvA8a8M7d58h3jYFGOUIAUTs7JWK X-Received: by 2002:a05:620a:bd5:b0:8c7:a53:4d17 with SMTP id af79cd13be357-8cd6d36d2c8mr1380873685a.21.1773060181887; Mon, 09 Mar 2026 05:43:01 -0700 (PDT) X-Received: by 2002:a05:620a:bd5:b0:8c7:a53:4d17 with SMTP id af79cd13be357-8cd6d36d2c8mr1380867385a.21.1773060181326; Mon, 09 Mar 2026 05:43:01 -0700 (PDT) Received: from brgl-qcom.local ([2a01:cb1d:dc:7e00:494a:62d9:d95b:cb98]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48539e574b5sm107803345e9.8.2026.03.09.05.42.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Mar 2026 05:43:00 -0700 (PDT) From: Bartosz Golaszewski Date: Mon, 09 Mar 2026 13:42:38 +0100 Subject: [PATCH v2 2/6] gpio: move hogs into GPIO core 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: quoted-printable Message-Id: <20260309-gpio-hog-fwnode-v2-2-4e61f3dbf06a@oss.qualcomm.com> References: <20260309-gpio-hog-fwnode-v2-0-4e61f3dbf06a@oss.qualcomm.com> In-Reply-To: <20260309-gpio-hog-fwnode-v2-0-4e61f3dbf06a@oss.qualcomm.com> To: Linus Walleij , Bartosz Golaszewski , Geert Uytterhoeven , Frank Rowand , Mika Westerberg , Andy Shevchenko , Aaro Koskinen , Janusz Krzysztofik , Tony Lindgren , Russell King , Jonathan Corbet , Shuah Khan Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org, linux-doc@vger.kernel.org, brgl@kernel.org, Bartosz Golaszewski , Mika Westerberg X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=14044; i=bartosz.golaszewski@oss.qualcomm.com; h=from:subject:message-id; bh=OUFgb8Qz0GK1/gaXT/PVQevLnAPBCQbbPDyCF7sXUFQ=; b=owEBbQKS/ZANAwAKAQWdLsv/NoTDAcsmYgBprsBId9xcXzbOth7Gymbfaqjt9FRe/KfnJPjDp N79jEB98kuJAjMEAAEKAB0WIQSR5RMt5bVGHXuiZfwFnS7L/zaEwwUCaa7ASAAKCRAFnS7L/zaE w32CEAC8sYufJWmJsDubtmeQtDqgG+SKFTxD8RZzD13supY6t4IIE/KWCXM0gTcC3W6PjEDHNfP KNCQIiRTOdAomxOA6EqCH+yCZ11JB4IGziV2yWdLndApXo1Ed8xDy7SWPZ8G0/vHSBs/boYUoPK nQPUEsPZ0ISPv6tgv55CH18vSkiefuBCcr5bJg4s8JdwyVqkB83541iB/8Jvi+yT6JtbV5EVqv8 aHAJcuvw2BbG9Rcf6UypwtNZbY1gycDWmzEAIb4tKn0qLkRKUH+RhCNGR2YGBNUXrLJeSq3QTxy l2nlWHBIb+k/tK1Clv9x9MBRLOZeBHxjOZ9oSh+wnsOe4086HiPRXsHagBoIFYyYjvK9dXWHw+E RLl3I1yrTBvSg60lM7nACrMZn+tgg771KEvO2zzT9Q2fUjLdLBQy5WD+rPoxYAbaYY8a4ul5ziK lVHD/sNM7IAO35s62jap6cE2dnEQ/wQPCK10EeQOd/WiLvaWOjPUjfRbZU6+Qkw814I2DAdVzn/ E8S09juG5h310jQhecvQJj/ExFwi68IOn8bb53jxUemooNiCRPwnQPubxPjtVb5Zw4eV50R5WJ+ fkjRDsxOe9e0HJGFpNedW4poL828rzAEOPZF/t7FS1rgdZwSeFLrm2Dw/Fo/f/qLR+M90pwf7pF 6NdvOsvUttOfNNA== X-Developer-Key: i=bartosz.golaszewski@oss.qualcomm.com; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 X-Proofpoint-GUID: JgGaw6xjzCepFzS91tR6g-InC2PYEl4g X-Authority-Analysis: v=2.4 cv=I+Vohdgg c=1 sm=1 tr=0 ts=69aec056 cx=c_pps a=qKBjSQ1v91RyAK45QCPf5w==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=Yq5XynenixoA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=QyXUC8HyAAAA:8 a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8 a=WIzJRdd3zNLVKdG7TxsA:9 a=QEXdDO2ut3YA:10 a=NFOGd7dJGGMPyQGDc5-O:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMzA5MDExNiBTYWx0ZWRfXz/vP2y3WSm57 W6J/RGolieGAW+fYLvfqnXJTZA0n/V+thzWAkgAe1GQey75clF55SNYSnIqn5EE/ssI/tVA+cUE UKA4zaks0+CwmJ+sYoKI064PpCgR7xJtmgmhs00D/VYo5jSbCOO9QvAAKnN/UNyWoLQhWnJLFe7 jClEGvZSUy2VU2MU/pJw/qMtx9+rhEPU9uxYxzmbPZ+94TH5Zd7Lo1cUSlEVhpQ/gAjnQoVkzHp GU7bXovJujpNv7HIc5fKIzjoHDjZP6/6l41887OSJ9nXUBFfc0sq7NhKnq95Y8wXCmNIFXKuxYz gC3Z1bbvlV7SYKP0yAxTbzKU0iAe8ACTNcrmTO9YEf1MPgpT1THPLMUhHrmbK9IUrJzMSYpBX3B pYN7A01ceuOfeqOmdTvW1djR51XOEhubp2ewSUwYS1l1Q62/Se6lZ9F7OAATawx6PybZ0c4e8be 6gQ0+ukDPhI6HoK7bBg== X-Proofpoint-ORIG-GUID: JgGaw6xjzCepFzS91tR6g-InC2PYEl4g X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-03-09_03,2026-03-06_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 spamscore=0 malwarescore=0 suspectscore=0 bulkscore=0 lowpriorityscore=0 clxscore=1015 priorityscore=1501 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2603090116 Refactor line hogging code by moving the parts duplicated in gpiolib-acpi-core.c and gpiolib-of.c into gpiolib.c, leaving just the OF-specific bits in the latter. This makes fwnode the primary API for setting up hogs and allows to use software nodes in addition to ACPI and OF nodes. Reviewed-by: Mika Westerberg Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-acpi-core.c | 70 ------------------- drivers/gpio/gpiolib-of.c | 143 +++++------------------------------= ---- drivers/gpio/gpiolib-of.h | 10 +++ drivers/gpio/gpiolib.c | 98 ++++++++++++++++++++++++++- drivers/gpio/gpiolib.h | 3 + 5 files changed, 125 insertions(+), 199 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-c= ore.c index ced6375d1badf9e113e708ce4bc9f83071f9acca..09f860200a059b1d17c652b9aa6= 6a49abea3cb4f 100644 --- a/drivers/gpio/gpiolib-acpi-core.c +++ b/drivers/gpio/gpiolib-acpi-core.c @@ -1220,75 +1220,6 @@ static void acpi_gpiochip_free_regions(struct acpi_g= pio_chip *achip) } } =20 -static struct gpio_desc * -acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, - struct fwnode_handle *fwnode, - const char **name, - unsigned long *lflags, - enum gpiod_flags *dflags) -{ - struct gpio_chip *chip =3D achip->chip; - struct gpio_desc *desc; - u32 gpios[2]; - int ret; - - *lflags =3D GPIO_LOOKUP_FLAGS_DEFAULT; - *dflags =3D GPIOD_ASIS; - *name =3D NULL; - - ret =3D fwnode_property_read_u32_array(fwnode, "gpios", gpios, - ARRAY_SIZE(gpios)); - if (ret < 0) - return ERR_PTR(ret); - - desc =3D gpiochip_get_desc(chip, gpios[0]); - if (IS_ERR(desc)) - return desc; - - if (gpios[1]) - *lflags |=3D GPIO_ACTIVE_LOW; - - if (fwnode_property_present(fwnode, "input")) - *dflags |=3D GPIOD_IN; - else if (fwnode_property_present(fwnode, "output-low")) - *dflags |=3D GPIOD_OUT_LOW; - else if (fwnode_property_present(fwnode, "output-high")) - *dflags |=3D GPIOD_OUT_HIGH; - else - return ERR_PTR(-EINVAL); - - fwnode_property_read_string(fwnode, "line-name", name); - - return desc; -} - -static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) -{ - struct gpio_chip *chip =3D achip->chip; - - device_for_each_child_node_scoped(chip->parent, fwnode) { - unsigned long lflags; - enum gpiod_flags dflags; - struct gpio_desc *desc; - const char *name; - int ret; - - if (!fwnode_property_present(fwnode, "gpio-hog")) - continue; - - desc =3D acpi_gpiochip_parse_own_gpio(achip, fwnode, &name, - &lflags, &dflags); - if (IS_ERR(desc)) - continue; - - ret =3D gpiod_hog(desc, name, lflags, dflags); - if (ret) { - dev_err(chip->parent, "Failed to hog GPIO\n"); - return; - } - } -} - void acpi_gpiochip_add(struct gpio_chip *chip) { struct acpi_gpio_chip *acpi_gpio; @@ -1321,7 +1252,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip) } =20 acpi_gpiochip_request_regions(acpi_gpio); - acpi_gpiochip_scan_gpios(acpi_gpio); acpi_dev_clear_dependencies(adev); } =20 diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 08b7b662512b825086cd70440be98b59befc3ffe..bc56003025258eba29c0897c43b= 29101fd490b17 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -735,139 +736,26 @@ struct gpio_desc *of_find_gpio(struct device_node *n= p, const char *con_id, return desc; } =20 -/** - * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GP= IO API - * @np: device node to get GPIO from - * @chip: GPIO chip whose hog is parsed - * @idx: Index of the GPIO to parse - * @name: GPIO line name - * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from - * of_find_gpio() or of_parse_own_gpio() - * @dflags: gpiod_flags - optional GPIO initialization flags - * - * Returns: - * GPIO descriptor to use with Linux GPIO API, or one of the errno - * value on the error condition. - */ -static struct gpio_desc *of_parse_own_gpio(struct device_node *np, - struct gpio_chip *chip, - unsigned int idx, const char **name, - unsigned long *lflags, - enum gpiod_flags *dflags) +int of_gpiochip_get_lflags(struct gpio_chip *chip, + struct fwnode_reference_args *gpiospec, + unsigned long *lflags) { - struct device_node *chip_np; enum of_gpio_flags xlate_flags; - struct of_phandle_args gpiospec; + struct of_phandle_args args; struct gpio_desc *desc; - unsigned int i; - u32 tmp; - int ret; - - chip_np =3D dev_of_node(&chip->gpiodev->dev); - if (!chip_np) - return ERR_PTR(-EINVAL); - - xlate_flags =3D 0; - *lflags =3D GPIO_LOOKUP_FLAGS_DEFAULT; - *dflags =3D GPIOD_ASIS; =20 - ret =3D of_property_read_u32(chip_np, "#gpio-cells", &tmp); - if (ret) - return ERR_PTR(ret); + args.np =3D to_of_node(gpiospec->fwnode); + args.args_count =3D gpiospec->nargs; =20 - gpiospec.np =3D chip_np; - gpiospec.args_count =3D tmp; + for (int i =3D 0; i < args.args_count; i++) + args.args[i] =3D gpiospec->args[i]; =20 - for (i =3D 0; i < tmp; i++) { - ret =3D of_property_read_u32_index(np, "gpios", idx * tmp + i, - &gpiospec.args[i]); - if (ret) - return ERR_PTR(ret); - } - - desc =3D of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags); + desc =3D of_xlate_and_get_gpiod_flags(chip, &args, &xlate_flags); if (IS_ERR(desc)) - return desc; + return PTR_ERR(desc); =20 *lflags =3D of_convert_gpio_flags(xlate_flags); =20 - if (of_property_read_bool(np, "input")) - *dflags |=3D GPIOD_IN; - else if (of_property_read_bool(np, "output-low")) - *dflags |=3D GPIOD_OUT_LOW; - else if (of_property_read_bool(np, "output-high")) - *dflags |=3D GPIOD_OUT_HIGH; - else { - pr_warn("GPIO line %d (%pOFn): no hogging state specified, bailing out\n= ", - desc_to_gpio(desc), np); - return ERR_PTR(-EINVAL); - } - - if (name && of_property_read_string(np, "line-name", name)) - *name =3D np->name; - - return desc; -} - -/** - * of_gpiochip_add_hog - Add all hogs in a hog device node - * @chip: gpio chip to act on - * @hog: device node describing the hogs - * - * Returns: - * 0 on success, or negative errno on failure. - */ -static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node = *hog) -{ - enum gpiod_flags dflags; - struct gpio_desc *desc; - unsigned long lflags; - const char *name; - unsigned int i; - int ret; - - for (i =3D 0;; i++) { - desc =3D of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags); - if (IS_ERR(desc)) - break; - - ret =3D gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) - return ret; - -#ifdef CONFIG_OF_DYNAMIC - WRITE_ONCE(desc->hog, hog); -#endif - } - - return 0; -} - -/** - * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions - * @chip: gpio chip to act on - * - * This is only used by of_gpiochip_add to request/set GPIO initial - * configuration. - * - * Returns: - * 0 on success, or negative errno on failure. - */ -static int of_gpiochip_scan_gpios(struct gpio_chip *chip) -{ - int ret; - - for_each_available_child_of_node_scoped(dev_of_node(&chip->gpiodev->dev),= np) { - if (!of_property_read_bool(np, "gpio-hog")) - continue; - - ret =3D of_gpiochip_add_hog(chip, np); - if (ret < 0) - return ret; - - of_node_set_flag(np, OF_POPULATED); - } - return 0; } =20 @@ -922,7 +810,7 @@ static int of_gpio_notify(struct notifier_block *nb, un= signed long action, if (!gdev) return NOTIFY_DONE; /* not for us */ =20 - ret =3D of_gpiochip_add_hog(gpio_device_get_chip(gdev), rd->dn); + ret =3D gpiochip_add_hog(gpio_device_get_chip(gdev), of_fwnode_handle(rd= ->dn)); if (ret < 0) { pr_err("%s: failed to add hogs for %pOF\n", __func__, rd->dn); @@ -1201,9 +1089,10 @@ int of_gpiochip_add(struct gpio_chip *chip) =20 of_node_get(np); =20 - ret =3D of_gpiochip_scan_gpios(chip); - if (ret) - of_node_put(np); + for_each_available_child_of_node_scoped(np, child) { + if (of_property_read_bool(child, "gpio-hog")) + of_node_set_flag(child, OF_POPULATED); + } =20 return ret; } diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 2257f7a498a10d69980f0c8afd48d5b661632d87..218cfe5bc4ac31a7c48306a08b4= feafc06c0ad55 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -10,6 +10,7 @@ =20 struct device_node; struct fwnode_handle; +struct fwnode_reference_args; =20 struct gpio_chip; struct gpio_desc; @@ -24,6 +25,9 @@ int of_gpiochip_add(struct gpio_chip *gc); void of_gpiochip_remove(struct gpio_chip *gc); bool of_gpiochip_instance_match(struct gpio_chip *gc, unsigned int index); int of_gpio_count(const struct fwnode_handle *fwnode, const char *con_id); +int of_gpiochip_get_lflags(struct gpio_chip *chip, + struct fwnode_reference_args *gpiospec, + unsigned long *lflags); #else static inline struct gpio_desc *of_find_gpio(struct device_node *np, const char *con_id, @@ -44,6 +48,12 @@ static inline int of_gpio_count(const struct fwnode_hand= le *fwnode, { return 0; } +static inline int of_gpiochip_get_lflags(struct gpio_chip *chip, + struct fwnode_reference_args *gpiospec, + unsigned long *lflags) +{ + return -ENOENT; +} #endif /* CONFIG_OF_GPIO */ =20 extern struct notifier_block gpio_of_notifier; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 581d00c128b608c30f45c12e968c15628e205870..b993cdae79e6dc389ca42ed079b= 3e39d1f9fed5a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -948,7 +948,7 @@ static void gpiochip_machine_hog(struct gpio_chip *gc, = struct gpiod_hog *hog) __func__, gc->label, hog->chip_hwnum, rv); } =20 -static void machine_gpiochip_add(struct gpio_chip *gc) +static void gpiochip_machine_hog_lines(struct gpio_chip *gc) { struct gpiod_hog *hog; =20 @@ -960,6 +960,98 @@ static void machine_gpiochip_add(struct gpio_chip *gc) } } =20 +int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode) +{ + struct fwnode_handle *gc_node =3D dev_fwnode(&gc->gpiodev->dev); + struct fwnode_reference_args gpiospec; + enum gpiod_flags dflags; + struct gpio_desc *desc; + unsigned long lflags; + const char *name; + int ret, argc; + u32 gpios[3]; /* We support up to three-cell bindings. */ + u32 cells; + + lflags =3D GPIO_LOOKUP_FLAGS_DEFAULT; + dflags =3D GPIOD_ASIS; + name =3D NULL; + + argc =3D fwnode_property_count_u32(fwnode, "gpios"); + if (argc < 0) + return argc; + if (argc > 3) + return -EINVAL; + + ret =3D fwnode_property_read_u32_array(fwnode, "gpios", gpios, argc); + if (ret < 0) + return ret; + + if (is_of_node(fwnode)) { + /* + * OF-nodes need some additional special handling for + * translating of devicetree flags. + */ + ret =3D fwnode_property_read_u32(gc_node, "#gpio-cells", &cells); + if (ret) + return ret; + if (!ret && argc !=3D cells) + return -EINVAL; + + memset(&gpiospec, 0, sizeof(gpiospec)); + gpiospec.fwnode =3D fwnode; + gpiospec.nargs =3D argc; + + for (int i =3D 0; i < argc; i++) + gpiospec.args[i] =3D gpios[i]; + + ret =3D of_gpiochip_get_lflags(gc, &gpiospec, &lflags); + if (ret) + return ret; + } else { + /* + * GPIO_ACTIVE_LOW is currently the only lookup flag + * supported for non-OF firmware nodes. + */ + if (gpios[1]) + lflags |=3D GPIO_ACTIVE_LOW; + } + + if (fwnode_property_present(fwnode, "input")) + dflags |=3D GPIOD_IN; + else if (fwnode_property_present(fwnode, "output-low")) + dflags |=3D GPIOD_OUT_LOW; + else if (fwnode_property_present(fwnode, "output-high")) + dflags |=3D GPIOD_OUT_HIGH; + else + return -EINVAL; + + fwnode_property_read_string(fwnode, "line-name", &name); + + desc =3D gpiochip_get_desc(gc, gpios[0]); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + return gpiod_hog(desc, name, lflags, dflags); +} + +static int gpiochip_hog_lines(struct gpio_chip *gc) +{ + int ret; + + device_for_each_child_node_scoped(&gc->gpiodev->dev, fwnode) { + if (!fwnode_property_present(fwnode, "gpio-hog")) + continue; + + ret =3D gpiochip_add_hog(gc, fwnode); + if (ret) + return ret; + } + + gpiochip_machine_hog_lines(gc); + + return 0; +} + static void gpiochip_setup_devs(void) { struct gpio_device *gdev; @@ -1209,7 +1301,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, =20 acpi_gpiochip_add(gc); =20 - machine_gpiochip_add(gc); + ret =3D gpiochip_hog_lines(gc); + if (ret) + goto err_remove_of_chip; =20 ret =3D gpiochip_irqchip_init_valid_mask(gc); if (ret) diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 8d1a762f9d11bfc29c9102be02d7b640aa7daad3..dc4cb61a93187659d943f4ce362= 2bc1755e9fd42 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -23,6 +23,8 @@ =20 #define GPIOCHIP_NAME "gpiochip" =20 +struct fwnode_handle; + /** * struct gpio_device - internal state container for GPIO devices * @dev: the GPIO device struct @@ -274,6 +276,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const= char *con_id, int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounc= e); int gpiod_hog(struct gpio_desc *desc, const char *name, unsigned long lflags, enum gpiod_flags dflags); +int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode); int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev); struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwn= um); const char *gpiod_get_label(struct gpio_desc *desc); --=20 2.47.3