gsi.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * ACPI GSI IRQ layer
  3. *
  4. * Copyright (C) 2015 ARM Ltd.
  5. * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/acpi.h>
  12. #include <linux/irq.h>
  13. #include <linux/irqdomain.h>
  14. #include <linux/of.h>
  15. enum acpi_irq_model_id acpi_irq_model;
  16. static struct fwnode_handle *acpi_gsi_domain_id;
  17. /**
  18. * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
  19. * @gsi: GSI IRQ number to map
  20. * @irq: pointer where linux IRQ number is stored
  21. *
  22. * irq location updated with irq value [>0 on success, 0 on failure]
  23. *
  24. * Returns: linux IRQ number on success (>0)
  25. * -EINVAL on failure
  26. */
  27. int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
  28. {
  29. struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
  30. DOMAIN_BUS_ANY);
  31. *irq = irq_find_mapping(d, gsi);
  32. /*
  33. * *irq == 0 means no mapping, that should
  34. * be reported as a failure
  35. */
  36. return (*irq > 0) ? *irq : -EINVAL;
  37. }
  38. EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
  39. /**
  40. * acpi_register_gsi() - Map a GSI to a linux IRQ number
  41. * @dev: device for which IRQ has to be mapped
  42. * @gsi: GSI IRQ number
  43. * @trigger: trigger type of the GSI number to be mapped
  44. * @polarity: polarity of the GSI to be mapped
  45. *
  46. * Returns: a valid linux IRQ number on success
  47. * -EINVAL on failure
  48. */
  49. int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
  50. int polarity)
  51. {
  52. struct irq_fwspec fwspec;
  53. if (WARN_ON(!acpi_gsi_domain_id)) {
  54. pr_warn("GSI: No registered irqchip, giving up\n");
  55. return -EINVAL;
  56. }
  57. fwspec.fwnode = acpi_gsi_domain_id;
  58. fwspec.param[0] = gsi;
  59. fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
  60. fwspec.param_count = 2;
  61. return irq_create_fwspec_mapping(&fwspec);
  62. }
  63. EXPORT_SYMBOL_GPL(acpi_register_gsi);
  64. /**
  65. * acpi_unregister_gsi() - Free a GSI<->linux IRQ number mapping
  66. * @gsi: GSI IRQ number
  67. */
  68. void acpi_unregister_gsi(u32 gsi)
  69. {
  70. struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
  71. DOMAIN_BUS_ANY);
  72. int irq = irq_find_mapping(d, gsi);
  73. irq_dispose_mapping(irq);
  74. }
  75. EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
  76. /**
  77. * acpi_set_irq_model - Setup the GSI irqdomain information
  78. * @model: the value assigned to acpi_irq_model
  79. * @fwnode: the irq_domain identifier for mapping and looking up
  80. * GSI interrupts
  81. */
  82. void __init acpi_set_irq_model(enum acpi_irq_model_id model,
  83. struct fwnode_handle *fwnode)
  84. {
  85. acpi_irq_model = model;
  86. acpi_gsi_domain_id = fwnode;
  87. }