VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   30 Branches   50 Tags
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:
pinctrl: starfive: Reset pinmux settings
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: