Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // MXS GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
0004 // Copyright 2008 Juergen Beisert, kernel@pengutronix.de
0005 //
0006 // Based on code from Freescale,
0007 // Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
0008 
0009 #include <linux/err.h>
0010 #include <linux/init.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/irq.h>
0014 #include <linux/irqdomain.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 #include <linux/gpio/driver.h>
0021 #include <linux/module.h>
0022 
0023 #define MXS_SET     0x4
0024 #define MXS_CLR     0x8
0025 
0026 #define PINCTRL_DOUT(p)     ((is_imx23_gpio(p) ? 0x0500 : 0x0700) + (p->id) * 0x10)
0027 #define PINCTRL_DIN(p)      ((is_imx23_gpio(p) ? 0x0600 : 0x0900) + (p->id) * 0x10)
0028 #define PINCTRL_DOE(p)      ((is_imx23_gpio(p) ? 0x0700 : 0x0b00) + (p->id) * 0x10)
0029 #define PINCTRL_PIN2IRQ(p)  ((is_imx23_gpio(p) ? 0x0800 : 0x1000) + (p->id) * 0x10)
0030 #define PINCTRL_IRQEN(p)    ((is_imx23_gpio(p) ? 0x0900 : 0x1100) + (p->id) * 0x10)
0031 #define PINCTRL_IRQLEV(p)   ((is_imx23_gpio(p) ? 0x0a00 : 0x1200) + (p->id) * 0x10)
0032 #define PINCTRL_IRQPOL(p)   ((is_imx23_gpio(p) ? 0x0b00 : 0x1300) + (p->id) * 0x10)
0033 #define PINCTRL_IRQSTAT(p)  ((is_imx23_gpio(p) ? 0x0c00 : 0x1400) + (p->id) * 0x10)
0034 
0035 #define GPIO_INT_FALL_EDGE  0x0
0036 #define GPIO_INT_LOW_LEV    0x1
0037 #define GPIO_INT_RISE_EDGE  0x2
0038 #define GPIO_INT_HIGH_LEV   0x3
0039 #define GPIO_INT_LEV_MASK   (1 << 0)
0040 #define GPIO_INT_POL_MASK   (1 << 1)
0041 
0042 enum mxs_gpio_id {
0043     IMX23_GPIO,
0044     IMX28_GPIO,
0045 };
0046 
0047 struct mxs_gpio_port {
0048     void __iomem *base;
0049     int id;
0050     int irq;
0051     struct irq_domain *domain;
0052     struct gpio_chip gc;
0053     struct device *dev;
0054     enum mxs_gpio_id devid;
0055     u32 both_edges;
0056 };
0057 
0058 static inline int is_imx23_gpio(struct mxs_gpio_port *port)
0059 {
0060     return port->devid == IMX23_GPIO;
0061 }
0062 
0063 /* Note: This driver assumes 32 GPIOs are handled in one register */
0064 
0065 static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
0066 {
0067     u32 val;
0068     u32 pin_mask = 1 << d->hwirq;
0069     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0070     struct irq_chip_type *ct = irq_data_get_chip_type(d);
0071     struct mxs_gpio_port *port = gc->private;
0072     void __iomem *pin_addr;
0073     int edge;
0074 
0075     if (!(ct->type & type))
0076         if (irq_setup_alt_chip(d, type))
0077             return -EINVAL;
0078 
0079     port->both_edges &= ~pin_mask;
0080     switch (type) {
0081     case IRQ_TYPE_EDGE_BOTH:
0082         val = readl(port->base + PINCTRL_DIN(port)) & pin_mask;
0083         if (val)
0084             edge = GPIO_INT_FALL_EDGE;
0085         else
0086             edge = GPIO_INT_RISE_EDGE;
0087         port->both_edges |= pin_mask;
0088         break;
0089     case IRQ_TYPE_EDGE_RISING:
0090         edge = GPIO_INT_RISE_EDGE;
0091         break;
0092     case IRQ_TYPE_EDGE_FALLING:
0093         edge = GPIO_INT_FALL_EDGE;
0094         break;
0095     case IRQ_TYPE_LEVEL_LOW:
0096         edge = GPIO_INT_LOW_LEV;
0097         break;
0098     case IRQ_TYPE_LEVEL_HIGH:
0099         edge = GPIO_INT_HIGH_LEV;
0100         break;
0101     default:
0102         return -EINVAL;
0103     }
0104 
0105     /* set level or edge */
0106     pin_addr = port->base + PINCTRL_IRQLEV(port);
0107     if (edge & GPIO_INT_LEV_MASK) {
0108         writel(pin_mask, pin_addr + MXS_SET);
0109         writel(pin_mask, port->base + PINCTRL_IRQEN(port) + MXS_SET);
0110     } else {
0111         writel(pin_mask, pin_addr + MXS_CLR);
0112         writel(pin_mask, port->base + PINCTRL_PIN2IRQ(port) + MXS_SET);
0113     }
0114 
0115     /* set polarity */
0116     pin_addr = port->base + PINCTRL_IRQPOL(port);
0117     if (edge & GPIO_INT_POL_MASK)
0118         writel(pin_mask, pin_addr + MXS_SET);
0119     else
0120         writel(pin_mask, pin_addr + MXS_CLR);
0121 
0122     writel(pin_mask, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
0123 
0124     return 0;
0125 }
0126 
0127 static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
0128 {
0129     u32 bit, val, edge;
0130     void __iomem *pin_addr;
0131 
0132     bit = 1 << gpio;
0133 
0134     pin_addr = port->base + PINCTRL_IRQPOL(port);
0135     val = readl(pin_addr);
0136     edge = val & bit;
0137 
0138     if (edge)
0139         writel(bit, pin_addr + MXS_CLR);
0140     else
0141         writel(bit, pin_addr + MXS_SET);
0142 }
0143 
0144 /* MXS has one interrupt *per* gpio port */
0145 static void mxs_gpio_irq_handler(struct irq_desc *desc)
0146 {
0147     u32 irq_stat;
0148     struct mxs_gpio_port *port = irq_desc_get_handler_data(desc);
0149 
0150     desc->irq_data.chip->irq_ack(&desc->irq_data);
0151 
0152     irq_stat = readl(port->base + PINCTRL_IRQSTAT(port)) &
0153             readl(port->base + PINCTRL_IRQEN(port));
0154 
0155     while (irq_stat != 0) {
0156         int irqoffset = fls(irq_stat) - 1;
0157         if (port->both_edges & (1 << irqoffset))
0158             mxs_flip_edge(port, irqoffset);
0159 
0160         generic_handle_domain_irq(port->domain, irqoffset);
0161         irq_stat &= ~(1 << irqoffset);
0162     }
0163 }
0164 
0165 /*
0166  * Set interrupt number "irq" in the GPIO as a wake-up source.
0167  * While system is running, all registered GPIO interrupts need to have
0168  * wake-up enabled. When system is suspended, only selected GPIO interrupts
0169  * need to have wake-up enabled.
0170  * @param  irq          interrupt source number
0171  * @param  enable       enable as wake-up if equal to non-zero
0172  * @return       This function returns 0 on success.
0173  */
0174 static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
0175 {
0176     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0177     struct mxs_gpio_port *port = gc->private;
0178 
0179     if (enable)
0180         enable_irq_wake(port->irq);
0181     else
0182         disable_irq_wake(port->irq);
0183 
0184     return 0;
0185 }
0186 
0187 static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
0188 {
0189     struct irq_chip_generic *gc;
0190     struct irq_chip_type *ct;
0191     int rv;
0192 
0193     gc = devm_irq_alloc_generic_chip(port->dev, "gpio-mxs", 2, irq_base,
0194                      port->base, handle_level_irq);
0195     if (!gc)
0196         return -ENOMEM;
0197 
0198     gc->private = port;
0199 
0200     ct = &gc->chip_types[0];
0201     ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
0202     ct->chip.irq_ack = irq_gc_ack_set_bit;
0203     ct->chip.irq_mask = irq_gc_mask_disable_reg;
0204     ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
0205     ct->chip.irq_set_type = mxs_gpio_set_irq_type;
0206     ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
0207     ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
0208     ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
0209     ct->regs.enable = PINCTRL_PIN2IRQ(port) + MXS_SET;
0210     ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
0211 
0212     ct = &gc->chip_types[1];
0213     ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
0214     ct->chip.irq_ack = irq_gc_ack_set_bit;
0215     ct->chip.irq_mask = irq_gc_mask_disable_reg;
0216     ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
0217     ct->chip.irq_set_type = mxs_gpio_set_irq_type;
0218     ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
0219     ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
0220     ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
0221     ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET;
0222     ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR;
0223     ct->handler = handle_level_irq;
0224 
0225     rv = devm_irq_setup_generic_chip(port->dev, gc, IRQ_MSK(32),
0226                      IRQ_GC_INIT_NESTED_LOCK,
0227                      IRQ_NOREQUEST, 0);
0228 
0229     return rv;
0230 }
0231 
0232 static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
0233 {
0234     struct mxs_gpio_port *port = gpiochip_get_data(gc);
0235 
0236     return irq_find_mapping(port->domain, offset);
0237 }
0238 
0239 static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
0240 {
0241     struct mxs_gpio_port *port = gpiochip_get_data(gc);
0242     u32 mask = 1 << offset;
0243     u32 dir;
0244 
0245     dir = readl(port->base + PINCTRL_DOE(port));
0246     if (dir & mask)
0247         return GPIO_LINE_DIRECTION_OUT;
0248 
0249     return GPIO_LINE_DIRECTION_IN;
0250 }
0251 
0252 static const struct of_device_id mxs_gpio_dt_ids[] = {
0253     { .compatible = "fsl,imx23-gpio", .data = (void *) IMX23_GPIO, },
0254     { .compatible = "fsl,imx28-gpio", .data = (void *) IMX28_GPIO, },
0255     { /* sentinel */ }
0256 };
0257 MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
0258 
0259 static int mxs_gpio_probe(struct platform_device *pdev)
0260 {
0261     struct device_node *np = pdev->dev.of_node;
0262     struct device_node *parent;
0263     static void __iomem *base;
0264     struct mxs_gpio_port *port;
0265     int irq_base;
0266     int err;
0267 
0268     port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
0269     if (!port)
0270         return -ENOMEM;
0271 
0272     port->id = of_alias_get_id(np, "gpio");
0273     if (port->id < 0)
0274         return port->id;
0275     port->devid = (enum mxs_gpio_id)of_device_get_match_data(&pdev->dev);
0276     port->dev = &pdev->dev;
0277     port->irq = platform_get_irq(pdev, 0);
0278     if (port->irq < 0)
0279         return port->irq;
0280 
0281     /*
0282      * map memory region only once, as all the gpio ports
0283      * share the same one
0284      */
0285     if (!base) {
0286         parent = of_get_parent(np);
0287         base = of_iomap(parent, 0);
0288         of_node_put(parent);
0289         if (!base)
0290             return -EADDRNOTAVAIL;
0291     }
0292     port->base = base;
0293 
0294     /* initially disable the interrupts */
0295     writel(0, port->base + PINCTRL_PIN2IRQ(port));
0296     writel(0, port->base + PINCTRL_IRQEN(port));
0297 
0298     /* clear address has to be used to clear IRQSTAT bits */
0299     writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
0300 
0301     irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
0302     if (irq_base < 0) {
0303         err = irq_base;
0304         goto out_iounmap;
0305     }
0306 
0307     port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
0308                          &irq_domain_simple_ops, NULL);
0309     if (!port->domain) {
0310         err = -ENODEV;
0311         goto out_iounmap;
0312     }
0313 
0314     /* gpio-mxs can be a generic irq chip */
0315     err = mxs_gpio_init_gc(port, irq_base);
0316     if (err < 0)
0317         goto out_irqdomain_remove;
0318 
0319     /* setup one handler for each entry */
0320     irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
0321                      port);
0322 
0323     err = bgpio_init(&port->gc, &pdev->dev, 4,
0324              port->base + PINCTRL_DIN(port),
0325              port->base + PINCTRL_DOUT(port) + MXS_SET,
0326              port->base + PINCTRL_DOUT(port) + MXS_CLR,
0327              port->base + PINCTRL_DOE(port), NULL, 0);
0328     if (err)
0329         goto out_irqdomain_remove;
0330 
0331     port->gc.to_irq = mxs_gpio_to_irq;
0332     port->gc.get_direction = mxs_gpio_get_direction;
0333     port->gc.base = port->id * 32;
0334 
0335     err = gpiochip_add_data(&port->gc, port);
0336     if (err)
0337         goto out_irqdomain_remove;
0338 
0339     return 0;
0340 
0341 out_irqdomain_remove:
0342     irq_domain_remove(port->domain);
0343 out_iounmap:
0344     iounmap(port->base);
0345     return err;
0346 }
0347 
0348 static struct platform_driver mxs_gpio_driver = {
0349     .driver     = {
0350         .name   = "gpio-mxs",
0351         .of_match_table = mxs_gpio_dt_ids,
0352         .suppress_bind_attrs = true,
0353     },
0354     .probe      = mxs_gpio_probe,
0355 };
0356 
0357 static int __init mxs_gpio_init(void)
0358 {
0359     return platform_driver_register(&mxs_gpio_driver);
0360 }
0361 postcore_initcall(mxs_gpio_init);
0362 
0363 MODULE_AUTHOR("Freescale Semiconductor, "
0364           "Daniel Mack <danielncaiaq.de>, "
0365           "Juergen Beisert <kernel@pengutronix.de>");
0366 MODULE_DESCRIPTION("Freescale MXS GPIO");
0367 MODULE_LICENSE("GPL");