Lines Matching +full:irq +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Userspace I/O platform driver with generic IRQ handling code.
9 * Based on uio_pdrv.c by Uwe Kleine-Koenig,
23 #include <linux/irq.h>
45 struct uio_pdrv_genirq_platdata *priv = info->priv; in uio_pdrv_genirq_open()
47 /* Wait until the Runtime PM code has woken up the device */ in uio_pdrv_genirq_open()
48 pm_runtime_get_sync(&priv->pdev->dev); in uio_pdrv_genirq_open()
54 struct uio_pdrv_genirq_platdata *priv = info->priv; in uio_pdrv_genirq_release()
56 /* Tell the Runtime PM code that the device has become idle */ in uio_pdrv_genirq_release()
57 pm_runtime_put_sync(&priv->pdev->dev); in uio_pdrv_genirq_release()
61 static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info) in uio_pdrv_genirq_handler() argument
63 struct uio_pdrv_genirq_platdata *priv = dev_info->priv; in uio_pdrv_genirq_handler()
69 spin_lock(&priv->lock); in uio_pdrv_genirq_handler()
70 if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags)) in uio_pdrv_genirq_handler()
71 disable_irq_nosync(irq); in uio_pdrv_genirq_handler()
72 spin_unlock(&priv->lock); in uio_pdrv_genirq_handler()
79 struct uio_pdrv_genirq_platdata *priv = dev_info->priv; in uio_pdrv_genirq_irqcontrol()
84 * state to prevent per-irq depth damage. in uio_pdrv_genirq_irqcontrol()
87 * with irq handler on SMP systems. in uio_pdrv_genirq_irqcontrol()
90 spin_lock_irqsave(&priv->lock, flags); in uio_pdrv_genirq_irqcontrol()
92 if (__test_and_clear_bit(UIO_IRQ_DISABLED, &priv->flags)) in uio_pdrv_genirq_irqcontrol()
93 enable_irq(dev_info->irq); in uio_pdrv_genirq_irqcontrol()
95 if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags)) in uio_pdrv_genirq_irqcontrol()
96 disable_irq_nosync(dev_info->irq); in uio_pdrv_genirq_irqcontrol()
98 spin_unlock_irqrestore(&priv->lock, flags); in uio_pdrv_genirq_irqcontrol()
105 struct device *dev = data; in uio_pdrv_genirq_cleanup()
112 struct uio_info *uioinfo = dev_get_platdata(&pdev->dev); in uio_pdrv_genirq_probe()
113 struct fwnode_handle *node = dev_fwnode(&pdev->dev); in uio_pdrv_genirq_probe()
116 int ret = -EINVAL; in uio_pdrv_genirq_probe()
122 /* alloc uioinfo for one device */ in uio_pdrv_genirq_probe()
123 uioinfo = devm_kzalloc(&pdev->dev, sizeof(*uioinfo), in uio_pdrv_genirq_probe()
126 dev_err(&pdev->dev, "unable to kmalloc\n"); in uio_pdrv_genirq_probe()
127 return -ENOMEM; in uio_pdrv_genirq_probe()
130 if (!device_property_read_string(&pdev->dev, "linux,uio-name", &name)) in uio_pdrv_genirq_probe()
131 uioinfo->name = devm_kstrdup(&pdev->dev, name, GFP_KERNEL); in uio_pdrv_genirq_probe()
133 uioinfo->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, in uio_pdrv_genirq_probe()
136 uioinfo->version = "devicetree"; in uio_pdrv_genirq_probe()
140 if (!uioinfo || !uioinfo->name || !uioinfo->version) { in uio_pdrv_genirq_probe()
141 dev_err(&pdev->dev, "missing platform_data\n"); in uio_pdrv_genirq_probe()
145 if (uioinfo->handler || uioinfo->irqcontrol || in uio_pdrv_genirq_probe()
146 uioinfo->irq_flags & IRQF_SHARED) { in uio_pdrv_genirq_probe()
147 dev_err(&pdev->dev, "interrupt configuration error\n"); in uio_pdrv_genirq_probe()
151 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in uio_pdrv_genirq_probe()
153 dev_err(&pdev->dev, "unable to kmalloc\n"); in uio_pdrv_genirq_probe()
154 return -ENOMEM; in uio_pdrv_genirq_probe()
157 priv->uioinfo = uioinfo; in uio_pdrv_genirq_probe()
158 spin_lock_init(&priv->lock); in uio_pdrv_genirq_probe()
159 priv->flags = 0; /* interrupt is enabled to begin with */ in uio_pdrv_genirq_probe()
160 priv->pdev = pdev; in uio_pdrv_genirq_probe()
162 if (!uioinfo->irq) { in uio_pdrv_genirq_probe()
164 uioinfo->irq = ret; in uio_pdrv_genirq_probe()
165 if (ret == -ENXIO) in uio_pdrv_genirq_probe()
166 uioinfo->irq = UIO_IRQ_NONE; in uio_pdrv_genirq_probe()
167 else if (ret == -EPROBE_DEFER) in uio_pdrv_genirq_probe()
170 dev_err(&pdev->dev, "failed to get IRQ\n"); in uio_pdrv_genirq_probe()
175 if (uioinfo->irq) { in uio_pdrv_genirq_probe()
176 struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq); in uio_pdrv_genirq_probe()
180 * irq will fire again since clearing of the actual cause, on in uio_pdrv_genirq_probe()
181 * device level, is done in userspace in uio_pdrv_genirq_probe()
183 * irq is configured. in uio_pdrv_genirq_probe()
187 dev_dbg(&pdev->dev, "disable lazy unmask\n"); in uio_pdrv_genirq_probe()
188 irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY); in uio_pdrv_genirq_probe()
192 uiomem = &uioinfo->mem[0]; in uio_pdrv_genirq_probe()
194 for (i = 0; i < pdev->num_resources; ++i) { in uio_pdrv_genirq_probe()
195 struct resource *r = &pdev->resource[i]; in uio_pdrv_genirq_probe()
197 if (r->flags != IORESOURCE_MEM) in uio_pdrv_genirq_probe()
200 if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { in uio_pdrv_genirq_probe()
201 dev_warn(&pdev->dev, "device has more than " in uio_pdrv_genirq_probe()
207 uiomem->memtype = UIO_MEM_PHYS; in uio_pdrv_genirq_probe()
208 uiomem->addr = r->start & PAGE_MASK; in uio_pdrv_genirq_probe()
209 uiomem->offs = r->start & ~PAGE_MASK; in uio_pdrv_genirq_probe()
210 uiomem->size = (uiomem->offs + resource_size(r) in uio_pdrv_genirq_probe()
211 + PAGE_SIZE - 1) & PAGE_MASK; in uio_pdrv_genirq_probe()
212 uiomem->name = r->name; in uio_pdrv_genirq_probe()
216 while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { in uio_pdrv_genirq_probe()
217 uiomem->size = 0; in uio_pdrv_genirq_probe()
224 * for performing hardware specific acknowledge and re-enabling of in uio_pdrv_genirq_probe()
230 uioinfo->handler = uio_pdrv_genirq_handler; in uio_pdrv_genirq_probe()
231 uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; in uio_pdrv_genirq_probe()
232 uioinfo->open = uio_pdrv_genirq_open; in uio_pdrv_genirq_probe()
233 uioinfo->release = uio_pdrv_genirq_release; in uio_pdrv_genirq_probe()
234 uioinfo->priv = priv; in uio_pdrv_genirq_probe()
236 /* Enable Runtime PM for this device: in uio_pdrv_genirq_probe()
237 * The device starts in suspended state to allow the hardware to be in uio_pdrv_genirq_probe()
241 pm_runtime_enable(&pdev->dev); in uio_pdrv_genirq_probe()
243 ret = devm_add_action_or_reset(&pdev->dev, uio_pdrv_genirq_cleanup, in uio_pdrv_genirq_probe()
244 &pdev->dev); in uio_pdrv_genirq_probe()
248 ret = devm_uio_register_device(&pdev->dev, priv->uioinfo); in uio_pdrv_genirq_probe()
250 dev_err(&pdev->dev, "unable to register uio device\n"); in uio_pdrv_genirq_probe()
255 static int uio_pdrv_genirq_runtime_nop(struct device *dev) in uio_pdrv_genirq_runtime_nop()
257 /* Runtime PM callback shared between ->runtime_suspend() in uio_pdrv_genirq_runtime_nop()
258 * and ->runtime_resume(). Simply returns success. in uio_pdrv_genirq_runtime_nop()
262 * Runtime PM code to turn off power to the device while the in uio_pdrv_genirq_runtime_nop()
263 * device is unused, ie before open() and after release(). in uio_pdrv_genirq_runtime_nop()
284 MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio");
299 MODULE_DESCRIPTION("Userspace I/O platform driver with generic IRQ handling");