1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com> 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <dm/device-internal.h> 9 #include <dm/lists.h> 10 #include <dm/pinctrl.h> 11 #include <fdt_support.h> 12 #include <linux/err.h> 13 #include <linux/io.h> 14 #include <linux/sizes.h> 15 #include <asm/gpio.h> 16 17 #include "pinctrl-meson.h" 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 static const char *meson_pinctrl_dummy_name = "_dummy"; 22 23 int meson_pinctrl_get_groups_count(struct udevice *dev) 24 { 25 struct meson_pinctrl *priv = dev_get_priv(dev); 26 27 return priv->data->num_groups; 28 } 29 30 const char *meson_pinctrl_get_group_name(struct udevice *dev, 31 unsigned int selector) 32 { 33 struct meson_pinctrl *priv = dev_get_priv(dev); 34 35 if (!priv->data->groups[selector].name) 36 return meson_pinctrl_dummy_name; 37 38 return priv->data->groups[selector].name; 39 } 40 41 int meson_pinmux_get_functions_count(struct udevice *dev) 42 { 43 struct meson_pinctrl *priv = dev_get_priv(dev); 44 45 return priv->data->num_funcs; 46 } 47 48 const char *meson_pinmux_get_function_name(struct udevice *dev, 49 unsigned int selector) 50 { 51 struct meson_pinctrl *priv = dev_get_priv(dev); 52 53 return priv->data->funcs[selector].name; 54 } 55 56 static int meson_gpio_calc_reg_and_bit(struct udevice *dev, unsigned int offset, 57 enum meson_reg_type reg_type, 58 unsigned int *reg, unsigned int *bit) 59 { 60 struct meson_pinctrl *priv = dev_get_priv(dev); 61 struct meson_bank *bank = NULL; 62 struct meson_reg_desc *desc; 63 unsigned int pin; 64 int i; 65 66 pin = priv->data->pin_base + offset; 67 68 for (i = 0; i < priv->data->num_banks; i++) { 69 if (pin >= priv->data->banks[i].first && 70 pin <= priv->data->banks[i].last) { 71 bank = &priv->data->banks[i]; 72 break; 73 } 74 } 75 76 if (!bank) 77 return -EINVAL; 78 79 desc = &bank->regs[reg_type]; 80 *reg = desc->reg * 4; 81 *bit = desc->bit + pin - bank->first; 82 83 return 0; 84 } 85 86 int meson_gpio_get(struct udevice *dev, unsigned int offset) 87 { 88 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 89 unsigned int reg, bit; 90 int ret; 91 92 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_IN, ®, 93 &bit); 94 if (ret) 95 return ret; 96 97 return !!(readl(priv->reg_gpio + reg) & BIT(bit)); 98 } 99 100 int meson_gpio_set(struct udevice *dev, unsigned int offset, int value) 101 { 102 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 103 unsigned int reg, bit; 104 int ret; 105 106 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, ®, 107 &bit); 108 if (ret) 109 return ret; 110 111 clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0); 112 113 return 0; 114 } 115 116 int meson_gpio_get_direction(struct udevice *dev, unsigned int offset) 117 { 118 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 119 unsigned int reg, bit, val; 120 int ret; 121 122 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 123 &bit); 124 if (ret) 125 return ret; 126 127 val = readl(priv->reg_gpio + reg); 128 129 return (val & BIT(bit)) ? GPIOF_INPUT : GPIOF_OUTPUT; 130 } 131 132 int meson_gpio_direction_input(struct udevice *dev, unsigned int offset) 133 { 134 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 135 unsigned int reg, bit; 136 int ret; 137 138 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 139 &bit); 140 if (ret) 141 return ret; 142 143 setbits_le32(priv->reg_gpio + reg, BIT(bit)); 144 145 return 0; 146 } 147 148 int meson_gpio_direction_output(struct udevice *dev, 149 unsigned int offset, int value) 150 { 151 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 152 unsigned int reg, bit; 153 int ret; 154 155 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 156 &bit); 157 if (ret) 158 return ret; 159 160 clrbits_le32(priv->reg_gpio + reg, BIT(bit)); 161 162 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, ®, 163 &bit); 164 if (ret) 165 return ret; 166 167 clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0); 168 169 return 0; 170 } 171 172 static int meson_pinconf_bias_set(struct udevice *dev, unsigned int pin, 173 unsigned int param) 174 { 175 struct meson_pinctrl *priv = dev_get_priv(dev); 176 unsigned int offset = pin - priv->data->pin_base; 177 unsigned int reg, bit; 178 int ret; 179 180 ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULLEN, ®, &bit); 181 if (ret) 182 return ret; 183 184 if (param == PIN_CONFIG_BIAS_DISABLE) { 185 clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 0); 186 return 0; 187 } 188 189 /* othewise, enable the bias and select level */ 190 clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 1); 191 ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULL, ®, &bit); 192 if (ret) 193 return ret; 194 195 clrsetbits_le32(priv->reg_pull + reg, BIT(bit), 196 param == PIN_CONFIG_BIAS_PULL_UP); 197 198 return 0; 199 } 200 201 int meson_pinconf_set(struct udevice *dev, unsigned int pin, 202 unsigned int param, unsigned int arg) 203 { 204 int ret; 205 206 switch (param) { 207 case PIN_CONFIG_BIAS_DISABLE: 208 case PIN_CONFIG_BIAS_PULL_UP: 209 case PIN_CONFIG_BIAS_PULL_DOWN: 210 ret = meson_pinconf_bias_set(dev, pin, param); 211 break; 212 213 default: 214 dev_err(dev, "unsupported configuration parameter %u\n", param); 215 return -EINVAL; 216 } 217 218 return ret; 219 } 220 221 int meson_pinconf_group_set(struct udevice *dev, 222 unsigned int group_selector, 223 unsigned int param, unsigned int arg) 224 { 225 struct meson_pinctrl *priv = dev_get_priv(dev); 226 struct meson_pmx_group *grp = &priv->data->groups[group_selector]; 227 int i, ret; 228 229 for (i = 0; i < grp->num_pins; i++) { 230 ret = meson_pinconf_set(dev, grp->pins[i], param, arg); 231 if (ret) 232 return ret; 233 } 234 235 return 0; 236 } 237 238 int meson_gpio_probe(struct udevice *dev) 239 { 240 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 241 struct gpio_dev_priv *uc_priv; 242 243 uc_priv = dev_get_uclass_priv(dev); 244 uc_priv->bank_name = priv->data->name; 245 uc_priv->gpio_count = priv->data->num_pins; 246 247 return 0; 248 } 249 250 static fdt_addr_t parse_address(int offset, const char *name, int na, int ns) 251 { 252 int index, len = 0; 253 const fdt32_t *reg; 254 255 index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name); 256 if (index < 0) 257 return FDT_ADDR_T_NONE; 258 259 reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len); 260 if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) 261 return FDT_ADDR_T_NONE; 262 263 reg += index * (na + ns); 264 265 return fdt_translate_address((void *)gd->fdt_blob, offset, reg); 266 } 267 268 int meson_pinctrl_probe(struct udevice *dev) 269 { 270 struct meson_pinctrl *priv = dev_get_priv(dev); 271 struct uclass_driver *drv; 272 struct udevice *gpio_dev; 273 fdt_addr_t addr; 274 int node, gpio = -1, len; 275 int na, ns; 276 char *name; 277 278 na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent)); 279 if (na < 1) { 280 debug("bad #address-cells\n"); 281 return -EINVAL; 282 } 283 284 ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); 285 if (ns < 1) { 286 debug("bad #size-cells\n"); 287 return -EINVAL; 288 } 289 290 fdt_for_each_subnode(node, gd->fdt_blob, dev_of_offset(dev)) { 291 if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) { 292 gpio = node; 293 break; 294 } 295 } 296 297 if (!gpio) { 298 debug("gpio node not found\n"); 299 return -EINVAL; 300 } 301 302 addr = parse_address(gpio, "mux", na, ns); 303 if (addr == FDT_ADDR_T_NONE) { 304 debug("mux address not found\n"); 305 return -EINVAL; 306 } 307 priv->reg_mux = (void __iomem *)addr; 308 309 addr = parse_address(gpio, "gpio", na, ns); 310 if (addr == FDT_ADDR_T_NONE) { 311 debug("gpio address not found\n"); 312 return -EINVAL; 313 } 314 priv->reg_gpio = (void __iomem *)addr; 315 316 addr = parse_address(gpio, "pull", na, ns); 317 if (addr == FDT_ADDR_T_NONE) { 318 debug("pull address not found\n"); 319 return -EINVAL; 320 } 321 priv->reg_pull = (void __iomem *)addr; 322 323 addr = parse_address(gpio, "pull-enable", na, ns); 324 /* Use pull region if pull-enable one is not present */ 325 if (addr == FDT_ADDR_T_NONE) 326 priv->reg_pullen = priv->reg_pull; 327 else 328 priv->reg_pullen = (void __iomem *)addr; 329 330 priv->data = (struct meson_pinctrl_data *)dev_get_driver_data(dev); 331 332 /* Lookup GPIO driver */ 333 drv = lists_uclass_lookup(UCLASS_GPIO); 334 if (!drv) { 335 puts("Cannot find GPIO driver\n"); 336 return -ENOENT; 337 } 338 339 name = calloc(1, 32); 340 sprintf(name, "meson-gpio"); 341 342 /* Create child device UCLASS_GPIO and bind it */ 343 device_bind(dev, priv->data->gpio_driver, name, NULL, gpio, &gpio_dev); 344 dev_set_of_offset(gpio_dev, gpio); 345 346 return 0; 347 } 348