diff --git a/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi index f997d908e4b4ce..bc533f32964067 100644 --- a/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi @@ -111,7 +111,7 @@ <&csi0>, "sync-gpios:4", <&csi0>, "sync-gpios:8=0", ; - strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.strict_gpiod=y"; + strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.persist_gpio_outputs=n"; }; }; diff --git a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi index 89d12634f20b81..f88de824e9d7d7 100644 --- a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi @@ -99,7 +99,7 @@ nvmem_cust_rw = <&nvmem_cust>,"rw?"; nvmem_priv_rw = <&nvmem_priv>,"rw?"; nvmem_mac_rw = <&nvmem_mac>,"rw?"; - strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.strict_gpiod=y"; + strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n"; }; }; diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 675cf96d7465bd..cfb51cf2f7662b 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -244,9 +244,9 @@ static const char * const irq_type_names[] = { [IRQ_TYPE_LEVEL_LOW] = "level-low", }; -static bool strict_gpiod; -module_param(strict_gpiod, bool, 0644); -MODULE_PARM_DESC(strict_gpiod, "unless true, outputs remain outputs when freed"); +static bool persist_gpio_outputs = true; +module_param(persist_gpio_outputs, bool, 0644); +MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed"); static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg) { @@ -945,10 +945,14 @@ static int bcm2835_pmx_free(struct pinctrl_dev *pctldev, struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); - /* Return non-GPIOs to GPIO_IN, unless strict_gpiod is set */ - if (strict_gpiod || (fsel != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_OUT)) - bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN); + if (fsel == BCM2835_FSEL_GPIO_IN) + return 0; + + if (persist_gpio_outputs && fsel == BCM2835_FSEL_GPIO_OUT) + return 0; + /* disable by setting to GPIO_IN */ + bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN); return 0; } @@ -990,7 +994,7 @@ static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset) { - (void)bcm2835_pmx_free(pctldev, offset); + bcm2835_pmx_free(pctldev, offset); } static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, @@ -1378,6 +1382,9 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) goto out_remove; } + dev_info(dev, "GPIO_OUT persistence: %s\n", + persist_gpio_outputs ? "yes" : "no"); + return 0; out_remove: diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c index 292051168b61f7..6684b171e98b5d 100644 --- a/drivers/pinctrl/pinctrl-rp1.c +++ b/drivers/pinctrl/pinctrl-rp1.c @@ -573,9 +573,9 @@ static const char * const irq_type_names[] = { [IRQ_TYPE_LEVEL_LOW] = "level-low", }; -static bool strict_gpiod; -module_param(strict_gpiod, bool, 0644); -MODULE_PARM_DESC(strict_gpiod, "unless true, outputs remain outputs when freed"); +static bool persist_gpio_outputs = true; +module_param(persist_gpio_outputs, bool, 0644); +MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed"); static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, unsigned long *configs, @@ -1205,11 +1205,12 @@ static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); u32 fsel = rp1_get_fsel(pin); - /* Return non-GPIOs to GPIO_IN, unless strict_gpiod is set */ - if (strict_gpiod || fsel != RP1_FSEL_GPIO) { - rp1_set_dir(pin, RP1_DIR_INPUT); - rp1_set_fsel(pin, RP1_FSEL_GPIO); - } + /* Return all pins to GPIO_IN, unless persist_gpio_outputs is set */ + if (persist_gpio_outputs && fsel == RP1_FSEL_GPIO) + return 0; + + rp1_set_dir(pin, RP1_DIR_INPUT); + rp1_set_fsel(pin, RP1_FSEL_GPIO); return 0; }