| // SPDX-License-Identifier: GPL-2.0 | |
| #include <dm.h> | |
| #include <regmap.h> | |
| #include <syscon.h> | |
| #include <dm/device_compat.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 = sizeof(struct bcm6838_pinctrl_priv), | |
| .probe = bcm6838_pinctrl_probe, | |
| }; |