1// SPDX-License-Identifier: GPL-2.0 2 3#include <common.h> 4#include <dm.h> 5#include <regmap.h> 6#include <syscon.h> 7#include <dm/device_compat.h> 8#include <dm/pinctrl.h> 9 10#define BCM6838_CMD_LOAD_MUX 0x21 11 12#define BCM6838_FUNC_OFFS 12 13#define BCM6838_FUNC_MASK (0x37 << BCM6838_FUNC_OFFS) 14#define BCM6838_PIN_OFFS 0 15#define BCM6838_PIN_MASK (0xfff << BCM6838_PIN_OFFS) 16 17#define BCM6838_MAX_PIN_NAME_LEN 8 18static char bcm6838_pin_name[BCM6838_MAX_PIN_NAME_LEN]; 19 20#define BCM6838_MAX_FUNC_NAME_LEN 8 21static char bcm6838_func_name[BCM6838_MAX_FUNC_NAME_LEN]; 22 23struct bcm6838_test_port_hw { 24 unsigned long port_blk_data1; 25 unsigned long port_blk_data2; 26 unsigned long port_command; 27}; 28 29static const struct bcm6838_test_port_hw bcm6838_hw = { 30 .port_blk_data1 = 0x10, 31 .port_blk_data2 = 0x14, 32 .port_command = 0x18 33}; 34 35struct bcm6838_pinctrl_priv { 36 const struct bcm6838_test_port_hw *hw; 37 struct regmap *regmap; 38 u32 pins_count; 39 u32 functions_count; 40}; 41 42int bcm6838_pinctrl_get_pins_count(struct udevice *dev) 43{ 44 struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev); 45 46 return priv->pins_count; 47} 48 49const char *bcm6838_pinctrl_get_pin_name(struct udevice *dev, 50 unsigned int selector) 51{ 52 snprintf(bcm6838_pin_name, BCM6838_MAX_PIN_NAME_LEN, "%u", selector); 53 return bcm6838_pin_name; 54} 55 56int bcm6838_pinctrl_get_functions_count(struct udevice *dev) 57{ 58 struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev); 59 60 return priv->functions_count; 61} 62 63const char *bcm6838_pinctrl_get_function_name(struct udevice *dev, 64 unsigned int selector) 65{ 66 snprintf(bcm6838_func_name, BCM6838_MAX_FUNC_NAME_LEN, "%u", selector); 67 return bcm6838_func_name; 68} 69 70int bcm6838_pinctrl_pinmux_set(struct udevice *dev, 71 unsigned int pin_selector, 72 unsigned int func_selector) 73{ 74 struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev); 75 const struct bcm6838_test_port_hw *hw = priv->hw; 76 unsigned int data; 77 78 regmap_write(priv->regmap, hw->port_blk_data1, 0); 79 data = (func_selector << BCM6838_FUNC_OFFS) & BCM6838_FUNC_MASK; 80 data |= (pin_selector << BCM6838_PIN_OFFS) & BCM6838_PIN_MASK; 81 regmap_write(priv->regmap, hw->port_blk_data2, data); 82 regmap_write(priv->regmap, hw->port_command, BCM6838_CMD_LOAD_MUX); 83 84 return 0; 85} 86 87int bcm6838_pinctrl_probe(struct udevice *dev) 88{ 89 struct bcm6838_pinctrl_priv *priv = dev_get_priv(dev); 90 const struct bcm6838_test_port_hw *hw = 91 (const struct bcm6838_test_port_hw *)dev_get_driver_data(dev); 92 int err; 93 u32 phandle; 94 ofnode node; 95 96 err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle); 97 if (err) { 98 dev_err(dev, "%s: unable to read regmap\n", __func__); 99 goto out; 100 } 101 102 node = ofnode_get_by_phandle(phandle); 103 if (!ofnode_valid(node)) { 104 dev_err(dev, "%s: unable to find node\n", __func__); 105 err = -EINVAL; 106 goto out; 107 } 108 109 priv->regmap = syscon_node_to_regmap(node); 110 if (!priv->regmap) { 111 dev_err(dev, "%s: unable to find regmap\n", __func__); 112 err = -ENODEV; 113 goto out; 114 } 115 116 err = ofnode_read_u32(dev_ofnode(dev), "brcm,pins-count", 117 &priv->pins_count); 118 if (err) { 119 dev_err(dev, "%s: unable to read brcm,pins-count\n", 120 __func__); 121 goto out; 122 } 123 124 err = ofnode_read_u32(dev_ofnode(dev), "brcm,functions-count", 125 &priv->functions_count); 126 if (err) { 127 dev_err(dev, "%s: unable to read brcm,functions-count\n", 128 __func__); 129 goto out; 130 } 131 132 priv->hw = hw; 133 134 out: 135 return err; 136} 137 138const struct pinctrl_ops bcm6838_pinctrl_ops = { 139 .set_state = pinctrl_generic_set_state, 140 .get_pins_count = bcm6838_pinctrl_get_pins_count, 141 .get_pin_name = bcm6838_pinctrl_get_pin_name, 142 .get_functions_count = bcm6838_pinctrl_get_functions_count, 143 .get_function_name = bcm6838_pinctrl_get_function_name, 144 .pinmux_set = bcm6838_pinctrl_pinmux_set, 145}; 146 147static const struct udevice_id bcm6838_pinctrl_match[] = { 148 { 149 .compatible = "brcm,bcm6838-pinctrl", 150 .data = (ulong)&bcm6838_hw, 151 }, 152 { /* sentinel */ } 153}; 154 155U_BOOT_DRIVER(bcm6838_pinctrl) = { 156 .name = "bcm6838_pinctrl", 157 .id = UCLASS_PINCTRL, 158 .of_match = bcm6838_pinctrl_match, 159 .ops = &bcm6838_pinctrl_ops, 160 .priv_auto = sizeof(struct bcm6838_pinctrl_priv), 161 .probe = bcm6838_pinctrl_probe, 162}; 163