Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2013 Altera Corporation
0004  * Based on gpio-mpc8xxx.c
0005  */
0006 
0007 #include <linux/io.h>
0008 #include <linux/module.h>
0009 #include <linux/gpio/driver.h>
0010 #include <linux/of_gpio.h> /* For of_mm_gpio_chip */
0011 #include <linux/platform_device.h>
0012 
0013 #define ALTERA_GPIO_MAX_NGPIO       32
0014 #define ALTERA_GPIO_DATA        0x0
0015 #define ALTERA_GPIO_DIR         0x4
0016 #define ALTERA_GPIO_IRQ_MASK        0x8
0017 #define ALTERA_GPIO_EDGE_CAP        0xc
0018 
0019 /**
0020 * struct altera_gpio_chip
0021 * @mmchip       : memory mapped chip structure.
0022 * @gpio_lock        : synchronization lock so that new irq/set/get requests
0023 *             will be blocked until the current one completes.
0024 * @interrupt_trigger    : specifies the hardware configured IRQ trigger type
0025 *             (rising, falling, both, high)
0026 * @mapped_irq       : kernel mapped irq number.
0027 * @irq_chip     : IRQ chip configuration
0028 */
0029 struct altera_gpio_chip {
0030     struct of_mm_gpio_chip mmchip;
0031     raw_spinlock_t gpio_lock;
0032     int interrupt_trigger;
0033     int mapped_irq;
0034     struct irq_chip irq_chip;
0035 };
0036 
0037 static void altera_gpio_irq_unmask(struct irq_data *d)
0038 {
0039     struct altera_gpio_chip *altera_gc;
0040     struct of_mm_gpio_chip *mm_gc;
0041     unsigned long flags;
0042     u32 intmask;
0043 
0044     altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
0045     mm_gc = &altera_gc->mmchip;
0046 
0047     raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
0048     intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
0049     /* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
0050     intmask |= BIT(irqd_to_hwirq(d));
0051     writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
0052     raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
0053 }
0054 
0055 static void altera_gpio_irq_mask(struct irq_data *d)
0056 {
0057     struct altera_gpio_chip *altera_gc;
0058     struct of_mm_gpio_chip *mm_gc;
0059     unsigned long flags;
0060     u32 intmask;
0061 
0062     altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
0063     mm_gc = &altera_gc->mmchip;
0064 
0065     raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
0066     intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
0067     /* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
0068     intmask &= ~BIT(irqd_to_hwirq(d));
0069     writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
0070     raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
0071 }
0072 
0073 /*
0074  * This controller's IRQ type is synthesized in hardware, so this function
0075  * just checks if the requested set_type matches the synthesized IRQ type
0076  */
0077 static int altera_gpio_irq_set_type(struct irq_data *d,
0078                    unsigned int type)
0079 {
0080     struct altera_gpio_chip *altera_gc;
0081 
0082     altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
0083 
0084     if (type == IRQ_TYPE_NONE) {
0085         irq_set_handler_locked(d, handle_bad_irq);
0086         return 0;
0087     }
0088     if (type == altera_gc->interrupt_trigger) {
0089         if (type == IRQ_TYPE_LEVEL_HIGH)
0090             irq_set_handler_locked(d, handle_level_irq);
0091         else
0092             irq_set_handler_locked(d, handle_simple_irq);
0093         return 0;
0094     }
0095     irq_set_handler_locked(d, handle_bad_irq);
0096     return -EINVAL;
0097 }
0098 
0099 static unsigned int altera_gpio_irq_startup(struct irq_data *d)
0100 {
0101     altera_gpio_irq_unmask(d);
0102 
0103     return 0;
0104 }
0105 
0106 static int altera_gpio_get(struct gpio_chip *gc, unsigned offset)
0107 {
0108     struct of_mm_gpio_chip *mm_gc;
0109 
0110     mm_gc = to_of_mm_gpio_chip(gc);
0111 
0112     return !!(readl(mm_gc->regs + ALTERA_GPIO_DATA) & BIT(offset));
0113 }
0114 
0115 static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
0116 {
0117     struct of_mm_gpio_chip *mm_gc;
0118     struct altera_gpio_chip *chip;
0119     unsigned long flags;
0120     unsigned int data_reg;
0121 
0122     mm_gc = to_of_mm_gpio_chip(gc);
0123     chip = gpiochip_get_data(gc);
0124 
0125     raw_spin_lock_irqsave(&chip->gpio_lock, flags);
0126     data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
0127     if (value)
0128         data_reg |= BIT(offset);
0129     else
0130         data_reg &= ~BIT(offset);
0131     writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
0132     raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
0133 }
0134 
0135 static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
0136 {
0137     struct of_mm_gpio_chip *mm_gc;
0138     struct altera_gpio_chip *chip;
0139     unsigned long flags;
0140     unsigned int gpio_ddr;
0141 
0142     mm_gc = to_of_mm_gpio_chip(gc);
0143     chip = gpiochip_get_data(gc);
0144 
0145     raw_spin_lock_irqsave(&chip->gpio_lock, flags);
0146     /* Set pin as input, assumes software controlled IP */
0147     gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
0148     gpio_ddr &= ~BIT(offset);
0149     writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
0150     raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
0151 
0152     return 0;
0153 }
0154 
0155 static int altera_gpio_direction_output(struct gpio_chip *gc,
0156         unsigned offset, int value)
0157 {
0158     struct of_mm_gpio_chip *mm_gc;
0159     struct altera_gpio_chip *chip;
0160     unsigned long flags;
0161     unsigned int data_reg, gpio_ddr;
0162 
0163     mm_gc = to_of_mm_gpio_chip(gc);
0164     chip = gpiochip_get_data(gc);
0165 
0166     raw_spin_lock_irqsave(&chip->gpio_lock, flags);
0167     /* Sets the GPIO value */
0168     data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
0169     if (value)
0170         data_reg |= BIT(offset);
0171     else
0172         data_reg &= ~BIT(offset);
0173     writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
0174 
0175     /* Set pin as output, assumes software controlled IP */
0176     gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
0177     gpio_ddr |= BIT(offset);
0178     writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
0179     raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
0180 
0181     return 0;
0182 }
0183 
0184 static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
0185 {
0186     struct altera_gpio_chip *altera_gc;
0187     struct irq_chip *chip;
0188     struct of_mm_gpio_chip *mm_gc;
0189     struct irq_domain *irqdomain;
0190     unsigned long status;
0191     int i;
0192 
0193     altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
0194     chip = irq_desc_get_chip(desc);
0195     mm_gc = &altera_gc->mmchip;
0196     irqdomain = altera_gc->mmchip.gc.irq.domain;
0197 
0198     chained_irq_enter(chip, desc);
0199 
0200     while ((status =
0201           (readl(mm_gc->regs + ALTERA_GPIO_EDGE_CAP) &
0202           readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
0203         writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP);
0204         for_each_set_bit(i, &status, mm_gc->gc.ngpio)
0205             generic_handle_domain_irq(irqdomain, i);
0206     }
0207 
0208     chained_irq_exit(chip, desc);
0209 }
0210 
0211 static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
0212 {
0213     struct altera_gpio_chip *altera_gc;
0214     struct irq_chip *chip;
0215     struct of_mm_gpio_chip *mm_gc;
0216     struct irq_domain *irqdomain;
0217     unsigned long status;
0218     int i;
0219 
0220     altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
0221     chip = irq_desc_get_chip(desc);
0222     mm_gc = &altera_gc->mmchip;
0223     irqdomain = altera_gc->mmchip.gc.irq.domain;
0224 
0225     chained_irq_enter(chip, desc);
0226 
0227     status = readl(mm_gc->regs + ALTERA_GPIO_DATA);
0228     status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
0229 
0230     for_each_set_bit(i, &status, mm_gc->gc.ngpio)
0231         generic_handle_domain_irq(irqdomain, i);
0232 
0233     chained_irq_exit(chip, desc);
0234 }
0235 
0236 static int altera_gpio_probe(struct platform_device *pdev)
0237 {
0238     struct device_node *node = pdev->dev.of_node;
0239     int reg, ret;
0240     struct altera_gpio_chip *altera_gc;
0241     struct gpio_irq_chip *girq;
0242 
0243     altera_gc = devm_kzalloc(&pdev->dev, sizeof(*altera_gc), GFP_KERNEL);
0244     if (!altera_gc)
0245         return -ENOMEM;
0246 
0247     raw_spin_lock_init(&altera_gc->gpio_lock);
0248 
0249     if (of_property_read_u32(node, "altr,ngpio", &reg))
0250         /* By default assume maximum ngpio */
0251         altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
0252     else
0253         altera_gc->mmchip.gc.ngpio = reg;
0254 
0255     if (altera_gc->mmchip.gc.ngpio > ALTERA_GPIO_MAX_NGPIO) {
0256         dev_warn(&pdev->dev,
0257             "ngpio is greater than %d, defaulting to %d\n",
0258             ALTERA_GPIO_MAX_NGPIO, ALTERA_GPIO_MAX_NGPIO);
0259         altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
0260     }
0261 
0262     altera_gc->mmchip.gc.direction_input    = altera_gpio_direction_input;
0263     altera_gc->mmchip.gc.direction_output   = altera_gpio_direction_output;
0264     altera_gc->mmchip.gc.get        = altera_gpio_get;
0265     altera_gc->mmchip.gc.set        = altera_gpio_set;
0266     altera_gc->mmchip.gc.owner      = THIS_MODULE;
0267     altera_gc->mmchip.gc.parent     = &pdev->dev;
0268 
0269     altera_gc->mapped_irq = platform_get_irq_optional(pdev, 0);
0270 
0271     if (altera_gc->mapped_irq < 0)
0272         goto skip_irq;
0273 
0274     if (of_property_read_u32(node, "altr,interrupt-type", &reg)) {
0275         dev_err(&pdev->dev,
0276             "altr,interrupt-type value not set in device tree\n");
0277         return -EINVAL;
0278     }
0279     altera_gc->interrupt_trigger = reg;
0280 
0281     altera_gc->irq_chip.name = "altera-gpio";
0282     altera_gc->irq_chip.irq_mask     = altera_gpio_irq_mask;
0283     altera_gc->irq_chip.irq_unmask   = altera_gpio_irq_unmask;
0284     altera_gc->irq_chip.irq_set_type = altera_gpio_irq_set_type;
0285     altera_gc->irq_chip.irq_startup  = altera_gpio_irq_startup;
0286     altera_gc->irq_chip.irq_shutdown = altera_gpio_irq_mask;
0287 
0288     girq = &altera_gc->mmchip.gc.irq;
0289     girq->chip = &altera_gc->irq_chip;
0290     if (altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH)
0291         girq->parent_handler = altera_gpio_irq_leveL_high_handler;
0292     else
0293         girq->parent_handler = altera_gpio_irq_edge_handler;
0294     girq->num_parents = 1;
0295     girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents),
0296                      GFP_KERNEL);
0297     if (!girq->parents)
0298         return -ENOMEM;
0299     girq->default_type = IRQ_TYPE_NONE;
0300     girq->handler = handle_bad_irq;
0301     girq->parents[0] = altera_gc->mapped_irq;
0302 
0303 skip_irq:
0304     ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc);
0305     if (ret) {
0306         dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
0307         return ret;
0308     }
0309 
0310     platform_set_drvdata(pdev, altera_gc);
0311 
0312     return 0;
0313 }
0314 
0315 static int altera_gpio_remove(struct platform_device *pdev)
0316 {
0317     struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev);
0318 
0319     of_mm_gpiochip_remove(&altera_gc->mmchip);
0320 
0321     return 0;
0322 }
0323 
0324 static const struct of_device_id altera_gpio_of_match[] = {
0325     { .compatible = "altr,pio-1.0", },
0326     {},
0327 };
0328 MODULE_DEVICE_TABLE(of, altera_gpio_of_match);
0329 
0330 static struct platform_driver altera_gpio_driver = {
0331     .driver = {
0332         .name   = "altera_gpio",
0333         .of_match_table = of_match_ptr(altera_gpio_of_match),
0334     },
0335     .probe      = altera_gpio_probe,
0336     .remove     = altera_gpio_remove,
0337 };
0338 
0339 static int __init altera_gpio_init(void)
0340 {
0341     return platform_driver_register(&altera_gpio_driver);
0342 }
0343 subsys_initcall(altera_gpio_init);
0344 
0345 static void __exit altera_gpio_exit(void)
0346 {
0347     platform_driver_unregister(&altera_gpio_driver);
0348 }
0349 module_exit(altera_gpio_exit);
0350 
0351 MODULE_AUTHOR("Tien Hock Loh <thloh@altera.com>");
0352 MODULE_DESCRIPTION("Altera GPIO driver");
0353 MODULE_LICENSE("GPL");