Lines Matching +full:cygnus +full:- +full:ccm +full:- +full:gpio
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2014-2017 Broadcom
7 * This file contains the Broadcom Iproc GPIO driver that supports 3
8 * GPIO controllers on Iproc including the ASIU GPIO controller, the
9 * chipCommonG GPIO controller, and the always-on GPIO controller. Basic
13 * It provides the functionality where pins from the GPIO can be
14 * individually muxed to GPIO function, if individual pad
19 #include <linux/gpio/driver.h>
30 #include <linux/pinctrl/pinconf-generic.h>
34 #include "../pinctrl-utils.h"
49 /* drive strength control for ASIU GPIO */
52 /* pinconf for CCM GPIO */
56 /* pinconf for CRMU(aon) GPIO and CCM GPIO*/
68 #define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
85 * Iproc GPIO core
88 * @base: I/O register base for Iproc GPIO controller
89 * @io_ctrl: I/O register base for certain type of Iproc GPIO controller that
90 * has the PINCONF support implemented outside of the GPIO block
92 * @gc: GPIO chip
93 * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
94 * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
95 * that can be individually muxed to GPIO
125 * Mapping from PINCONF pins to GPIO pins is 1-to-1
133 * iproc_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
134 * Iproc GPIO register
136 * @chip: Iproc GPIO device
138 * @gpio: GPIO pin
142 unsigned gpio, bool set) in iproc_set_bit() argument
144 unsigned int offset = IPROC_GPIO_REG(gpio, reg); in iproc_set_bit()
145 unsigned int shift = IPROC_GPIO_SHIFT(gpio); in iproc_set_bit()
148 val = readl(chip->base + offset); in iproc_set_bit()
153 writel(val, chip->base + offset); in iproc_set_bit()
157 unsigned gpio) in iproc_get_bit() argument
159 unsigned int offset = IPROC_GPIO_REG(gpio, reg); in iproc_get_bit()
160 unsigned int shift = IPROC_GPIO_SHIFT(gpio); in iproc_get_bit()
162 return !!(readl(chip->base + offset) & BIT(shift)); in iproc_get_bit()
174 /* go through the entire GPIO banks and handle all interrupts */ in iproc_gpio_irq_handler()
175 for (i = 0; i < chip->num_banks; i++) { in iproc_gpio_irq_handler()
176 unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) + in iproc_gpio_irq_handler()
186 writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) + in iproc_gpio_irq_handler()
189 generic_handle_domain_irq(gc->irq.domain, pin); in iproc_gpio_irq_handler()
201 unsigned gpio = d->hwirq; in iproc_gpio_irq_ack() local
202 unsigned int offset = IPROC_GPIO_REG(gpio, in iproc_gpio_irq_ack()
204 unsigned int shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_irq_ack()
207 writel(val, chip->base + offset); in iproc_gpio_irq_ack()
211 * iproc_gpio_irq_set_mask - mask/unmask a GPIO interrupt
214 * @unmask: mask/unmask GPIO interrupt
220 unsigned gpio = irqd_to_hwirq(d); in iproc_gpio_irq_set_mask() local
222 iproc_set_bit(chip, IPROC_GPIO_INT_MSK_OFFSET, gpio, unmask); in iproc_gpio_irq_set_mask()
231 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_irq_mask()
233 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_irq_mask()
244 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_irq_unmask()
246 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_irq_unmask()
253 unsigned gpio = d->hwirq; in iproc_gpio_irq_set_type() local
281 dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n", in iproc_gpio_irq_set_type()
283 return -EINVAL; in iproc_gpio_irq_set_type()
286 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_irq_set_type()
287 iproc_set_bit(chip, IPROC_GPIO_INT_TYPE_OFFSET, gpio, in iproc_gpio_irq_set_type()
289 iproc_set_bit(chip, IPROC_GPIO_INT_DE_OFFSET, gpio, dual_edge); in iproc_gpio_irq_set_type()
290 iproc_set_bit(chip, IPROC_GPIO_INT_EDGE_OFFSET, gpio, in iproc_gpio_irq_set_type()
298 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_irq_set_type()
300 dev_dbg(chip->dev, in iproc_gpio_irq_set_type()
301 "gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n", in iproc_gpio_irq_set_type()
302 gpio, level_triggered, dual_edge, rising_or_high); in iproc_gpio_irq_set_type()
312 seq_puts(p, dev_name(chip->dev)); in iproc_gpio_irq_print_chip()
328 * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO
334 /* not all Iproc GPIO pins can be muxed individually */ in iproc_gpio_request()
335 if (!chip->pinmux_is_supported) in iproc_gpio_request()
345 if (!chip->pinmux_is_supported) in iproc_gpio_free()
351 static int iproc_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) in iproc_gpio_direction_input() argument
356 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_direction_input()
357 iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, false); in iproc_gpio_direction_input()
358 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_direction_input()
360 dev_dbg(chip->dev, "gpio:%u set input\n", gpio); in iproc_gpio_direction_input()
365 static int iproc_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, in iproc_gpio_direction_output() argument
371 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_direction_output()
372 iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, true); in iproc_gpio_direction_output()
373 iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); in iproc_gpio_direction_output()
374 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_direction_output()
376 dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val); in iproc_gpio_direction_output()
381 static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) in iproc_gpio_get_direction() argument
384 unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); in iproc_gpio_get_direction()
385 unsigned int shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_get_direction()
387 if (readl(chip->base + offset) & BIT(shift)) in iproc_gpio_get_direction()
393 static int iproc_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) in iproc_gpio_set() argument
398 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_set()
399 iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); in iproc_gpio_set()
400 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_set()
402 dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val); in iproc_gpio_set()
407 static int iproc_gpio_get(struct gpio_chip *gc, unsigned gpio) in iproc_gpio_get() argument
410 unsigned int offset = IPROC_GPIO_REG(gpio, in iproc_gpio_get()
412 unsigned int shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_get()
414 return !!(readl(chip->base + offset) & BIT(shift)); in iproc_gpio_get()
433 if (!chip->nr_pinconf_disable) in iproc_pinconf_param_is_disabled()
436 for (i = 0; i < chip->nr_pinconf_disable; i++) in iproc_pinconf_param_is_disabled()
437 if (chip->pinconf_disable[i] == param) in iproc_pinconf_param_is_disabled()
460 chip->pinconf_disable = devm_kcalloc(chip->dev, nbits, in iproc_pinconf_disable_map_create()
461 sizeof(*chip->pinconf_disable), in iproc_pinconf_disable_map_create()
463 if (!chip->pinconf_disable) in iproc_pinconf_disable_map_create()
464 return -ENOMEM; in iproc_pinconf_disable_map_create()
466 chip->nr_pinconf_disable = nbits; in iproc_pinconf_disable_map_create()
471 chip->pinconf_disable[nbits++] = iproc_pinconf_disable_map[bit]; in iproc_pinconf_disable_map_create()
483 * GPIO specific PINCONF configurations
498 static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio, in iproc_gpio_set_pull() argument
506 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_set_pull()
507 if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { in iproc_gpio_set_pull()
508 base = chip->io_ctrl; in iproc_gpio_set_pull()
509 shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_set_pull()
514 /* no pull-up or pull-down */ in iproc_gpio_set_pull()
528 iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, in iproc_gpio_set_pull()
531 iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio, in iproc_gpio_set_pull()
533 iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, in iproc_gpio_set_pull()
538 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_set_pull()
539 dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up); in iproc_gpio_set_pull()
544 static void iproc_gpio_get_pull(struct iproc_gpio *chip, unsigned gpio, in iproc_gpio_get_pull() argument
552 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_get_pull()
553 if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { in iproc_gpio_get_pull()
554 base = chip->io_ctrl; in iproc_gpio_get_pull()
555 shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_get_pull()
564 *disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio); in iproc_gpio_get_pull()
565 *pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio); in iproc_gpio_get_pull()
567 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_get_pull()
570 #define DRV_STRENGTH_OFFSET(gpio, bit, type) ((type) == IOCTRL_TYPE_AON ? \ argument
571 ((2 - (bit)) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \
574 ((bit) * 4 + IPROC_GPIO_REG(gpio, IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET)))
576 static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio, in iproc_gpio_set_strength() argument
586 return -ENOTSUPP; in iproc_gpio_set_strength()
588 if (chip->io_ctrl) { in iproc_gpio_set_strength()
589 base = chip->io_ctrl; in iproc_gpio_set_strength()
591 base = chip->base; in iproc_gpio_set_strength()
594 shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_set_strength()
596 dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio, in iproc_gpio_set_strength()
599 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_set_strength()
600 strength = (strength / 2) - 1; in iproc_gpio_set_strength()
602 offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); in iproc_gpio_set_strength()
608 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_set_strength()
613 static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio, in iproc_gpio_get_strength() argument
621 if (chip->io_ctrl) { in iproc_gpio_get_strength()
622 base = chip->io_ctrl; in iproc_gpio_get_strength()
624 base = chip->base; in iproc_gpio_get_strength()
627 shift = IPROC_GPIO_SHIFT(gpio); in iproc_gpio_get_strength()
629 raw_spin_lock_irqsave(&chip->lock, flags); in iproc_gpio_get_strength()
632 offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); in iproc_gpio_get_strength()
640 raw_spin_unlock_irqrestore(&chip->lock, flags); in iproc_gpio_get_strength()
650 unsigned gpio = iproc_pin_to_gpio(pin); in iproc_pin_config_get() local
656 return -ENOTSUPP; in iproc_pin_config_get()
660 iproc_gpio_get_pull(chip, gpio, &disable, &pull_up); in iproc_pin_config_get()
664 return -EINVAL; in iproc_pin_config_get()
667 iproc_gpio_get_pull(chip, gpio, &disable, &pull_up); in iproc_pin_config_get()
671 return -EINVAL; in iproc_pin_config_get()
674 iproc_gpio_get_pull(chip, gpio, &disable, &pull_up); in iproc_pin_config_get()
678 return -EINVAL; in iproc_pin_config_get()
681 ret = iproc_gpio_get_strength(chip, gpio, &arg); in iproc_pin_config_get()
689 return -ENOTSUPP; in iproc_pin_config_get()
692 return -ENOTSUPP; in iproc_pin_config_get()
701 unsigned i, gpio = iproc_pin_to_gpio(pin); in iproc_pin_config_set() local
702 int ret = -ENOTSUPP; in iproc_pin_config_set()
708 return -ENOTSUPP; in iproc_pin_config_set()
714 ret = iproc_gpio_set_pull(chip, gpio, true, false); in iproc_pin_config_set()
720 ret = iproc_gpio_set_pull(chip, gpio, false, true); in iproc_pin_config_set()
726 ret = iproc_gpio_set_pull(chip, gpio, false, false); in iproc_pin_config_set()
732 ret = iproc_gpio_set_strength(chip, gpio, arg); in iproc_pin_config_set()
738 dev_err(chip->dev, "invalid configuration\n"); in iproc_pin_config_set()
739 return -ENOTSUPP; in iproc_pin_config_set()
754 * Iproc GPIO controller supports some PINCONF related configurations such as
755 * pull up, pull down, and drive strength, when the pin is configured to GPIO
757 * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
758 * local GPIO pins
762 struct pinctrl_desc *pctldesc = &chip->pctldesc; in iproc_gpio_register_pinconf()
764 struct gpio_chip *gc = &chip->gc; in iproc_gpio_register_pinconf()
767 pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL); in iproc_gpio_register_pinconf()
769 return -ENOMEM; in iproc_gpio_register_pinconf()
771 for (i = 0; i < gc->ngpio; i++) { in iproc_gpio_register_pinconf()
773 pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL, in iproc_gpio_register_pinconf()
774 "gpio-%d", i); in iproc_gpio_register_pinconf()
776 return -ENOMEM; in iproc_gpio_register_pinconf()
779 pctldesc->name = dev_name(chip->dev); in iproc_gpio_register_pinconf()
780 pctldesc->pctlops = &iproc_pctrl_ops; in iproc_gpio_register_pinconf()
781 pctldesc->pins = pins; in iproc_gpio_register_pinconf()
782 pctldesc->npins = gc->ngpio; in iproc_gpio_register_pinconf()
783 pctldesc->confops = &iproc_pconf_ops; in iproc_gpio_register_pinconf()
785 chip->pctl = devm_pinctrl_register(chip->dev, pctldesc, chip); in iproc_gpio_register_pinconf()
786 if (IS_ERR(chip->pctl)) { in iproc_gpio_register_pinconf()
787 dev_err(chip->dev, "unable to register pinctrl device\n"); in iproc_gpio_register_pinconf()
788 return PTR_ERR(chip->pctl); in iproc_gpio_register_pinconf()
795 { .compatible = "brcm,iproc-gpio" },
796 { .compatible = "brcm,cygnus-ccm-gpio" },
797 { .compatible = "brcm,cygnus-asiu-gpio" },
798 { .compatible = "brcm,cygnus-crmu-gpio" },
799 { .compatible = "brcm,iproc-nsp-gpio" },
800 { .compatible = "brcm,iproc-stingray-gpio" },
806 struct device *dev = &pdev->dev; in iproc_gpio_probe()
816 if (of_device_is_compatible(dev->of_node, "brcm,iproc-nsp-gpio")) in iproc_gpio_probe()
819 else if (of_device_is_compatible(dev->of_node, in iproc_gpio_probe()
820 "brcm,iproc-stingray-gpio")) in iproc_gpio_probe()
825 return -ENOMEM; in iproc_gpio_probe()
827 chip->dev = dev; in iproc_gpio_probe()
830 chip->base = devm_platform_ioremap_resource(pdev, 0); in iproc_gpio_probe()
831 if (IS_ERR(chip->base)) { in iproc_gpio_probe()
833 return PTR_ERR(chip->base); in iproc_gpio_probe()
838 chip->io_ctrl = devm_ioremap_resource(dev, res); in iproc_gpio_probe()
839 if (IS_ERR(chip->io_ctrl)) in iproc_gpio_probe()
840 return PTR_ERR(chip->io_ctrl); in iproc_gpio_probe()
841 if (of_device_is_compatible(dev->of_node, in iproc_gpio_probe()
842 "brcm,cygnus-ccm-gpio")) in iproc_gpio_probe()
848 chip->io_ctrl_type = io_ctrl_type; in iproc_gpio_probe()
850 if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) { in iproc_gpio_probe()
851 dev_err(&pdev->dev, "missing ngpios DT property\n"); in iproc_gpio_probe()
852 return -ENODEV; in iproc_gpio_probe()
855 raw_spin_lock_init(&chip->lock); in iproc_gpio_probe()
857 gc = &chip->gc; in iproc_gpio_probe()
858 gc->base = -1; in iproc_gpio_probe()
859 gc->ngpio = ngpios; in iproc_gpio_probe()
860 chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK; in iproc_gpio_probe()
861 gc->label = dev_name(dev); in iproc_gpio_probe()
862 gc->parent = dev; in iproc_gpio_probe()
863 gc->request = iproc_gpio_request; in iproc_gpio_probe()
864 gc->free = iproc_gpio_free; in iproc_gpio_probe()
865 gc->direction_input = iproc_gpio_direction_input; in iproc_gpio_probe()
866 gc->direction_output = iproc_gpio_direction_output; in iproc_gpio_probe()
867 gc->get_direction = iproc_gpio_get_direction; in iproc_gpio_probe()
868 gc->set = iproc_gpio_set; in iproc_gpio_probe()
869 gc->get = iproc_gpio_get; in iproc_gpio_probe()
871 chip->pinmux_is_supported = of_property_read_bool(dev->of_node, in iproc_gpio_probe()
872 "gpio-ranges"); in iproc_gpio_probe()
874 /* optional GPIO interrupt support */ in iproc_gpio_probe()
879 girq = &gc->irq; in iproc_gpio_probe()
881 girq->parent_handler = iproc_gpio_irq_handler; in iproc_gpio_probe()
882 girq->num_parents = 1; in iproc_gpio_probe()
883 girq->parents = devm_kcalloc(dev, 1, in iproc_gpio_probe()
884 sizeof(*girq->parents), in iproc_gpio_probe()
886 if (!girq->parents) in iproc_gpio_probe()
887 return -ENOMEM; in iproc_gpio_probe()
888 girq->parents[0] = irq; in iproc_gpio_probe()
889 girq->default_type = IRQ_TYPE_NONE; in iproc_gpio_probe()
890 girq->handler = handle_bad_irq; in iproc_gpio_probe()
895 return dev_err_probe(dev, ret, "unable to add GPIO chip\n"); in iproc_gpio_probe()
925 .name = "iproc-gpio",