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 <log.h> 9#include <malloc.h> 10#include <asm/global_data.h> 11#include <dm/device-internal.h> 12#include <dm/device_compat.h> 13#include <dm/lists.h> 14#include <dm/pinctrl.h> 15#include <fdt_support.h> 16#include <linux/bitops.h> 17#include <linux/err.h> 18#include <linux/io.h> 19#include <linux/libfdt.h> 20#include <linux/sizes.h> 21#include <asm/gpio.h> 22 23#include "pinctrl-meson.h" 24 25DECLARE_GLOBAL_DATA_PTR; 26 27static const char *meson_pinctrl_dummy_name = "_dummy"; 28 29static char pin_name[PINNAME_SIZE]; 30 31int meson_pinctrl_get_groups_count(struct udevice *dev) 32{ 33 struct meson_pinctrl *priv = dev_get_priv(dev); 34 35 return priv->data->num_groups; 36} 37 38const char *meson_pinctrl_get_group_name(struct udevice *dev, 39 unsigned int selector) 40{ 41 struct meson_pinctrl *priv = dev_get_priv(dev); 42 43 if (!priv->data->groups[selector].name) 44 return meson_pinctrl_dummy_name; 45 46 return priv->data->groups[selector].name; 47} 48 49int meson_pinctrl_get_pins_count(struct udevice *dev) 50{ 51 struct meson_pinctrl *priv = dev_get_priv(dev); 52 53 return priv->data->num_pins; 54} 55 56const char *meson_pinctrl_get_pin_name(struct udevice *dev, 57 unsigned int selector) 58{ 59 struct meson_pinctrl *priv = dev_get_priv(dev); 60 61 if (selector > priv->data->num_pins || 62 selector > priv->data->funcs[0].num_groups) 63 snprintf(pin_name, PINNAME_SIZE, "Error"); 64 else 65 snprintf(pin_name, PINNAME_SIZE, "%s", 66 priv->data->funcs[0].groups[selector]); 67 68 return pin_name; 69} 70 71int meson_pinmux_get_functions_count(struct udevice *dev) 72{ 73 struct meson_pinctrl *priv = dev_get_priv(dev); 74 75 return priv->data->num_funcs; 76} 77 78const char *meson_pinmux_get_function_name(struct udevice *dev, 79 unsigned int selector) 80{ 81 struct meson_pinctrl *priv = dev_get_priv(dev); 82 83 return priv->data->funcs[selector].name; 84} 85 86static int meson_gpio_calc_reg_and_bit(struct udevice *dev, unsigned int offset, 87 enum meson_reg_type reg_type, 88 unsigned int *reg, unsigned int *bit) 89{ 90 struct meson_pinctrl *priv = dev_get_priv(dev); 91 struct meson_bank *bank = NULL; 92 struct meson_reg_desc *desc; 93 unsigned int pin; 94 int i; 95 96 pin = priv->data->pin_base + offset; 97 98 for (i = 0; i < priv->data->num_banks; i++) { 99 if (pin >= priv->data->banks[i].first && 100 pin <= priv->data->banks[i].last) { 101 bank = &priv->data->banks[i]; 102 break; 103 } 104 } 105 106 if (!bank) 107 return -EINVAL; 108 109 desc = &bank->regs[reg_type]; 110 *reg = desc->reg * 4; 111 *bit = desc->bit + pin - bank->first; 112 113 return 0; 114} 115 116int meson_gpio_get(struct udevice *dev, unsigned int offset) 117{ 118 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 119 unsigned int reg, bit; 120 int ret; 121 122 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_IN, ®, 123 &bit); 124 if (ret) 125 return ret; 126 127 return !!(readl(priv->reg_gpio + reg) & BIT(bit)); 128} 129 130int meson_gpio_set(struct udevice *dev, unsigned int offset, int value) 131{ 132 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 133 unsigned int reg, bit; 134 int ret; 135 136 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, ®, 137 &bit); 138 if (ret) 139 return ret; 140 141 clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0); 142 143 return 0; 144} 145 146int meson_gpio_get_direction(struct udevice *dev, unsigned int offset) 147{ 148 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 149 unsigned int reg, bit, val; 150 int ret; 151 152 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 153 &bit); 154 if (ret) 155 return ret; 156 157 val = readl(priv->reg_gpio + reg); 158 159 return (val & BIT(bit)) ? GPIOF_INPUT : GPIOF_OUTPUT; 160} 161 162int meson_gpio_direction_input(struct udevice *dev, unsigned int offset) 163{ 164 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 165 unsigned int reg, bit; 166 int ret; 167 168 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 169 &bit); 170 if (ret) 171 return ret; 172 173 setbits_le32(priv->reg_gpio + reg, BIT(bit)); 174 175 return 0; 176} 177 178int meson_gpio_direction_output(struct udevice *dev, 179 unsigned int offset, int value) 180{ 181 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 182 unsigned int reg, bit; 183 int ret; 184 185 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, ®, 186 &bit); 187 if (ret) 188 return ret; 189 190 clrbits_le32(priv->reg_gpio + reg, BIT(bit)); 191 192 ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, ®, 193 &bit); 194 if (ret) 195 return ret; 196 197 clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0); 198 199 return 0; 200} 201 202static int meson_pinconf_bias_set(struct udevice *dev, unsigned int pin, 203 unsigned int param) 204{ 205 struct meson_pinctrl *priv = dev_get_priv(dev); 206 unsigned int offset = pin - priv->data->pin_base; 207 unsigned int reg, bit; 208 int ret; 209 210 ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULLEN, ®, &bit); 211 if (ret) 212 return ret; 213 214 if (param == PIN_CONFIG_BIAS_DISABLE) { 215 clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 0); 216 return 0; 217 } 218 219 /* othewise, enable the bias and select level */ 220 clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), BIT(bit)); 221 ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULL, ®, &bit); 222 if (ret) 223 return ret; 224 225 clrsetbits_le32(priv->reg_pull + reg, BIT(bit), 226 (param == PIN_CONFIG_BIAS_PULL_UP ? BIT(bit) : 0)); 227 228 return 0; 229} 230 231static int meson_pinconf_drive_strength_set(struct udevice *dev, 232 unsigned int pin, 233 unsigned int drive_strength_ua) 234{ 235 struct meson_pinctrl *priv = dev_get_priv(dev); 236 unsigned int offset = pin - priv->data->pin_base; 237 unsigned int reg, bit; 238 unsigned int ds_val; 239 int ret; 240 241 if (!priv->reg_ds) { 242 dev_err(dev, "drive-strength-microamp not supported\n"); 243 return -ENOTSUPP; 244 } 245 246 ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DS, ®, &bit); 247 if (ret) 248 return ret; 249 250 bit = bit << 1; 251 252 if (drive_strength_ua <= 500) { 253 ds_val = MESON_PINCONF_DRV_500UA; 254 } else if (drive_strength_ua <= 2500) { 255 ds_val = MESON_PINCONF_DRV_2500UA; 256 } else if (drive_strength_ua <= 3000) { 257 ds_val = MESON_PINCONF_DRV_3000UA; 258 } else if (drive_strength_ua <= 4000) { 259 ds_val = MESON_PINCONF_DRV_4000UA; 260 } else { 261 dev_warn(dev, 262 "pin %u: invalid drive-strength-microamp : %d , default to 4mA\n", 263 pin, drive_strength_ua); 264 ds_val = MESON_PINCONF_DRV_4000UA; 265 } 266 267 clrsetbits_le32(priv->reg_ds + reg, 0x3 << bit, ds_val << bit); 268 269 return 0; 270} 271 272int meson_pinconf_set(struct udevice *dev, unsigned int pin, 273 unsigned int param, unsigned int arg) 274{ 275 int ret; 276 277 switch (param) { 278 case PIN_CONFIG_BIAS_DISABLE: 279 case PIN_CONFIG_BIAS_PULL_UP: 280 case PIN_CONFIG_BIAS_PULL_DOWN: 281 ret = meson_pinconf_bias_set(dev, pin, param); 282 break; 283 case PIN_CONFIG_DRIVE_STRENGTH_UA: 284 ret = meson_pinconf_drive_strength_set(dev, pin, arg); 285 break; 286 default: 287 dev_err(dev, "unsupported configuration parameter %u\n", param); 288 return -EINVAL; 289 } 290 291 return ret; 292} 293 294int meson_pinconf_group_set(struct udevice *dev, 295 unsigned int group_selector, 296 unsigned int param, unsigned int arg) 297{ 298 struct meson_pinctrl *priv = dev_get_priv(dev); 299 struct meson_pmx_group *grp = &priv->data->groups[group_selector]; 300 int i, ret; 301 302 for (i = 0; i < grp->num_pins; i++) { 303 ret = meson_pinconf_set(dev, grp->pins[i], param, arg); 304 if (ret) 305 return ret; 306 } 307 308 return 0; 309} 310 311int meson_gpio_probe(struct udevice *dev) 312{ 313 struct meson_pinctrl *priv = dev_get_priv(dev->parent); 314 struct gpio_dev_priv *uc_priv; 315 316 uc_priv = dev_get_uclass_priv(dev); 317 uc_priv->bank_name = priv->data->name; 318 uc_priv->gpio_count = priv->data->num_pins; 319 320 return 0; 321} 322 323static fdt_addr_t parse_address(int offset, const char *name, int na, int ns) 324{ 325 int index, len = 0; 326 const fdt32_t *reg; 327 328 index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name); 329 if (index < 0) 330 return FDT_ADDR_T_NONE; 331 332 reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len); 333 if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) 334 return FDT_ADDR_T_NONE; 335 336 reg += index * (na + ns); 337 338 return fdt_translate_address((void *)gd->fdt_blob, offset, reg); 339} 340 341int meson_pinctrl_probe(struct udevice *dev) 342{ 343 struct meson_pinctrl *priv = dev_get_priv(dev); 344 struct uclass_driver *drv; 345 struct udevice *gpio_dev; 346 fdt_addr_t addr; 347 int node, gpio = -1, len; 348 int na, ns; 349 char *name; 350 351 /* FIXME: Should use livetree */ 352 na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent)); 353 if (na < 1) { 354 debug("bad #address-cells\n"); 355 return -EINVAL; 356 } 357 358 ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); 359 if (ns < 1) { 360 debug("bad #size-cells\n"); 361 return -EINVAL; 362 } 363 364 fdt_for_each_subnode(node, gd->fdt_blob, dev_of_offset(dev)) { 365 if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) { 366 gpio = node; 367 break; 368 } 369 } 370 371 if (!gpio) { 372 debug("gpio node not found\n"); 373 return -EINVAL; 374 } 375 376 addr = parse_address(gpio, "mux", na, ns); 377 if (addr == FDT_ADDR_T_NONE) { 378 debug("mux address not found\n"); 379 return -EINVAL; 380 } 381 priv->reg_mux = (void __iomem *)addr; 382 383 addr = parse_address(gpio, "gpio", na, ns); 384 if (addr == FDT_ADDR_T_NONE) { 385 debug("gpio address not found\n"); 386 return -EINVAL; 387 } 388 priv->reg_gpio = (void __iomem *)addr; 389 390 addr = parse_address(gpio, "pull", na, ns); 391 /* Use gpio region if pull one is not present */ 392 if (addr == FDT_ADDR_T_NONE) 393 priv->reg_pull = priv->reg_gpio; 394 else 395 priv->reg_pull = (void __iomem *)addr; 396 397 addr = parse_address(gpio, "pull-enable", na, ns); 398 /* Use pull region if pull-enable one is not present */ 399 if (addr == FDT_ADDR_T_NONE) 400 priv->reg_pullen = priv->reg_pull; 401 else 402 priv->reg_pullen = (void __iomem *)addr; 403 404 addr = parse_address(gpio, "ds", na, ns); 405 /* Drive strength region is optional */ 406 if (addr == FDT_ADDR_T_NONE) 407 priv->reg_ds = NULL; 408 else 409 priv->reg_ds = (void __iomem *)addr; 410 411 priv->data = (struct meson_pinctrl_data *)dev_get_driver_data(dev); 412 413 /* Lookup GPIO driver */ 414 drv = lists_uclass_lookup(UCLASS_GPIO); 415 if (!drv) { 416 puts("Cannot find GPIO driver\n"); 417 return -ENOENT; 418 } 419 420 name = calloc(1, 32); 421 sprintf(name, "meson-gpio"); 422 423 /* Create child device UCLASS_GPIO and bind it */ 424 device_bind(dev, priv->data->gpio_driver, name, NULL, 425 offset_to_ofnode(gpio), &gpio_dev); 426 427 return 0; 428} 429