aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/mach-bcm283x/include/mach/gpio.h2
-rw-r--r--board/raspberrypi/rpi/rpi.c5
-rw-r--r--configs/rpi_0_w_defconfig4
-rw-r--r--configs/rpi_2_defconfig4
-rw-r--r--configs/rpi_3_32b_defconfig4
-rw-r--r--configs/rpi_3_defconfig4
-rw-r--r--configs/rpi_defconfig4
-rw-r--r--drivers/gpio/bcm2835_gpio.c29
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/broadcom/Kconfig7
-rw-r--r--drivers/pinctrl/broadcom/Makefile7
-rw-r--r--drivers/pinctrl/broadcom/pinctrl-bcm283x.c152
14 files changed, 202 insertions, 23 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d459153..aa161c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -100,6 +100,7 @@ F: drivers/mmc/bcm2835_sdhci.c
F: drivers/serial/serial_bcm283x_mu.c
F: drivers/video/bcm2835.c
F: include/dm/platform_data/serial_bcm283x_mu.h
+F: drivers/pinctrl/broadcom/
ARM FREESCALE IMX
M: Stefano Babic <sbabic@denx.de>
diff --git a/arch/arm/mach-bcm283x/include/mach/gpio.h b/arch/arm/mach-bcm283x/include/mach/gpio.h
index daaee52..7b4ddc9 100644
--- a/arch/arm/mach-bcm283x/include/mach/gpio.h
+++ b/arch/arm/mach-bcm283x/include/mach/gpio.h
@@ -61,6 +61,4 @@ struct bcm2835_gpio_platdata {
unsigned long base;
};
-int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio);
-
#endif /* _BCM2835_GPIO_H_ */
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 3b7a54f..c8924d4 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -24,6 +24,7 @@
#include <asm/armv8/mmu.h>
#endif
#include <watchdog.h>
+#include <dm/pinctrl.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -430,10 +431,10 @@ static bool rpi_is_serial_active(void)
* out whether it is available is to check if the RX pin is muxed.
*/
- if (uclass_first_device(UCLASS_GPIO, &dev) || !dev)
+ if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
return true;
- if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5)
+ if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT5)
return false;
return true;
diff --git a/configs/rpi_0_w_defconfig b/configs/rpi_0_w_defconfig
index 1248294..8ed7a58 100644
--- a/configs/rpi_0_w_defconfig
+++ b/configs/rpi_0_w_defconfig
@@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig
index c45ffb6..b30e6e1 100644
--- a/configs/rpi_2_defconfig
+++ b/configs/rpi_2_defconfig
@@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig
index f7aed35..bb40644 100644
--- a/configs/rpi_3_32b_defconfig
+++ b/configs/rpi_3_32b_defconfig
@@ -34,3 +34,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig
index 9416e3b..8306bc2 100644
--- a/configs/rpi_3_defconfig
+++ b/configs/rpi_3_defconfig
@@ -34,3 +34,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig
index 3bfa745..a7a079d 100644
--- a/configs/rpi_defconfig
+++ b/configs/rpi_defconfig
@@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index beaa218..d68f8df 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <dm.h>
+#include <dm/pinctrl.h>
#include <errno.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -14,6 +15,7 @@
struct bcm2835_gpios {
struct bcm2835_gpio_regs *reg;
+ struct udevice *pinctrl;
};
static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
@@ -29,7 +31,7 @@ static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
return 0;
}
-static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio,
+static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio,
int value)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
@@ -73,19 +75,12 @@ static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio,
return 0;
}
-int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- u32 val;
-
- val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
-
- return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
-}
-
static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
{
- int funcid = bcm2835_gpio_get_func_id(dev, offset);
+ struct bcm2835_gpios *priv = dev_get_priv(dev);
+ int funcid;
+
+ funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset);
switch (funcid) {
case BCM2835_GPIO_OUTPUT:
@@ -97,7 +92,6 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
}
}
-
static const struct dm_gpio_ops gpio_bcm2835_ops = {
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
@@ -116,15 +110,13 @@ static int bcm2835_gpio_probe(struct udevice *dev)
uc_priv->gpio_count = BCM2835_GPIO_COUNT;
gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
+ /* We know we're spawned by the pinctrl driver */
+ gpios->pinctrl = dev->parent;
+
return 0;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct udevice_id bcm2835_gpio_id[] = {
- {.compatible = "brcm,bcm2835-gpio"},
- {}
-};
-
static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev)
{
struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
@@ -142,7 +134,6 @@ static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev)
U_BOOT_DRIVER(gpio_bcm2835) = {
.name = "gpio_bcm2835",
.id = UCLASS_GPIO,
- .of_match = of_match_ptr(bcm2835_gpio_id),
.ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata),
.platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata),
.ops = &gpio_bcm2835_ops,
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7e8e4b0..0a4dd3c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -306,5 +306,6 @@ source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/exynos/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
+source "drivers/pinctrl/broadcom/Kconfig"
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8c04028..c7135d2 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_ARCH_MVEBU) += mvebu/
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
+obj-y += broadcom/
diff --git a/drivers/pinctrl/broadcom/Kconfig b/drivers/pinctrl/broadcom/Kconfig
new file mode 100644
index 0000000..4056782
--- /dev/null
+++ b/drivers/pinctrl/broadcom/Kconfig
@@ -0,0 +1,7 @@
+config PINCTRL_BCM283X
+ depends on ARCH_BCM283X && PINCTRL_FULL && OF_CONTROL
+ default y
+ bool "Broadcom 283x family pin control driver"
+ help
+ Support pin multiplexing and pin configuration control on
+ Broadcom's 283x family of SoCs.
diff --git a/drivers/pinctrl/broadcom/Makefile b/drivers/pinctrl/broadcom/Makefile
new file mode 100644
index 0000000..2a1e550
--- /dev/null
+++ b/drivers/pinctrl/broadcom/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+#
+# SPDX-License-Identifier: GPL-2.0
+# https://spdx.org/licenses
+
+obj-$(CONFIG_PINCTRL_BCM283X) += pinctrl-bcm283x.o
diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
new file mode 100644
index 0000000..83dde23
--- /dev/null
+++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * Based on drivers/pinctrl/mvebu/pinctrl-mvebu.c and
+ * drivers/gpio/bcm2835_gpio.c
+ *
+ * This driver gets instantiated by the GPIO driver, because both devices
+ * share the same device node.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#include <common.h>
+#include <config.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+struct bcm283x_pinctrl_priv {
+ u32 *base_reg;
+};
+
+#define MAX_PINS_PER_BANK 16
+
+static void bcm2835_gpio_set_func_id(struct udevice *dev, unsigned int gpio,
+ int func)
+{
+ struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+ int reg_offset;
+ int field_offset;
+
+ reg_offset = BCM2835_GPIO_FSEL_BANK(gpio);
+ field_offset = BCM2835_GPIO_FSEL_SHIFT(gpio);
+
+ clrsetbits_le32(&priv->base_reg[reg_offset],
+ BCM2835_GPIO_FSEL_MASK << field_offset,
+ (func & BCM2835_GPIO_FSEL_MASK) << field_offset);
+}
+
+static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio)
+{
+ struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+ u32 val;
+
+ val = readl(&priv->base_reg[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+ return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
+}
+
+/*
+ * bcm283x_pinctrl_set_state: configure pin functions.
+ * @dev: the pinctrl device to be configured.
+ * @config: the state to be configured.
+ * @return: 0 in success
+ */
+int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
+{
+ u32 pin_arr[MAX_PINS_PER_BANK];
+ u32 function;
+ int i, len, pin_count = 0;
+
+ if (!dev_read_prop(config, "brcm,pins", &len) || !len ||
+ len & 0x3 || dev_read_u32_array(config, "brcm,pins", pin_arr,
+ len / sizeof(u32))) {
+ debug("Failed reading pins array for pinconfig %s (%d)\n",
+ config->name, len);
+ return -EINVAL;
+ }
+
+ pin_count = len / sizeof(u32);
+
+ function = dev_read_u32_default(config, "brcm,function", -1);
+ if (function < 0) {
+ debug("Failed reading function for pinconfig %s (%d)\n",
+ config->name, function);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < pin_count; i++)
+ bcm2835_gpio_set_func_id(dev, pin_arr[i], function);
+
+ return 0;
+}
+
+static int bcm283x_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
+ int index)
+{
+ if (banknum != 0)
+ return -EINVAL;
+
+ return bcm2835_gpio_get_func_id(dev, index);
+}
+
+static const struct udevice_id bcm2835_pinctrl_id[] = {
+ {.compatible = "brcm,bcm2835-gpio"},
+ {}
+};
+
+int bcm283x_pinctl_probe(struct udevice *dev)
+{
+ struct bcm283x_pinctrl_priv *priv;
+ int ret;
+ struct udevice *pdev;
+
+ priv = dev_get_priv(dev);
+ if (!priv) {
+ debug("%s: Failed to get private\n", __func__);
+ return -EINVAL;
+ }
+
+ priv->base_reg = dev_read_addr_ptr(dev);
+ if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
+ debug("%s: Failed to get base address\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Create GPIO device as well */
+ ret = device_bind(dev, lists_driver_lookup_name("gpio_bcm2835"),
+ "gpio_bcm2835", NULL, dev_of_offset(dev), &pdev);
+ if (ret) {
+ /*
+ * While we really want the pinctrl driver to work to make
+ * devices go where they should go, the GPIO controller is
+ * not quite as crucial as it's only rarely used, so don't
+ * fail here.
+ */
+ printf("Failed to bind GPIO driver\n");
+ }
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm283x_pinctrl_ops = {
+ .set_state = bcm283x_pinctrl_set_state,
+ .get_gpio_mux = bcm283x_pinctrl_get_gpio_mux,
+};
+
+U_BOOT_DRIVER(pinctrl_bcm283x) = {
+ .name = "bcm283x_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(bcm2835_pinctrl_id),
+ .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv),
+ .ops = &bcm283x_pinctrl_ops,
+ .probe = bcm283x_pinctl_probe
+};