pinctrl: bcm6838: add pinctrl support
authorPhilippe Reynes <philippe.reynes@softathome.com>
Mon, 13 Aug 2018 12:23:07 +0000 (14:23 +0200)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Sat, 22 Sep 2018 18:49:59 +0000 (20:49 +0200)
Add pinctrl support for broadcom bcm6838 SoC.

Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt [new file with mode: 0644]
drivers/pinctrl/broadcom/Kconfig
drivers/pinctrl/broadcom/Makefile
drivers/pinctrl/broadcom/pinctrl-bcm6838.c [new file with mode: 0644]

diff --git a/doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt b/doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt
new file mode 100644 (file)
index 0000000..2034f05
--- /dev/null
@@ -0,0 +1,35 @@
+* broadcom bcm6838 pinctrl
+
+Required properties for the pinctrl driver:
+- compatible:     "brcm,bcm6838-pinctrl"
+- regmap:                 specify the gpio test port syscon
+- brcm,pins-count:      the number of pin
+- brcm,functions-count: the number of function
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices.
+
+Example:
+
+               gpio_test_port: syscon@14e00294 {
+                       compatible = "syscon";
+                       reg = <0x14e00294 0x1c>;
+               };
+
+               pinctrl: pinctrl {
+                       compatible = "brcm,bcm6838-pinctrl";
+                       regmap = <&gpio_test_port>;
+                       brcm,pins-count = <74>;
+                       brcm,functions-count = <8>;
+
+                       usb0: usb0 {
+                               usb0_pwrflt {
+                                       pins = "69";
+                                       function = "1";
+                               };
+                               usb0_pwron {
+                                       pins = "70";
+                                       function = "1";
+                               };
+                       };
+               };
index 4056782..b01b725 100644 (file)
@@ -5,3 +5,11 @@ config PINCTRL_BCM283X
        help
           Support pin multiplexing and pin configuration control on
           Broadcom's 283x family of SoCs.
+
+config PINCTRL_BCM6838
+       depends on ARCH_BMIPS && PINCTRL_FULL && OF_CONTROL
+       default y
+       bool "Broadcom 6838 family pin control driver"
+       help
+          Support pin multiplexing and pin configuration control on
+          Broadcom's 6838 family of SoCs.
index 99c7c23..f94f3ce 100644 (file)
@@ -5,3 +5,4 @@
 # https://spdx.org/licenses
 
 obj-$(CONFIG_PINCTRL_BCM283X) += pinctrl-bcm283x.o
+obj-$(CONFIG_PINCTRL_BCM6838) += pinctrl-bcm6838.o
diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm6838.c b/drivers/pinctrl/broadcom/pinctrl-bcm6838.c
new file mode 100644 (file)
index 0000000..48c0b6b
--- /dev/null
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <dm.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dm/pinctrl.h>
+
+#define BCM6838_CMD_LOAD_MUX            0x21
+
+#define BCM6838_FUNC_OFFS               12
+#define BCM6838_FUNC_MASK               (0x37 << BCM6838_FUNC_OFFS)
+#define BCM6838_PIN_OFFS                 0
+#define BCM6838_PIN_MASK                (0xfff << BCM6838_PIN_OFFS)
+
+#define BCM6838_MAX_PIN_NAME_LEN         8
+static char bcm6838_pin_name[BCM6838_MAX_PIN_NAME_LEN];
+
+#define BCM6838_MAX_FUNC_NAME_LEN        8
+static char bcm6838_func_name[BCM6838_MAX_FUNC_NAME_LEN];
+
+struct bcm6838_test_port_hw {
+       unsigned long port_blk_data1;
+       unsigned long port_blk_data2;
+       unsigned long port_command;
+};
+
+static const struct bcm6838_test_port_hw bcm6838_hw = {
+       .port_blk_data1 = 0x10,
+       .port_blk_data2 = 0x14,
+       .port_command   = 0x18
+};
+
+struct bcm6838_pinctrl_priv {
+       const struct bcm6838_test_port_hw *hw;
+       struct regmap *regmap;
+       u32 pins_count;
+       u32 functions_count;
+};
+
+int bcm6838_pinctrl_get_pins_count(struct udevice *dev)
+{
+       struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->pins_count;
+}
+
+const char *bcm6838_pinctrl_get_pin_name(struct udevice *dev,
+                                        unsigned int selector)
+{
+       snprintf(bcm6838_pin_name, BCM6838_MAX_PIN_NAME_LEN, "%u", selector);
+       return bcm6838_pin_name;
+}
+
+int bcm6838_pinctrl_get_functions_count(struct udevice *dev)
+{
+       struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->functions_count;
+}
+
+const char *bcm6838_pinctrl_get_function_name(struct udevice *dev,
+                                             unsigned int selector)
+{
+       snprintf(bcm6838_func_name, BCM6838_MAX_FUNC_NAME_LEN, "%u", selector);
+       return bcm6838_func_name;
+}
+
+int bcm6838_pinctrl_pinmux_set(struct udevice *dev,
+                              unsigned int pin_selector,
+                              unsigned int func_selector)
+{
+       struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct bcm6838_test_port_hw *hw = priv->hw;
+       unsigned int data;
+
+       regmap_write(priv->regmap, hw->port_blk_data1, 0);
+       data = (func_selector << BCM6838_FUNC_OFFS) & BCM6838_FUNC_MASK;
+       data |= (pin_selector << BCM6838_PIN_OFFS) & BCM6838_PIN_MASK;
+       regmap_write(priv->regmap, hw->port_blk_data2, data);
+       regmap_write(priv->regmap, hw->port_command, BCM6838_CMD_LOAD_MUX);
+
+       return 0;
+}
+
+int bcm6838_pinctrl_probe(struct udevice *dev)
+{
+       struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct bcm6838_test_port_hw *hw =
+               (const struct bcm6838_test_port_hw *)dev_get_driver_data(dev);
+       int err;
+       u32 phandle;
+       ofnode node;
+
+       err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle);
+       if (err) {
+               dev_err(dev, "%s: unable to read regmap\n", __func__);
+               goto out;
+       }
+
+       node = ofnode_get_by_phandle(phandle);
+       if (!ofnode_valid(node)) {
+               dev_err(dev, "%s: unable to find node\n", __func__);
+               err = -EINVAL;
+               goto out;
+       }
+
+       priv->regmap = syscon_node_to_regmap(node);
+       if (!priv->regmap) {
+               dev_err(dev, "%s: unable to find regmap\n", __func__);
+               err = -ENODEV;
+               goto out;
+       }
+
+       err = ofnode_read_u32(dev_ofnode(dev), "brcm,pins-count",
+                             &priv->pins_count);
+       if (err) {
+               dev_err(dev, "%s: unable to read brcm,pins-count\n",
+                       __func__);
+               goto out;
+       }
+
+       err = ofnode_read_u32(dev_ofnode(dev), "brcm,functions-count",
+                             &priv->functions_count);
+       if (err) {
+               dev_err(dev, "%s: unable to read brcm,functions-count\n",
+                       __func__);
+               goto out;
+       }
+
+       priv->hw = hw;
+
+ out:
+       return err;
+}
+
+const struct pinctrl_ops bcm6838_pinctrl_ops = {
+       .set_state = pinctrl_generic_set_state,
+       .get_pins_count = bcm6838_pinctrl_get_pins_count,
+       .get_pin_name = bcm6838_pinctrl_get_pin_name,
+       .get_functions_count = bcm6838_pinctrl_get_functions_count,
+       .get_function_name = bcm6838_pinctrl_get_function_name,
+       .pinmux_set = bcm6838_pinctrl_pinmux_set,
+};
+
+static const struct udevice_id bcm6838_pinctrl_match[] = {
+       {
+               .compatible = "brcm,bcm6838-pinctrl",
+               .data = (ulong)&bcm6838_hw,
+       },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6838_pinctrl) = {
+       .name = "bcm6838_pinctrl",
+       .id = UCLASS_PINCTRL,
+       .of_match = bcm6838_pinctrl_match,
+       .ops = &bcm6838_pinctrl_ops,
+       .priv_auto_alloc_size = sizeof(struct bcm6838_pinctrl_priv),
+       .probe = bcm6838_pinctrl_probe,
+};