[PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver
Sascha Hauer
s.hauer at pengutronix.de
Thu May 4 01:17:35 PDT 2023
Like done in Linux, for easier code sharing.
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
arch/arm/Kconfig | 1 +
drivers/gpio/Kconfig | 7 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rockchip.c | 196 +++++++++++++++++++++++++++++
drivers/pinctrl/pinctrl-rockchip.c | 178 --------------------------
5 files changed, 205 insertions(+), 178 deletions(-)
create mode 100644 drivers/gpio/gpio-rockchip.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5aef8fcd3b..37fe591000 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -260,6 +260,7 @@ config ARCH_ROCKCHIP
select OFTREE
select HAVE_PBL_MULTI_IMAGES
select HAS_DEBUG_LL
+ imply GPIO_ROCKCHIP
config ARCH_STM32MP
bool "STMicroelectronics STM32MP"
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index dd2b56d256..e19f5a5aba 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -155,6 +155,13 @@ config GPIO_RASPBERRYPI_EXP
Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
the firmware mailbox to communicate with VideoCore on BCM283x chips.
+config GPIO_ROCKCHIP
+ bool "Rockchip GPIO support"
+ depends on ARCH_ROCKCHIP
+ help
+ Say yes here to include the driver for the GPIO controller found on
+ Rockchip SoCs.
+
config GPIO_STMPE
depends on MFD_STMPE
bool "STMPE GPIO Expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 90ab0a8b28..628e975285 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
+obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_DESIGNWARE) += gpio-dw.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
new file mode 100644
index 0000000000..b01a30c18a
--- /dev/null
+++ b/drivers/gpio/gpio-rockchip.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <of.h>
+#include <gpio.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/basic_mmio_gpio.h>
+#include <mach/rockchip/rockchip.h>
+
+struct rockchip_gpiochip {
+ struct device *dev;
+ void __iomem *reg_base;
+ struct clk *clk;
+ struct bgpio_chip bgpio_chip;
+};
+
+/* GPIO registers */
+enum {
+ RK_GPIO_SWPORT_DR = 0x00,
+ RK_GPIO_SWPORT_DDR = 0x04,
+ RK_GPIO_EXT_PORT = 0x50,
+};
+
+/* GPIO registers */
+enum {
+ RK_GPIOV2_DR_L = 0x00,
+ RK_GPIOV2_DR_H = 0x04,
+ RK_GPIOV2_DDR_L = 0x08,
+ RK_GPIOV2_DDR_H = 0x0c,
+ RK_GPIOV2_EXT_PORT = 0x70,
+};
+
+static struct rockchip_gpiochip *gc_to_rockchip_pinctrl(struct gpio_chip *gc)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+ return container_of(bgc, struct rockchip_gpiochip, bgpio_chip);
+}
+
+static int rockchip_gpiov2_direction_input(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+ u32 mask;
+
+ mask = 1 << (16 + (gpio % 16));
+
+ if (gpio < 16)
+ writel(mask, rgc->reg_base + RK_GPIOV2_DDR_L);
+ else
+ writel(mask, rgc->reg_base + RK_GPIOV2_DDR_H);
+
+ return 0;
+}
+
+static int rockchip_gpiov2_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+ u32 r;
+
+ if (gpio < 16)
+ r = readl(rgc->reg_base + RK_GPIOV2_DDR_L);
+ else
+ r = readl(rgc->reg_base + RK_GPIOV2_DDR_H);
+
+ return r & BIT(gpio % 16) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
+static void rockchip_gpiov2_set_value(struct gpio_chip *gc, unsigned int gpio,
+ int val)
+{
+ struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+ u32 mask, vval = 0;
+
+ mask = 1 << (16 + (gpio % 16));
+ if (val)
+ vval = 1 << (gpio % 16);
+
+ if (gpio < 16)
+ writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_L);
+ else
+ writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_H);
+}
+
+static int rockchip_gpiov2_direction_output(struct gpio_chip *gc,
+ unsigned int gpio, int val)
+{
+ struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+ u32 mask, out, vval = 0;
+
+ mask = 1 << (16 + (gpio % 16));
+ out = 1 << (gpio % 16);
+ if (val)
+ vval = 1 << (gpio % 16);
+
+ if (gpio < 16) {
+ writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_L);
+ writel(mask | out, rgc->reg_base + RK_GPIOV2_DDR_L);
+ } else {
+ writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_H);
+ writel(mask | out, rgc->reg_base + RK_GPIOV2_DDR_H);
+ }
+
+ return 0;
+}
+
+static int rockchip_gpiov2_get_value(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+ u32 mask, r;
+
+ mask = 1 << (gpio % 32);
+ r = readl(rgc->reg_base + RK_GPIOV2_EXT_PORT);
+
+ return r & mask ? 1 : 0;
+}
+
+static struct gpio_ops rockchip_gpio_ops = {
+ .direction_input = rockchip_gpiov2_direction_input,
+ .direction_output = rockchip_gpiov2_direction_output,
+ .get = rockchip_gpiov2_get_value,
+ .set = rockchip_gpiov2_set_value,
+ .get_direction = rockchip_gpiov2_get_direction,
+};
+
+static int rockchip_gpio_probe(struct device *dev)
+{
+ struct rockchip_gpiochip *rgc;
+ struct gpio_chip *gpio;
+ struct resource *res;
+ void __iomem *reg_base;
+ int ret;
+
+ rgc = xzalloc(sizeof(*rgc));
+ gpio = &rgc->bgpio_chip.gc;
+
+ res = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ rgc->reg_base = IOMEM(res->start);
+
+ rgc->clk = clk_get(dev, NULL);
+
+ if (IS_ERR(rgc->clk))
+ return PTR_ERR(rgc->clk);
+
+ ret = clk_enable(rgc->clk);
+ if (ret)
+ return ret;
+
+ reg_base = rgc->reg_base;
+
+ if (rockchip_soc() == 3568) {
+ gpio->ngpio = 32;
+ gpio->dev = dev;
+ gpio->ops = &rockchip_gpio_ops;
+ gpio->base = of_alias_get_id(dev->of_node, "gpio");
+ if (gpio->base < 0)
+ return -EINVAL;
+ gpio->base *= 32;
+ } else {
+ ret = bgpio_init(&rgc->bgpio_chip, dev, 4,
+ reg_base + RK_GPIO_EXT_PORT,
+ reg_base + RK_GPIO_SWPORT_DR, NULL,
+ reg_base + RK_GPIO_SWPORT_DDR, NULL, 0);
+ if (ret)
+ return ret;
+ }
+
+ ret = gpiochip_add(&rgc->bgpio_chip.gc);
+ if (ret) {
+ dev_err(dev, "failed to register gpio_chip:: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct of_device_id rockchip_gpio_dt_match[] = {
+ {
+ .compatible = "rockchip,gpio-bank",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver rockchip_gpio_driver = {
+ .name = "rockchip-gpio",
+ .probe = rockchip_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(rockchip_gpio_dt_match),
+};
+
+core_platform_driver(rockchip_gpio_driver);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 4021f7ff23..6547423261 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -90,167 +90,6 @@ enum {
RK_BIAS_BUS_HOLD,
};
-/* GPIO registers */
-enum {
- RK_GPIO_SWPORT_DR = 0x00,
- RK_GPIO_SWPORT_DDR = 0x04,
- RK_GPIO_EXT_PORT = 0x50,
-};
-
-/* GPIO registers */
-enum {
- RK_GPIOV2_DR_L = 0x00,
- RK_GPIOV2_DR_H = 0x04,
- RK_GPIOV2_DDR_L = 0x08,
- RK_GPIOV2_DDR_H = 0x0c,
- RK_GPIOV2_EXT_PORT = 0x70,
-};
-
-static struct rockchip_pin_bank *gc_to_rockchip_pinctrl(struct gpio_chip *gc)
-{
- struct bgpio_chip *bgc = to_bgpio_chip(gc);
-
- return container_of(bgc, struct rockchip_pin_bank, bgpio_chip);
-}
-
-static int rockchip_gpiov2_direction_input(struct gpio_chip *gc, unsigned int gpio)
-{
- struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
- u32 mask;
-
- mask = 1 << (16 + (gpio % 16));
-
- if (gpio < 16)
- writel(mask, bank->reg_base + RK_GPIOV2_DDR_L);
- else
- writel(mask, bank->reg_base + RK_GPIOV2_DDR_H);
-
- return 0;
-}
-
-static int rockchip_gpiov2_get_direction(struct gpio_chip *gc, unsigned int gpio)
-{
- struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
- u32 r;
-
- if (gpio < 16)
- r = readl(bank->reg_base + RK_GPIOV2_DDR_L);
- else
- r = readl(bank->reg_base + RK_GPIOV2_DDR_H);
-
- return r & BIT(gpio % 16) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
-}
-
-static void rockchip_gpiov2_set_value(struct gpio_chip *gc, unsigned int gpio,
- int val)
-{
- struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
- u32 mask, vval = 0;
-
- mask = 1 << (16 + (gpio % 16));
- if (val)
- vval = 1 << (gpio % 16);
-
- if (gpio < 16)
- writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L);
- else
- writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H);
-}
-
-static int rockchip_gpiov2_direction_output(struct gpio_chip *gc,
- unsigned int gpio, int val)
-{
- struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
- u32 mask, out, vval = 0;
-
- mask = 1 << (16 + (gpio % 16));
- out = 1 << (gpio % 16);
- if (val)
- vval = 1 << (gpio % 16);
-
- if (gpio < 16) {
- writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L);
- writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_L);
- } else {
- writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H);
- writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_H);
- }
-
- return 0;
-}
-
-static int rockchip_gpiov2_get_value(struct gpio_chip *gc, unsigned int gpio)
-{
- struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
- u32 mask, r;
-
- mask = 1 << (gpio % 32);
- r = readl(bank->reg_base + RK_GPIOV2_EXT_PORT);
-
- return r & mask ? 1 : 0;
-}
-
-static struct gpio_ops rockchip_gpio_ops = {
- .direction_input = rockchip_gpiov2_direction_input,
- .direction_output = rockchip_gpiov2_direction_output,
- .get = rockchip_gpiov2_get_value,
- .set = rockchip_gpiov2_set_value,
- .get_direction = rockchip_gpiov2_get_direction,
-};
-
-static int rockchip_gpio_probe(struct device *dev)
-{
- struct rockchip_pinctrl *info = dev->parent->priv;
- struct rockchip_pin_ctrl *ctrl = info->ctrl;
- struct rockchip_pin_bank *bank;
- struct gpio_chip *gpio;
- void __iomem *reg_base;
- int ret, bankno;
-
- bankno = of_alias_get_id(dev->of_node, "gpio");
- if (bankno >= ctrl->nr_banks)
- bankno = -EINVAL;
- if (bankno < 0)
- return bankno;
-
- bank = &ctrl->pin_banks[bankno];
- gpio = &bank->bgpio_chip.gc;
-
- if (!bank->valid)
- dev_warn(dev, "bank %s is not valid\n", bank->name);
-
- reg_base = bank->reg_base;
-
- if (ctrl->type == RK3568) {
- gpio->ngpio = 32;
- gpio->dev = dev;
- gpio->ops = &rockchip_gpio_ops;
- gpio->base = bankno;
- if (gpio->base < 0)
- return -EINVAL;
- gpio->base *= 32;
- } else {
- ret = bgpio_init(&bank->bgpio_chip, dev, 4,
- reg_base + RK_GPIO_EXT_PORT,
- reg_base + RK_GPIO_SWPORT_DR, NULL,
- reg_base + RK_GPIO_SWPORT_DDR, NULL, 0);
- if (ret)
- return ret;
- }
-
- bank->bgpio_chip.gc.dev = dev;
-
- bank->bgpio_chip.gc.ngpio = bank->nr_pins;
- ret = gpiochip_add(&bank->bgpio_chip.gc);
- if (ret) {
- dev_err(dev, "failed to register gpio_chip %s, error code: %d\n",
- bank->name, ret);
- return ret;
- }
-
- return 0;
-}
-
static struct rockchip_pinctrl *to_rockchip_pinctrl(struct pinctrl_device *pdev)
{
return container_of(pdev, struct rockchip_pinctrl, pctl_dev);
@@ -1145,20 +984,3 @@ static struct driver rockchip_pinctrl_driver = {
};
core_platform_driver(rockchip_pinctrl_driver);
-
-static struct of_device_id rockchip_gpio_dt_match[] = {
- {
- .compatible = "rockchip,gpio-bank",
- .data = &rk2928_pin_ctrl,
- }, {
- /* sentinel */
- }
-};
-
-static struct driver rockchip_gpio_driver = {
- .name = "rockchip-gpio",
- .probe = rockchip_gpio_probe,
- .of_compatible = DRV_OF_COMPAT(rockchip_gpio_dt_match),
-};
-
-core_platform_driver(rockchip_gpio_driver);
--
2.39.2
More information about the barebox
mailing list