diff options
Diffstat (limited to 'drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c')
-rw-r--r-- | drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c index 27f99183d994..a39ef71de9e7 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; @@ -1210,6 +1214,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; @@ -1271,6 +1334,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: |