[PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Like done in Linux, for easier code sharing.

Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
 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





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux