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