Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: cygnus: add gpio/pinconf driver

This adds the initial support of the Broadcom Cygnus GPIO/PINCONF driver
that supports all 3 GPIO controllers on Cygnus including the ASIU GPIO
controller, the chipCommonG GPIO controller, and the always-on GPIO
controller. Basic PINCONF configurations such as bias pull up/down, and
drive strength are also supported in this driver.

Pins from the ASIU GPIO controller can be individually muxed to GPIO
function, through interaction with the Cygnus IOMUX controller

Signed-off-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
Tested-by: Dmitry Torokhov <dtor@chromium.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Ray Jui and committed by
Linus Walleij
b64333ce 2dffad82

+930
+22
drivers/pinctrl/bcm/Kconfig
··· 20 20 select PINMUX 21 21 select PINCONF 22 22 23 + config PINCTRL_CYGNUS_GPIO 24 + bool "Broadcom Cygnus GPIO (with PINCONF) driver" 25 + depends on OF_GPIO && ARCH_BCM_CYGNUS 26 + select GPIOLIB_IRQCHIP 27 + select PINCONF 28 + select GENERIC_PINCONF 29 + default ARCH_BCM_CYGNUS 30 + help 31 + Say yes here to enable the Broadcom Cygnus GPIO driver. 32 + 33 + The Broadcom Cygnus SoC has 3 GPIO controllers including the ASIU 34 + GPIO controller (ASIU), the chipCommonG GPIO controller (CCM), and 35 + the always-ON GPIO controller (CRMU/AON). All 3 GPIO controllers are 36 + supported by this driver. 37 + 38 + All 3 Cygnus GPIO controllers support basic PINCONF functions such 39 + as bias pull up, pull down, and drive strength configurations, when 40 + these pins are muxed to GPIO. 41 + 42 + Pins from the ASIU GPIO can be individually muxed to GPIO function, 43 + through interaction with the Cygnus IOMUX controller. 44 + 23 45 config PINCTRL_CYGNUS_MUX 24 46 bool "Broadcom Cygnus IOMUX driver" 25 47 depends on (ARCH_BCM_CYGNUS || COMPILE_TEST)
+1
drivers/pinctrl/bcm/Makefile
··· 2 2 3 3 obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o 4 4 obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o 5 + obj-$(CONFIG_PINCTRL_CYGNUS_GPIO) += pinctrl-cygnus-gpio.o 5 6 obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o
+907
drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
··· 1 + /* 2 + * Copyright (C) 2014-2015 Broadcom Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License as 6 + * published by the Free Software Foundation version 2. 7 + * 8 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 9 + * kind, whether express or implied; without even the implied warranty 10 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * This file contains the Broadcom Cygnus GPIO driver that supports 3 14 + * GPIO controllers on Cygnus including the ASIU GPIO controller, the 15 + * chipCommonG GPIO controller, and the always-on GPIO controller. Basic 16 + * PINCONF such as bias pull up/down, and drive strength are also supported 17 + * in this driver. 18 + * 19 + * Pins from the ASIU GPIO can be individually muxed to GPIO function, 20 + * through the interaction with the Cygnus IOMUX controller 21 + */ 22 + 23 + #include <linux/kernel.h> 24 + #include <linux/slab.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/io.h> 27 + #include <linux/gpio.h> 28 + #include <linux/ioport.h> 29 + #include <linux/of_device.h> 30 + #include <linux/of_irq.h> 31 + #include <linux/pinctrl/pinctrl.h> 32 + #include <linux/pinctrl/pinmux.h> 33 + #include <linux/pinctrl/pinconf.h> 34 + #include <linux/pinctrl/pinconf-generic.h> 35 + 36 + #include "../pinctrl-utils.h" 37 + 38 + #define CYGNUS_GPIO_DATA_IN_OFFSET 0x00 39 + #define CYGNUS_GPIO_DATA_OUT_OFFSET 0x04 40 + #define CYGNUS_GPIO_OUT_EN_OFFSET 0x08 41 + #define CYGNUS_GPIO_IN_TYPE_OFFSET 0x0c 42 + #define CYGNUS_GPIO_INT_DE_OFFSET 0x10 43 + #define CYGNUS_GPIO_INT_EDGE_OFFSET 0x14 44 + #define CYGNUS_GPIO_INT_MSK_OFFSET 0x18 45 + #define CYGNUS_GPIO_INT_STAT_OFFSET 0x1c 46 + #define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20 47 + #define CYGNUS_GPIO_INT_CLR_OFFSET 0x24 48 + #define CYGNUS_GPIO_PAD_RES_OFFSET 0x34 49 + #define CYGNUS_GPIO_RES_EN_OFFSET 0x38 50 + 51 + /* drive strength control for ASIU GPIO */ 52 + #define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58 53 + 54 + /* drive strength control for CCM/CRMU (AON) GPIO */ 55 + #define CYGNUS_GPIO_DRV0_CTRL_OFFSET 0x00 56 + 57 + #define GPIO_BANK_SIZE 0x200 58 + #define NGPIOS_PER_BANK 32 59 + #define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) 60 + 61 + #define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg)) 62 + #define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) 63 + 64 + #define GPIO_DRV_STRENGTH_BIT_SHIFT 20 65 + #define GPIO_DRV_STRENGTH_BITS 3 66 + #define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1) 67 + 68 + /* 69 + * Cygnus GPIO core 70 + * 71 + * @dev: pointer to device 72 + * @base: I/O register base for Cygnus GPIO controller 73 + * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that 74 + * has the PINCONF support implemented outside of the GPIO block 75 + * @lock: lock to protect access to I/O registers 76 + * @gc: GPIO chip 77 + * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs 78 + * @pinmux_is_supported: flag to indicate this GPIO controller contains pins 79 + * that can be individually muxed to GPIO 80 + * @pctl: pointer to pinctrl_dev 81 + * @pctldesc: pinctrl descriptor 82 + */ 83 + struct cygnus_gpio { 84 + struct device *dev; 85 + 86 + void __iomem *base; 87 + void __iomem *io_ctrl; 88 + 89 + spinlock_t lock; 90 + 91 + struct gpio_chip gc; 92 + unsigned num_banks; 93 + 94 + bool pinmux_is_supported; 95 + 96 + struct pinctrl_dev *pctl; 97 + struct pinctrl_desc pctldesc; 98 + }; 99 + 100 + static inline struct cygnus_gpio *to_cygnus_gpio(struct gpio_chip *gc) 101 + { 102 + return container_of(gc, struct cygnus_gpio, gc); 103 + } 104 + 105 + /* 106 + * Mapping from PINCONF pins to GPIO pins is 1-to-1 107 + */ 108 + static inline unsigned cygnus_pin_to_gpio(unsigned pin) 109 + { 110 + return pin; 111 + } 112 + 113 + /** 114 + * cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a 115 + * Cygnus GPIO register 116 + * 117 + * @cygnus_gpio: Cygnus GPIO device 118 + * @reg: register offset 119 + * @gpio: GPIO pin 120 + * @set: set or clear 121 + */ 122 + static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg, 123 + unsigned gpio, bool set) 124 + { 125 + unsigned int offset = CYGNUS_GPIO_REG(gpio, reg); 126 + unsigned int shift = CYGNUS_GPIO_SHIFT(gpio); 127 + u32 val; 128 + 129 + val = readl(chip->base + offset); 130 + if (set) 131 + val |= BIT(shift); 132 + else 133 + val &= ~BIT(shift); 134 + writel(val, chip->base + offset); 135 + } 136 + 137 + static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg, 138 + unsigned gpio) 139 + { 140 + unsigned int offset = CYGNUS_GPIO_REG(gpio, reg); 141 + unsigned int shift = CYGNUS_GPIO_SHIFT(gpio); 142 + 143 + return !!(readl(chip->base + offset) & BIT(shift)); 144 + } 145 + 146 + static void cygnus_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 147 + { 148 + struct gpio_chip *gc = irq_desc_get_handler_data(desc); 149 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 150 + struct irq_chip *irq_chip = irq_desc_get_chip(desc); 151 + int i, bit; 152 + 153 + chained_irq_enter(irq_chip, desc); 154 + 155 + /* go through the entire GPIO banks and handle all interrupts */ 156 + for (i = 0; i < chip->num_banks; i++) { 157 + unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) + 158 + CYGNUS_GPIO_INT_MSTAT_OFFSET); 159 + 160 + for_each_set_bit(bit, &val, NGPIOS_PER_BANK) { 161 + unsigned pin = NGPIOS_PER_BANK * i + bit; 162 + int child_irq = irq_find_mapping(gc->irqdomain, pin); 163 + 164 + /* 165 + * Clear the interrupt before invoking the 166 + * handler, so we do not leave any window 167 + */ 168 + writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) + 169 + CYGNUS_GPIO_INT_CLR_OFFSET); 170 + 171 + generic_handle_irq(child_irq); 172 + } 173 + } 174 + 175 + chained_irq_exit(irq_chip, desc); 176 + } 177 + 178 + 179 + static void cygnus_gpio_irq_ack(struct irq_data *d) 180 + { 181 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 182 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 183 + unsigned gpio = d->hwirq; 184 + unsigned int offset = CYGNUS_GPIO_REG(gpio, 185 + CYGNUS_GPIO_INT_CLR_OFFSET); 186 + unsigned int shift = CYGNUS_GPIO_SHIFT(gpio); 187 + u32 val = BIT(shift); 188 + 189 + writel(val, chip->base + offset); 190 + } 191 + 192 + /** 193 + * cygnus_gpio_irq_set_mask - mask/unmask a GPIO interrupt 194 + * 195 + * @d: IRQ chip data 196 + * @unmask: mask/unmask GPIO interrupt 197 + */ 198 + static void cygnus_gpio_irq_set_mask(struct irq_data *d, bool unmask) 199 + { 200 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 201 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 202 + unsigned gpio = d->hwirq; 203 + 204 + cygnus_set_bit(chip, CYGNUS_GPIO_INT_MSK_OFFSET, gpio, unmask); 205 + } 206 + 207 + static void cygnus_gpio_irq_mask(struct irq_data *d) 208 + { 209 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 210 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 211 + unsigned long flags; 212 + 213 + spin_lock_irqsave(&chip->lock, flags); 214 + cygnus_gpio_irq_set_mask(d, false); 215 + spin_unlock_irqrestore(&chip->lock, flags); 216 + } 217 + 218 + static void cygnus_gpio_irq_unmask(struct irq_data *d) 219 + { 220 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 221 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 222 + unsigned long flags; 223 + 224 + spin_lock_irqsave(&chip->lock, flags); 225 + cygnus_gpio_irq_set_mask(d, true); 226 + spin_unlock_irqrestore(&chip->lock, flags); 227 + } 228 + 229 + static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type) 230 + { 231 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 232 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 233 + unsigned gpio = d->hwirq; 234 + bool level_triggered = false; 235 + bool dual_edge = false; 236 + bool rising_or_high = false; 237 + unsigned long flags; 238 + 239 + switch (type & IRQ_TYPE_SENSE_MASK) { 240 + case IRQ_TYPE_EDGE_RISING: 241 + rising_or_high = true; 242 + break; 243 + 244 + case IRQ_TYPE_EDGE_FALLING: 245 + break; 246 + 247 + case IRQ_TYPE_EDGE_BOTH: 248 + dual_edge = true; 249 + break; 250 + 251 + case IRQ_TYPE_LEVEL_HIGH: 252 + level_triggered = true; 253 + rising_or_high = true; 254 + break; 255 + 256 + case IRQ_TYPE_LEVEL_LOW: 257 + level_triggered = true; 258 + break; 259 + 260 + default: 261 + dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n", 262 + type); 263 + return -EINVAL; 264 + } 265 + 266 + spin_lock_irqsave(&chip->lock, flags); 267 + cygnus_set_bit(chip, CYGNUS_GPIO_IN_TYPE_OFFSET, gpio, 268 + level_triggered); 269 + cygnus_set_bit(chip, CYGNUS_GPIO_INT_DE_OFFSET, gpio, dual_edge); 270 + cygnus_set_bit(chip, CYGNUS_GPIO_INT_EDGE_OFFSET, gpio, 271 + rising_or_high); 272 + spin_unlock_irqrestore(&chip->lock, flags); 273 + 274 + dev_dbg(chip->dev, 275 + "gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n", 276 + gpio, level_triggered, dual_edge, rising_or_high); 277 + 278 + return 0; 279 + } 280 + 281 + static struct irq_chip cygnus_gpio_irq_chip = { 282 + .name = "bcm-cygnus-gpio", 283 + .irq_ack = cygnus_gpio_irq_ack, 284 + .irq_mask = cygnus_gpio_irq_mask, 285 + .irq_unmask = cygnus_gpio_irq_unmask, 286 + .irq_set_type = cygnus_gpio_irq_set_type, 287 + }; 288 + 289 + /* 290 + * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO 291 + */ 292 + static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset) 293 + { 294 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 295 + unsigned gpio = gc->base + offset; 296 + 297 + /* not all Cygnus GPIO pins can be muxed individually */ 298 + if (!chip->pinmux_is_supported) 299 + return 0; 300 + 301 + return pinctrl_request_gpio(gpio); 302 + } 303 + 304 + static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset) 305 + { 306 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 307 + unsigned gpio = gc->base + offset; 308 + 309 + if (!chip->pinmux_is_supported) 310 + return; 311 + 312 + pinctrl_free_gpio(gpio); 313 + } 314 + 315 + static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) 316 + { 317 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 318 + unsigned long flags; 319 + 320 + spin_lock_irqsave(&chip->lock, flags); 321 + cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, false); 322 + spin_unlock_irqrestore(&chip->lock, flags); 323 + 324 + dev_dbg(chip->dev, "gpio:%u set input\n", gpio); 325 + 326 + return 0; 327 + } 328 + 329 + static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, 330 + int val) 331 + { 332 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 333 + unsigned long flags; 334 + 335 + spin_lock_irqsave(&chip->lock, flags); 336 + cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, true); 337 + cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); 338 + spin_unlock_irqrestore(&chip->lock, flags); 339 + 340 + dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val); 341 + 342 + return 0; 343 + } 344 + 345 + static void cygnus_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) 346 + { 347 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 348 + unsigned long flags; 349 + 350 + spin_lock_irqsave(&chip->lock, flags); 351 + cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); 352 + spin_unlock_irqrestore(&chip->lock, flags); 353 + 354 + dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val); 355 + } 356 + 357 + static int cygnus_gpio_get(struct gpio_chip *gc, unsigned gpio) 358 + { 359 + struct cygnus_gpio *chip = to_cygnus_gpio(gc); 360 + unsigned int offset = CYGNUS_GPIO_REG(gpio, 361 + CYGNUS_GPIO_DATA_IN_OFFSET); 362 + unsigned int shift = CYGNUS_GPIO_SHIFT(gpio); 363 + 364 + return !!(readl(chip->base + offset) & BIT(shift)); 365 + } 366 + 367 + static int cygnus_get_groups_count(struct pinctrl_dev *pctldev) 368 + { 369 + return 1; 370 + } 371 + 372 + /* 373 + * Only one group: "gpio_grp", since this local pinctrl device only performs 374 + * GPIO specific PINCONF configurations 375 + */ 376 + static const char *cygnus_get_group_name(struct pinctrl_dev *pctldev, 377 + unsigned selector) 378 + { 379 + return "gpio_grp"; 380 + } 381 + 382 + static const struct pinctrl_ops cygnus_pctrl_ops = { 383 + .get_groups_count = cygnus_get_groups_count, 384 + .get_group_name = cygnus_get_group_name, 385 + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 386 + .dt_free_map = pinctrl_utils_dt_free_map, 387 + }; 388 + 389 + static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio, 390 + bool disable, bool pull_up) 391 + { 392 + unsigned long flags; 393 + 394 + spin_lock_irqsave(&chip->lock, flags); 395 + 396 + if (disable) { 397 + cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, false); 398 + } else { 399 + cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio, 400 + pull_up); 401 + cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, true); 402 + } 403 + 404 + spin_unlock_irqrestore(&chip->lock, flags); 405 + 406 + dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up); 407 + 408 + return 0; 409 + } 410 + 411 + static void cygnus_gpio_get_pull(struct cygnus_gpio *chip, unsigned gpio, 412 + bool *disable, bool *pull_up) 413 + { 414 + unsigned long flags; 415 + 416 + spin_lock_irqsave(&chip->lock, flags); 417 + *disable = !cygnus_get_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio); 418 + *pull_up = cygnus_get_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio); 419 + spin_unlock_irqrestore(&chip->lock, flags); 420 + } 421 + 422 + static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio, 423 + unsigned strength) 424 + { 425 + void __iomem *base; 426 + unsigned int i, offset, shift; 427 + u32 val; 428 + unsigned long flags; 429 + 430 + /* make sure drive strength is supported */ 431 + if (strength < 2 || strength > 16 || (strength % 2)) 432 + return -ENOTSUPP; 433 + 434 + if (chip->io_ctrl) { 435 + base = chip->io_ctrl; 436 + offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET; 437 + } else { 438 + base = chip->base; 439 + offset = CYGNUS_GPIO_REG(gpio, 440 + CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET); 441 + } 442 + 443 + shift = CYGNUS_GPIO_SHIFT(gpio); 444 + 445 + dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio, 446 + strength); 447 + 448 + spin_lock_irqsave(&chip->lock, flags); 449 + strength = (strength / 2) - 1; 450 + for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { 451 + val = readl(base + offset); 452 + val &= ~BIT(shift); 453 + val |= ((strength >> i) & 0x1) << shift; 454 + writel(val, base + offset); 455 + offset += 4; 456 + } 457 + spin_unlock_irqrestore(&chip->lock, flags); 458 + 459 + return 0; 460 + } 461 + 462 + static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio, 463 + u16 *strength) 464 + { 465 + void __iomem *base; 466 + unsigned int i, offset, shift; 467 + u32 val; 468 + unsigned long flags; 469 + 470 + if (chip->io_ctrl) { 471 + base = chip->io_ctrl; 472 + offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET; 473 + } else { 474 + base = chip->base; 475 + offset = CYGNUS_GPIO_REG(gpio, 476 + CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET); 477 + } 478 + 479 + shift = CYGNUS_GPIO_SHIFT(gpio); 480 + 481 + spin_lock_irqsave(&chip->lock, flags); 482 + *strength = 0; 483 + for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { 484 + val = readl(base + offset) & BIT(shift); 485 + val >>= shift; 486 + *strength += (val << i); 487 + offset += 4; 488 + } 489 + 490 + /* convert to mA */ 491 + *strength = (*strength + 1) * 2; 492 + spin_unlock_irqrestore(&chip->lock, flags); 493 + 494 + return 0; 495 + } 496 + 497 + static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, 498 + unsigned long *config) 499 + { 500 + struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev); 501 + enum pin_config_param param = pinconf_to_config_param(*config); 502 + unsigned gpio = cygnus_pin_to_gpio(pin); 503 + u16 arg; 504 + bool disable, pull_up; 505 + int ret; 506 + 507 + switch (param) { 508 + case PIN_CONFIG_BIAS_DISABLE: 509 + cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up); 510 + if (disable) 511 + return 0; 512 + else 513 + return -EINVAL; 514 + 515 + case PIN_CONFIG_BIAS_PULL_UP: 516 + cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up); 517 + if (!disable && pull_up) 518 + return 0; 519 + else 520 + return -EINVAL; 521 + 522 + case PIN_CONFIG_BIAS_PULL_DOWN: 523 + cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up); 524 + if (!disable && !pull_up) 525 + return 0; 526 + else 527 + return -EINVAL; 528 + 529 + case PIN_CONFIG_DRIVE_STRENGTH: 530 + ret = cygnus_gpio_get_strength(chip, gpio, &arg); 531 + if (ret) 532 + return ret; 533 + else 534 + *config = pinconf_to_config_packed(param, arg); 535 + 536 + return 0; 537 + 538 + default: 539 + return -ENOTSUPP; 540 + } 541 + 542 + return -ENOTSUPP; 543 + } 544 + 545 + static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, 546 + unsigned long *configs, unsigned num_configs) 547 + { 548 + struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev); 549 + enum pin_config_param param; 550 + u16 arg; 551 + unsigned i, gpio = cygnus_pin_to_gpio(pin); 552 + int ret = -ENOTSUPP; 553 + 554 + for (i = 0; i < num_configs; i++) { 555 + param = pinconf_to_config_param(configs[i]); 556 + arg = pinconf_to_config_argument(configs[i]); 557 + 558 + switch (param) { 559 + case PIN_CONFIG_BIAS_DISABLE: 560 + ret = cygnus_gpio_set_pull(chip, gpio, true, false); 561 + if (ret < 0) 562 + goto out; 563 + break; 564 + 565 + case PIN_CONFIG_BIAS_PULL_UP: 566 + ret = cygnus_gpio_set_pull(chip, gpio, false, true); 567 + if (ret < 0) 568 + goto out; 569 + break; 570 + 571 + case PIN_CONFIG_BIAS_PULL_DOWN: 572 + ret = cygnus_gpio_set_pull(chip, gpio, false, false); 573 + if (ret < 0) 574 + goto out; 575 + break; 576 + 577 + case PIN_CONFIG_DRIVE_STRENGTH: 578 + ret = cygnus_gpio_set_strength(chip, gpio, arg); 579 + if (ret < 0) 580 + goto out; 581 + break; 582 + 583 + default: 584 + dev_err(chip->dev, "invalid configuration\n"); 585 + return -ENOTSUPP; 586 + } 587 + } /* for each config */ 588 + 589 + out: 590 + return ret; 591 + } 592 + 593 + static const struct pinconf_ops cygnus_pconf_ops = { 594 + .is_generic = true, 595 + .pin_config_get = cygnus_pin_config_get, 596 + .pin_config_set = cygnus_pin_config_set, 597 + }; 598 + 599 + /* 600 + * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX 601 + * pinctrl pin space 602 + */ 603 + struct cygnus_gpio_pin_range { 604 + unsigned offset; 605 + unsigned pin_base; 606 + unsigned num_pins; 607 + }; 608 + 609 + #define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n } 610 + 611 + /* 612 + * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins 613 + */ 614 + static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = { 615 + CYGNUS_PINRANGE(0, 42, 1), 616 + CYGNUS_PINRANGE(1, 44, 3), 617 + CYGNUS_PINRANGE(4, 48, 1), 618 + CYGNUS_PINRANGE(5, 50, 3), 619 + CYGNUS_PINRANGE(8, 126, 1), 620 + CYGNUS_PINRANGE(9, 155, 1), 621 + CYGNUS_PINRANGE(10, 152, 1), 622 + CYGNUS_PINRANGE(11, 154, 1), 623 + CYGNUS_PINRANGE(12, 153, 1), 624 + CYGNUS_PINRANGE(13, 127, 3), 625 + CYGNUS_PINRANGE(16, 140, 1), 626 + CYGNUS_PINRANGE(17, 145, 7), 627 + CYGNUS_PINRANGE(24, 130, 10), 628 + CYGNUS_PINRANGE(34, 141, 4), 629 + CYGNUS_PINRANGE(38, 54, 1), 630 + CYGNUS_PINRANGE(39, 56, 3), 631 + CYGNUS_PINRANGE(42, 60, 3), 632 + CYGNUS_PINRANGE(45, 64, 3), 633 + CYGNUS_PINRANGE(48, 68, 2), 634 + CYGNUS_PINRANGE(50, 84, 6), 635 + CYGNUS_PINRANGE(56, 94, 6), 636 + CYGNUS_PINRANGE(62, 72, 1), 637 + CYGNUS_PINRANGE(63, 70, 1), 638 + CYGNUS_PINRANGE(64, 80, 1), 639 + CYGNUS_PINRANGE(65, 74, 3), 640 + CYGNUS_PINRANGE(68, 78, 1), 641 + CYGNUS_PINRANGE(69, 82, 1), 642 + CYGNUS_PINRANGE(70, 156, 17), 643 + CYGNUS_PINRANGE(87, 104, 12), 644 + CYGNUS_PINRANGE(99, 102, 2), 645 + CYGNUS_PINRANGE(101, 90, 4), 646 + CYGNUS_PINRANGE(105, 116, 10), 647 + CYGNUS_PINRANGE(123, 11, 1), 648 + CYGNUS_PINRANGE(124, 38, 4), 649 + CYGNUS_PINRANGE(128, 43, 1), 650 + CYGNUS_PINRANGE(129, 47, 1), 651 + CYGNUS_PINRANGE(130, 49, 1), 652 + CYGNUS_PINRANGE(131, 53, 1), 653 + CYGNUS_PINRANGE(132, 55, 1), 654 + CYGNUS_PINRANGE(133, 59, 1), 655 + CYGNUS_PINRANGE(134, 63, 1), 656 + CYGNUS_PINRANGE(135, 67, 1), 657 + CYGNUS_PINRANGE(136, 71, 1), 658 + CYGNUS_PINRANGE(137, 73, 1), 659 + CYGNUS_PINRANGE(138, 77, 1), 660 + CYGNUS_PINRANGE(139, 79, 1), 661 + CYGNUS_PINRANGE(140, 81, 1), 662 + CYGNUS_PINRANGE(141, 83, 1), 663 + CYGNUS_PINRANGE(142, 10, 1) 664 + }; 665 + 666 + /* 667 + * The Cygnus IOMUX controller mainly supports group based mux configuration, 668 + * but certain pins can be muxed to GPIO individually. Only the ASIU GPIO 669 + * controller can support this, so it's an optional configuration 670 + * 671 + * Return -ENODEV means no support and that's fine 672 + */ 673 + static int cygnus_gpio_pinmux_add_range(struct cygnus_gpio *chip) 674 + { 675 + struct device_node *node = chip->dev->of_node; 676 + struct device_node *pinmux_node; 677 + struct platform_device *pinmux_pdev; 678 + struct gpio_chip *gc = &chip->gc; 679 + int i, ret = 0; 680 + 681 + /* parse DT to find the phandle to the pinmux controller */ 682 + pinmux_node = of_parse_phandle(node, "pinmux", 0); 683 + if (!pinmux_node) 684 + return -ENODEV; 685 + 686 + pinmux_pdev = of_find_device_by_node(pinmux_node); 687 + /* no longer need the pinmux node */ 688 + of_node_put(pinmux_node); 689 + if (!pinmux_pdev) { 690 + dev_err(chip->dev, "failed to get pinmux device\n"); 691 + return -EINVAL; 692 + } 693 + 694 + /* now need to create the mapping between local GPIO and PINMUX pins */ 695 + for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) { 696 + ret = gpiochip_add_pin_range(gc, dev_name(&pinmux_pdev->dev), 697 + cygnus_gpio_pintable[i].offset, 698 + cygnus_gpio_pintable[i].pin_base, 699 + cygnus_gpio_pintable[i].num_pins); 700 + if (ret) { 701 + dev_err(chip->dev, "unable to add GPIO pin range\n"); 702 + goto err_put_device; 703 + } 704 + } 705 + 706 + chip->pinmux_is_supported = true; 707 + 708 + /* no need for pinmux_pdev device reference anymore */ 709 + put_device(&pinmux_pdev->dev); 710 + return 0; 711 + 712 + err_put_device: 713 + put_device(&pinmux_pdev->dev); 714 + gpiochip_remove_pin_ranges(gc); 715 + return ret; 716 + } 717 + 718 + /* 719 + * Cygnus GPIO controller supports some PINCONF related configurations such as 720 + * pull up, pull down, and drive strength, when the pin is configured to GPIO 721 + * 722 + * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the 723 + * local GPIO pins 724 + */ 725 + static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip) 726 + { 727 + struct pinctrl_desc *pctldesc = &chip->pctldesc; 728 + struct pinctrl_pin_desc *pins; 729 + struct gpio_chip *gc = &chip->gc; 730 + int i; 731 + 732 + pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL); 733 + if (!pins) 734 + return -ENOMEM; 735 + 736 + for (i = 0; i < gc->ngpio; i++) { 737 + pins[i].number = i; 738 + pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL, 739 + "gpio-%d", i); 740 + if (!pins[i].name) 741 + return -ENOMEM; 742 + } 743 + 744 + pctldesc->name = dev_name(chip->dev); 745 + pctldesc->pctlops = &cygnus_pctrl_ops; 746 + pctldesc->pins = pins; 747 + pctldesc->npins = gc->ngpio; 748 + pctldesc->confops = &cygnus_pconf_ops; 749 + 750 + chip->pctl = pinctrl_register(pctldesc, chip->dev, chip); 751 + if (!chip->pctl) { 752 + dev_err(chip->dev, "unable to register pinctrl device\n"); 753 + return -EINVAL; 754 + } 755 + 756 + return 0; 757 + } 758 + 759 + static void cygnus_gpio_unregister_pinconf(struct cygnus_gpio *chip) 760 + { 761 + if (chip->pctl) 762 + pinctrl_unregister(chip->pctl); 763 + } 764 + 765 + struct cygnus_gpio_data { 766 + unsigned num_gpios; 767 + }; 768 + 769 + static const struct cygnus_gpio_data cygnus_cmm_gpio_data = { 770 + .num_gpios = 24, 771 + }; 772 + 773 + static const struct cygnus_gpio_data cygnus_asiu_gpio_data = { 774 + .num_gpios = 146, 775 + }; 776 + 777 + static const struct cygnus_gpio_data cygnus_crmu_gpio_data = { 778 + .num_gpios = 6, 779 + }; 780 + 781 + static const struct of_device_id cygnus_gpio_of_match[] = { 782 + { 783 + .compatible = "brcm,cygnus-ccm-gpio", 784 + .data = &cygnus_cmm_gpio_data, 785 + }, 786 + { 787 + .compatible = "brcm,cygnus-asiu-gpio", 788 + .data = &cygnus_asiu_gpio_data, 789 + }, 790 + { 791 + .compatible = "brcm,cygnus-crmu-gpio", 792 + .data = &cygnus_crmu_gpio_data, 793 + } 794 + }; 795 + 796 + static int cygnus_gpio_probe(struct platform_device *pdev) 797 + { 798 + struct device *dev = &pdev->dev; 799 + struct resource *res; 800 + struct cygnus_gpio *chip; 801 + struct gpio_chip *gc; 802 + u32 ngpios; 803 + int irq, ret; 804 + const struct of_device_id *match; 805 + const struct cygnus_gpio_data *gpio_data; 806 + 807 + match = of_match_device(cygnus_gpio_of_match, dev); 808 + if (!match) 809 + return -ENODEV; 810 + gpio_data = match->data; 811 + ngpios = gpio_data->num_gpios; 812 + 813 + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 814 + if (!chip) 815 + return -ENOMEM; 816 + 817 + chip->dev = dev; 818 + platform_set_drvdata(pdev, chip); 819 + 820 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 821 + chip->base = devm_ioremap_resource(dev, res); 822 + if (IS_ERR(chip->base)) { 823 + dev_err(dev, "unable to map I/O memory\n"); 824 + return PTR_ERR(chip->base); 825 + } 826 + 827 + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 828 + if (res) { 829 + chip->io_ctrl = devm_ioremap_resource(dev, res); 830 + if (IS_ERR(chip->io_ctrl)) { 831 + dev_err(dev, "unable to map I/O memory\n"); 832 + return PTR_ERR(chip->io_ctrl); 833 + } 834 + } 835 + 836 + spin_lock_init(&chip->lock); 837 + 838 + gc = &chip->gc; 839 + gc->base = -1; 840 + gc->ngpio = ngpios; 841 + chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK; 842 + gc->label = dev_name(dev); 843 + gc->dev = dev; 844 + gc->of_node = dev->of_node; 845 + gc->request = cygnus_gpio_request; 846 + gc->free = cygnus_gpio_free; 847 + gc->direction_input = cygnus_gpio_direction_input; 848 + gc->direction_output = cygnus_gpio_direction_output; 849 + gc->set = cygnus_gpio_set; 850 + gc->get = cygnus_gpio_get; 851 + 852 + ret = gpiochip_add(gc); 853 + if (ret < 0) { 854 + dev_err(dev, "unable to add GPIO chip\n"); 855 + return ret; 856 + } 857 + 858 + ret = cygnus_gpio_pinmux_add_range(chip); 859 + if (ret && ret != -ENODEV) { 860 + dev_err(dev, "unable to add GPIO pin range\n"); 861 + goto err_rm_gpiochip; 862 + } 863 + 864 + ret = cygnus_gpio_register_pinconf(chip); 865 + if (ret) { 866 + dev_err(dev, "unable to register pinconf\n"); 867 + goto err_rm_gpiochip; 868 + } 869 + 870 + /* optional GPIO interrupt support */ 871 + irq = platform_get_irq(pdev, 0); 872 + if (irq) { 873 + ret = gpiochip_irqchip_add(gc, &cygnus_gpio_irq_chip, 0, 874 + handle_simple_irq, IRQ_TYPE_NONE); 875 + if (ret) { 876 + dev_err(dev, "no GPIO irqchip\n"); 877 + goto err_unregister_pinconf; 878 + } 879 + 880 + gpiochip_set_chained_irqchip(gc, &cygnus_gpio_irq_chip, irq, 881 + cygnus_gpio_irq_handler); 882 + } 883 + 884 + return 0; 885 + 886 + err_unregister_pinconf: 887 + cygnus_gpio_unregister_pinconf(chip); 888 + 889 + err_rm_gpiochip: 890 + gpiochip_remove(gc); 891 + 892 + return ret; 893 + } 894 + 895 + static struct platform_driver cygnus_gpio_driver = { 896 + .driver = { 897 + .name = "cygnus-gpio", 898 + .of_match_table = cygnus_gpio_of_match, 899 + }, 900 + .probe = cygnus_gpio_probe, 901 + }; 902 + 903 + static int __init cygnus_gpio_init(void) 904 + { 905 + return platform_driver_probe(&cygnus_gpio_driver, cygnus_gpio_probe); 906 + } 907 + arch_initcall_sync(cygnus_gpio_init);