Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2015-2018 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/siox.h>
0008 #include <linux/gpio/driver.h>
0009 #include <linux/of.h>
0010 
0011 struct gpio_siox_ddata {
0012     struct gpio_chip gchip;
0013     struct irq_chip ichip;
0014     struct mutex lock;
0015     u8 setdata[1];
0016     u8 getdata[3];
0017 
0018     raw_spinlock_t irqlock;
0019     u32 irq_enable;
0020     u32 irq_status;
0021     u32 irq_type[20];
0022 };
0023 
0024 /*
0025  * Note that this callback only sets the value that is clocked out in the next
0026  * cycle.
0027  */
0028 static int gpio_siox_set_data(struct siox_device *sdevice, u8 status, u8 buf[])
0029 {
0030     struct gpio_siox_ddata *ddata = dev_get_drvdata(&sdevice->dev);
0031 
0032     mutex_lock(&ddata->lock);
0033     buf[0] = ddata->setdata[0];
0034     mutex_unlock(&ddata->lock);
0035 
0036     return 0;
0037 }
0038 
0039 static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[])
0040 {
0041     struct gpio_siox_ddata *ddata = dev_get_drvdata(&sdevice->dev);
0042     size_t offset;
0043     u32 trigger;
0044 
0045     mutex_lock(&ddata->lock);
0046 
0047     raw_spin_lock_irq(&ddata->irqlock);
0048 
0049     for (offset = 0; offset < 12; ++offset) {
0050         unsigned int bitpos = 11 - offset;
0051         unsigned int gpiolevel = buf[bitpos / 8] & (1 << bitpos % 8);
0052         unsigned int prev_level =
0053             ddata->getdata[bitpos / 8] & (1 << (bitpos % 8));
0054         u32 irq_type = ddata->irq_type[offset];
0055 
0056         if (gpiolevel) {
0057             if ((irq_type & IRQ_TYPE_LEVEL_HIGH) ||
0058                 ((irq_type & IRQ_TYPE_EDGE_RISING) && !prev_level))
0059                 ddata->irq_status |= 1 << offset;
0060         } else {
0061             if ((irq_type & IRQ_TYPE_LEVEL_LOW) ||
0062                 ((irq_type & IRQ_TYPE_EDGE_FALLING) && prev_level))
0063                 ddata->irq_status |= 1 << offset;
0064         }
0065     }
0066 
0067     trigger = ddata->irq_status & ddata->irq_enable;
0068 
0069     raw_spin_unlock_irq(&ddata->irqlock);
0070 
0071     ddata->getdata[0] = buf[0];
0072     ddata->getdata[1] = buf[1];
0073     ddata->getdata[2] = buf[2];
0074 
0075     mutex_unlock(&ddata->lock);
0076 
0077     for (offset = 0; offset < 12; ++offset) {
0078         if (trigger & (1 << offset)) {
0079             struct irq_domain *irqdomain = ddata->gchip.irq.domain;
0080             unsigned int irq = irq_find_mapping(irqdomain, offset);
0081 
0082             /*
0083              * Conceptually handle_nested_irq should call the flow
0084              * handler of the irq chip. But it doesn't, so we have
0085              * to clean the irq_status here.
0086              */
0087             raw_spin_lock_irq(&ddata->irqlock);
0088             ddata->irq_status &= ~(1 << offset);
0089             raw_spin_unlock_irq(&ddata->irqlock);
0090 
0091             handle_nested_irq(irq);
0092         }
0093     }
0094 
0095     return 0;
0096 }
0097 
0098 static void gpio_siox_irq_ack(struct irq_data *d)
0099 {
0100     struct irq_chip *ic = irq_data_get_irq_chip(d);
0101     struct gpio_siox_ddata *ddata =
0102         container_of(ic, struct gpio_siox_ddata, ichip);
0103 
0104     raw_spin_lock(&ddata->irqlock);
0105     ddata->irq_status &= ~(1 << d->hwirq);
0106     raw_spin_unlock(&ddata->irqlock);
0107 }
0108 
0109 static void gpio_siox_irq_mask(struct irq_data *d)
0110 {
0111     struct irq_chip *ic = irq_data_get_irq_chip(d);
0112     struct gpio_siox_ddata *ddata =
0113         container_of(ic, struct gpio_siox_ddata, ichip);
0114 
0115     raw_spin_lock(&ddata->irqlock);
0116     ddata->irq_enable &= ~(1 << d->hwirq);
0117     raw_spin_unlock(&ddata->irqlock);
0118 }
0119 
0120 static void gpio_siox_irq_unmask(struct irq_data *d)
0121 {
0122     struct irq_chip *ic = irq_data_get_irq_chip(d);
0123     struct gpio_siox_ddata *ddata =
0124         container_of(ic, struct gpio_siox_ddata, ichip);
0125 
0126     raw_spin_lock(&ddata->irqlock);
0127     ddata->irq_enable |= 1 << d->hwirq;
0128     raw_spin_unlock(&ddata->irqlock);
0129 }
0130 
0131 static int gpio_siox_irq_set_type(struct irq_data *d, u32 type)
0132 {
0133     struct irq_chip *ic = irq_data_get_irq_chip(d);
0134     struct gpio_siox_ddata *ddata =
0135         container_of(ic, struct gpio_siox_ddata, ichip);
0136 
0137     raw_spin_lock(&ddata->irqlock);
0138     ddata->irq_type[d->hwirq] = type;
0139     raw_spin_unlock(&ddata->irqlock);
0140 
0141     return 0;
0142 }
0143 
0144 static int gpio_siox_get(struct gpio_chip *chip, unsigned int offset)
0145 {
0146     struct gpio_siox_ddata *ddata =
0147         container_of(chip, struct gpio_siox_ddata, gchip);
0148     int ret;
0149 
0150     mutex_lock(&ddata->lock);
0151 
0152     if (offset >= 12) {
0153         unsigned int bitpos = 19 - offset;
0154 
0155         ret = ddata->setdata[0] & (1 << bitpos);
0156     } else {
0157         unsigned int bitpos = 11 - offset;
0158 
0159         ret = ddata->getdata[bitpos / 8] & (1 << (bitpos % 8));
0160     }
0161 
0162     mutex_unlock(&ddata->lock);
0163 
0164     return ret;
0165 }
0166 
0167 static void gpio_siox_set(struct gpio_chip *chip,
0168               unsigned int offset, int value)
0169 {
0170     struct gpio_siox_ddata *ddata =
0171         container_of(chip, struct gpio_siox_ddata, gchip);
0172     u8 mask = 1 << (19 - offset);
0173 
0174     mutex_lock(&ddata->lock);
0175 
0176     if (value)
0177         ddata->setdata[0] |= mask;
0178     else
0179         ddata->setdata[0] &= ~mask;
0180 
0181     mutex_unlock(&ddata->lock);
0182 }
0183 
0184 static int gpio_siox_direction_input(struct gpio_chip *chip,
0185                      unsigned int offset)
0186 {
0187     if (offset >= 12)
0188         return -EINVAL;
0189 
0190     return 0;
0191 }
0192 
0193 static int gpio_siox_direction_output(struct gpio_chip *chip,
0194                       unsigned int offset, int value)
0195 {
0196     if (offset < 12)
0197         return -EINVAL;
0198 
0199     gpio_siox_set(chip, offset, value);
0200     return 0;
0201 }
0202 
0203 static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset)
0204 {
0205     if (offset < 12)
0206         return GPIO_LINE_DIRECTION_IN;
0207     else
0208         return GPIO_LINE_DIRECTION_OUT;
0209 }
0210 
0211 static int gpio_siox_probe(struct siox_device *sdevice)
0212 {
0213     struct gpio_siox_ddata *ddata;
0214     struct gpio_irq_chip *girq;
0215     struct device *dev = &sdevice->dev;
0216     int ret;
0217 
0218     ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
0219     if (!ddata)
0220         return -ENOMEM;
0221 
0222     dev_set_drvdata(dev, ddata);
0223 
0224     mutex_init(&ddata->lock);
0225     raw_spin_lock_init(&ddata->irqlock);
0226 
0227     ddata->gchip.base = -1;
0228     ddata->gchip.can_sleep = 1;
0229     ddata->gchip.parent = dev;
0230     ddata->gchip.owner = THIS_MODULE;
0231     ddata->gchip.get = gpio_siox_get;
0232     ddata->gchip.set = gpio_siox_set;
0233     ddata->gchip.direction_input = gpio_siox_direction_input;
0234     ddata->gchip.direction_output = gpio_siox_direction_output;
0235     ddata->gchip.get_direction = gpio_siox_get_direction;
0236     ddata->gchip.ngpio = 20;
0237 
0238     ddata->ichip.name = "siox-gpio";
0239     ddata->ichip.irq_ack = gpio_siox_irq_ack;
0240     ddata->ichip.irq_mask = gpio_siox_irq_mask;
0241     ddata->ichip.irq_unmask = gpio_siox_irq_unmask;
0242     ddata->ichip.irq_set_type = gpio_siox_irq_set_type;
0243 
0244     girq = &ddata->gchip.irq;
0245     girq->chip = &ddata->ichip;
0246     girq->default_type = IRQ_TYPE_NONE;
0247     girq->handler = handle_level_irq;
0248     girq->threaded = true;
0249 
0250     ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
0251     if (ret)
0252         dev_err(dev, "Failed to register gpio chip (%d)\n", ret);
0253 
0254     return ret;
0255 }
0256 
0257 static struct siox_driver gpio_siox_driver = {
0258     .probe = gpio_siox_probe,
0259     .set_data = gpio_siox_set_data,
0260     .get_data = gpio_siox_get_data,
0261     .driver = {
0262         .name = "gpio-siox",
0263     },
0264 };
0265 module_siox_driver(gpio_siox_driver);
0266 
0267 MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
0268 MODULE_DESCRIPTION("SIOX gpio driver");
0269 MODULE_LICENSE("GPL v2");