Starfive JH8100 SoC consists of 4 pinctrl domains - sys_east,
sys_west, sys_gmac, and aon. This patch series adds pinctrl
drivers for these 4 pinctrl domains and this patch series is
depending on the JH8100 base patch series in [1] and [2].
The relevant dt-binding documentation for each pinctrl domain has
been updated accordingly.
[1] https://lore.kernel.org/lkml/[email protected]/
[2] https://lore.kernel.org/lkml/[email protected]/
Alex Soo (6):
dt-bindings: pinctrl: starfive: add JH8100 pinctrl bindings
pinctrl: starfive: jh8100: add pinctrl driver for sys_east domain
pinctrl: starfive: jh8100: add pinctrl driver for sys_west domain
pinctrl: starfive: jh8100: add pinctrl driver for sys_gmac domain
pinctrl: starfive: jh8100: add pinctrl driver for AON domain
riscv: dts: starfive: jh8100: add pinctrl device tree nodes
.../pinctrl/starfive,jh8100-aon-pinctrl.yaml | 183 +++
.../starfive,jh8100-sys-east-pinctrl.yaml | 188 +++
.../starfive,jh8100-sys-gmac-pinctrl.yaml | 124 ++
.../starfive,jh8100-sys-west-pinctrl.yaml | 188 +++
MAINTAINERS | 7 +
arch/riscv/boot/dts/starfive/jh8100-evb.dts | 5 +
arch/riscv/boot/dts/starfive/jh8100-pinfunc.h | 418 +++++++
arch/riscv/boot/dts/starfive/jh8100.dtsi | 44 +
drivers/pinctrl/starfive/Kconfig | 57 +
drivers/pinctrl/starfive/Makefile | 6 +
.../starfive/pinctrl-starfive-jh8100-aon.c | 241 ++++
.../pinctrl-starfive-jh8100-sys-east.c | 326 +++++
.../pinctrl-starfive-jh8100-sys-gmac.c | 164 +++
.../pinctrl-starfive-jh8100-sys-west.c | 264 ++++
.../starfive/pinctrl-starfive-jh8100.c | 1090 +++++++++++++++++
.../starfive/pinctrl-starfive-jh8100.h | 85 ++
.../pinctrl/starfive,jh8100-pinctrl.h | 303 +++++
17 files changed, 3693 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh8100-aon-pinctrl.yaml
create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh8100-sys-east-pinctrl.yaml
create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh8100-sys-gmac-pinctrl.yaml
create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh8100-sys-west-pinctrl.yaml
create mode 100644 arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-east.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-gmac.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-west.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
create mode 100644 include/dt-bindings/pinctrl/starfive,jh8100-pinctrl.h
base-commit: ddb42e41c0991b443dd6cc97213b478a7324d72b
--
2.25.1
Add pinctrl driver for sys_east domain.
Signed-off-by: Alex Soo <[email protected]>
Reviewed-by: Ley Foon Tan <[email protected]>
---
drivers/pinctrl/starfive/Kconfig | 21 +
drivers/pinctrl/starfive/Makefile | 3 +
.../pinctrl-starfive-jh8100-sys-east.c | 326 +++++
.../starfive/pinctrl-starfive-jh8100.c | 1090 +++++++++++++++++
.../starfive/pinctrl-starfive-jh8100.h | 79 ++
5 files changed, 1519 insertions(+)
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-east.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100.c
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
index 8192ac2087fc..afcbf9d4dc8d 100644
--- a/drivers/pinctrl/starfive/Kconfig
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -49,3 +49,24 @@ config PINCTRL_STARFIVE_JH7110_AON
This also provides an interface to the GPIO pins not used by other
peripherals supporting inputs, outputs, configuring pull-up/pull-down
and interrupts on input changes.
+
+config PINCTRL_STARFIVE_JH8100
+ bool
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select OF_GPIO
+
+config PINCTRL_STARFIVE_JH8100_SYS_EAST
+ tristate "StarFive JH8100 SoC System IOMUX-East pinctrl and GPIO driver"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ depends on OF
+ select PINCTRL_STARFIVE_JH8100
+ default ARCH_STARFIVE
+ help
+ Say yes here to support system iomux-east pin control on the StarFive JH8100 SoC.
+ This also provides an interface to the GPIO pins not used by other
+ peripherals supporting inputs, outputs, configuring pull-up/pull-down
+ and interrupts on input changes.
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
index ee0d32d085cb..45698c502b48 100644
--- a/drivers/pinctrl/starfive/Makefile
+++ b/drivers/pinctrl/starfive/Makefile
@@ -5,3 +5,6 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH7100) += pinctrl-starfive-jh7100.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH7110) += pinctrl-starfive-jh7110.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_SYS) += pinctrl-starfive-jh7110-sys.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_AON) += pinctrl-starfive-jh7110-aon.o
+
+obj-$(CONFIG_PINCTRL_STARFIVE_JH8100) += pinctrl-starfive-jh8100.o
+obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_EAST) += pinctrl-starfive-jh8100-sys-east.o
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-east.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-east.c
new file mode 100644
index 000000000000..a0585bd18fc8
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-east.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC sys east controller
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/gpio/driver.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+#include "../pinconf.h"
+#include "pinctrl-starfive-jh8100.h"
+
+#define JH8100_SYS_E_NGPIO 48
+#define JH8100_SYS_E_GC_BASE 16
+
+/* registers */
+#define JH8100_SYS_E_DOEN 0x000
+#define JH8100_SYS_E_DOUT 0x030
+#define JH8100_SYS_E_GPI 0x060
+#define JH8100_SYS_E_GPIOIN 0x0f4
+
+#define JH8100_SYS_E_GPIOEN 0x0b8
+#define JH8100_SYS_E_GPIOIS0 0x0bc
+#define JH8100_SYS_E_GPIOIS1 0x0c0
+#define JH8100_SYS_E_GPIOIC0 0x0c4
+#define JH8100_SYS_E_GPIOIC1 0x0c8
+#define JH8100_SYS_E_GPIOIBE0 0x0cc
+#define JH8100_SYS_E_GPIOIBE1 0x0d0
+#define JH8100_SYS_E_GPIOIEV0 0x0d4
+#define JH8100_SYS_E_GPIOIEV1 0x0d8
+#define JH8100_SYS_E_GPIOIE0 0x0dc
+#define JH8100_SYS_E_GPIOIE1 0x0e0
+#define JH8100_SYS_E_GPIORIS0 0x0e4
+#define JH8100_SYS_E_GPIORIS1 0x0e8
+#define JH8100_SYS_E_GPIOMIS0 0x0ec
+#define JH8100_SYS_E_GPIOMIS1 0x0f0
+
+#define JH8100_SYS_E_GPO_PDA_00_47_CFG 0x114
+
+static const struct pinctrl_pin_desc jh8100_sys_e_pins[] = {
+ PINCTRL_PIN(PAD_GPIO0_E, "SYS_E_GPIO0"),
+ PINCTRL_PIN(PAD_GPIO1_E, "SYS_E_GPIO1"),
+ PINCTRL_PIN(PAD_GPIO2_E, "SYS_E_GPIO2"),
+ PINCTRL_PIN(PAD_GPIO3_E, "SYS_E_GPIO3"),
+ PINCTRL_PIN(PAD_GPIO4_E, "SYS_E_GPIO4"),
+ PINCTRL_PIN(PAD_GPIO5_E, "SYS_E_GPIO5"),
+ PINCTRL_PIN(PAD_GPIO6_E, "SYS_E_GPIO6"),
+ PINCTRL_PIN(PAD_GPIO7_E, "SYS_E_GPIO7"),
+ PINCTRL_PIN(PAD_GPIO8_E, "SYS_E_GPIO8"),
+ PINCTRL_PIN(PAD_GPIO9_E, "SYS_E_GPIO9"),
+ PINCTRL_PIN(PAD_GPIO10_E, "SYS_E_GPIO10"),
+ PINCTRL_PIN(PAD_GPIO11_E, "SYS_E_GPIO11"),
+ PINCTRL_PIN(PAD_GPIO12_E, "SYS_E_GPIO12"),
+ PINCTRL_PIN(PAD_GPIO13_E, "SYS_E_GPIO13"),
+ PINCTRL_PIN(PAD_GPIO14_E, "SYS_E_GPIO14"),
+ PINCTRL_PIN(PAD_GPIO15_E, "SYS_E_GPIO15"),
+ PINCTRL_PIN(PAD_GPIO16_E, "SYS_E_GPIO16"),
+ PINCTRL_PIN(PAD_GPIO17_E, "SYS_E_GPIO17"),
+ PINCTRL_PIN(PAD_GPIO18_E, "SYS_E_GPIO18"),
+ PINCTRL_PIN(PAD_GPIO19_E, "SYS_E_GPIO19"),
+ PINCTRL_PIN(PAD_GPIO20_E, "SYS_E_GPIO20"),
+ PINCTRL_PIN(PAD_GPIO21_E, "SYS_E_GPIO21"),
+ PINCTRL_PIN(PAD_GPIO22_E, "SYS_E_GPIO22"),
+ PINCTRL_PIN(PAD_GPIO23_E, "SYS_E_GPIO23"),
+ PINCTRL_PIN(PAD_GPIO24_E, "SYS_E_GPIO24"),
+ PINCTRL_PIN(PAD_GPIO25_E, "SYS_E_GPIO25"),
+ PINCTRL_PIN(PAD_GPIO26_E, "SYS_E_GPIO26"),
+ PINCTRL_PIN(PAD_GPIO27_E, "SYS_E_GPIO27"),
+ PINCTRL_PIN(PAD_GPIO28_E, "SYS_E_GPIO28"),
+ PINCTRL_PIN(PAD_GPIO29_E, "SYS_E_GPIO29"),
+ PINCTRL_PIN(PAD_GPIO30_E, "SYS_E_GPIO30"),
+ PINCTRL_PIN(PAD_GPIO31_E, "SYS_E_GPIO31"),
+ PINCTRL_PIN(PAD_GPIO32_E, "SYS_E_GPIO32"),
+ PINCTRL_PIN(PAD_GPIO33_E, "SYS_E_GPIO33"),
+ PINCTRL_PIN(PAD_GPIO34_E, "SYS_E_GPIO34"),
+ PINCTRL_PIN(PAD_GPIO35_E, "SYS_E_GPIO35"),
+ PINCTRL_PIN(PAD_GPIO36_E, "SYS_E_GPIO36"),
+ PINCTRL_PIN(PAD_GPIO37_E, "SYS_E_GPIO37"),
+ PINCTRL_PIN(PAD_GPIO38_E, "SYS_E_GPIO38"),
+ PINCTRL_PIN(PAD_GPIO39_E, "SYS_E_GPIO39"),
+ PINCTRL_PIN(PAD_GPIO40_E, "SYS_E_GPIO40"),
+ PINCTRL_PIN(PAD_GPIO41_E, "SYS_E_GPIO41"),
+ PINCTRL_PIN(PAD_GPIO42_E, "SYS_E_GPIO42"),
+ PINCTRL_PIN(PAD_GPIO43_E, "SYS_E_GPIO43"),
+ PINCTRL_PIN(PAD_GPIO44_E, "SYS_E_GPIO44"),
+ PINCTRL_PIN(PAD_GPIO45_E, "SYS_E_GPIO45"),
+ PINCTRL_PIN(PAD_GPIO46_E, "SYS_E_GPIO46"),
+ PINCTRL_PIN(PAD_GPIO47_E, "SYS_E_GPIO47"),
+};
+
+struct jh8100_sys_e_func_sel {
+ u16 offset;
+ u8 shift;
+ u8 max;
+};
+
+static const struct jh8100_sys_e_func_sel
+ jh8100_sys_e_func_sel[ARRAY_SIZE(jh8100_sys_e_pins)] = {
+ [PAD_GPIO20_E] = { 0x1d4, 0, 2 },
+ [PAD_GPIO21_E] = { 0x1d4, 2, 2 },
+ [PAD_GPIO22_E] = { 0x1d4, 4, 2 },
+ [PAD_GPIO23_E] = { 0x1d4, 6, 2 },
+ [PAD_GPIO24_E] = { 0x1d4, 8, 2 },
+ [PAD_GPIO25_E] = { 0x1d4, 10, 2 },
+ [PAD_GPIO26_E] = { 0x1d4, 12, 2 },
+ [PAD_GPIO27_E] = { 0x1d4, 14, 2 },
+ [PAD_GPIO28_E] = { 0x1d4, 16, 2 },
+ [PAD_GPIO29_E] = { 0x1d4, 18, 2 },
+ [PAD_GPIO30_E] = { 0x1d4, 20, 2 },
+ [PAD_GPIO31_E] = { 0x1d4, 22, 2 },
+ [PAD_GPIO32_E] = { 0x1d4, 24, 2 },
+ [PAD_GPIO33_E] = { 0x1d4, 26, 2 },
+ [PAD_GPIO34_E] = { 0x1d4, 28, 2 },
+ [PAD_GPIO35_E] = { 0x1d4, 30, 2 },
+
+ [PAD_GPIO36_E] = { 0x1d8, 0, 2 },
+ [PAD_GPIO37_E] = { 0x1d8, 2, 2 },
+ [PAD_GPIO38_E] = { 0x1d8, 4, 2 },
+ [PAD_GPIO39_E] = { 0x1d8, 6, 2 },
+ [PAD_GPIO40_E] = { 0x1d8, 8, 2 },
+ [PAD_GPIO41_E] = { 0x1d8, 10, 2 },
+ [PAD_GPIO42_E] = { 0x1d8, 12, 2 },
+ [PAD_GPIO43_E] = { 0x1d8, 14, 2 },
+ [PAD_GPIO44_E] = { 0x1d8, 16, 2 },
+ [PAD_GPIO45_E] = { 0x1d8, 18, 2 },
+ [PAD_GPIO46_E] = { 0x1d8, 20, 2 },
+ [PAD_GPIO47_E] = { 0x1d8, 22, 2 },
+};
+
+static void jh8100_sys_e_set_function(struct jh8100_pinctrl *sfp,
+ unsigned int pin, u32 func)
+{
+ const struct jh8100_sys_e_func_sel *fs = &jh8100_sys_e_func_sel[pin];
+ unsigned long flags;
+ void __iomem *reg;
+ u32 mask;
+
+ if (!fs->offset)
+ return;
+
+ if (func > fs->max)
+ return;
+
+ reg = sfp->base + fs->offset;
+ func = func << fs->shift;
+ mask = 0x3U << fs->shift;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ func |= readl_relaxed(reg) & ~mask;
+ writel_relaxed(func, reg);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_sys_e_set_one_pin_mux(struct jh8100_pinctrl *sfp,
+ unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func)
+{
+ if (pin < sfp->gc.ngpio && func == 0)
+ jh8100_set_gpiomux(sfp, pin, din, dout, doen);
+
+ if (pin < sfp->gc.ngpio && func == 1)
+ jh8100_sys_e_set_function(sfp, pin, func);
+
+ return 0;
+}
+
+static int jh8100_sys_e_get_padcfg_base(struct jh8100_pinctrl *sfp,
+ unsigned int pin)
+{
+ if (pin <= PAD_GPIO47_E)
+ return JH8100_SYS_E_GPO_PDA_00_47_CFG;
+ else
+ return -1;
+}
+
+static void jh8100_sys_e_irq_handler(struct irq_desc *desc)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_desc(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long mis;
+ unsigned int pin;
+
+ chained_irq_enter(chip, desc);
+
+ mis = readl_relaxed(sfp->base + JH8100_SYS_E_GPIOMIS0);
+ for_each_set_bit(pin, &mis, 32)
+ generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+ mis = readl_relaxed(sfp->base + JH8100_SYS_E_GPIOMIS1);
+ for_each_set_bit(pin, &mis, 16)
+ generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
+
+ chained_irq_exit(chip, desc);
+}
+
+static int jh8100_sys_e_init_hw(struct gpio_chip *gc)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+
+ /* mask all GPIO interrupts */
+ writel(0U, sfp->base + JH8100_SYS_E_GPIOIE0);
+ writel(0U, sfp->base + JH8100_SYS_E_GPIOIE1);
+ /* clear edge interrupt flags */
+ writel(0U, sfp->base + JH8100_SYS_E_GPIOIC0);
+ writel(~0U, sfp->base + JH8100_SYS_E_GPIOIC0);
+ writel(0U, sfp->base + JH8100_SYS_E_GPIOIC1);
+ writel(~0U, sfp->base + JH8100_SYS_E_GPIOIC1);
+ /* enable GPIO interrupts */
+ writel(1U, sfp->base + JH8100_SYS_E_GPIOEN);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int jh8100_sys_e_pinctrl_suspend(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_EAST_REG_NUM; i++)
+ sfp->jh8100_sys_east_regs[i] = readl_relaxed(sfp->base + (i * 4));
+
+ return pinctrl_force_sleep(sfp->pctl);
+}
+
+static int jh8100_sys_e_pinctrl_resume(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_EAST_REG_NUM; i++)
+ writel_relaxed(sfp->jh8100_sys_east_regs[i], sfp->base + (i * 4));
+
+ return pinctrl_force_default(sfp->pctl);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(jh8100_sys_e_pinctrl_dev_pm_ops,
+ jh8100_sys_e_pinctrl_suspend,
+ jh8100_sys_e_pinctrl_resume);
+
+static const struct jh8100_gpio_irq_reg jh8100_sys_e_irq_reg = {
+ .is_reg_base = JH8100_SYS_E_GPIOIS0,
+ .ic_reg_base = JH8100_SYS_E_GPIOIC0,
+ .ibe_reg_base = JH8100_SYS_E_GPIOIBE0,
+ .iev_reg_base = JH8100_SYS_E_GPIOIEV0,
+ .ie_reg_base = JH8100_SYS_E_GPIOIE0,
+ .ris_reg_base = JH8100_SYS_E_GPIORIS0,
+ .mis_reg_base = JH8100_SYS_E_GPIOMIS0,
+};
+
+static const struct jh8100_pinctrl_soc_info jh8100_sys_e_pinctrl_info = {
+ .pins = jh8100_sys_e_pins,
+ .npins = ARRAY_SIZE(jh8100_sys_e_pins),
+ .ngpios = JH8100_SYS_E_NGPIO,
+ .gc_base = JH8100_SYS_E_GC_BASE,
+ .dout_reg_base = JH8100_SYS_E_DOUT,
+ .dout_mask = GENMASK(6, 0),
+ .doen_reg_base = JH8100_SYS_E_DOEN,
+ .doen_mask = GENMASK(5, 0),
+ .gpi_reg_base = JH8100_SYS_E_GPI,
+ .gpi_mask = GENMASK(5, 0),
+ .gpioin_reg_base = JH8100_SYS_E_GPIOIN,
+ .irq_reg = &jh8100_sys_e_irq_reg,
+ .jh8100_set_one_pin_mux = jh8100_sys_e_set_one_pin_mux,
+ .jh8100_get_padcfg_base = jh8100_sys_e_get_padcfg_base,
+ .jh8100_gpio_irq_handler = jh8100_sys_e_irq_handler,
+ .jh8100_gpio_init_hw = jh8100_sys_e_init_hw,
+};
+
+static const struct of_device_id jh8100_sys_e_pinctrl_of_match[] = {
+ {
+ .compatible = "starfive,jh8100-sys-pinctrl-east",
+ .data = &jh8100_sys_e_pinctrl_info,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh8100_sys_e_pinctrl_of_match);
+
+static struct platform_driver jh8100_sys_e_pinctrl_driver = {
+ .probe = jh8100_pinctrl_probe,
+ .driver = {
+ .name = "starfive-jh8100-sys-pinctrl-east",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &jh8100_sys_e_pinctrl_dev_pm_ops,
+#endif
+ .of_match_table = jh8100_sys_e_pinctrl_of_match,
+ },
+};
+module_platform_driver(jh8100_sys_e_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC sys east controller");
+MODULE_AUTHOR("Alex Soo <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.c
new file mode 100644
index 000000000000..65c2f0ba7315
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.c
@@ -0,0 +1,1090 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+#include "../pinconf.h"
+#include "pinctrl-starfive-jh8100.h"
+
+#define pin_to_hwirq(sfp) (((sfp)->wakeup_gpio) - ((sfp)->gc.base))
+
+/* pad control bits */
+#define JH8100_PADCFG_POS BIT(7)
+#define JH8100_PADCFG_SMT BIT(6)
+#define JH8100_PADCFG_SLEW BIT(5)
+#define JH8100_PADCFG_PD BIT(4)
+#define JH8100_PADCFG_PU BIT(3)
+#define JH8100_PADCFG_BIAS (JH8100_PADCFG_PD | JH8100_PADCFG_PU)
+#define JH8100_PADCFG_DS_MASK GENMASK(2, 1)
+#define JH8100_PADCFG_DS_2MA (0U << 1)
+#define JH8100_PADCFG_DS_4MA BIT(1)
+#define JH8100_PADCFG_DS_8MA (2U << 1)
+#define JH8100_PADCFG_DS_12MA (3U << 1)
+#define JH8100_PADCFG_IE BIT(0)
+
+/*
+ * The packed pinmux values from the device tree look like this:
+ *
+ * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
+ * | din | dout | doen | function | pin |
+ */
+static unsigned int jh8100_pinmux_din(u32 v)
+{
+ return (v & GENMASK(31, 24)) >> 24;
+}
+
+static u32 jh8100_pinmux_dout(u32 v)
+{
+ return (v & GENMASK(23, 16)) >> 16;
+}
+
+static u32 jh8100_pinmux_doen(u32 v)
+{
+ return (v & GENMASK(15, 10)) >> 10;
+}
+
+static u32 jh8100_pinmux_function(u32 v)
+{
+ return (v & GENMASK(9, 8)) >> 8;
+}
+
+static unsigned int jh8100_pinmux_pin(u32 v)
+{
+ return v & GENMASK(7, 0);
+}
+
+static struct jh8100_pinctrl *jh8100_from_irq_data(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ return container_of(gc, struct jh8100_pinctrl, gc);
+}
+
+struct jh8100_pinctrl *jh8100_from_irq_desc(struct irq_desc *desc)
+{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+
+ return container_of(gc, struct jh8100_pinctrl, gc);
+}
+EXPORT_SYMBOL_GPL(jh8100_from_irq_desc);
+
+#ifdef CONFIG_DEBUG_FS
+static void jh8100_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+
+ seq_printf(s, "%s", dev_name(pctldev->dev));
+
+ if (pin < sfp->gc.ngpio) {
+ unsigned int offset = 4 * (pin / 4);
+ unsigned int shift = 8 * (pin % 4);
+ u32 dout = readl_relaxed(sfp->base + info->dout_reg_base + offset);
+ u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset);
+ u32 gpi = readl_relaxed(sfp->base + info->gpi_reg_base + offset);
+
+ dout = (dout >> shift) & info->dout_mask;
+ doen = (doen >> shift) & info->doen_mask;
+ gpi = ((gpi >> shift) - 2) & info->gpi_mask;
+
+ seq_printf(s, " dout=%u doen=%u din=%u", dout, doen, gpi);
+ }
+}
+#else
+#define jh8100_pin_dbg_show NULL
+#endif
+
+static int jh8100_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ struct device *dev = sfp->gc.parent;
+ struct device_node *child;
+ struct pinctrl_map *map;
+ const char **pgnames;
+ const char *grpname;
+ int ngroups;
+ int nmaps;
+ int ret;
+
+ ngroups = 0;
+ for_each_child_of_node(np, child)
+ ngroups += 1;
+ nmaps = 2 * ngroups;
+
+ pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
+ if (!pgnames)
+ return -ENOMEM;
+
+ map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ nmaps = 0;
+ ngroups = 0;
+ mutex_lock(&sfp->mutex);
+ for_each_child_of_node(np, child) {
+ int npins = of_property_count_u32_elems(child, "pinmux");
+ int *pins;
+ u32 *pinmux;
+ int i;
+
+ if (npins < 1) {
+ dev_err(dev,
+ "invalid pinctrl group %pOFn.%pOFn: pinmux not set\n",
+ np, child);
+ ret = -EINVAL;
+ goto put_child;
+ }
+
+ grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", np, child);
+ if (!grpname) {
+ ret = -ENOMEM;
+ goto put_child;
+ }
+
+ pgnames[ngroups++] = grpname;
+
+ pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins) {
+ ret = -ENOMEM;
+ goto put_child;
+ }
+
+ pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
+ if (!pinmux) {
+ ret = -ENOMEM;
+ goto put_child;
+ }
+
+ ret = of_property_read_u32_array(child, "pinmux", pinmux, npins);
+ if (ret)
+ goto put_child;
+
+ for (i = 0; i < npins; i++)
+ pins[i] = jh8100_pinmux_pin(pinmux[i]);
+
+ map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+ map[nmaps].data.mux.function = np->name;
+ map[nmaps].data.mux.group = grpname;
+ nmaps += 1;
+
+ ret = pinctrl_generic_add_group(pctldev, grpname,
+ pins, npins, pinmux);
+ if (ret < 0) {
+ dev_err(dev, "error adding group %s: %d\n", grpname, ret);
+ goto put_child;
+ }
+
+ ret = pinconf_generic_parse_dt_config(child, pctldev,
+ &map[nmaps].data.configs.configs,
+ &map[nmaps].data.configs.num_configs);
+ if (ret) {
+ dev_err(dev, "error parsing pin config of group %s: %d\n",
+ grpname, ret);
+ goto put_child;
+ }
+
+ /* don't create a map if there are no pinconf settings */
+ if (map[nmaps].data.configs.num_configs == 0)
+ continue;
+
+ map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ map[nmaps].data.configs.group_or_pin = grpname;
+ nmaps += 1;
+ }
+
+ ret = pinmux_generic_add_function(pctldev, np->name,
+ pgnames, ngroups, NULL);
+ if (ret < 0) {
+ dev_err(dev, "error adding function %s: %d\n", np->name, ret);
+ goto free_map;
+ }
+ mutex_unlock(&sfp->mutex);
+
+ *maps = map;
+ *num_maps = nmaps;
+ return 0;
+
+put_child:
+ of_node_put(child);
+free_map:
+ pinctrl_utils_free_map(pctldev, map, nmaps);
+ mutex_unlock(&sfp->mutex);
+ return ret;
+}
+
+static const struct pinctrl_ops jh8100_pinctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .pin_dbg_show = jh8100_pin_dbg_show,
+ .dt_node_to_map = jh8100_dt_node_to_map,
+ .dt_free_map = pinctrl_utils_free_map,
+};
+
+void jh8100_set_gpiomux(struct jh8100_pinctrl *sfp, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen)
+{
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+
+ unsigned int offset = 4 * (pin / 4);
+ unsigned int shift = 8 * (pin % 4);
+ u32 dout_mask = info->dout_mask << shift;
+ u32 doen_mask = info->doen_mask << shift;
+ u32 ival, imask;
+ u32 tmp;
+ void __iomem *reg_dout;
+ void __iomem *reg_doen;
+ void __iomem *reg_din;
+ unsigned long flags;
+
+ reg_dout = sfp->base + info->dout_reg_base + offset;
+ reg_doen = sfp->base + info->doen_reg_base + offset;
+ dout <<= shift;
+ doen <<= shift;
+ if (din != GPI_NONE) {
+ unsigned int ioffset = 4 * (din / 4);
+ unsigned int ishift = 8 * (din % 4);
+
+ reg_din = sfp->base + info->gpi_reg_base + ioffset;
+ ival = (pin + 2) << ishift;
+ imask = info->gpi_mask << ishift;
+ } else {
+ reg_din = NULL;
+ }
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ dout |= readl_relaxed(reg_dout) & ~dout_mask;
+ writel_relaxed(dout, reg_dout);
+ doen |= readl_relaxed(reg_doen) & ~doen_mask;
+ writel_relaxed(doen, reg_doen);
+ if (reg_din) {
+ tmp = readl_relaxed(reg_din) & ~imask;
+ writel_relaxed(tmp, reg_din);
+ ival |= readl_relaxed(reg_din) & ~imask;
+ writel_relaxed(ival, reg_din);
+ }
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+EXPORT_SYMBOL_GPL(jh8100_set_gpiomux);
+
+static int jh8100_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int fsel, unsigned int gsel)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ const struct group_desc *group;
+ const u32 *pinmux;
+ unsigned int i;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ pinmux = group->data;
+ if (info->jh8100_set_one_pin_mux)
+ for (i = 0; i < group->num_pins; i++) {
+ u32 v = pinmux[i];
+
+ info->jh8100_set_one_pin_mux(sfp,
+ jh8100_pinmux_pin(v),
+ jh8100_pinmux_din(v),
+ jh8100_pinmux_dout(v),
+ jh8100_pinmux_doen(v),
+ jh8100_pinmux_function(v));
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops jh8100_pinmux_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = jh8100_set_mux,
+ .strict = true,
+};
+
+static const u8 jh8100_drive_strength_mA[4] = { 2, 4, 8, 12 };
+
+static u32 jh8100_padcfg_ds_to_mA(u32 padcfg)
+{
+ return jh8100_drive_strength_mA[(padcfg >> 1) & 3U];
+}
+
+static u32 jh8100_padcfg_ds_from_mA(u32 v)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (v <= jh8100_drive_strength_mA[i])
+ break;
+ }
+ return i << 1;
+}
+
+static void jh8100_padcfg_rmw(struct jh8100_pinctrl *sfp,
+ unsigned int pin, u32 mask, u32 value)
+{
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ void __iomem *reg;
+ unsigned long flags;
+ int padcfg_base;
+
+ if (!info->jh8100_get_padcfg_base)
+ return;
+
+ padcfg_base = info->jh8100_get_padcfg_base(sfp, pin);
+ if (padcfg_base < 0)
+ return;
+
+ reg = sfp->base + padcfg_base + 4 * pin;
+ value &= mask;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ value |= readl_relaxed(reg) & ~mask;
+ writel_relaxed(value, reg);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ int param = pinconf_to_config_param(*config);
+ u32 padcfg, arg;
+ bool enabled;
+ int padcfg_base;
+
+ if (!info->jh8100_get_padcfg_base)
+ return 0;
+
+ padcfg_base = info->jh8100_get_padcfg_base(sfp, pin);
+ if (padcfg_base < 0)
+ return 0;
+
+ padcfg = readl_relaxed(sfp->base + padcfg_base + 4 * pin);
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ enabled = !(padcfg & JH8100_PADCFG_BIAS);
+ arg = 0;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ enabled = padcfg & JH8100_PADCFG_PD;
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ enabled = padcfg & JH8100_PADCFG_PU;
+ arg = 1;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ enabled = true;
+ arg = jh8100_padcfg_ds_to_mA(padcfg);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ enabled = padcfg & JH8100_PADCFG_IE;
+ arg = enabled;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ enabled = padcfg & JH8100_PADCFG_SMT;
+ arg = enabled;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ enabled = true;
+ arg = !!(padcfg & JH8100_PADCFG_SLEW);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+ return enabled ? 0 : -EINVAL;
+}
+
+static int jh8100_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int gsel,
+ unsigned long *config)
+{
+ const struct group_desc *group;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ return jh8100_pinconf_get(pctldev, group->pins[0], config);
+}
+
+static int jh8100_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int gsel,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ const struct group_desc *group;
+ u16 mask, value;
+ int i;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ mask = 0;
+ value = 0;
+ for (i = 0; i < num_configs; i++) {
+ int param = pinconf_to_config_param(configs[i]);
+ u32 arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ mask |= JH8100_PADCFG_BIAS;
+ value &= ~JH8100_PADCFG_BIAS;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask |= JH8100_PADCFG_BIAS;
+ value = (value & ~JH8100_PADCFG_BIAS) | JH8100_PADCFG_PD;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask |= JH8100_PADCFG_BIAS;
+ value = (value & ~JH8100_PADCFG_BIAS) | JH8100_PADCFG_PU;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ mask |= JH8100_PADCFG_DS_MASK;
+ value = (value & ~JH8100_PADCFG_DS_MASK) |
+ jh8100_padcfg_ds_from_mA(arg);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ mask |= JH8100_PADCFG_IE;
+ if (arg)
+ value |= JH8100_PADCFG_IE;
+ else
+ value &= ~JH8100_PADCFG_IE;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ mask |= JH8100_PADCFG_SMT;
+ if (arg)
+ value |= JH8100_PADCFG_SMT;
+ else
+ value &= ~JH8100_PADCFG_SMT;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ mask |= JH8100_PADCFG_SLEW;
+ if (arg)
+ value |= JH8100_PADCFG_SLEW;
+ else
+ value &= ~JH8100_PADCFG_SLEW;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ }
+
+ for (i = 0; i < group->num_pins; i++)
+ jh8100_padcfg_rmw(sfp, group->pins[i], mask, value);
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void jh8100_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct jh8100_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ u32 value;
+ int padcfg_base;
+
+ if (!info->jh8100_get_padcfg_base)
+ return;
+
+ padcfg_base = info->jh8100_get_padcfg_base(sfp, pin);
+ if (padcfg_base < 0)
+ return;
+
+ value = readl_relaxed(sfp->base + padcfg_base + 4 * pin);
+ seq_printf(s, " (0x%02x)", value);
+}
+#else
+#define jh8100_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops jh8100_pinconf_ops = {
+ .pin_config_get = jh8100_pinconf_get,
+ .pin_config_group_get = jh8100_pinconf_group_get,
+ .pin_config_group_set = jh8100_pinconf_group_set,
+ .pin_config_dbg_show = jh8100_pinconf_dbg_show,
+ .is_generic = true,
+};
+
+static int jh8100_gpio_request(struct gpio_chip *gc, unsigned int gpio)
+{
+ return pinctrl_gpio_request(gc, gpio);
+}
+
+static void jh8100_gpio_free(struct gpio_chip *gc, unsigned int gpio)
+{
+ pinctrl_gpio_free(gc, gpio);
+}
+
+static int jh8100_gpio_get_direction(struct gpio_chip *gc,
+ unsigned int gpio)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ unsigned int offset = 4 * (gpio / 4);
+ unsigned int shift = 8 * (gpio % 4);
+ u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset);
+
+ doen = (doen >> shift) & info->doen_mask;
+
+ return doen == GPOEN_ENABLE ?
+ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
+
+static int jh8100_gpio_direction_input(struct gpio_chip *gc,
+ unsigned int gpio)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+
+ /* enable input and schmitt trigger */
+ jh8100_padcfg_rmw(sfp, gpio,
+ JH8100_PADCFG_IE | JH8100_PADCFG_SMT,
+ JH8100_PADCFG_IE | JH8100_PADCFG_SMT);
+
+ if (info->jh8100_set_one_pin_mux)
+ info->jh8100_set_one_pin_mux(sfp, gpio,
+ GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0);
+
+ return 0;
+}
+
+static int jh8100_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int gpio, int value)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+
+ if (info->jh8100_set_one_pin_mux)
+ info->jh8100_set_one_pin_mux(sfp, gpio,
+ GPI_NONE, value ? GPOUT_HIGH : GPOUT_LOW,
+ GPOEN_ENABLE, 0);
+
+ /* disable input, schmitt trigger and bias */
+ jh8100_padcfg_rmw(sfp, gpio,
+ JH8100_PADCFG_IE | JH8100_PADCFG_SMT |
+ JH8100_PADCFG_BIAS, 0);
+ return 0;
+}
+
+static int jh8100_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ void __iomem *reg = sfp->base + info->gpioin_reg_base
+ + 4 * (gpio / 32);
+
+ return !!(readl_relaxed(reg) & BIT(gpio % 32));
+}
+
+static void jh8100_gpio_set(struct gpio_chip *gc,
+ unsigned int gpio, int value)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ const struct jh8100_pinctrl_soc_info *info = sfp->info;
+ unsigned int offset = 4 * (gpio / 4);
+ unsigned int shift = 8 * (gpio % 4);
+ void __iomem *reg_dout = sfp->base + info->dout_reg_base + offset;
+ u32 dout = (value ? GPOUT_HIGH : GPOUT_LOW) << shift;
+ u32 mask = info->dout_mask << shift;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ dout |= readl_relaxed(reg_dout) & ~mask;
+ writel_relaxed(dout, reg_dout);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_gpio_set_config(struct gpio_chip *gc,
+ unsigned int gpio, unsigned long config)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+ u32 arg = pinconf_to_config_argument(config);
+ u32 value;
+ u32 mask;
+
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ mask = JH8100_PADCFG_BIAS;
+ value = 0;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask = JH8100_PADCFG_BIAS;
+ value = JH8100_PADCFG_PD;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask = JH8100_PADCFG_BIAS;
+ value = JH8100_PADCFG_PU;
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return 0;
+ case PIN_CONFIG_INPUT_ENABLE:
+ mask = JH8100_PADCFG_IE;
+ value = arg ? JH8100_PADCFG_IE : 0;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ mask = JH8100_PADCFG_SMT;
+ value = arg ? JH8100_PADCFG_SMT : 0;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ jh8100_padcfg_rmw(sfp, gpio, mask, value);
+ return 0;
+}
+
+static int jh8100_gpio_add_pin_ranges(struct gpio_chip *gc)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+
+ sfp->gpios.name = sfp->gc.label;
+ sfp->gpios.base = sfp->gc.base;
+ sfp->gpios.pin_base = 0;
+ sfp->gpios.npins = sfp->gc.ngpio;
+ sfp->gpios.gc = &sfp->gc;
+ pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
+ return 0;
+}
+
+static void jh8100_irq_ack(struct irq_data *d)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ const struct jh8100_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *ic = sfp->base + irq_reg->ic_reg_base
+ + 4 * (gpio / 32);
+ u32 mask = BIT(gpio % 32);
+ unsigned long flags;
+ u32 value;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ value = readl_relaxed(ic) & ~mask;
+ writel_relaxed(value, ic);
+ writel_relaxed(value | mask, ic);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void jh8100_irq_mask(struct irq_data *d)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ const struct jh8100_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *ie = sfp->base + irq_reg->ie_reg_base
+ + 4 * (gpio / 32);
+ u32 mask = BIT(gpio % 32);
+ unsigned long flags;
+ u32 value;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ value = readl_relaxed(ie) & ~mask;
+ writel_relaxed(value, ie);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+
+ gpiochip_disable_irq(&sfp->gc, d->hwirq);
+}
+
+static void jh8100_irq_mask_ack(struct irq_data *d)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ const struct jh8100_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *ie = sfp->base + irq_reg->ie_reg_base
+ + 4 * (gpio / 32);
+ void __iomem *ic = sfp->base + irq_reg->ic_reg_base
+ + 4 * (gpio / 32);
+ u32 mask = BIT(gpio % 32);
+ unsigned long flags;
+ u32 value;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ value = readl_relaxed(ie) & ~mask;
+ writel_relaxed(value, ie);
+
+ value = readl_relaxed(ic) & ~mask;
+ writel_relaxed(value, ic);
+ writel_relaxed(value | mask, ic);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void jh8100_irq_unmask(struct irq_data *d)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ const struct jh8100_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *ie = sfp->base + irq_reg->ie_reg_base
+ + 4 * (gpio / 32);
+ u32 mask = BIT(gpio % 32);
+ unsigned long flags;
+ u32 value;
+
+ gpiochip_enable_irq(&sfp->gc, d->hwirq);
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ value = readl_relaxed(ie) | mask;
+ writel_relaxed(value, ie);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_irq_set_type(struct irq_data *d, unsigned int trigger)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ const struct jh8100_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *base = sfp->base + 4 * (gpio / 32);
+ u32 mask = BIT(gpio % 32);
+ u32 irq_type, edge_both, polarity;
+ unsigned long flags;
+
+ switch (trigger) {
+ case IRQ_TYPE_EDGE_RISING:
+ irq_type = mask; /* 1: edge triggered */
+ edge_both = 0; /* 0: single edge */
+ polarity = mask; /* 1: rising edge */
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ irq_type = mask; /* 1: edge triggered */
+ edge_both = 0; /* 0: single edge */
+ polarity = 0; /* 0: falling edge */
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ irq_type = mask; /* 1: edge triggered */
+ edge_both = mask; /* 1: both edges */
+ polarity = 0; /* 0: ignored */
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ irq_type = 0; /* 0: level triggered */
+ edge_both = 0; /* 0: ignored */
+ polarity = mask; /* 1: high level */
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ irq_type = 0; /* 0: level triggered */
+ edge_both = 0; /* 0: ignored */
+ polarity = 0; /* 0: low level */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (trigger & IRQ_TYPE_EDGE_BOTH)
+ irq_set_handler_locked(d, handle_edge_irq);
+ else
+ irq_set_handler_locked(d, handle_level_irq);
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ irq_type |= readl_relaxed(base + irq_reg->is_reg_base) & ~mask;
+ writel_relaxed(irq_type, base + irq_reg->is_reg_base);
+
+ edge_both |= readl_relaxed(base + irq_reg->ibe_reg_base) & ~mask;
+ writel_relaxed(edge_both, base + irq_reg->ibe_reg_base);
+
+ polarity |= readl_relaxed(base + irq_reg->iev_reg_base) & ~mask;
+ writel_relaxed(polarity, base + irq_reg->iev_reg_base);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+ return 0;
+}
+
+static irqreturn_t jh8100_gpio_wake_irq_handler(int irq, void *data)
+{
+ struct jh8100_pinctrl *sfp = data;
+
+ if (!sfp || irq != sfp->wakeup_irq)
+ return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
+static int jh8100_irq_set_wake(struct irq_data *d, unsigned int enable)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_data(d);
+ int ret = 0;
+
+ if (enable)
+ ret = enable_irq_wake(sfp->wakeup_irq);
+ else
+ ret = disable_irq_wake(sfp->wakeup_irq);
+ if (ret)
+ dev_err(sfp->dev, "failed to %s wake-up interrupt\n",
+ enable ? "enable" : "disable");
+
+ return ret;
+}
+
+static struct irq_chip jh8100_irq_chip = {
+ .irq_ack = jh8100_irq_ack,
+ .irq_mask = jh8100_irq_mask,
+ .irq_mask_ack = jh8100_irq_mask_ack,
+ .irq_unmask = jh8100_irq_unmask,
+ .irq_set_type = jh8100_irq_set_type,
+ .irq_set_wake = jh8100_irq_set_wake,
+ .flags = IRQCHIP_SET_TYPE_MASKED |
+ IRQCHIP_IMMUTABLE |
+ IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND |
+ IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SKIP_SET_WAKE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int jh8100_gpio_irq_setup(struct device *dev, struct jh8100_pinctrl *sfp)
+{
+ struct device_node *np = dev->of_node;
+ struct irq_desc *desc;
+ irq_hw_number_t hwirq;
+ int i, ret;
+
+ if (!sfp->gc.irq.domain) {
+ sfp->irq_domain = irq_domain_add_linear(np, sfp->gc.ngpio,
+ &irq_domain_simple_ops,
+ sfp);
+ } else {
+ sfp->irq_domain = sfp->gc.irq.domain;
+ }
+
+ if (!sfp->irq_domain) {
+ dev_err(dev, "Couldn't allocate IRQ domain\n");
+ return -ENXIO;
+ }
+
+ for (i = 0; i < sfp->gc.ngpio; i++) {
+ int virq = irq_create_mapping(sfp->irq_domain, i);
+
+ irq_set_chip_and_handler(virq, &jh8100_irq_chip,
+ handle_edge_irq);
+ irq_set_chip_data(virq, &sfp->gc);
+ }
+
+ sfp->wakeup_gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+ hwirq = pin_to_hwirq(sfp);
+ sfp->wakeup_irq = irq_find_mapping(sfp->irq_domain, hwirq);
+ desc = irq_to_desc(sfp->wakeup_irq);
+
+ if (!(desc->status_use_accessors & IRQ_NOREQUEST)) {
+ device_init_wakeup(dev, 1);
+ ret = devm_request_threaded_irq(dev, sfp->wakeup_irq, NULL,
+ jh8100_gpio_wake_irq_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT |
+ IRQF_SHARED,
+ "wakeup-gpio", sfp);
+ if (ret) {
+ dev_err_probe(dev, ret, "unable to request wake IRQ %d\n",
+ sfp->wakeup_irq);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void jh8100_disable_clock(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+int jh8100_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct jh8100_pinctrl_soc_info *info;
+ struct jh8100_pinctrl *sfp;
+ struct pinctrl_desc *jh8100_pinctrl_desc;
+ struct reset_control *rst;
+ struct clk *clk;
+ int ret;
+
+ info = of_device_get_match_data(&pdev->dev);
+ if (!info)
+ return -ENODEV;
+
+ if (!info->pins || !info->npins) {
+ dev_err(dev, "wrong pinctrl info\n");
+ return -EINVAL;
+ }
+
+ sfp = devm_kzalloc(dev, sizeof(*sfp), GFP_KERNEL);
+ if (!sfp)
+ return -ENOMEM;
+
+ sfp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(sfp->base))
+ return PTR_ERR(sfp->base);
+
+ clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "could not get clock\n");
+
+ rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(rst))
+ return dev_err_probe(dev, PTR_ERR(rst), "could not get reset control\n");
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not enable clock\n");
+
+ ret = devm_add_action_or_reset(dev, jh8100_disable_clock, clk);
+ if (ret)
+ return ret;
+
+ /*
+ * we don't want to assert reset and risk undoing pin muxing for the
+ * early boot serial console, but let's make sure the reset line is
+ * deasserted in case someone runs a really minimal bootloader.
+ */
+ ret = reset_control_deassert(rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not deassert reset\n");
+
+ jh8100_pinctrl_desc = devm_kzalloc(&pdev->dev,
+ sizeof(*jh8100_pinctrl_desc),
+ GFP_KERNEL);
+ if (!jh8100_pinctrl_desc)
+ return -ENOMEM;
+
+ jh8100_pinctrl_desc->name = dev_name(dev);
+ jh8100_pinctrl_desc->pins = info->pins;
+ jh8100_pinctrl_desc->npins = info->npins;
+ jh8100_pinctrl_desc->pctlops = &jh8100_pinctrl_ops;
+ jh8100_pinctrl_desc->pmxops = &jh8100_pinmux_ops;
+ jh8100_pinctrl_desc->confops = &jh8100_pinconf_ops;
+ jh8100_pinctrl_desc->owner = THIS_MODULE;
+
+ sfp->info = info;
+ sfp->dev = dev;
+ platform_set_drvdata(pdev, sfp);
+ sfp->gc.parent = dev;
+ raw_spin_lock_init(&sfp->lock);
+ mutex_init(&sfp->mutex);
+
+ ret = devm_pinctrl_register_and_init(dev,
+ jh8100_pinctrl_desc,
+ sfp, &sfp->pctl);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "could not register pinctrl driver\n");
+
+ sfp->gc.label = dev_name(dev);
+ sfp->gc.owner = THIS_MODULE;
+ sfp->gc.request = jh8100_gpio_request;
+ sfp->gc.free = jh8100_gpio_free;
+ sfp->gc.get_direction = jh8100_gpio_get_direction;
+ sfp->gc.direction_input = jh8100_gpio_direction_input;
+ sfp->gc.direction_output = jh8100_gpio_direction_output;
+ sfp->gc.get = jh8100_gpio_get;
+ sfp->gc.set = jh8100_gpio_set;
+ sfp->gc.set_config = jh8100_gpio_set_config;
+ sfp->gc.add_pin_ranges = jh8100_gpio_add_pin_ranges;
+ sfp->gc.base = info->gc_base;
+ sfp->gc.ngpio = info->ngpios;
+
+ if (info->irq_reg) {
+ jh8100_irq_chip.name = sfp->gc.label;
+ gpio_irq_chip_set_chip(&sfp->gc.irq, &jh8100_irq_chip);
+ sfp->gc.irq.parent_handler = info->jh8100_gpio_irq_handler;
+ sfp->gc.irq.num_parents = 1;
+ sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents,
+ sizeof(*sfp->gc.irq.parents),
+ GFP_KERNEL);
+ if (!sfp->gc.irq.parents)
+ return -ENOMEM;
+ sfp->gc.irq.default_type = IRQ_TYPE_NONE;
+ sfp->gc.irq.handler = handle_bad_irq;
+ sfp->gc.irq.init_hw = info->jh8100_gpio_init_hw;
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+ sfp->gc.irq.parents[0] = ret;
+ }
+
+ if (sfp->gc.ngpio > 0) {
+ ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not register gpiochip\n");
+
+ dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
+ }
+
+ if (of_property_read_bool(np, "wakeup-source")) {
+ ret = jh8100_gpio_irq_setup(dev, sfp);
+ if (ret) {
+ return dev_err_probe(dev, ret,
+ "failed to setup gpio irq wake\n");
+ }
+
+ ret = dev_pm_set_wake_irq(dev, sfp->wakeup_irq);
+ if (ret) {
+ return dev_err_probe(dev, ret,
+ "failed to enable gpio irq wake\n");
+ }
+ }
+
+ return pinctrl_enable(sfp->pctl);
+}
+EXPORT_SYMBOL_GPL(jh8100_pinctrl_probe);
+
+MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC");
+MODULE_AUTHOR("Alex Soo <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
new file mode 100644
index 000000000000..d84b88c0568d
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#ifndef __PINCTRL_STARFIVE_JH8100_H__
+#define __PINCTRL_STARFIVE_JH8100_H__
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#define JH8100_SYS_EAST_REG_NUM 116
+
+struct jh8100_pinctrl {
+ struct device *dev;
+ struct gpio_chip gc;
+ struct pinctrl_gpio_range gpios;
+ raw_spinlock_t lock;
+ void __iomem *base;
+ struct pinctrl_dev *pctl;
+ /* register read/write mutex */
+ struct mutex mutex;
+ const struct jh8100_pinctrl_soc_info *info;
+ unsigned int jh8100_sys_east_regs[JH8100_SYS_EAST_REG_NUM];
+ /* wakeup */
+ int wakeup_gpio;
+ int wakeup_irq;
+ struct irq_domain *irq_domain;
+};
+
+struct jh8100_gpio_irq_reg {
+ unsigned int is_reg_base;
+ unsigned int ic_reg_base;
+ unsigned int ibe_reg_base;
+ unsigned int iev_reg_base;
+ unsigned int ie_reg_base;
+ unsigned int ris_reg_base;
+ unsigned int mis_reg_base;
+};
+
+struct jh8100_pinctrl_soc_info {
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ unsigned int ngpios;
+ unsigned int gc_base;
+
+ /* gpio dout/doen/din/gpioinput register */
+ unsigned int dout_reg_base;
+ unsigned int dout_mask;
+ unsigned int doen_reg_base;
+ unsigned int doen_mask;
+ unsigned int gpi_reg_base;
+ unsigned int gpi_mask;
+ unsigned int gpioin_reg_base;
+
+ const struct jh8100_gpio_irq_reg *irq_reg;
+
+ /* generic pinmux */
+ int (*jh8100_set_one_pin_mux)(struct jh8100_pinctrl *sfp,
+ unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func);
+ /* gpio chip */
+ int (*jh8100_get_padcfg_base)(struct jh8100_pinctrl *sfp,
+ unsigned int pin);
+ void (*jh8100_gpio_irq_handler)(struct irq_desc *desc);
+ int (*jh8100_gpio_init_hw)(struct gpio_chip *gc);
+};
+
+void jh8100_set_gpiomux(struct jh8100_pinctrl *sfp, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen);
+int jh8100_pinctrl_probe(struct platform_device *pdev);
+struct jh8100_pinctrl *jh8100_from_irq_desc(struct irq_desc *desc);
+
+#endif /* __PINCTRL_STARFIVE_JH8100_H__ */
--
2.25.1
Add pinctrl driver for sys_west domain.
Signed-off-by: Alex Soo <[email protected]>
Reviewed-by: Ley Foon Tan <[email protected]>
---
drivers/pinctrl/starfive/Kconfig | 12 +
drivers/pinctrl/starfive/Makefile | 1 +
.../pinctrl-starfive-jh8100-sys-west.c | 264 ++++++++++++++++++
.../starfive/pinctrl-starfive-jh8100.h | 2 +
4 files changed, 279 insertions(+)
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-west.c
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
index afcbf9d4dc8d..d78f161a636c 100644
--- a/drivers/pinctrl/starfive/Kconfig
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -70,3 +70,15 @@ config PINCTRL_STARFIVE_JH8100_SYS_EAST
This also provides an interface to the GPIO pins not used by other
peripherals supporting inputs, outputs, configuring pull-up/pull-down
and interrupts on input changes.
+
+config PINCTRL_STARFIVE_JH8100_SYS_WEST
+ tristate "StarFive JH8100 SoC System IOMUX-West pinctrl and GPIO driver"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ depends on OF
+ select PINCTRL_STARFIVE_JH8100
+ default ARCH_STARFIVE
+ help
+ Say yes here to support system iomux-west pin control on the StarFive JH8100 SoC.
+ This also provides an interface to the GPIO pins not used by other
+ peripherals supporting inputs, outputs, configuring pull-up/pull-down
+ and interrupts on input changes.
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
index 45698c502b48..784465157ae2 100644
--- a/drivers/pinctrl/starfive/Makefile
+++ b/drivers/pinctrl/starfive/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_AON) += pinctrl-starfive-jh7110-aon.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100) += pinctrl-starfive-jh8100.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_EAST) += pinctrl-starfive-jh8100-sys-east.o
+obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_WEST) += pinctrl-starfive-jh8100-sys-west.o
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-west.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-west.c
new file mode 100644
index 000000000000..398821fc1f78
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-west.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC sys west controller
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+#include "../pinconf.h"
+#include "pinctrl-starfive-jh8100.h"
+
+#define JH8100_SYS_W_NGPIO 16
+#define JH8100_SYS_W_GC_BASE 0
+
+/* registers */
+#define JH8100_SYS_W_DOEN 0x000
+#define JH8100_SYS_W_DOUT 0x010
+#define JH8100_SYS_W_GPI 0x020
+#define JH8100_SYS_W_GPIOIN 0x068
+
+#define JH8100_SYS_W_GPIOEN 0x048
+#define JH8100_SYS_W_GPIOIS0 0x04c
+#define JH8100_SYS_W_GPIOIC0 0x050
+#define JH8100_SYS_W_GPIOIBE0 0x054
+#define JH8100_SYS_W_GPIOIEV0 0x058
+#define JH8100_SYS_W_GPIOIE0 0x05c
+#define JH8100_SYS_W_GPIORIS0 0x060
+#define JH8100_SYS_W_GPIOMIS0 0x064
+
+#define JH8100_SYS_W_GPO_PDA_00_15_CFG 0x074
+
+static const struct pinctrl_pin_desc jh8100_sys_w_pins[] = {
+ PINCTRL_PIN(PAD_GPIO0_W, "SYS_W_GPIO0"),
+ PINCTRL_PIN(PAD_GPIO1_W, "SYS_W_GPIO1"),
+ PINCTRL_PIN(PAD_GPIO2_W, "SYS_W_GPIO2"),
+ PINCTRL_PIN(PAD_GPIO3_W, "SYS_W_GPIO3"),
+ PINCTRL_PIN(PAD_GPIO4_W, "SYS_W_GPIO4"),
+ PINCTRL_PIN(PAD_GPIO5_W, "SYS_W_GPIO5"),
+ PINCTRL_PIN(PAD_GPIO6_W, "SYS_W_GPIO6"),
+ PINCTRL_PIN(PAD_GPIO7_W, "SYS_W_GPIO7"),
+ PINCTRL_PIN(PAD_GPIO8_W, "SYS_W_GPIO8"),
+ PINCTRL_PIN(PAD_GPIO9_W, "SYS_W_GPIO9"),
+ PINCTRL_PIN(PAD_GPIO10_W, "SYS_W_GPIO10"),
+ PINCTRL_PIN(PAD_GPIO11_W, "SYS_W_GPIO11"),
+ PINCTRL_PIN(PAD_GPIO12_W, "SYS_W_GPIO12"),
+ PINCTRL_PIN(PAD_GPIO13_W, "SYS_W_GPIO13"),
+ PINCTRL_PIN(PAD_GPIO14_W, "SYS_W_GPIO14"),
+ PINCTRL_PIN(PAD_GPIO15_W, "SYS_W_GPIO15"),
+};
+
+struct jh8100_sys_w_func_sel {
+ u16 offset;
+ u8 shift;
+ u8 max;
+};
+
+static const struct jh8100_sys_w_func_sel
+ jh8100_sys_w_func_sel[ARRAY_SIZE(jh8100_sys_w_pins)] = {
+ [PAD_GPIO0_W] = { 0xb4, 0, 2 },
+ [PAD_GPIO1_W] = { 0xb4, 12, 2 },
+ [PAD_GPIO2_W] = { 0xb4, 14, 2 },
+ [PAD_GPIO3_W] = { 0xb4, 16, 2 },
+ [PAD_GPIO4_W] = { 0xb4, 18, 2 },
+ [PAD_GPIO5_W] = { 0xb4, 20, 2 },
+ [PAD_GPIO6_W] = { 0xb4, 22, 2 },
+ [PAD_GPIO7_W] = { 0xb4, 24, 2 },
+ [PAD_GPIO8_W] = { 0xb4, 26, 2 },
+ [PAD_GPIO9_W] = { 0xb4, 28, 2 },
+ [PAD_GPIO10_W] = { 0xb4, 2, 2 },
+ [PAD_GPIO11_W] = { 0xb4, 4, 2 },
+ [PAD_GPIO12_W] = { 0xb4, 6, 2 },
+ [PAD_GPIO13_W] = { 0xb4, 8, 2 },
+ [PAD_GPIO14_W] = { 0xb4, 10, 2 },
+};
+
+static void jh8100_sys_w_set_function(struct jh8100_pinctrl *sfp,
+ unsigned int pin, u32 func)
+{
+ const struct jh8100_sys_w_func_sel *fs = &jh8100_sys_w_func_sel[pin];
+ unsigned long flags;
+ void __iomem *reg;
+ u32 mask;
+
+ if (!fs->offset)
+ return;
+
+ if (func > fs->max)
+ return;
+
+ reg = sfp->base + fs->offset;
+ func = func << fs->shift;
+ mask = 0x3U << fs->shift;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ func |= readl_relaxed(reg) & ~mask;
+ writel_relaxed(func, reg);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_sys_w_set_one_pin_mux(struct jh8100_pinctrl *sfp,
+ unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func)
+{
+ if (pin < sfp->gc.ngpio - 1 && func == 0)
+ jh8100_set_gpiomux(sfp, pin, din, dout, doen);
+
+ if (pin < sfp->gc.ngpio - 1 && func == 2)
+ jh8100_sys_w_set_function(sfp, pin, func);
+
+ return 0;
+}
+
+static int jh8100_sys_w_get_padcfg_base(struct jh8100_pinctrl *sfp,
+ unsigned int pin)
+{
+ if (pin <= PAD_GPIO15_W)
+ return JH8100_SYS_W_GPO_PDA_00_15_CFG;
+ else
+ return -1;
+}
+
+static void jh8100_sys_w_irq_handler(struct irq_desc *desc)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_desc(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long mis;
+ unsigned int pin;
+
+ chained_irq_enter(chip, desc);
+
+ mis = readl_relaxed(sfp->base + JH8100_SYS_W_GPIOMIS0);
+ for_each_set_bit(pin, &mis, 16)
+ generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+ chained_irq_exit(chip, desc);
+}
+
+static int jh8100_sys_w_init_hw(struct gpio_chip *gc)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+
+ /* mask all GPIO interrupts */
+ writel(0U, sfp->base + JH8100_SYS_W_GPIOIE0);
+ /* clear edge interrupt flags */
+ writel(0U, sfp->base + JH8100_SYS_W_GPIOIC0);
+ writel(~0U, sfp->base + JH8100_SYS_W_GPIOIC0);
+ /* enable GPIO interrupts */
+ writel(1U, sfp->base + JH8100_SYS_W_GPIOEN);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int jh8100_sys_w_pinctrl_suspend(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_WEST_REG_NUM; i++)
+ sfp->jh8100_sys_west_regs[i] = readl_relaxed(sfp->base + (i * 4));
+
+ return pinctrl_force_sleep(sfp->pctl);
+}
+
+static int jh8100_sys_w_pinctrl_resume(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_WEST_REG_NUM; i++)
+ writel_relaxed(sfp->jh8100_sys_west_regs[i], sfp->base + (i * 4));
+
+ return pinctrl_force_default(sfp->pctl);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(jh8100_sys_w_pinctrl_dev_pm_ops,
+ jh8100_sys_w_pinctrl_suspend,
+ jh8100_sys_w_pinctrl_resume);
+
+static const struct jh8100_gpio_irq_reg jh8100_sys_w_irq_reg = {
+ .is_reg_base = JH8100_SYS_W_GPIOIS0,
+ .ic_reg_base = JH8100_SYS_W_GPIOIC0,
+ .ibe_reg_base = JH8100_SYS_W_GPIOIBE0,
+ .iev_reg_base = JH8100_SYS_W_GPIOIEV0,
+ .ie_reg_base = JH8100_SYS_W_GPIOIE0,
+ .ris_reg_base = JH8100_SYS_W_GPIORIS0,
+ .mis_reg_base = JH8100_SYS_W_GPIOMIS0,
+};
+
+static const struct jh8100_pinctrl_soc_info jh8100_sys_w_pinctrl_info = {
+ .pins = jh8100_sys_w_pins,
+ .npins = ARRAY_SIZE(jh8100_sys_w_pins),
+ .ngpios = JH8100_SYS_W_NGPIO,
+ .gc_base = JH8100_SYS_W_GC_BASE,
+ .dout_reg_base = JH8100_SYS_W_DOUT,
+ .dout_mask = GENMASK(5, 0),
+ .doen_reg_base = JH8100_SYS_W_DOEN,
+ .doen_mask = GENMASK(4, 0),
+ .gpi_reg_base = JH8100_SYS_W_GPI,
+ .gpi_mask = GENMASK(4, 0),
+ .gpioin_reg_base = JH8100_SYS_W_GPIOIN,
+ .irq_reg = &jh8100_sys_w_irq_reg,
+ .jh8100_set_one_pin_mux = jh8100_sys_w_set_one_pin_mux,
+ .jh8100_get_padcfg_base = jh8100_sys_w_get_padcfg_base,
+ .jh8100_gpio_irq_handler = jh8100_sys_w_irq_handler,
+ .jh8100_gpio_init_hw = jh8100_sys_w_init_hw,
+};
+
+static const struct of_device_id jh8100_sys_w_pinctrl_of_match[] = {
+ {
+ .compatible = "starfive,jh8100-sys-pinctrl-west",
+ .data = &jh8100_sys_w_pinctrl_info,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh8100_sys_w_pinctrl_of_match);
+
+static struct platform_driver jh8100_sys_w_pinctrl_driver = {
+ .probe = jh8100_pinctrl_probe,
+ .driver = {
+ .name = "starfive-jh8100-sys-pinctrl-west",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &jh8100_sys_w_pinctrl_dev_pm_ops,
+#endif
+ .of_match_table = jh8100_sys_w_pinctrl_of_match,
+ },
+};
+module_platform_driver(jh8100_sys_w_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC sys west controller");
+MODULE_AUTHOR("Alex Soo <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
index d84b88c0568d..6264931ddb82 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
@@ -13,6 +13,7 @@
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
+#define JH8100_SYS_WEST_REG_NUM 44
#define JH8100_SYS_EAST_REG_NUM 116
struct jh8100_pinctrl {
@@ -25,6 +26,7 @@ struct jh8100_pinctrl {
/* register read/write mutex */
struct mutex mutex;
const struct jh8100_pinctrl_soc_info *info;
+ unsigned int jh8100_sys_west_regs[JH8100_SYS_WEST_REG_NUM];
unsigned int jh8100_sys_east_regs[JH8100_SYS_EAST_REG_NUM];
/* wakeup */
int wakeup_gpio;
--
2.25.1
Add pinctrl driver for sys_gmac domain.
Signed-off-by: Alex Soo <[email protected]>
Reviewed-by: Ley Foon Tan <[email protected]>
---
drivers/pinctrl/starfive/Kconfig | 12 ++
drivers/pinctrl/starfive/Makefile | 1 +
.../pinctrl-starfive-jh8100-sys-gmac.c | 164 ++++++++++++++++++
.../starfive/pinctrl-starfive-jh8100.h | 2 +
4 files changed, 179 insertions(+)
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-gmac.c
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
index d78f161a636c..bb1fb3788d5b 100644
--- a/drivers/pinctrl/starfive/Kconfig
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -82,3 +82,15 @@ config PINCTRL_STARFIVE_JH8100_SYS_WEST
This also provides an interface to the GPIO pins not used by other
peripherals supporting inputs, outputs, configuring pull-up/pull-down
and interrupts on input changes.
+
+config PINCTRL_STARFIVE_JH8100_SYS_GMAC
+ tristate "StarFive JH8100 SoC System IOMUX-GMAC pinctrl and GPIO driver"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ depends on OF
+ select PINCTRL_STARFIVE_JH8100
+ default ARCH_STARFIVE
+ help
+ Say yes here to support system iomux-gmac pin control on the StarFive JH8100 SoC.
+ This also provides a syscon interface to configure the GMAC1 voltage level for RGMII(1.8V
+ 2.5V), GMII(2.5V/3.3V), to configure the SDIO1 voltage level to support the 3.3/1.8V voltage
+ switching in high-speed mode, and configure the GMAC1 network interface and timing (slew rate).
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
index 784465157ae2..236a693a8aef 100644
--- a/drivers/pinctrl/starfive/Makefile
+++ b/drivers/pinctrl/starfive/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_AON) += pinctrl-starfive-jh7110-aon.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100) += pinctrl-starfive-jh8100.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_EAST) += pinctrl-starfive-jh8100-sys-east.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_WEST) += pinctrl-starfive-jh8100-sys-west.o
+obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_GMAC) += pinctrl-starfive-jh8100-sys-gmac.o
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-gmac.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-gmac.c
new file mode 100644
index 000000000000..dbbac86dd265
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-sys-gmac.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC sys gmac controller
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+#include "../pinconf.h"
+#include "pinctrl-starfive-jh8100.h"
+
+#define JH8100_SYS_G_NGPIO 0
+#define JH8100_SYS_G_GC_BASE 64
+
+static const struct pinctrl_pin_desc jh8100_sys_gmac_pins[] = {
+ PINCTRL_PIN(PAD_GMAC1_MDC, "SYS_G_GMAC1_MDC"),
+ PINCTRL_PIN(PAD_GMAC1_MDIO, "SYS_G_GMAC1_MDIO"),
+ PINCTRL_PIN(PAD_GMAC1_RXD0, "SYS_G_GMAC1_RXD0"),
+ PINCTRL_PIN(PAD_GMAC1_RXD1, "SYS_G_GMAC1_RXD1"),
+ PINCTRL_PIN(PAD_GMAC1_RXD2, "SYS_G_GMAC1_RXD2"),
+ PINCTRL_PIN(PAD_GMAC1_RXD3, "SYS_G_GMAC1_RXD3"),
+ PINCTRL_PIN(PAD_GMAC1_RXDV, "SYS_G_GMAC1_RXDV"),
+ PINCTRL_PIN(PAD_GMAC1_RXC, "SYS_G_GMAC1_RXC"),
+ PINCTRL_PIN(PAD_GMAC1_TXD0, "SYS_G_GMAC1_TXD0"),
+ PINCTRL_PIN(PAD_GMAC1_TXD1, "SYS_G_GMAC1_TXD1"),
+ PINCTRL_PIN(PAD_GMAC1_TXD2, "SYS_G_GMAC1_TXD2"),
+ PINCTRL_PIN(PAD_GMAC1_TXD3, "SYS_G_GMAC1_TXD3"),
+ PINCTRL_PIN(PAD_GMAC1_TXEN, "SYS_G_GMAC1_TXEN"),
+ PINCTRL_PIN(PAD_GMAC1_TXC, "SYS_G_GMAC1_TXC")
+};
+
+struct jh8100_sys_gmac_func_sel {
+ u16 offset;
+ u8 shift;
+ u8 max;
+};
+
+static const struct jh8100_sys_gmac_func_sel
+ jh8100_sys_gmac_func_sel[ARRAY_SIZE(jh8100_sys_gmac_pins)] = {
+ [PAD_GMAC1_RXC] = { 0x048, 0, 2 },
+};
+
+static void jh8100_sys_gmac_set_function(struct jh8100_pinctrl *sfp,
+ unsigned int pin, u32 func)
+{
+ const struct jh8100_sys_gmac_func_sel *fs = &jh8100_sys_gmac_func_sel[pin];
+ unsigned long flags;
+ void __iomem *reg;
+ u32 mask;
+
+ if (!fs->offset)
+ return;
+
+ if (func > fs->max)
+ return;
+
+ reg = sfp->base + fs->offset;
+ func = func << fs->shift;
+ mask = 0x3U << fs->shift;
+
+ raw_spin_lock_irqsave(&sfp->lock, flags);
+ func |= readl_relaxed(reg) & ~mask;
+ writel_relaxed(func, reg);
+ raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int jh8100_sys_gmac_set_one_pin_mux(struct jh8100_pinctrl *sfp,
+ unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func)
+{
+ jh8100_sys_gmac_set_function(sfp, pin, func);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int jh8100_sys_gmac_pinctrl_suspend(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_GMAC_REG_NUM; i++)
+ sfp->jh8100_sys_gmac_regs[i] = readl_relaxed(sfp->base + (i * 4));
+
+ return pinctrl_force_sleep(sfp->pctl);
+}
+
+static int jh8100_sys_gmac_pinctrl_resume(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ for (i = 0; i < JH8100_SYS_GMAC_REG_NUM; i++)
+ writel_relaxed(sfp->jh8100_sys_gmac_regs[i], sfp->base + (i * 4));
+
+ return pinctrl_force_default(sfp->pctl);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(jh8100_sys_gmac_pinctrl_dev_pm_ops,
+ jh8100_sys_gmac_pinctrl_suspend,
+ jh8100_sys_gmac_pinctrl_resume);
+
+static const struct jh8100_pinctrl_soc_info jh8100_sys_gmac_pinctrl_info = {
+ .pins = jh8100_sys_gmac_pins,
+ .npins = ARRAY_SIZE(jh8100_sys_gmac_pins),
+ .ngpios = JH8100_SYS_G_NGPIO,
+ .gc_base = JH8100_SYS_G_GC_BASE,
+ .jh8100_set_one_pin_mux = jh8100_sys_gmac_set_one_pin_mux,
+};
+
+static const struct of_device_id jh8100_sys_gmac_pinctrl_of_match[] = {
+ {
+ .compatible = "starfive,jh8100-sys-pinctrl-gmac",
+ .data = &jh8100_sys_gmac_pinctrl_info,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh8100_sys_gmac_pinctrl_of_match);
+
+static struct platform_driver jh8100_sys_gmac_pinctrl_driver = {
+ .probe = jh8100_pinctrl_probe,
+ .driver = {
+ .name = "starfive-jh8100-sys-pinctrl-gmac",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &jh8100_sys_gmac_pinctrl_dev_pm_ops,
+#endif
+ .of_match_table = jh8100_sys_gmac_pinctrl_of_match,
+ },
+};
+module_platform_driver(jh8100_sys_gmac_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC sys gmac controller");
+MODULE_AUTHOR("Alex Soo <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
index 6264931ddb82..43b62609fa3e 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
@@ -15,6 +15,7 @@
#define JH8100_SYS_WEST_REG_NUM 44
#define JH8100_SYS_EAST_REG_NUM 116
+#define JH8100_SYS_GMAC_REG_NUM 19
struct jh8100_pinctrl {
struct device *dev;
@@ -28,6 +29,7 @@ struct jh8100_pinctrl {
const struct jh8100_pinctrl_soc_info *info;
unsigned int jh8100_sys_west_regs[JH8100_SYS_WEST_REG_NUM];
unsigned int jh8100_sys_east_regs[JH8100_SYS_EAST_REG_NUM];
+ unsigned int jh8100_sys_gmac_regs[JH8100_SYS_GMAC_REG_NUM];
/* wakeup */
int wakeup_gpio;
int wakeup_irq;
--
2.25.1
Add pinctrl driver for AON domain.
Signed-off-by: Alex Soo <[email protected]>
Reviewed-by: Ley Foon Tan <[email protected]>
---
MAINTAINERS | 7 +
drivers/pinctrl/starfive/Kconfig | 12 +
drivers/pinctrl/starfive/Makefile | 1 +
.../starfive/pinctrl-starfive-jh8100-aon.c | 241 ++++++++++++++++++
.../starfive/pinctrl-starfive-jh8100.h | 2 +
5 files changed, 263 insertions(+)
create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 53084079f5f5..451ee21086a7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20776,6 +20776,13 @@ S: Maintained
F: drivers/reset/starfive/reset-starfive-jh81*
F: include/dt-bindings/reset/starfive?jh81*.h
+STARFIVE JH8100 PINCTRL DRIVERS
+M: Alex Soo <[email protected]>
+S: Supported
+F: Documentation/devicetree/bindings/pinctrl/starfive,jh81*.yaml
+F: drivers/pinctrl/starfive/pinctrl-starfive-jh81*
+F: include/dt-bindings/pinctrl/starfive,jh8100-pinctrl.h
+
STATIC BRANCH/CALL
M: Peter Zijlstra <[email protected]>
M: Josh Poimboeuf <[email protected]>
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
index bb1fb3788d5b..4d62d7199f5d 100644
--- a/drivers/pinctrl/starfive/Kconfig
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -94,3 +94,15 @@ config PINCTRL_STARFIVE_JH8100_SYS_GMAC
This also provides a syscon interface to configure the GMAC1 voltage level for RGMII(1.8V
2.5V), GMII(2.5V/3.3V), to configure the SDIO1 voltage level to support the 3.3/1.8V voltage
switching in high-speed mode, and configure the GMAC1 network interface and timing (slew rate).
+
+config PINCTRL_STARFIVE_JH8100_AON
+ tristate "Always-on pinctrl and GPIO driver for the StarFive JH8100 SoC"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ depends on OF
+ select PINCTRL_STARFIVE_JH8100
+ default ARCH_STARFIVE
+ help
+ Say yes here to support always-on pin control on the StarFive JH8100 SoC.
+ This also provides a syscon interface to configure the GMAC0 voltage level for RGMII(1.8V
+ 2.5V), GMII(2.5V/3.3V), to configure the SDIO0 voltage level to support the 3.3/1.8V voltage
+ switching in high-speed mode, and configure the GMAC0 network interface and timing (slew rate).
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
index 236a693a8aef..46b1ab97779b 100644
--- a/drivers/pinctrl/starfive/Makefile
+++ b/drivers/pinctrl/starfive/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH8100) += pinctrl-starfive-jh8100.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_EAST) += pinctrl-starfive-jh8100-sys-east.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_WEST) += pinctrl-starfive-jh8100-sys-west.o
obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_GMAC) += pinctrl-starfive-jh8100-sys-gmac.o
+obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_AON) += pinctrl-starfive-jh8100-aon.o
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c
new file mode 100644
index 000000000000..fc478bc0e0b2
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl / GPIO driver for StarFive JH8100 SoC aon controller
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+#include "pinctrl-starfive-jh8100.h"
+
+#define JH8100_AON_NGPIO 16
+#define JH8100_AON_GC_BASE 64
+
+/* registers */
+#define JH8100_AON_DOEN 0x00
+#define JH8100_AON_DOUT 0x10
+#define JH8100_AON_GPI 0x20
+#define JH8100_AON_GPIOIN 0x54
+
+#define JH8100_AON_GPIOEN 0x34
+#define JH8100_AON_GPIOIS 0x38
+#define JH8100_AON_GPIOIC 0x3c
+#define JH8100_AON_GPIOIBE 0x40
+#define JH8100_AON_GPIOIEV 0x44
+#define JH8100_AON_GPIOIE 0x48
+#define JH8100_AON_GPIORIS 0x4c
+#define JH8100_AON_GPIOMIS 0x50
+
+#define JH8100_AON_GPO_PDA_0_14_CFG 0x90
+
+static const struct pinctrl_pin_desc jh8100_aon_pins[] = {
+ PINCTRL_PIN(PAD_RGPIO0, "AON_RGPIO0"),
+ PINCTRL_PIN(PAD_RGPIO1, "AON_RGPIO1"),
+ PINCTRL_PIN(PAD_RGPIO2, "AON_RGPIO2"),
+ PINCTRL_PIN(PAD_RGPIO3, "AON_RGPIO3"),
+ PINCTRL_PIN(PAD_RGPIO4, "AON_RGPIO4"),
+ PINCTRL_PIN(PAD_RGPIO5, "AON_RGPIO5"),
+ PINCTRL_PIN(PAD_RGPIO6, "AON_RGPIO6"),
+ PINCTRL_PIN(PAD_RGPIO7, "AON_RGPIO7"),
+ PINCTRL_PIN(PAD_RGPIO8, "AON_RGPIO8"),
+ PINCTRL_PIN(PAD_RGPIO9, "AON_RGPIO9"),
+ PINCTRL_PIN(PAD_RGPIO10, "AON_RGPIO10"),
+ PINCTRL_PIN(PAD_RGPIO11, "AON_RGPIO11"),
+ PINCTRL_PIN(PAD_RGPIO12, "AON_RGPIO12"),
+ PINCTRL_PIN(PAD_RGPIO13, "AON_RGPIO13"),
+ PINCTRL_PIN(PAD_RGPIO14, "AON_RGPIO14"),
+ PINCTRL_PIN(PAD_RGPIO15, "AON_RGPIO15"),
+ PINCTRL_PIN(PAD_TESTEN, "AON_TESTEN"),
+ PINCTRL_PIN(PAD_RSTN, "AON_RSTN"),
+ PINCTRL_PIN(PAD_OSCK_XIN, "AON_OSCK_XIN"),
+ PINCTRL_PIN(PAD_OSCK_XOUT, "AON_OSCK_XOUT"),
+ PINCTRL_PIN(PAD_OSCM_XIN, "AON_OSCM_XIN"),
+ PINCTRL_PIN(PAD_OSCM_XOUT, "AON_OSCM_XOUT"),
+ PINCTRL_PIN(PAD_GMAC0_MDC, "AON_GMAC0_MDC"),
+ PINCTRL_PIN(PAD_GMAC0_MDIO, "AON_GMAC0_MDIO"),
+ PINCTRL_PIN(PAD_GMAC0_RXD0, "AON_GMAC0_RXD0"),
+ PINCTRL_PIN(PAD_GMAC0_RXD1, "AON_GMAC0_RXD1"),
+ PINCTRL_PIN(PAD_GMAC0_RXD2, "AON_GMAC0_RXD2"),
+ PINCTRL_PIN(PAD_GMAC0_RXD3, "AON_GMAC0_RXD3"),
+ PINCTRL_PIN(PAD_GMAC0_RXDV, "AON_GMAC0_RXDV"),
+ PINCTRL_PIN(PAD_GMAC0_RXC, "AON_GMAC0_RXC"),
+ PINCTRL_PIN(PAD_GMAC0_TXD0, "AON_GMAC0_TXD0"),
+ PINCTRL_PIN(PAD_GMAC0_TXD1, "AON_GMAC0_TXD1"),
+ PINCTRL_PIN(PAD_GMAC0_TXD2, "AON_GMAC0_TXD2"),
+ PINCTRL_PIN(PAD_GMAC0_TXD3, "AON_GMAC0_TXD3"),
+ PINCTRL_PIN(PAD_GMAC0_TXEN, "AON_GMAC0_TXEN"),
+ PINCTRL_PIN(PAD_GMAC0_TXC, "AON_GMAC0_TXC"),
+};
+
+static int jh8100_aon_set_one_pin_mux(struct jh8100_pinctrl *sfp,
+ unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func)
+{
+ if (pin < sfp->gc.ngpio && func == 0)
+ jh8100_set_gpiomux(sfp, pin, din, dout, doen);
+
+ return 0;
+}
+
+static int jh8100_aon_get_padcfg_base(struct jh8100_pinctrl *sfp,
+ unsigned int pin)
+{
+ if (pin < PAD_GMAC0_MDC)
+ return JH8100_AON_GPO_PDA_0_14_CFG;
+
+ return -1;
+}
+
+static void jh8100_aon_irq_handler(struct irq_desc *desc)
+{
+ struct jh8100_pinctrl *sfp = jh8100_from_irq_desc(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long mis;
+ unsigned int pin;
+
+ chained_irq_enter(chip, desc);
+
+ mis = readl_relaxed(sfp->base + JH8100_AON_GPIOMIS);
+ for_each_set_bit(pin, &mis, JH8100_AON_NGPIO)
+ generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+ chained_irq_exit(chip, desc);
+}
+
+static int jh8100_aon_init_hw(struct gpio_chip *gc)
+{
+ struct jh8100_pinctrl *sfp = container_of(gc,
+ struct jh8100_pinctrl, gc);
+
+ /* mask all GPIO interrupts */
+ writel_relaxed(0, sfp->base + JH8100_AON_GPIOIE);
+ /* clear edge interrupt flags */
+ writel_relaxed(0, sfp->base + JH8100_AON_GPIOIC);
+ writel_relaxed(0x0fff, sfp->base + JH8100_AON_GPIOIC);
+ /* enable GPIO interrupts */
+ writel_relaxed(1, sfp->base + JH8100_AON_GPIOEN);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int jh8100_aon_pinctrl_suspend(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(sfp->wakeup_irq);
+
+ for (i = 0; i < JH8100_AON_REG_NUM; i++)
+ sfp->jh8100_aon_regs[i] = readl_relaxed(sfp->base + (i * 4));
+
+ return pinctrl_force_sleep(sfp->pctl);
+}
+
+static int jh8100_aon_pinctrl_resume(struct device *dev)
+{
+ struct jh8100_pinctrl *sfp;
+ int i;
+
+ sfp = dev_get_drvdata(dev);
+ if (!sfp)
+ return -EINVAL;
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(sfp->wakeup_irq);
+
+ for (i = 0; i < JH8100_AON_REG_NUM; i++)
+ writel_relaxed(sfp->jh8100_aon_regs[i], sfp->base + (i * 4));
+
+ return pinctrl_force_default(sfp->pctl);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(jh8100_aon_pinctrl_dev_pm_ops,
+ jh8100_aon_pinctrl_suspend,
+ jh8100_aon_pinctrl_resume);
+
+static const struct jh8100_gpio_irq_reg jh8100_aon_irq_reg = {
+ .is_reg_base = JH8100_AON_GPIOIS,
+ .ic_reg_base = JH8100_AON_GPIOIC,
+ .ibe_reg_base = JH8100_AON_GPIOIBE,
+ .iev_reg_base = JH8100_AON_GPIOIEV,
+ .ie_reg_base = JH8100_AON_GPIOIE,
+ .ris_reg_base = JH8100_AON_GPIORIS,
+ .mis_reg_base = JH8100_AON_GPIOMIS,
+};
+
+static const struct jh8100_pinctrl_soc_info jh8100_aon_pinctrl_info = {
+ .pins = jh8100_aon_pins,
+ .npins = ARRAY_SIZE(jh8100_aon_pins),
+ .ngpios = JH8100_AON_NGPIO,
+ .gc_base = JH8100_AON_GC_BASE,
+ .dout_reg_base = JH8100_AON_DOUT,
+ .dout_mask = GENMASK(4, 0),
+ .doen_reg_base = JH8100_AON_DOEN,
+ .doen_mask = GENMASK(2, 0),
+ .gpi_reg_base = JH8100_AON_GPI,
+ .gpi_mask = GENMASK(4, 0),
+ .gpioin_reg_base = JH8100_AON_GPIOIN,
+ .irq_reg = &jh8100_aon_irq_reg,
+ .jh8100_set_one_pin_mux = jh8100_aon_set_one_pin_mux,
+ .jh8100_get_padcfg_base = jh8100_aon_get_padcfg_base,
+ .jh8100_gpio_irq_handler = jh8100_aon_irq_handler,
+ .jh8100_gpio_init_hw = jh8100_aon_init_hw,
+};
+
+static const struct of_device_id jh8100_aon_pinctrl_of_match[] = {
+ {
+ .compatible = "starfive,jh8100-aon-pinctrl",
+ .data = &jh8100_aon_pinctrl_info,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh8100_aon_pinctrl_of_match);
+
+static struct platform_driver jh8100_aon_pinctrl_driver = {
+ .probe = jh8100_pinctrl_probe,
+ .driver = {
+ .name = "starfive-jh8100-aon-pinctrl",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &jh8100_aon_pinctrl_dev_pm_ops,
+#endif
+ .of_match_table = jh8100_aon_pinctrl_of_match,
+ },
+};
+module_platform_driver(jh8100_aon_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC aon controller");
+MODULE_AUTHOR("Alex Soo <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
index 43b62609fa3e..8347fa83e8dd 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h
@@ -16,6 +16,7 @@
#define JH8100_SYS_WEST_REG_NUM 44
#define JH8100_SYS_EAST_REG_NUM 116
#define JH8100_SYS_GMAC_REG_NUM 19
+#define JH8100_AON_REG_NUM 65
struct jh8100_pinctrl {
struct device *dev;
@@ -30,6 +31,7 @@ struct jh8100_pinctrl {
unsigned int jh8100_sys_west_regs[JH8100_SYS_WEST_REG_NUM];
unsigned int jh8100_sys_east_regs[JH8100_SYS_EAST_REG_NUM];
unsigned int jh8100_sys_gmac_regs[JH8100_SYS_GMAC_REG_NUM];
+ unsigned int jh8100_aon_regs[JH8100_AON_REG_NUM];
/* wakeup */
int wakeup_gpio;
int wakeup_irq;
--
2.25.1
Add pinctrl_east/pinctrl_west/pinctrl_gmac/pinctrl_aon device
tree nodes for JH8100 SoC.
Signed-off-by: Alex Soo <[email protected]>
Reviewed-by: Ley Foon Tan <[email protected]>
---
arch/riscv/boot/dts/starfive/jh8100-evb.dts | 5 +
arch/riscv/boot/dts/starfive/jh8100-pinfunc.h | 418 ++++++++++++++++++
arch/riscv/boot/dts/starfive/jh8100.dtsi | 44 ++
3 files changed, 467 insertions(+)
create mode 100644 arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
diff --git a/arch/riscv/boot/dts/starfive/jh8100-evb.dts b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
index c16bc25d8988..8634e41984f8 100644
--- a/arch/riscv/boot/dts/starfive/jh8100-evb.dts
+++ b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
@@ -26,3 +26,8 @@ memory@40000000 {
&uart0 {
status = "okay";
};
+
+&pinctrl_aon {
+ wakeup-gpios = <&pinctrl_aon PAD_RGPIO2 GPIO_ACTIVE_HIGH>;
+ wakeup-source;
+};
diff --git a/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
new file mode 100644
index 000000000000..3fb16ef62d90
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
@@ -0,0 +1,418 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Alex Soo <[email protected]>
+ *
+ */
+
+#ifndef __JH8100_PINFUNC_H__
+#define __JH8100_PINFUNC_H__
+
+/*
+ * mux bits:
+ * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
+ * | din | dout | doen | function | gpio nr |
+ *
+ * dout: output signal
+ * doen: output enable signal
+ * din: optional input signal, 0xff = none
+ * function:
+ * gpio nr: gpio number, 0 - 63
+ */
+#define GPIOMUX(n, dout, doen, din) ( \
+ (((din) & 0xff) << 24) | \
+ (((dout) & 0xff) << 16) | \
+ (((doen) & 0x3f) << 10) | \
+ ((n) & 0x3f))
+
+#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) & 0xff))
+
+/* sys_iomux_east dout */
+#define GPOUT_LOW 0
+#define GPOUT_HIGH 1
+#define GPOUT_SYS_CAN0_STBY 2
+#define GPOUT_SYS_CAN0_TST_NEXT_BIT 3
+#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT 4
+#define GPOUT_SYS_CAN0_TXD 5
+#define GPOUT_SYS_I2C0_CLK 6
+#define GPOUT_SYS_I2C0_DATA 7
+#define GPOUT_SYS_I2S0_STEREO_RSCKO 8
+#define GPOUT_SYS_I2S0_STEREO_RWSO 9
+#define GPOUT_SYS_I2S0_STEREO_SDO_0 10
+#define GPOUT_SYS_I2S0_STEREO_SDO_1 11
+#define GPOUT_SYS_I2S0_STEREO_TSCKO 12
+#define GPOUT_SYS_I2S0_STEREO_TWSO 13
+#define GPOUT_SYS_SPI0_MO 14
+#define GPOUT_SYS_SPI0_SS0 15
+#define GPOUT_SYS_SPI0_SS1 16
+#define GPOUT_SYS_SPI0_SS2 17
+#define GPOUT_SYS_SPI0_SS3 18
+#define GPOUT_SYS_SPI0_SCLK 19
+#define GPOUT_SYS_SPI0_SO 20
+#define GPOUT_SYS_UART0_DTR 21
+#define GPOUT_SYS_UART0_RTS 22
+#define GPOUT_SYS_UART0_TX 23
+#define GPOUT_SYS_USB0_DBG_DRIVE_VBUS 24
+#define GPOUT_SYS_PDM_MCLK 25
+#define GPOUT_SYS_PWM_CHANNEL0 26
+#define GPOUT_SYS_PWM_CHANNEL1 27
+#define GPOUT_SYS_PWM_CHANNEL2 28
+#define GPOUT_SYS_PWM_CHANNEL3 29
+#define GPOUT_SYS_PWM_CHANNEL4 30
+#define GPOUT_SYS_PWM_CHANNEL5 31
+#define GPOUT_SYS_PWM_CHANNEL6 32
+#define GPOUT_SYS_PWM_CHANNEL7 33
+#define GPOUT_SYS_SMBUS0_CLK 34
+#define GPOUT_SYS_SMBUS0_DATA 35
+#define GPOUT_SYS_SMBUS0_SUSPEND 36
+#define GPOUT_SYS_CLK_GCLK1 37
+#define GPOUT_SYS_CLK_GCLK2 38
+#define GPOUT_SYS_CLK_GCLK3 39
+#define GPOUT_SYS_CLK_GCLK4 40
+#define GPOUT_SYS_CLK_GCLK6 41
+#define GPOUT_SYS_CLK_GCLK7 42
+#define GPOUT_SYS_MCLK 43
+#define GPOUT_SYS_USB0_TYPEC_DRIVE_VBUS 44
+#define GPOUT_SYS_WATCHDOG0_RESET 45
+#define GPOUT_SYS_CAN1_STBY 46
+#define GPOUT_SYS_CAN1_TST_NEXT_BIT 47
+#define GPOUT_SYS_CAN1_TST_SAMPLE_POINT 48
+#define GPOUT_SYS_CAN1_TXD 49
+#define GPOUT_SYS_I2C1_CLK 50
+#define GPOUT_SYS_I2C1_DATA 51
+#define GPOUT_SYS_I2S1_RSCKO 52
+#define GPOUT_SYS_I2S1_RWSO 53
+#define GPOUT_SYS_I2S1_SDO0 54
+#define GPOUT_SYS_I2S1_SDO1 55
+#define GPOUT_SYS_I2S1_SDO2 56
+#define GPOUT_SYS_I2S1_SDO3 57
+#define GPOUT_SYS_I2S1_SDO4 58
+#define GPOUT_SYS_I2S1_SDO5 59
+#define GPOUT_SYS_I2S1_SDO6 60
+#define GPOUT_SYS_I2S1_SDO7 61
+#define GPOUT_SYS_I2S1_TSCKO 62
+#define GPOUT_SYS_I2S1_TWSO 63
+#define GPOUT_SYS_SDIO1_PU_PD_DATA2 64
+#define GPOUT_SYS_SDIO1_BUS_POWER 65
+#define GPOUT_SYS_SDIO1_RESET 66
+#define GPOUT_SYS_SDIO1_BUS_VOLTAGE_0 67
+#define GPOUT_SYS_SDIO1_BUS_VOLTAGE_1 68
+#define GPOUT_SYS_SDIO1_BUS_VOLTAGE_2 69
+#define GPOUT_SYS_SDIO1_LED 70
+#define GPOUT_SYS_SPI1_MO 71
+#define GPOUT_SYS_SPI1_SS0 72
+#define GPOUT_SYS_SPI1_SS1 73
+#define GPOUT_SYS_SPI1_SS2 74
+#define GPOUT_SYS_SPI1_SS3 75
+#define GPOUT_SYS_SPI1_SCLK 76
+#define GPOUT_SYS_SPI1_SO 77
+#define GPOUT_SYS_UART1_DTR 78
+#define GPOUT_SYS_UART1_RTS 79
+#define GPOUT_SYS_UART1_TX 80
+#define GPOUT_SYS_USB1_DBG_DRIVE_VBUS 81
+#define GPOUT_SYS_I2C2_CLK 82
+#define GPOUT_SYS_I2C2_DATA 83
+#define GPOUT_SYS_UART2_DTR 84
+#define GPOUT_SYS_UART2_RTS 85
+#define GPOUT_SYS_UART2_TX 86
+#define GPOUT_SYS_USB2_DBG_DRIVE_VBUS 87
+#define GPOUT_SYS_I2C3_CLK 88
+#define GPOUT_SYS_I2C3_DATA 89
+#define GPOUT_SYS_UART3_DTR 90
+#define GPOUT_SYS_UART3_RTS 91
+#define GPOUT_SYS_UART3_TX 92
+#define GPOUT_SYS_USB3_DBG_DRIVE_VBUS 93
+#define GPOUT_SYS_I2C4_CLK 94
+#define GPOUT_SYS_I2C4_DATA 95
+#define GPOUT_SYS_UART4_DTR 96
+#define GPOUT_SYS_UART4_RTS 97
+#define GPOUT_SYS_UART4_TX 98
+#define GPOUT_SYS_I2C5_CLK 99
+#define GPOUT_SYS_I2C5_DATA 100
+
+/* sys_iomux_west dout */
+#define GPOUT_SYS_RSVD0 2
+#define GPOUT_SYS_RSVD1 3
+#define GPOUT_SYS_RSVD2 4
+#define GPOUT_SYS_RSVD3 5
+#define GPOUT_SYS_RSVD4 6
+#define GPOUT_SYS_RSVD5 7
+#define GPOUT_SYS_RSVD6 8
+#define GPOUT_SYS_RSVD7 9
+#define GPOUT_SYS_RSVD8 10
+#define GPOUT_SYS_HD_AUDIO0_BCLK 11
+#define GPOUT_SYS_HD_AUDIO0_RST 12
+#define GPOUT_SYS_HD_AUDIO0_SDI0_O 13
+#define GPOUT_SYS_HD_AUDIO0_SDI1_O 14
+#define GPOUT_SYS_HD_AUDIO0_SDO0 15
+#define GPOUT_SYS_HD_AUDIO0_SDO1 16
+#define GPOUT_SYS_HD_AUDIO0_SYNC 17
+#define GPOUT_SYS_HIFI4_JTAG_TDO 18
+#define GPOUT_SYS_CLK_GCLK5 19
+#define GPOUT_SYS_SMBUS1_CLK 20
+#define GPOUT_SYS_SMBUS1_DATA 21
+#define GPOUT_SYS_SMBUS1_SUSPEND 22
+#define GPOUT_SYS_SPI2_MO 23
+#define GPOUT_SYS_SPI2_SS0 24
+#define GPOUT_SYS_SPI2_SS1 25
+#define GPOUT_SYS_SPI2_SS2 26
+#define GPOUT_SYS_SPI2_SS3 27
+#define GPOUT_SYS_SPI2_SCLK 28
+#define GPOUT_SYS_SPI2_SO 29
+#define GPOUT_SYS_UART5_DTR 30
+#define GPOUT_SYS_UART5_RTS 31
+#define GPOUT_SYS_UART5_TX 32
+#define GPOUT_SYS_I2C6_CLK 33
+#define GPOUT_SYS_I2C6_DATA 34
+#define GPOUT_SYS_UART6_DTR 35
+#define GPOUT_SYS_UART6_RTS 36
+#define GPOUT_SYS_UART6_TX 37
+#define GPOUT_SYS_I2C7_CLK 38
+#define GPOUT_SYS_I2C7_DATA 39
+
+/* aon_iomux dout */
+#define GPOUT_AON_CLK_32K 2
+#define GPOUT_AON_CLK_GCLK0 3
+#define GPOUT_AON_CLK_GCLK_OSC 4
+#define GPOUT_AON_SIG_STUB_POWER_EN_O 5
+#define GPOUT_AON_EMMC_PU_PD_DATA2 6
+#define GPOUT_AON_EMMC_BUS_POWER 7
+#define GPOUT_AON_EMMC_BUS_VOLTAGE_0 8
+#define GPOUT_AON_EMMC_BUS_VOLTAGE_1 9
+#define GPOUT_AON_EMMC_BUS_VOLTAGE_2 10
+#define GPOUT_AON_EMMC_LED 11
+#define GPOUT_AON_SDIO0_PU_PD_DATA2 12
+#define GPOUT_AON_SDIO0_BUS_POWER 13
+#define GPOUT_AON_SDIO0_RESET 14
+#define GPOUT_AON_SDIO0_BUS_VOLTAGE_0 15
+#define GPOUT_AON_SDIO0_BUS_VOLTAGE_1 16
+#define GPOUT_AON_SDIO0_BUS_VOLTAGE_2 17
+#define GPOUT_AON_SDIO0_LED 18
+#define GPOUT_AON_JTAG_TDO 19
+#define GPOUT_AON_SCP_POWER_EN 20
+#define GPOUT_AON_WATCHDOG1_RESET 21
+#define GPOUT_AON_UART7_TX 22
+#define GPOUT_AON_I2C8_CLK 23
+#define GPOUT_AON_I2C8_DATA 24
+
+/* sys_iomux_east doen */
+#define GPOEN_SYS_ENABLE 0
+#define GPOEN_SYS_DISABLE 1
+#define GPOEN_SYS_I2C0_CLK 2
+#define GPOEN_SYS_I2C0_DATA 3
+#define GPOEN_SYS_I2S0_STEREO_SDOE_0 4
+#define GPOEN_SYS_I2S0_STEREO_SDOE_1 5
+#define GPOEN_SYS_SPI0_N_MO_EN 6
+#define GPOEN_SYS_SPI0_N_SCLK_EN 7
+#define GPOEN_SYS_SPI0_N_SO_EN 8
+#define GPOEN_SYS_SPI0_N_SS_EN 9
+#define GPOEN_SYS_PWM_CHANNEL0 10
+#define GPOEN_SYS_PWM_CHANNEL1 11
+#define GPOEN_SYS_PWM_CHANNEL2 12
+#define GPOEN_SYS_PWM_CHANNEL3 13
+#define GPOEN_SYS_PWM_CHANNEL4 14
+#define GPOEN_SYS_PWM_CHANNEL5 15
+#define GPOEN_SYS_PWM_CHANNEL6 16
+#define GPOEN_SYS_PWM_CHANNEL7 17
+#define GPOEN_SYS_SMBUS0_CLK 18
+#define GPOEN_SYS_SMBUS0_DATA 19
+#define GPOEN_SYS_SMBUS0_ALERT 20
+#define GPOEN_SYS_I2C1_CLK 21
+#define GPOEN_SYS_I2C1_DATA 22
+#define GPOEN_SYS_I2S1_SDO0 23
+#define GPOEN_SYS_I2S1_SDO1 24
+#define GPOEN_SYS_I2S1_SDO2 25
+#define GPOEN_SYS_I2S1_SDO3 26
+#define GPOEN_SYS_I2S1_SDO4 27
+#define GPOEN_SYS_I2S1_SDO5 28
+#define GPOEN_SYS_I2S1_SDO6 29
+#define GPOEN_SYS_I2S1_SDO7 30
+#define GPOEN_SYS_SPI1_N_MO_EN 31
+#define GPOEN_SYS_SPI1_N_SCLK_EN 32
+#define GPOEN_SYS_SPI1_N_SO_EN 33
+#define GPOEN_SYS_SPI1_N_SS_EN 34
+#define GPOEN_SYS_I2C2_CLK 35
+#define GPOEN_SYS_I2C2_DATA 36
+#define GPOEN_SYS_I2C3_CLK 37
+#define GPOEN_SYS_I2C3_DATA 38
+#define GPOEN_SYS_I2C4_CLK 39
+#define GPOEN_SYS_I2C4_DATA 40
+#define GPOEN_SYS_I2C5_CLK 41
+#define GPOEN_SYS_I2C5_DATA 42
+
+/* sys_iomux_west doen */
+#define GPOEN_SYS_RSVD0 2
+#define GPOEN_SYS_RSVD1 3
+#define GPOEN_SYS_RSVD2 4
+#define GPOEN_SYS_RSVD3 5
+#define GPOEN_SYS_RSVD4 6
+#define GPOEN_SYS_RSVD5 7
+#define GPOEN_SYS_RSVD6 8
+#define GPOEN_SYS_HD_AUDIO0_SDI0 9
+#define GPOEN_SYS_HD_AUDIO0_SDI1 10
+#define GPOEN_SYS_HIFI4_JTAG_TDO 11
+#define GPOEN_SYS_SMBUS1_CLK 12
+#define GPOEN_SYS_SMBUS1_DATA 13
+#define GPOEN_SYS_SMBUS1_ALERT 14
+#define GPOEN_SYS_SPI2_MO 15
+#define GPOEN_SYS_SPI2_SCLK 16
+#define GPOEN_SYS_SPI2_SO 17
+#define GPOEN_SYS_SPI2_SS 18
+#define GPOEN_SYS_I2C6_CLK 19
+#define GPOEN_SYS_I2C6_DATA 20
+#define GPOEN_SYS_I2C7_CLK 21
+#define GPOEN_SYS_I2C7_DATA 22
+
+/* aon_iomux doen */
+#define GPOEN_AON_JTAG_TDO 2
+#define GPOEN_AON_I2C8_CLK 3
+#define GPOEN_AON_I2C8_DATA 4
+
+/* sys_iomux din */
+#define GPI_NONE 255
+
+/* sys_iomux_east din */
+#define GPI_SYS_CAN0_RXD 0
+#define GPI_SYS_I2C0_CLK 1
+#define GPI_SYS_I2C0_DATA 2
+#define GPI_SYS_SPI0_SCLK 3
+#define GPI_SYS_SPI0_MI 4
+#define GPI_SYS_SPI0_SS_N 5
+#define GPI_SYS_SPI0_SI 6
+#define GPI_SYS_UART0_CTS 7
+#define GPI_SYS_UART0_DCD 8
+#define GPI_SYS_UART0_DSR 9
+#define GPI_SYS_UART0_RI 10
+#define GPI_SYS_UART0_RX 11
+#define GPI_SYS_USB0_DBG_OVERCURRENT 12
+#define GPI_SYS_PDM_DMIC0 13
+#define GPI_SYS_PDM_DMIC1 14
+#define GPI_SYS_I2SRX0_SDIN0 15
+#define GPI_SYS_I2SRX0_SDIN1 16
+#define GPI_SYS_SMBUS0_CLK 17
+#define GPI_SYS_SMBUS0_DATA 18
+#define GPI_SYS_SMBUS0_ALERT 19
+#define GPI_SYS_JTAG_TCK 20
+#define GPI_SYS_MCLK_EXT 21
+#define GPI_SYS_I2SRX0_BCLK 22
+#define GPI_SYS_I2SRX0_LRCK 23
+#define GPI_SYS_I2STX0_BCLK 24
+#define GPI_SYS_I2STX0_LRCK 25
+#define GPI_SYS_SPI0_SCLK_IN0 26
+#define GPI_SYS_SPI0_SCLK_IN1 27
+#define GPI_SYS_I2S0_STEREO_RX_BCLK 28
+#define GPI_SYS_I2S0_STEREO_RX_LRCK 29
+#define GPI_SYS_I2S0_STEREO_TX_BCLK 30
+#define GPI_SYS_I2S0_STEREO_TX_LRCK 31
+#define GPI_SYS_I2S1_RX_BCLK 32
+#define GPI_SYS_I2S1_RX_LRCK 33
+#define GPI_SYS_I2S1_TX_BCLK 34
+#define GPI_SYS_I2S1_TX_LRCK 35
+#define GPI_SYS_USB0_TYPEC_OVERCURRENT 36
+#define GPI_SYS_CAN1_RXD 37
+#define GPI_SYS_I2C1_CLK 38
+#define GPI_SYS_I2C1_DATA 39
+#define GPI_SYS_I2S1_SDI_0 40
+#define GPI_SYS_I2S1_SDI_1 41
+#define GPI_SYS_I2S1_SDI_2 42
+#define GPI_SYS_I2S1_SDI_3 43
+#define GPI_SYS_I2S1_SDI_4 44
+#define GPI_SYS_I2S1_SDI_5 45
+#define GPI_SYS_I2S1_SDI_6 46
+#define GPI_SYS_I2S1_SDI_7 47
+#define GPI_SYS_SDIO1_CARD_DETECT 48
+#define GPI_SYS_SDIO1_WRITE_PROTECT 49
+#define GPI_SYS_SPI1_EXT_CLK 50
+#define GPI_SYS_SPI1_MI 51
+#define GPI_SYS_SPI1_SS_IN 52
+#define GPI_SYS_SPI1_SI 53
+#define GPI_SYS_UART1_CTS 54
+#define GPI_SYS_UART1_DCD 55
+#define GPI_SYS_UART1_DSR 56
+#define GPI_SYS_UART1_RI 57
+#define GPI_SYS_UART1_RX 58
+#define GPI_SYS_USB1_DBG_OVERCURRENT 59
+#define GPI_SYS_I2C2_CLK 60
+#define GPI_SYS_I2C2_DATA 61
+#define GPI_SYS_UART2_CTS 62
+#define GPI_SYS_UART2_DCD 63
+#define GPI_SYS_UART2_DSR 64
+#define GPI_SYS_UART2_RI 65
+#define GPI_SYS_UART2_RX 66
+#define GPI_SYS_USB2_DBG_OVERCURRENT 67
+#define GPI_SYS_I2C3_CLK 68
+#define GPI_SYS_I2C3_DATA 69
+#define GPI_SYS_UART3_CTS 70
+#define GPI_SYS_UART3_DCD 71
+#define GPI_SYS_UART3_DSR 72
+#define GPI_SYS_UART3_RI 73
+#define GPI_SYS_UART3_RX 74
+#define GPI_SYS_USB3_DBG_OVERCURRENT 75
+#define GPI_SYS_I2C4_CLK 76
+#define GPI_SYS_I2C4_DATA 77
+#define GPI_SYS_UART4_CTS 78
+#define GPI_SYS_UART4_DCD 79
+#define GPI_SYS_UART4_DSR 80
+#define GPI_SYS_UART4_RI 81
+#define GPI_SYS_UART4_RX 82
+#define GPI_SYS_I2C5_CLK 83
+#define GPI_SYS_I2C5_DATA 84
+
+/* sys_iomux_west din */
+#define GPI_SYS_RSVD0 0
+#define GPI_SYS_RSVD1 1
+#define GPI_SYS_RSVD2 2
+#define GPI_SYS_RSVD3 3
+#define GPI_SYS_RSVD4 4
+#define GPI_SYS_RSVD5 5
+#define GPI_SYS_RSVD6 6
+#define GPI_SYS_HD_AUDIO0_SDI0_I 7
+#define GPI_SYS_HD_AUDIO0_SDI1_I 8
+#define GPI_SYS_HIFI4_JTAG_TDI 9
+#define GPI_SYS_HIFI4_JTAG_TMS 10
+#define GPI_SYS_HIFI4_JTAG_RST 11
+#define GPI_SYS_RSVD7 12
+#define GPI_SYS_HIFI4_JTAG_TCK 13
+#define GPI_SYS_RSVD8 14
+#define GPI_SYS_SPI0_SCLK_IN2 15
+#define GPI_SYS_SMBUS1_CLK 16
+#define GPI_SYS_SMBUS1_DATA 17
+#define GPI_SYS_SMBUS1_ALERT 18
+#define GPI_SYS_SPI2_EXT_CLK 19
+#define GPI_SYS_SPI2_MI 20
+#define GPI_SYS_SPI2_SS_IN 21
+#define GPI_SYS_SPI2_SI 22
+#define GPI_SYS_UART5_CTS 23
+#define GPI_SYS_UART5_DCD 24
+#define GPI_SYS_UART5_DSR 25
+#define GPI_SYS_UART5_RI 26
+#define GPI_SYS_UART5_RX 27
+#define GPI_SYS_I2C6_CLK 28
+#define GPI_SYS_I2C6_DATA 29
+#define GPI_SYS_UART6_CTS 30
+#define GPI_SYS_UART6_DCD 31
+#define GPI_SYS_UART6_DSR 32
+#define GPI_SYS_UART6_RI 33
+#define GPI_SYS_UART6_RX 34
+#define GPI_SYS_I2C7_CLK 35
+#define GPI_SYS_I2C7_DATA 36
+
+/* aon_iomux din */
+#define GPI_AON_JTAG_TCK 0
+#define GPI_AON_SIG_STUB_RESERVED_0 1
+#define GPI_AON_SIG_STUB_RESERVED_1 2
+#define GPI_AON_SIG_STUB_RESERVED_2 3
+#define GPI_AON_XSPI0_GP_OPEN_DRAIN_0 4
+#define GPI_AON_XSPI0_GP_OPEN_DRAIN_1 5
+#define GPI_AON_XSPI0_GP_OPEN_DRAIN_2 6
+#define GPI_AON_XSPI0_GP_OPEN_DRAIN_3 7
+#define GPI_AON_SDIO0_CARD_DETECTION 8
+#define GPI_AON_SDIO0_WRITE_PROTECTION 9
+#define GPI_AON_SRC_BUF_JTAG_RST 10
+#define GPI_AON_JTAG_TDI 11
+#define GPI_AON_JTAG_TMS 12
+#define GPI_AON_UART7_RX 13
+#define GPI_AON_I2C8_CLK 14
+#define GPI_AON_I2C8_DATA 15
+
+#endif
diff --git a/arch/riscv/boot/dts/starfive/jh8100.dtsi b/arch/riscv/boot/dts/starfive/jh8100.dtsi
index 9863c61324a0..9c8ca73fffe0 100644
--- a/arch/riscv/boot/dts/starfive/jh8100.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh8100.dtsi
@@ -5,6 +5,8 @@
/dts-v1/;
#include <dt-bindings/clock/starfive,jh8100-crg.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h>
#include <dt-bindings/reset/starfive,jh8100-crg.h>
#include "jh8100-clk.dtsi"
@@ -360,6 +362,18 @@ uart4: serial@121a0000 {
status = "disabled";
};
+ pinctrl_east: pinctrl@122d0000 {
+ compatible = "starfive,jh8100-sys-pinctrl-east",
+ "syscon", "simple-mfd";
+ reg = <0x0 0x122d0000 0x0 0x10000>;
+ clocks = <&syscrg_ne SYSCRG_NE_CLK_IOMUX_EAST_PCLK>;
+ resets = <&syscrg_ne SYSCRG_NE_RSTN_SYS_IOMUX_E>;
+ interrupts = <182>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
syscrg_ne: syscrg_ne@12320000 {
compatible = "starfive,jh8100-syscrg-ne";
reg = <0x0 0x12320000 0x0 0x10000>;
@@ -434,6 +448,18 @@ syscrg_nw: syscrg_nw@123c0000 {
#reset-cells = <1>;
};
+ pinctrl_west: pinctrl@123e0000 {
+ compatible = "starfive,jh8100-sys-pinctrl-west",
+ "syscon", "simple-mfd";
+ reg = <0x0 0x123e0000 0x0 0x10000>;
+ clocks = <&syscrg_nw SYSCRG_NW_CLK_IOMUX_WEST_PCLK>;
+ resets = <&syscrg_nw SYSCRG_NW_RSTN_SYS_IOMUX_W>;
+ interrupts = <183>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
syscrg: syscrg@126d0000 {
compatible = "starfive,jh8100-syscrg";
reg = <0x0 0x126d0000 0x0 0x10000>;
@@ -458,6 +484,13 @@ syscrg_sw: syscrg_sw@12720000 {
#reset-cells = <1>;
};
+ pinctrl_gmac: pinctrl@12770000 {
+ compatible = "starfive,jh8100-sys-pinctrl-gmac",
+ "syscon", "simple-mfd";
+ status = "disabled";
+ reg = <0x0 0x12770000 0x0 0x10000>;
+ };
+
uart5: serial@127d0000 {
compatible = "starfive,jh8100-uart", "cdns,uart-r1p8";
reg = <0x0 0x127d0000 0x0 0x10000>;
@@ -476,6 +509,17 @@ uart6: serial@127e0000 {
status = "disabled";
};
+ pinctrl_aon: pinctrl@1f300000 {
+ compatible = "starfive,jh8100-aon-pinctrl",
+ "syscon", "simple-mfd";
+ reg = <0x0 0x1f300000 0x0 0x10000>;
+ resets = <&aoncrg AONCRG_RSTN_AON_IOMUX_PRESETN>;
+ interrupts = <160>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
aoncrg: aoncrg@1f310000 {
compatible = "starfive,jh8100-aoncrg";
reg = <0x0 0x1f310000 0x0 0x10000>;
--
2.25.1
On 21/12/2023 09:36, Alex Soo wrote:
> Add pinctrl_east/pinctrl_west/pinctrl_gmac/pinctrl_aon device
> tree nodes for JH8100 SoC.
>
> Signed-off-by: Alex Soo <[email protected]>
> Reviewed-by: Ley Foon Tan <[email protected]>
I have some doubts about it...
> ---
> arch/riscv/boot/dts/starfive/jh8100-evb.dts | 5 +
> arch/riscv/boot/dts/starfive/jh8100-pinfunc.h | 418 ++++++++++++++++++
> arch/riscv/boot/dts/starfive/jh8100.dtsi | 44 ++
> 3 files changed, 467 insertions(+)
> create mode 100644 arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
>
> diff --git a/arch/riscv/boot/dts/starfive/jh8100-evb.dts b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> index c16bc25d8988..8634e41984f8 100644
> --- a/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> +++ b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> @@ -26,3 +26,8 @@ memory@40000000 {
> &uart0 {
> status = "okay";
> };
> +
> +&pinctrl_aon {
Wrong order. Nodes do not go to the end.
> + wakeup-gpios = <&pinctrl_aon PAD_RGPIO2 GPIO_ACTIVE_HIGH>;
> + wakeup-source;
None of these were tested.
It does not look like you tested the DTS against bindings. Please run
`make dtbs_check W=1` (see
Documentation/devicetree/bindings/writing-schema.rst or
https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
for instructions).
> +};
> diff --git a/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> new file mode 100644
> index 000000000000..3fb16ef62d90
> --- /dev/null
> +++ b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> @@ -0,0 +1,418 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +/*
> + * Copyright (C) 2023 StarFive Technology Co., Ltd.
> + * Author: Alex Soo <[email protected]>
> + *
> + */
> +
> +#ifndef __JH8100_PINFUNC_H__
> +#define __JH8100_PINFUNC_H__
> +
> +/*
> + * mux bits:
> + * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
> + * | din | dout | doen | function | gpio nr |
> + *
> + * dout: output signal
> + * doen: output enable signal
> + * din: optional input signal, 0xff = none
> + * function:
> + * gpio nr: gpio number, 0 - 63
> + */
> +#define GPIOMUX(n, dout, doen, din) ( \
> + (((din) & 0xff) << 24) | \
> + (((dout) & 0xff) << 16) | \
> + (((doen) & 0x3f) << 10) | \
> + ((n) & 0x3f))
> +
> +#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) & 0xff))
> +
> +/* sys_iomux_east dout */
> +#define GPOUT_LOW 0
> +#define GPOUT_HIGH 1
Where are these used?
> +#define GPOUT_SYS_CAN0_STBY 2
> +#define GPOUT_SYS_CAN0_TST_NEXT_BIT 3
> +#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT 4
> +#define GPOUT_SYS_CAN0_TXD 5
> +#define GPOUT_SYS_I2C0_CLK 6
> +#define GPOUT_SYS_I2C0_DATA 7
> +#define GPOUT_SYS_I2S0_STEREO_RSCKO 8
You add here bunch of constants not used anywhere. No single example of
their usage, not a one.
Best regards,
Krzysztof
On 21/12/2023 09:36, Alex Soo wrote:
> Starfive JH8100 SoC consists of 4 pinctrl domains - sys_east,
> sys_west, sys_gmac, and aon. This patch series adds pinctrl
> drivers for these 4 pinctrl domains and this patch series is
> depending on the JH8100 base patch series in [1] and [2].
> The relevant dt-binding documentation for each pinctrl domain has
> been updated accordingly.
Please explain why this is RFC. Every patch is RFC, so what is special
about here? Usually this means work is not finished and should not be
merged, neither reviewed. If you spelled out here the reasons, it would
be easier for us to understand whether we should complain about broken
and non-building code or not.
Best regards,
Krzysztof
Hi Alex,
thanks for your patch!
On Thu, Dec 21, 2023 at 9:36 AM Alex Soo <[email protected]> wrote:
> pinctrl: starfive: jh8100: add pinctrl driver for sys_east domain
> pinctrl: starfive: jh8100: add pinctrl driver for sys_west domain
> pinctrl: starfive: jh8100: add pinctrl driver for sys_gmac domain
> pinctrl: starfive: jh8100: add pinctrl driver for AON domain
To my eye it looks like a lot of code is duplicated between the four subdrivers.
The pattern from other pin controllers is to create a file with all the common
code and then subdrivers for each sub-pincontroller that have their own
probe but calls into the library.
C.f.
drivers/pinctrl/qcom/pinctrl-apq8064.c:
static int apq8064_pinctrl_probe(struct platform_device *pdev)
{
return msm_pinctrl_probe(pdev, &apq8064_pinctrl);
}
And that function is in drivers/pinctrl/qcom/pinctrl-msm.c
and you find great inspiration in the qcom Kconfig and Makefile
and drivers/pinctrl/qcom/pinctrl-msm.h
that you can copypaste to pull this off.
Maybe you should start with a patch that extract the common stuff
from the existing jh7100/jh7110 drivers and then reuse that for
jh8100?
Yours,
Linus Walleij
> -----Original Message-----
> From: Krzysztof Kozlowski <[email protected]>
> Sent: Friday, December 22, 2023 12:20 AM
> To: Yuklin Soo <[email protected]>; Linus Walleij
> <[email protected]>; Bartosz Golaszewski
> <[email protected]>; Hal Feng <[email protected]>;
> Leyfoon Tan <[email protected]>; Jianlong Huang
> <[email protected]>; Emil Renner Berthing
> <[email protected]>; Rob Herring <[email protected]>; Krzysztof Kozlowski
> <[email protected]>; Conor Dooley <[email protected]>;
> Drew Fustini <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; Paul Walmsley
> <[email protected]>; Palmer Dabbelt <[email protected]>;
> Albert Ou <[email protected]>
> Subject: Re: [RFC PATCH 0/6] Add Pinctrl driver for Starfive JH8100 SoC
>
> On 21/12/2023 09:36, Alex Soo wrote:
> > Starfive JH8100 SoC consists of 4 pinctrl domains - sys_east,
> > sys_west, sys_gmac, and aon. This patch series adds pinctrl drivers
> > for these 4 pinctrl domains and this patch series is depending on the
> > JH8100 base patch series in [1] and [2].
> > The relevant dt-binding documentation for each pinctrl domain has been
> > updated accordingly.
>
> Please explain why this is RFC. Every patch is RFC, so what is special about
> here? Usually this means work is not finished and should not be merged,
> neither reviewed. If you spelled out here the reasons, it would be easier for
> us to understand whether we should complain about broken and non-
> building code or not.
This JH8100 SoC pinctrl patch is dependent on the following:
- Initial device tree support and dt-bindings for JH8100 SoC
https://lore.kernel.org/lkml/20231214-platonic-unhearing-27e2ec3d8f75@spud/
- Clock & Reset Support for JH8100 SoC
https://lore.kernel.org/lkml/[email protected]/
Refer to the first link, there is maintainer feedback that if our evaluation platform is FPGA-based (since actual silicon is still unavailable), they are not keen on merging the patches, and things like pinctrl or clock drivers should first be submitted as “not to be merged”, in other words, as RFC patches.
>
> Best regards,
> Krzysztof
Hi Alex,
thanks for your patch!
On Thu, Dec 21, 2023 at 9:36 AM Alex Soo <[email protected]> wrote:
> Add pinctrl driver for sys_east domain.
This commit message is wrong, it also contains the main driver for jh8100.
Please add some proper subject and commit message.
> Signed-off-by: Alex Soo <[email protected]>
> Reviewed-by: Ley Foon Tan <[email protected]>
(...)
> +#define pin_to_hwirq(sfp) (((sfp)->wakeup_gpio) - ((sfp)->gc.base))
Please do not reference gc.base like this, it is a gpio internal detail.
Also, turn this into a static inline function, the macro is hard to read.
> +/* pad control bits */
> +#define JH8100_PADCFG_POS BIT(7)
> +#define JH8100_PADCFG_SMT BIT(6)
> +#define JH8100_PADCFG_SLEW BIT(5)
> +#define JH8100_PADCFG_PD BIT(4)
> +#define JH8100_PADCFG_PU BIT(3)
> +#define JH8100_PADCFG_BIAS (JH8100_PADCFG_PD | JH8100_PADCFG_PU)
JH8100_PADCFG_BIAS_MASK
> +#define JH8100_PADCFG_DS_MASK GENMASK(2, 1)
> +#define JH8100_PADCFG_DS_2MA (0U << 1)
> +#define JH8100_PADCFG_DS_4MA BIT(1)
> +#define JH8100_PADCFG_DS_8MA (2U << 1)
> +#define JH8100_PADCFG_DS_12MA (3U << 1)
Please use (1U << 1) for 4MA, this looks weird otherwise.
> +static const struct pinconf_ops jh8100_pinconf_ops = {
> + .pin_config_get = jh8100_pinconf_get,
> + .pin_config_group_get = jh8100_pinconf_group_get,
> + .pin_config_group_set = jh8100_pinconf_group_set,
> + .pin_config_dbg_show = jh8100_pinconf_dbg_show,
> + .is_generic = true,
> +};
> +
> +static int jh8100_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> +{
> + return pinctrl_gpio_request(gc, gpio);
> +}
> +
> +static void jh8100_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> +{
> + pinctrl_gpio_free(gc, gpio);
> +}
Skip one level of indirection, just add pinctrl_gpio_request/free directly
into the vtable.
> +static int jh8100_gpio_set_config(struct gpio_chip *gc,
> + unsigned int gpio, unsigned long config)
> +{
> + struct jh8100_pinctrl *sfp = container_of(gc,
> + struct jh8100_pinctrl, gc);
> + u32 arg = pinconf_to_config_argument(config);
Please don't reimplement .set_config, just call into the pinctrl
backend using
set_config = gpiochip_generic_config
> +static int jh8100_gpio_add_pin_ranges(struct gpio_chip *gc)
> +{
> + struct jh8100_pinctrl *sfp = container_of(gc,
> + struct jh8100_pinctrl, gc);
> +
> + sfp->gpios.name = sfp->gc.label;
> + sfp->gpios.base = sfp->gc.base;
> + sfp->gpios.pin_base = 0;
> + sfp->gpios.npins = sfp->gc.ngpio;
> + sfp->gpios.gc = &sfp->gc;
> + pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
> + return 0;
> +}
Why are you not putting the ranges into the device tree where the
GPIO core will add them for you?
> + if (info->irq_reg) {
> + jh8100_irq_chip.name = sfp->gc.label;
That's not immutable. The struct should be const.
You have to use .irq_print_chip in the irq_chip.
> + gpio_irq_chip_set_chip(&sfp->gc.irq, &jh8100_irq_chip);
Use the convention:
struct gpio_irq_chip *girq;
girq = &chip->irq;
gpio_irq_chip_set_chip(girq, &nmk_irq_chip);
.. and use girq-> in the rest of the assignments.
> + dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
StarFive JH8100 (be precise)
Yours,
Linus Walleij
> -----Original Message-----
> From: Krzysztof Kozlowski <[email protected]>
> Sent: Thursday, December 21, 2023 11:53 PM
> To: Yuklin Soo <[email protected]>; Linus Walleij
> <[email protected]>; Bartosz Golaszewski
> <[email protected]>; Hal Feng <[email protected]>;
> Leyfoon Tan <[email protected]>; Jianlong Huang
> <[email protected]>; Emil Renner Berthing
> <[email protected]>; Rob Herring <[email protected]>; Krzysztof Kozlowski
> <[email protected]>; Conor Dooley <[email protected]>;
> Drew Fustini <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; Paul Walmsley
> <[email protected]>; Palmer Dabbelt <[email protected]>;
> Albert Ou <[email protected]>
> Subject: Re: [RFC PATCH 6/6] riscv: dts: starfive: jh8100: add pinctrl device tree
> nodes
>
> On 21/12/2023 09:36, Alex Soo wrote:
> > Add pinctrl_east/pinctrl_west/pinctrl_gmac/pinctrl_aon device tree
> > nodes for JH8100 SoC.
> >
> > Signed-off-by: Alex Soo <[email protected]>
> > Reviewed-by: Ley Foon Tan <[email protected]>
>
> I have some doubts about it...
>
> > ---
> > arch/riscv/boot/dts/starfive/jh8100-evb.dts | 5 +
> > arch/riscv/boot/dts/starfive/jh8100-pinfunc.h | 418 ++++++++++++++++++
> > arch/riscv/boot/dts/starfive/jh8100.dtsi | 44 ++
> > 3 files changed, 467 insertions(+)
> > create mode 100644 arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> >
> > diff --git a/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> > b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> > index c16bc25d8988..8634e41984f8 100644
> > --- a/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> > +++ b/arch/riscv/boot/dts/starfive/jh8100-evb.dts
> > @@ -26,3 +26,8 @@ memory@40000000 {
> > &uart0 {
> > status = "okay";
> > };
> > +
> > +&pinctrl_aon {
>
> Wrong order. Nodes do not go to the end.
Could you please explain what is meant by “Nodes do not go to the end.”? How it causes wrong order?
>
> > + wakeup-gpios = <&pinctrl_aon PAD_RGPIO2 GPIO_ACTIVE_HIGH>;
> > + wakeup-source;
>
> None of these were tested.
>
> It does not look like you tested the DTS against bindings. Please run `make
> dtbs_check W=1` (see Documentation/devicetree/bindings/writing-schema.rst
> or https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-
> sources-with-the-devicetree-schema/
> for instructions).
The “pinctrl_aon” document has been updated:
wakeup-gpios:
maxItems: 1
description: GPIO pin to be used for waking up the system from sleep mode.
wakeup-source:
maxItems: 1
description: to indicate pinctrl has wakeup capability.
Running “make dt_binding_check” and “make dtbs_check” tests are successful.
Will send out in next version.
>
> > +};
> > diff --git a/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> > b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> > new file mode 100644
> > index 000000000000..3fb16ef62d90
> > --- /dev/null
> > +++ b/arch/riscv/boot/dts/starfive/jh8100-pinfunc.h
> > @@ -0,0 +1,418 @@
> > +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> > +/*
> > + * Copyright (C) 2023 StarFive Technology Co., Ltd.
> > + * Author: Alex Soo <[email protected]>
> > + *
> > + */
> > +
> > +#ifndef __JH8100_PINFUNC_H__
> > +#define __JH8100_PINFUNC_H__
> > +
> > +/*
> > + * mux bits:
> > + * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
> > + * | din | dout | doen | function | gpio nr |
> > + *
> > + * dout: output signal
> > + * doen: output enable signal
> > + * din: optional input signal, 0xff = none
> > + * function:
> > + * gpio nr: gpio number, 0 - 63
> > + */
> > +#define GPIOMUX(n, dout, doen, din) ( \
> > + (((din) & 0xff) << 24) | \
> > + (((dout) & 0xff) << 16) | \
> > + (((doen) & 0x3f) << 10) | \
> > + ((n) & 0x3f))
> > +
> > +#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) &
> > +0xff))
> > +
> > +/* sys_iomux_east dout */
> > +#define GPOUT_LOW 0
> > +#define GPOUT_HIGH 1
>
> Where are these used?
These macros are used to set the logic level of a pin to 0 or 1 respectively:
can0_pins: can0-grp {
can0_rx-pins {
pinmux = <GPIOMUX(PAD_GPIO28_E, GPOUT_LOW,
GPOEN_SYS_DISABLE, GPI_SYS_CAN0_RXD)>;
bias-pull-up;
input-enable;
};
However, " GPOUT_LOW" and " GPOUT_LOW" will be removed from
"arch/riscv/boot/dts/starfive/jh8100-pinfunc.h", and kept in
" include/dt-bindings/pinctrl/starfive,jh8100-pinctrl.h".
>
> > +#define GPOUT_SYS_CAN0_STBY 2
> > +#define GPOUT_SYS_CAN0_TST_NEXT_BIT 3
> > +#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT 4
> > +#define GPOUT_SYS_CAN0_TXD 5
> > +#define GPOUT_SYS_I2C0_CLK 6
> > +#define GPOUT_SYS_I2C0_DATA 7
> > +#define GPOUT_SYS_I2S0_STEREO_RSCKO 8
>
> You add here bunch of constants not used anywhere. No single example of
> their usage, not a one.
These constants are indexes of output signals, and it is part of the pinmux value
to be written to an iomux register to configure which output signal will go through
which GPIO_PAD.
For i2c-0,
#define GPOUT_SYS_I2C0_CLK 6
#define GPOUT_SYS_I2C0_DATA 7
Output signal "GPOUT_SYS_I2C0_CLK" goes through PAD_GPIO9_E.
Output signal "GPOUT_SYS_I2C0_DATA" goes through PAD_GPIO10_E.
i2c0_pins: i2c0-grp {
i2c0-scl-pins {
pinmux = <GPIOMUX(PAD_GPIO9_E, GPOUT_SYS_I2C0_CLK,
GPOEN_SYS_I2C0_CLK,
GPI_SYS_I2C0_CLK)>;
bias-pull-up;
input-enable;
};
i2c0-sda-pins {
pinmux = <GPIOMUX(PAD_GPIO10_E, GPOUT_SYS_I2C0_DATA,
GPOEN_SYS_I2C0_DATA,
GPI_SYS_I2C0_DATA)>;
bias-pull-up;
input-enable;
};
};
Will add the above to device tree for next version.
>
> Best regards,
> Krzysztof
> -----Original Message-----
> From: Linus Walleij <[email protected]>
> Sent: Saturday, December 23, 2023 1:59 AM
> To: Yuklin Soo <[email protected]>
> Cc: Bartosz Golaszewski <[email protected]>; Hal Feng
> <[email protected]>; Leyfoon Tan <[email protected]>;
> Jianlong Huang <[email protected]>; Emil Renner Berthing
> <[email protected]>; Rob Herring <[email protected]>; Krzysztof Kozlowski
> <[email protected]>; Conor Dooley <[email protected]>;
> Drew Fustini <[email protected]>; [email protected]; linux-
> [email protected]; [email protected]; linux-
> [email protected]; Paul Walmsley <[email protected]>;
> Palmer Dabbelt <[email protected]>; Albert Ou
> <[email protected]>
> Subject: Re: [RFC PATCH 0/6] Add Pinctrl driver for Starfive JH8100 SoC
>
> Hi Alex,
>
> thanks for your patch!
>
> On Thu, Dec 21, 2023 at 9:36 AM Alex Soo <[email protected]>
> wrote:
>
> > pinctrl: starfive: jh8100: add pinctrl driver for sys_east domain
> > pinctrl: starfive: jh8100: add pinctrl driver for sys_west domain
> > pinctrl: starfive: jh8100: add pinctrl driver for sys_gmac domain
> > pinctrl: starfive: jh8100: add pinctrl driver for AON domain
>
> To my eye it looks like a lot of code is duplicated between the four subdrivers.
>
> The pattern from other pin controllers is to create a file with all the common
> code and then subdrivers for each sub-pincontroller that have their own
> probe but calls into the library.
>
> C.f.
> drivers/pinctrl/qcom/pinctrl-apq8064.c:
>
> static int apq8064_pinctrl_probe(struct platform_device *pdev) {
> return msm_pinctrl_probe(pdev, &apq8064_pinctrl); }
>
> And that function is in drivers/pinctrl/qcom/pinctrl-msm.c
> and you find great inspiration in the qcom Kconfig and Makefile and
> drivers/pinctrl/qcom/pinctrl-msm.h
> that you can copypaste to pull this off.
>
> Maybe you should start with a patch that extract the common stuff from the
> existing jh7100/jh7110 drivers and then reuse that for jh8100?
The duplicated codes in the subdrivers have been moved to the main driver.
The subdrivers will call those functions from the main driver.
The test results are successful and will submit in the next version for review.
>
> Yours,
> Linus Walleij
> -----Original Message-----
> From: Linus Walleij <[email protected]>
> Sent: Sunday, January 28, 2024 7:33 AM
> To: Yuklin Soo <[email protected]>
> Cc: Bartosz Golaszewski <[email protected]>; Hal Feng
> <[email protected]>; Leyfoon Tan <[email protected]>;
> Jianlong Huang <[email protected]>; Emil Renner Berthing
> <[email protected]>; Rob Herring <[email protected]>; Krzysztof Kozlowski
> <[email protected]>; Conor Dooley <[email protected]>;
> Drew Fustini <[email protected]>; [email protected]; linux-
> [email protected]; [email protected]; linux-
> [email protected]; Paul Walmsley <[email protected]>;
> Palmer Dabbelt <[email protected]>; Albert Ou
> <[email protected]>
> Subject: Re: [RFC PATCH 2/6] pinctrl: starfive: jh8100: add pinctrl driver for
> sys_east domain
>
> Hi Alex,
>
> thanks for your patch!
>
> On Thu, Dec 21, 2023 at 9:36 AM Alex Soo <[email protected]>
> wrote:
>
> > Add pinctrl driver for sys_east domain.
>
> This commit message is wrong, it also contains the main driver for jh8100.
> Please add some proper subject and commit message.
Will change the commit log to "add main and sys_east driver" to indicate the commit of both main and sys-east driver.
>
> > Signed-off-by: Alex Soo <[email protected]>
> > Reviewed-by: Ley Foon Tan <[email protected]>
> (...)
> > +#define pin_to_hwirq(sfp) (((sfp)->wakeup_gpio) - ((sfp)->gc.base))
>
> Please do not reference gc.base like this, it is a gpio internal detail.
>
> Also, turn this into a static inline function, the macro is hard to read.
The pin_to_hwirq macro will be converted to to a static inline function to hide gpio
internal detail, and for easier code readability.
>
> > +/* pad control bits */
> > +#define JH8100_PADCFG_POS BIT(7)
> > +#define JH8100_PADCFG_SMT BIT(6)
> > +#define JH8100_PADCFG_SLEW BIT(5)
> > +#define JH8100_PADCFG_PD BIT(4)
> > +#define JH8100_PADCFG_PU BIT(3)
> > +#define JH8100_PADCFG_BIAS (JH8100_PADCFG_PD |
> JH8100_PADCFG_PU)
>
> JH8100_PADCFG_BIAS_MASK
Will change to "JH8100_PADCFG_BIAS_MASK" in next version.
>
> > +#define JH8100_PADCFG_DS_MASK GENMASK(2, 1)
> > +#define JH8100_PADCFG_DS_2MA (0U << 1)
> > +#define JH8100_PADCFG_DS_4MA BIT(1)
> > +#define JH8100_PADCFG_DS_8MA (2U << 1)
> > +#define JH8100_PADCFG_DS_12MA (3U << 1)
>
> Please use (1U << 1) for 4MA, this looks weird otherwise.
Will change to "(1U << 1)" for 4MA in next version.
>
> > +static const struct pinconf_ops jh8100_pinconf_ops = {
> > + .pin_config_get = jh8100_pinconf_get,
> > + .pin_config_group_get = jh8100_pinconf_group_get,
> > + .pin_config_group_set = jh8100_pinconf_group_set,
> > + .pin_config_dbg_show = jh8100_pinconf_dbg_show,
> > + .is_generic = true,
> > +};
> > +
> > +static int jh8100_gpio_request(struct gpio_chip *gc, unsigned int
> > +gpio) {
> > + return pinctrl_gpio_request(gc, gpio); }
> > +
> > +static void jh8100_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > +{
> > + pinctrl_gpio_free(gc, gpio);
> > +}
>
> Skip one level of indirection, just add pinctrl_gpio_request/free directly into
> the vtable.
This will be fixed in next version.
>
> > +static int jh8100_gpio_set_config(struct gpio_chip *gc,
> > + unsigned int gpio, unsigned long
> > +config) {
> > + struct jh8100_pinctrl *sfp = container_of(gc,
> > + struct jh8100_pinctrl, gc);
> > + u32 arg = pinconf_to_config_argument(config);
>
> Please don't reimplement .set_config, just call into the pinctrl backend using
>
> .set_config = gpiochip_generic_config
Will replace "jh8100_gpio_set_config" by "gpiochip_generic_config" in next version.
>
> > +static int jh8100_gpio_add_pin_ranges(struct gpio_chip *gc) {
> > + struct jh8100_pinctrl *sfp = container_of(gc,
> > + struct jh8100_pinctrl, gc);
> > +
> > + sfp->gpios.name = sfp->gc.label;
> > + sfp->gpios.base = sfp->gc.base;
> > + sfp->gpios.pin_base = 0;
> > + sfp->gpios.npins = sfp->gc.ngpio;
> > + sfp->gpios.gc = &sfp->gc;
> > + pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
> > + return 0;
> > +}
>
> Why are you not putting the ranges into the device tree where the GPIO core
> will add them for you?
Will remove the jh8100_gpio_add_pin_ranges function and use gpio-ranges in device tree to
provide information for GPIO core to add pin range for each pin controller.
>
> > + if (info->irq_reg) {
> > + jh8100_irq_chip.name = sfp->gc.label;
>
> That's not immutable. The struct should be const.
> You have to use .irq_print_chip in the irq_chip.
The struct irq_chip will be used as a constant data structure.
Will add an irq_print_chip function to display irqchip name to user space.
>
> > + gpio_irq_chip_set_chip(&sfp->gc.irq,
> > + &jh8100_irq_chip);
>
> Use the convention:
>
> struct gpio_irq_chip *girq;
>
> girq = &chip->irq;
> gpio_irq_chip_set_chip(girq, &nmk_irq_chip);
>
> ... and use girq-> in the rest of the assignments.
girq will be used to represent GPIO interrupt controller.
>
> > + dev_info(dev, "StarFive GPIO chip registered %d
> > + GPIOs\n", sfp->gc.ngpio);
>
> StarFive JH8100 (be precise)
"StarFive GPIO" will be changed to "StarFive JH8100 GPIO".
>
> Yours,
> Linus Walleij