author: Emil Renner Berthing <kernel@esmil.dk> 2021-07-17 21:50:38 +0200
committer: Emil Renner Berthing <emil.renner.berthing@canonical.com> 2023-07-20 20:53:37 +0200
commit: e12cb03f171eb7524657712d025e137fa0ced0c5
parent: b0514850d1ce0d32c5d39c30fe61c9fde098893d
Commit Summary:
Diffstat:
2 files changed, 61 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
index f3258f2fd3a4..ce79d2ae3a32 100644
--- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
@@ -88,6 +88,10 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3, 4, 5, 6]
+ starfive,keep-gpiomux:
+ description: Keep pinmux for these GPIOs from being reset at boot.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
required:
- compatible
- reg
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
index 530fe340a9a1..6fe5e1e9baa9 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
@@ -203,6 +203,10 @@ static u16 starfive_drive_strength_from_max_mA(u32 i)
return (clamp(i, 14U, 63U) - 14) / 7;
}
+static bool keepmux;
+module_param(keepmux, bool, 0644);
+MODULE_PARM_DESC(keepmux, "Keep pinmux settings from previous boot stage");
+
struct starfive_pinctrl {
struct gpio_chip gc;
struct pinctrl_gpio_range gpios;
@@ -1225,6 +1229,65 @@ static void starfive_disable_clock(void *data)
clk_disable_unprepare(data);
}
+#define GPI_END (GPI_USB_OVER_CURRENT + 1)
+static void starfive_pinmux_reset(struct starfive_pinctrl *sfp)
+{
+ static const DECLARE_BITMAP(defaults, GPI_END) = {
+ BIT_MASK(GPI_I2C0_PAD_SCK_IN) |
+ BIT_MASK(GPI_I2C0_PAD_SDA_IN) |
+ BIT_MASK(GPI_I2C1_PAD_SCK_IN) |
+ BIT_MASK(GPI_I2C1_PAD_SDA_IN) |
+ BIT_MASK(GPI_I2C2_PAD_SCK_IN) |
+ BIT_MASK(GPI_I2C2_PAD_SDA_IN) |
+ BIT_MASK(GPI_I2C3_PAD_SCK_IN) |
+ BIT_MASK(GPI_I2C3_PAD_SDA_IN) |
+ BIT_MASK(GPI_SDIO0_PAD_CARD_DETECT_N) |
+
+ BIT_MASK(GPI_SDIO1_PAD_CARD_DETECT_N) |
+ BIT_MASK(GPI_SPI0_PAD_SS_IN_N) |
+ BIT_MASK(GPI_SPI1_PAD_SS_IN_N) |
+ BIT_MASK(GPI_SPI2_PAD_SS_IN_N) |
+ BIT_MASK(GPI_SPI2AHB_PAD_SS_N) |
+ BIT_MASK(GPI_SPI3_PAD_SS_IN_N),
+
+ BIT_MASK(GPI_UART0_PAD_SIN) |
+ BIT_MASK(GPI_UART1_PAD_SIN) |
+ BIT_MASK(GPI_UART2_PAD_SIN) |
+ BIT_MASK(GPI_UART3_PAD_SIN) |
+ BIT_MASK(GPI_USB_OVER_CURRENT)
+ };
+ DECLARE_BITMAP(keep, NR_GPIOS) = {};
+ struct device_node *np = sfp->gc.parent->of_node;
+ int len = of_property_count_u32_elems(np, "starfive,keep-gpiomux");
+ int i;
+
+ for (i = 0; i < len; i++) {
+ u32 gpio;
+
+ of_property_read_u32_index(np, "starfive,keep-gpiomux", i, &gpio);
+ if (gpio < NR_GPIOS)
+ set_bit(gpio, keep);
+ }
+
+ for (i = 0; i < NR_GPIOS; i++) {
+ if (test_bit(i, keep))
+ continue;
+
+ writel_relaxed(GPO_DISABLE, sfp->base + GPON_DOEN_CFG + 8 * i);
+ writel_relaxed(GPO_LOW, sfp->base + GPON_DOUT_CFG + 8 * i);
+ }
+
+ for (i = 0; i < GPI_END; i++) {
+ void __iomem *reg = sfp->base + GPI_CFG_OFFSET + 4 * i;
+ u32 din = readl_relaxed(reg);
+
+ if (din >= 2 && din < (NR_GPIOS + 2) && test_bit(din - 2, keep))
+ continue;
+
+ writel_relaxed(test_bit(i, defaults), reg);
+ }
+}
+
static int starfive_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1286,6 +1349,9 @@ static int starfive_probe(struct platform_device *pdev)
writel(value, sfp->padctl + IO_PADSHARE_SEL);
}
+ if (!keepmux)
+ starfive_pinmux_reset(sfp);
+
value = readl(sfp->padctl + IO_PADSHARE_SEL);
switch (value) {
case 0: