diff --git a/doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt b/doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt new file mode 100644 index 0000000..2034f05 --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/bcm6838-pinctrl.txt @@ -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"; + }; + }; + }; diff --git a/drivers/pinctrl/broadcom/Kconfig b/drivers/pinctrl/broadcom/Kconfig index 4056782..b01b725 100644 --- a/drivers/pinctrl/broadcom/Kconfig +++ b/drivers/pinctrl/broadcom/Kconfig @@ -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. diff --git a/drivers/pinctrl/broadcom/Makefile b/drivers/pinctrl/broadcom/Makefile index 99c7c23..f94f3ce 100644 --- a/drivers/pinctrl/broadcom/Makefile +++ b/drivers/pinctrl/broadcom/Makefile @@ -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 index 0000000..48c0b6b --- /dev/null +++ b/drivers/pinctrl/broadcom/pinctrl-bcm6838.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include + +#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, +};