summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-12-04 10:08:40 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2025-12-04 10:08:40 -0800
commit2aa680df68062e4e0c356ec2aa7100c13654907b (patch)
treeee3dc5125e11aac04f2e33922cfad4260e47de34 /drivers/gpio/gpiolib.c
parent6dfafbd0299a60bfb5d5e277fdf100037c7ded07 (diff)
parenteaf526cfa4e537af86543d77f402b9ae803f606e (diff)
Merge tag 'sound-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "The majority of changes at this time were about ASoC with a lot of code refactoring works. From the functionality POV, there isn't much to see, but we have a wide range of device-specific fixes and updates. Here are some highlights: - Continued ASoC API cleanup work, spanned over many files - Added a SoundWire SCDA generic class driver with regmap support - Enhancements and fixes for Cirrus, Intel, Maxim and Qualcomm. - Support for ASoC Allwinner A523, Mediatek MT8189, Qualcomm QCM2290, QRB2210 and SM6115, SpacemiT K1, and TI TAS2568, TAS5802, TAS5806, TAS5815, TAS5828 and TAS5830 - Usual HD-audio and USB-audio quirks and fixups - Support for Onkyo SE-300PCIE, TASCAM IF-FW/DM MkII Some gpiolib changes for shared GPIOs are included along with this PR for covering ASoC drivers changes" * tag 'sound-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (739 commits) ALSA: hda/realtek: Add PCI SSIDs to HP ProBook quirks ALSA: usb-audio: Simplify with usb_endpoint_max_periodic_payload() ALSA: hda/realtek: fix mute/micmute LEDs don't work for more HP laptops ALSA: rawmidi: Fix inconsistent indenting warning reported by smatch ALSA: dice: fix buffer overflow in detect_stream_formats() ASoC: codecs: Modify awinic amplifier dsp read and write functions ASoC: SDCA: Fixup some more Kconfig issues ASoC: cs35l56: Log a message if firmware is missing ASoC: nau8325: Delete a stray tab firmware: cs_dsp: Add test cases for client_ops == NULL firmware: cs_dsp: Don't require client to provide a struct cs_dsp_client_ops ASoC: fsl_micfil: Set channel range control ASoC: fsl_micfil: Add default quality for different platforms ASoC: intel: sof_sdw: Add codec_info for cs42l45 ASoC: sdw_utils: Add cs42l45 support functions ASoC: intel: sof_sdw: Add ability to have auxiliary devices ASoC: sdw_utils: Move codec_name to dai info ASoC: sdw_utils: Add codec_conf for every DAI ASoC: SDCA: Add terminal type into input/output widget name ASoC: SDCA: Align mute controls to ALSA expectations ...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c70
1 files changed, 61 insertions, 9 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index cd8800ba5825..476fcc897d90 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -37,6 +37,7 @@
#include "gpiolib-acpi.h"
#include "gpiolib-cdev.h"
#include "gpiolib-of.h"
+#include "gpiolib-shared.h"
#include "gpiolib-swnode.h"
#include "gpiolib-sysfs.h"
#include "gpiolib.h"
@@ -1200,6 +1201,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (ret)
goto err_remove_irqchip_mask;
+ ret = gpio_device_setup_shared(gdev);
+ if (ret)
+ goto err_remove_irqchip;
+
/*
* By first adding the chardev, and then adding the device,
* we get a device node entry in sysfs under
@@ -1211,10 +1216,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (gpiolib_initialized) {
ret = gpiochip_setup_dev(gdev);
if (ret)
- goto err_remove_irqchip;
+ goto err_teardown_shared;
}
+
return 0;
+err_teardown_shared:
+ gpio_device_teardown_shared(gdev);
err_remove_irqchip:
gpiochip_irqchip_remove(gc);
err_remove_irqchip_mask:
@@ -1283,6 +1291,7 @@ void gpiochip_remove(struct gpio_chip *gc)
/* Numb the device, cancelling all outstanding operations */
rcu_assign_pointer(gdev->chip, NULL);
synchronize_srcu(&gdev->srcu);
+ gpio_device_teardown_shared(gdev);
gpiochip_irqchip_remove(gc);
acpi_gpiochip_remove(gc);
of_gpiochip_remove(gc);
@@ -3982,6 +3991,26 @@ int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
/**
+ * gpiod_is_shared() - check if this GPIO can be shared by multiple consumers
+ * @desc: GPIO to inspect
+ *
+ * Returns:
+ * True if this GPIO can be shared by multiple consumers at once. False if it's
+ * a regular, exclusive GPIO.
+ *
+ * Note:
+ * This function returning true does not mean that this GPIO is currently being
+ * shared. It means the GPIO core has registered the fact that the firmware
+ * configuration indicates that it can be shared by multiple consumers and is
+ * in charge of arbitrating the access.
+ */
+bool gpiod_is_shared(const struct gpio_desc *desc)
+{
+ return test_bit(GPIOD_FLAG_SHARED_PROXY, &desc->flags);
+}
+EXPORT_SYMBOL_GPL(gpiod_is_shared);
+
+/**
* gpiod_to_irq() - return the IRQ corresponding to a GPIO
* @desc: gpio whose IRQ will be returned (already requested)
*
@@ -4652,11 +4681,29 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
scoped_guard(srcu, &gpio_devices_srcu) {
desc = gpiod_fwnode_lookup(fwnode, consumer, con_id, idx,
&flags, &lookupflags);
+ if (!IS_ERR_OR_NULL(desc) &&
+ test_bit(GPIOD_FLAG_SHARED, &desc->flags)) {
+ /*
+ * We're dealing with a GPIO shared by multiple
+ * consumers. This is the moment to add the machine
+ * lookup table for the proxy device as previously
+ * we only knew the consumer's fwnode.
+ */
+ ret = gpio_shared_add_proxy_lookup(consumer, lookupflags);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /* Trigger platform lookup for shared GPIO proxy. */
+ desc = ERR_PTR(-ENOENT);
+ /* Trigger it even for fwnode-only gpiod_get(). */
+ platform_lookup_allowed = true;
+ }
+
if (gpiod_not_found(desc) && platform_lookup_allowed) {
/*
* Either we are not using DT or ACPI, or their lookup
- * did not return a result. In that case, use platform
- * lookup as a fallback.
+ * did not return a result or this is a shared GPIO. In
+ * that case, use platform lookup as a fallback.
*/
dev_dbg(consumer,
"using lookup tables for GPIO lookup\n");
@@ -4679,14 +4726,19 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
return ERR_PTR(ret);
/*
- * This happens when there are several consumers for
- * the same GPIO line: we just return here without
- * further initialization. It is a bit of a hack.
- * This is necessary to support fixed regulators.
+ * This happens when there are several consumers for the same
+ * GPIO line: we just return here without further
+ * initialization. It's a hack introduced long ago to support
+ * fixed regulators. We now have a better solution with
+ * automated scanning where affected platforms just need to
+ * select the provided Kconfig option.
*
- * FIXME: Make this more sane and safe.
+ * FIXME: Remove the GPIOD_FLAGS_BIT_NONEXCLUSIVE flag after
+ * making sure all platforms use the new mechanism.
*/
- dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
+ dev_info(consumer,
+ "nonexclusive access to GPIO for %s, consider updating your code to using gpio-shared-proxy\n",
+ name);
return desc;
}