.. | .. |
---|
9 | 9 | #include <linux/kernel.h> |
---|
10 | 10 | #include <linux/module.h> |
---|
11 | 11 | #include <linux/slab.h> |
---|
12 | | -#include <linux/gpio.h> |
---|
13 | 12 | #include <linux/irq.h> |
---|
14 | 13 | #include <linux/irqdomain.h> |
---|
| 14 | +#include <linux/gpio/driver.h> |
---|
15 | 15 | #include <linux/mutex.h> |
---|
| 16 | +#include <linux/greybus.h> |
---|
16 | 17 | |
---|
17 | | -#include "greybus.h" |
---|
18 | 18 | #include "gbphy.h" |
---|
19 | 19 | |
---|
20 | 20 | struct gb_gpio_line { |
---|
.. | .. |
---|
39 | 39 | |
---|
40 | 40 | struct gpio_chip chip; |
---|
41 | 41 | struct irq_chip irqc; |
---|
42 | | - struct irq_chip *irqchip; |
---|
43 | | - struct irq_domain *irqdomain; |
---|
44 | | - unsigned int irq_base; |
---|
45 | | - irq_flow_handler_t irq_handler; |
---|
46 | | - unsigned int irq_default_type; |
---|
47 | 42 | struct mutex irq_lock; |
---|
48 | 43 | }; |
---|
49 | 44 | #define gpio_chip_to_gb_gpio_controller(chip) \ |
---|
.. | .. |
---|
74 | 69 | |
---|
75 | 70 | request.which = which; |
---|
76 | 71 | ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, |
---|
77 | | - &request, sizeof(request), NULL, 0); |
---|
| 72 | + &request, sizeof(request), NULL, 0); |
---|
78 | 73 | if (ret) { |
---|
79 | 74 | gbphy_runtime_put_autosuspend(gbphy_dev); |
---|
80 | 75 | return ret; |
---|
.. | .. |
---|
86 | 81 | } |
---|
87 | 82 | |
---|
88 | 83 | static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, |
---|
89 | | - u8 which) |
---|
| 84 | + u8 which) |
---|
90 | 85 | { |
---|
91 | 86 | struct gbphy_device *gbphy_dev = ggc->gbphy_dev; |
---|
92 | 87 | struct device *dev = &gbphy_dev->dev; |
---|
.. | .. |
---|
95 | 90 | |
---|
96 | 91 | request.which = which; |
---|
97 | 92 | ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, |
---|
98 | | - &request, sizeof(request), NULL, 0); |
---|
| 93 | + &request, sizeof(request), NULL, 0); |
---|
99 | 94 | if (ret) { |
---|
100 | 95 | dev_err(dev, "failed to deactivate gpio %u\n", which); |
---|
101 | 96 | goto out_pm_put; |
---|
.. | .. |
---|
108 | 103 | } |
---|
109 | 104 | |
---|
110 | 105 | static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, |
---|
111 | | - u8 which) |
---|
| 106 | + u8 which) |
---|
112 | 107 | { |
---|
113 | 108 | struct device *dev = &ggc->gbphy_dev->dev; |
---|
114 | 109 | struct gb_gpio_get_direction_request request; |
---|
.. | .. |
---|
133 | 128 | } |
---|
134 | 129 | |
---|
135 | 130 | static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, |
---|
136 | | - u8 which) |
---|
| 131 | + u8 which) |
---|
137 | 132 | { |
---|
138 | 133 | struct gb_gpio_direction_in_request request; |
---|
139 | 134 | int ret; |
---|
.. | .. |
---|
147 | 142 | } |
---|
148 | 143 | |
---|
149 | 144 | static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, |
---|
150 | | - u8 which, bool value_high) |
---|
| 145 | + u8 which, bool value_high) |
---|
151 | 146 | { |
---|
152 | 147 | struct gb_gpio_direction_out_request request; |
---|
153 | 148 | int ret; |
---|
.. | .. |
---|
162 | 157 | } |
---|
163 | 158 | |
---|
164 | 159 | static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, |
---|
165 | | - u8 which) |
---|
| 160 | + u8 which) |
---|
166 | 161 | { |
---|
167 | 162 | struct device *dev = &ggc->gbphy_dev->dev; |
---|
168 | 163 | struct gb_gpio_get_value_request request; |
---|
.. | .. |
---|
214 | 209 | } |
---|
215 | 210 | |
---|
216 | 211 | static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, |
---|
217 | | - u8 which, u16 debounce_usec) |
---|
| 212 | + u8 which, u16 debounce_usec) |
---|
218 | 213 | { |
---|
219 | 214 | struct gb_gpio_set_debounce_request request; |
---|
220 | 215 | int ret; |
---|
.. | .. |
---|
257 | 252 | } |
---|
258 | 253 | |
---|
259 | 254 | static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, |
---|
260 | | - u8 hwirq, u8 type) |
---|
| 255 | + u8 hwirq, u8 type) |
---|
261 | 256 | { |
---|
262 | 257 | struct device *dev = &ggc->gbphy_dev->dev; |
---|
263 | 258 | struct gb_gpio_irq_type_request request; |
---|
.. | .. |
---|
369 | 364 | struct gb_message *request; |
---|
370 | 365 | struct gb_gpio_irq_event_request *event; |
---|
371 | 366 | u8 type = op->type; |
---|
372 | | - int irq; |
---|
373 | | - struct irq_desc *desc; |
---|
| 367 | + int irq, ret; |
---|
374 | 368 | |
---|
375 | 369 | if (type != GB_GPIO_TYPE_IRQ_EVENT) { |
---|
376 | 370 | dev_err(dev, "unsupported unsolicited request: %u\n", type); |
---|
.. | .. |
---|
391 | 385 | return -EINVAL; |
---|
392 | 386 | } |
---|
393 | 387 | |
---|
394 | | - irq = irq_find_mapping(ggc->irqdomain, event->which); |
---|
| 388 | + irq = irq_find_mapping(ggc->chip.irq.domain, event->which); |
---|
395 | 389 | if (!irq) { |
---|
396 | 390 | dev_err(dev, "failed to find IRQ\n"); |
---|
397 | 391 | return -EINVAL; |
---|
398 | 392 | } |
---|
399 | | - desc = irq_to_desc(irq); |
---|
400 | | - if (!desc) { |
---|
401 | | - dev_err(dev, "failed to look up irq\n"); |
---|
402 | | - return -EINVAL; |
---|
403 | | - } |
---|
404 | 393 | |
---|
405 | 394 | local_irq_disable(); |
---|
406 | | - generic_handle_irq_desc(desc); |
---|
| 395 | + ret = generic_handle_irq(irq); |
---|
407 | 396 | local_irq_enable(); |
---|
408 | 397 | |
---|
409 | | - return 0; |
---|
| 398 | + if (ret) |
---|
| 399 | + dev_err(dev, "failed to invoke irq handler\n"); |
---|
| 400 | + |
---|
| 401 | + return ret; |
---|
410 | 402 | } |
---|
411 | 403 | |
---|
412 | 404 | static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset) |
---|
.. | .. |
---|
506 | 498 | return ret; |
---|
507 | 499 | } |
---|
508 | 500 | |
---|
509 | | -/** |
---|
510 | | - * gb_gpio_irq_map() - maps an IRQ into a GB gpio irqchip |
---|
511 | | - * @d: the irqdomain used by this irqchip |
---|
512 | | - * @irq: the global irq number used by this GB gpio irqchip irq |
---|
513 | | - * @hwirq: the local IRQ/GPIO line offset on this GB gpio |
---|
514 | | - * |
---|
515 | | - * This function will set up the mapping for a certain IRQ line on a |
---|
516 | | - * GB gpio by assigning the GB gpio as chip data, and using the irqchip |
---|
517 | | - * stored inside the GB gpio. |
---|
518 | | - */ |
---|
519 | | -static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, |
---|
520 | | - irq_hw_number_t hwirq) |
---|
521 | | -{ |
---|
522 | | - struct gpio_chip *chip = domain->host_data; |
---|
523 | | - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); |
---|
524 | | - |
---|
525 | | - irq_set_chip_data(irq, ggc); |
---|
526 | | - irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler); |
---|
527 | | - irq_set_noprobe(irq); |
---|
528 | | - /* |
---|
529 | | - * No set-up of the hardware will happen if IRQ_TYPE_NONE |
---|
530 | | - * is passed as default type. |
---|
531 | | - */ |
---|
532 | | - if (ggc->irq_default_type != IRQ_TYPE_NONE) |
---|
533 | | - irq_set_irq_type(irq, ggc->irq_default_type); |
---|
534 | | - |
---|
535 | | - return 0; |
---|
536 | | -} |
---|
537 | | - |
---|
538 | | -static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) |
---|
539 | | -{ |
---|
540 | | - irq_set_chip_and_handler(irq, NULL, NULL); |
---|
541 | | - irq_set_chip_data(irq, NULL); |
---|
542 | | -} |
---|
543 | | - |
---|
544 | | -static const struct irq_domain_ops gb_gpio_domain_ops = { |
---|
545 | | - .map = gb_gpio_irq_map, |
---|
546 | | - .unmap = gb_gpio_irq_unmap, |
---|
547 | | -}; |
---|
548 | | - |
---|
549 | | -/** |
---|
550 | | - * gb_gpio_irqchip_remove() - removes an irqchip added to a gb_gpio_controller |
---|
551 | | - * @ggc: the gb_gpio_controller to remove the irqchip from |
---|
552 | | - * |
---|
553 | | - * This is called only from gb_gpio_remove() |
---|
554 | | - */ |
---|
555 | | -static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) |
---|
556 | | -{ |
---|
557 | | - unsigned int offset; |
---|
558 | | - |
---|
559 | | - /* Remove all IRQ mappings and delete the domain */ |
---|
560 | | - if (ggc->irqdomain) { |
---|
561 | | - for (offset = 0; offset < (ggc->line_max + 1); offset++) |
---|
562 | | - irq_dispose_mapping(irq_find_mapping(ggc->irqdomain, |
---|
563 | | - offset)); |
---|
564 | | - irq_domain_remove(ggc->irqdomain); |
---|
565 | | - } |
---|
566 | | - |
---|
567 | | - if (ggc->irqchip) |
---|
568 | | - ggc->irqchip = NULL; |
---|
569 | | -} |
---|
570 | | - |
---|
571 | | -/** |
---|
572 | | - * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip |
---|
573 | | - * @chip: the gpio chip to add the irqchip to |
---|
574 | | - * @irqchip: the irqchip to add to the adapter |
---|
575 | | - * @first_irq: if not dynamically assigned, the base (first) IRQ to |
---|
576 | | - * allocate gpio irqs from |
---|
577 | | - * @handler: the irq handler to use (often a predefined irq core function) |
---|
578 | | - * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE |
---|
579 | | - * to have the core avoid setting up any default type in the hardware. |
---|
580 | | - * |
---|
581 | | - * This function closely associates a certain irqchip with a certain |
---|
582 | | - * gpio chip, providing an irq domain to translate the local IRQs to |
---|
583 | | - * global irqs, and making sure that the gpio chip |
---|
584 | | - * is passed as chip data to all related functions. Driver callbacks |
---|
585 | | - * need to use container_of() to get their local state containers back |
---|
586 | | - * from the gpio chip passed as chip data. An irqdomain will be stored |
---|
587 | | - * in the gpio chip that shall be used by the driver to handle IRQ number |
---|
588 | | - * translation. The gpio chip will need to be initialized and registered |
---|
589 | | - * before calling this function. |
---|
590 | | - */ |
---|
591 | | -static int gb_gpio_irqchip_add(struct gpio_chip *chip, |
---|
592 | | - struct irq_chip *irqchip, |
---|
593 | | - unsigned int first_irq, |
---|
594 | | - irq_flow_handler_t handler, |
---|
595 | | - unsigned int type) |
---|
596 | | -{ |
---|
597 | | - struct gb_gpio_controller *ggc; |
---|
598 | | - unsigned int offset; |
---|
599 | | - unsigned int irq_base; |
---|
600 | | - |
---|
601 | | - if (!chip || !irqchip) |
---|
602 | | - return -EINVAL; |
---|
603 | | - |
---|
604 | | - ggc = gpio_chip_to_gb_gpio_controller(chip); |
---|
605 | | - |
---|
606 | | - ggc->irqchip = irqchip; |
---|
607 | | - ggc->irq_handler = handler; |
---|
608 | | - ggc->irq_default_type = type; |
---|
609 | | - ggc->irqdomain = irq_domain_add_simple(NULL, |
---|
610 | | - ggc->line_max + 1, first_irq, |
---|
611 | | - &gb_gpio_domain_ops, chip); |
---|
612 | | - if (!ggc->irqdomain) { |
---|
613 | | - ggc->irqchip = NULL; |
---|
614 | | - return -EINVAL; |
---|
615 | | - } |
---|
616 | | - |
---|
617 | | - /* |
---|
618 | | - * Prepare the mapping since the irqchip shall be orthogonal to |
---|
619 | | - * any gpio calls. If the first_irq was zero, this is |
---|
620 | | - * necessary to allocate descriptors for all IRQs. |
---|
621 | | - */ |
---|
622 | | - for (offset = 0; offset < (ggc->line_max + 1); offset++) { |
---|
623 | | - irq_base = irq_create_mapping(ggc->irqdomain, offset); |
---|
624 | | - if (offset == 0) |
---|
625 | | - ggc->irq_base = irq_base; |
---|
626 | | - } |
---|
627 | | - |
---|
628 | | - return 0; |
---|
629 | | -} |
---|
630 | | - |
---|
631 | | -static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) |
---|
632 | | -{ |
---|
633 | | - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); |
---|
634 | | - |
---|
635 | | - return irq_find_mapping(ggc->irqdomain, offset); |
---|
636 | | -} |
---|
637 | | - |
---|
638 | 501 | static int gb_gpio_probe(struct gbphy_device *gbphy_dev, |
---|
639 | 502 | const struct gbphy_device_id *id) |
---|
640 | 503 | { |
---|
641 | 504 | struct gb_connection *connection; |
---|
642 | 505 | struct gb_gpio_controller *ggc; |
---|
643 | 506 | struct gpio_chip *gpio; |
---|
| 507 | + struct gpio_irq_chip *girq; |
---|
644 | 508 | struct irq_chip *irqc; |
---|
645 | 509 | int ret; |
---|
646 | 510 | |
---|
.. | .. |
---|
648 | 512 | if (!ggc) |
---|
649 | 513 | return -ENOMEM; |
---|
650 | 514 | |
---|
651 | | - connection = gb_connection_create(gbphy_dev->bundle, |
---|
652 | | - le16_to_cpu(gbphy_dev->cport_desc->id), |
---|
653 | | - gb_gpio_request_handler); |
---|
| 515 | + connection = |
---|
| 516 | + gb_connection_create(gbphy_dev->bundle, |
---|
| 517 | + le16_to_cpu(gbphy_dev->cport_desc->id), |
---|
| 518 | + gb_gpio_request_handler); |
---|
654 | 519 | if (IS_ERR(connection)) { |
---|
655 | 520 | ret = PTR_ERR(connection); |
---|
656 | 521 | goto exit_ggc_free; |
---|
.. | .. |
---|
693 | 558 | gpio->get = gb_gpio_get; |
---|
694 | 559 | gpio->set = gb_gpio_set; |
---|
695 | 560 | gpio->set_config = gb_gpio_set_config; |
---|
696 | | - gpio->to_irq = gb_gpio_to_irq; |
---|
697 | 561 | gpio->base = -1; /* Allocate base dynamically */ |
---|
698 | 562 | gpio->ngpio = ggc->line_max + 1; |
---|
699 | 563 | gpio->can_sleep = true; |
---|
| 564 | + |
---|
| 565 | + girq = &gpio->irq; |
---|
| 566 | + girq->chip = irqc; |
---|
| 567 | + /* The event comes from the outside so no parent handler */ |
---|
| 568 | + girq->parent_handler = NULL; |
---|
| 569 | + girq->num_parents = 0; |
---|
| 570 | + girq->parents = NULL; |
---|
| 571 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 572 | + girq->handler = handle_level_irq; |
---|
700 | 573 | |
---|
701 | 574 | ret = gb_connection_enable(connection); |
---|
702 | 575 | if (ret) |
---|
703 | 576 | goto exit_line_free; |
---|
704 | 577 | |
---|
705 | | - ret = gb_gpio_irqchip_add(gpio, irqc, 0, |
---|
706 | | - handle_level_irq, IRQ_TYPE_NONE); |
---|
707 | | - if (ret) { |
---|
708 | | - dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret); |
---|
709 | | - goto exit_line_free; |
---|
710 | | - } |
---|
711 | | - |
---|
712 | 578 | ret = gpiochip_add(gpio); |
---|
713 | 579 | if (ret) { |
---|
714 | 580 | dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret); |
---|
715 | | - goto exit_gpio_irqchip_remove; |
---|
| 581 | + goto exit_line_free; |
---|
716 | 582 | } |
---|
717 | 583 | |
---|
718 | 584 | gbphy_runtime_put_autosuspend(gbphy_dev); |
---|
719 | 585 | return 0; |
---|
720 | 586 | |
---|
721 | | -exit_gpio_irqchip_remove: |
---|
722 | | - gb_gpio_irqchip_remove(ggc); |
---|
723 | 587 | exit_line_free: |
---|
724 | 588 | kfree(ggc->lines); |
---|
725 | 589 | exit_connection_disable: |
---|
.. | .. |
---|
743 | 607 | |
---|
744 | 608 | gb_connection_disable_rx(connection); |
---|
745 | 609 | gpiochip_remove(&ggc->chip); |
---|
746 | | - gb_gpio_irqchip_remove(ggc); |
---|
747 | 610 | gb_connection_disable(connection); |
---|
748 | 611 | gb_connection_destroy(connection); |
---|
749 | 612 | kfree(ggc->lines); |
---|