Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
<&csi0>, "sync-gpios:4",
<&csi0>, "sync-gpios:8=0", <GPIO_ACTIVE_LOW>;

strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.strict_gpiod=y";
strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.persist_gpio_outputs=n";
};
};

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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";
};
};

Expand Down
21 changes: 14 additions & 7 deletions drivers/pinctrl/bcm/pinctrl-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 9 additions & 8 deletions drivers/pinctrl/pinctrl-rp1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down