.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2008, 2009 Provigent Ltd. |
---|
3 | 4 | * |
---|
4 | 5 | * Author: Baruch Siach <baruch@tkos.co.il> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | 6 | * |
---|
10 | 7 | * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061) |
---|
11 | 8 | * |
---|
.. | .. |
---|
19 | 16 | #include <linux/interrupt.h> |
---|
20 | 17 | #include <linux/irq.h> |
---|
21 | 18 | #include <linux/irqchip/chained_irq.h> |
---|
| 19 | +#include <linux/module.h> |
---|
22 | 20 | #include <linux/bitops.h> |
---|
23 | 21 | #include <linux/gpio/driver.h> |
---|
24 | 22 | #include <linux/device.h> |
---|
.. | .. |
---|
66 | 64 | { |
---|
67 | 65 | struct pl061 *pl061 = gpiochip_get_data(gc); |
---|
68 | 66 | |
---|
69 | | - return !(readb(pl061->base + GPIODIR) & BIT(offset)); |
---|
| 67 | + if (readb(pl061->base + GPIODIR) & BIT(offset)) |
---|
| 68 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 69 | + |
---|
| 70 | + return GPIO_LINE_DIRECTION_IN; |
---|
70 | 71 | } |
---|
71 | 72 | |
---|
72 | 73 | static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) |
---|
.. | .. |
---|
286 | 287 | { |
---|
287 | 288 | struct device *dev = &adev->dev; |
---|
288 | 289 | struct pl061 *pl061; |
---|
| 290 | + struct gpio_irq_chip *girq; |
---|
289 | 291 | int ret, irq; |
---|
290 | 292 | |
---|
291 | 293 | pl061 = devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL); |
---|
.. | .. |
---|
297 | 299 | return PTR_ERR(pl061->base); |
---|
298 | 300 | |
---|
299 | 301 | raw_spin_lock_init(&pl061->lock); |
---|
300 | | - if (of_property_read_bool(dev->of_node, "gpio-ranges")) { |
---|
301 | | - pl061->gc.request = gpiochip_generic_request; |
---|
302 | | - pl061->gc.free = gpiochip_generic_free; |
---|
303 | | - } |
---|
304 | | - |
---|
| 302 | + pl061->gc.request = gpiochip_generic_request; |
---|
| 303 | + pl061->gc.free = gpiochip_generic_free; |
---|
305 | 304 | pl061->gc.base = -1; |
---|
306 | 305 | pl061->gc.get_direction = pl061_get_direction; |
---|
307 | 306 | pl061->gc.direction_input = pl061_direction_input; |
---|
.. | .. |
---|
312 | 311 | pl061->gc.label = dev_name(dev); |
---|
313 | 312 | pl061->gc.parent = dev; |
---|
314 | 313 | pl061->gc.owner = THIS_MODULE; |
---|
315 | | - |
---|
316 | | - ret = gpiochip_add_data(&pl061->gc, pl061); |
---|
317 | | - if (ret) |
---|
318 | | - return ret; |
---|
319 | 314 | |
---|
320 | 315 | /* |
---|
321 | 316 | * irq_chip support |
---|
.. | .. |
---|
329 | 324 | |
---|
330 | 325 | writeb(0, pl061->base + GPIOIE); /* disable irqs */ |
---|
331 | 326 | irq = adev->irq[0]; |
---|
332 | | - if (irq < 0) { |
---|
333 | | - dev_err(&adev->dev, "invalid IRQ\n"); |
---|
334 | | - return -ENODEV; |
---|
335 | | - } |
---|
| 327 | + if (!irq) |
---|
| 328 | + dev_warn(&adev->dev, "IRQ support disabled\n"); |
---|
336 | 329 | pl061->parent_irq = irq; |
---|
337 | 330 | |
---|
338 | | - ret = gpiochip_irqchip_add(&pl061->gc, &pl061->irq_chip, |
---|
339 | | - 0, handle_bad_irq, |
---|
340 | | - IRQ_TYPE_NONE); |
---|
341 | | - if (ret) { |
---|
342 | | - dev_info(&adev->dev, "could not add irqchip\n"); |
---|
| 331 | + girq = &pl061->gc.irq; |
---|
| 332 | + girq->chip = &pl061->irq_chip; |
---|
| 333 | + girq->parent_handler = pl061_irq_handler; |
---|
| 334 | + girq->num_parents = 1; |
---|
| 335 | + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), |
---|
| 336 | + GFP_KERNEL); |
---|
| 337 | + if (!girq->parents) |
---|
| 338 | + return -ENOMEM; |
---|
| 339 | + girq->parents[0] = irq; |
---|
| 340 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 341 | + girq->handler = handle_bad_irq; |
---|
| 342 | + |
---|
| 343 | + ret = devm_gpiochip_add_data(dev, &pl061->gc, pl061); |
---|
| 344 | + if (ret) |
---|
343 | 345 | return ret; |
---|
344 | | - } |
---|
345 | | - gpiochip_set_chained_irqchip(&pl061->gc, &pl061->irq_chip, |
---|
346 | | - irq, pl061_irq_handler); |
---|
347 | 346 | |
---|
348 | 347 | amba_set_drvdata(adev, pl061); |
---|
349 | | - dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n", |
---|
350 | | - &adev->res.start); |
---|
| 348 | + dev_info(dev, "PL061 GPIO chip registered\n"); |
---|
351 | 349 | |
---|
352 | 350 | return 0; |
---|
353 | 351 | } |
---|
.. | .. |
---|
411 | 409 | }, |
---|
412 | 410 | { 0, 0 }, |
---|
413 | 411 | }; |
---|
| 412 | +MODULE_DEVICE_TABLE(amba, pl061_ids); |
---|
414 | 413 | |
---|
415 | 414 | static struct amba_driver pl061_gpio_driver = { |
---|
416 | 415 | .drv = { |
---|
.. | .. |
---|
422 | 421 | .id_table = pl061_ids, |
---|
423 | 422 | .probe = pl061_probe, |
---|
424 | 423 | }; |
---|
| 424 | +module_amba_driver(pl061_gpio_driver); |
---|
425 | 425 | |
---|
426 | | -static int __init pl061_gpio_init(void) |
---|
427 | | -{ |
---|
428 | | - return amba_driver_register(&pl061_gpio_driver); |
---|
429 | | -} |
---|
430 | | -device_initcall(pl061_gpio_init); |
---|
| 426 | +MODULE_LICENSE("GPL v2"); |
---|