irq.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2023 Cirrus Logic, Inc. and
  3. // Cirrus Logic International Semiconductor Ltd.
  4. #include <linux/device.h>
  5. #include <linux/fwnode.h>
  6. #include <linux/irq.h>
  7. #include <linux/irqdomain.h>
  8. #include <linux/soundwire/sdw.h>
  9. #include "irq.h"
  10. static int sdw_irq_map(struct irq_domain *h, unsigned int virq,
  11. irq_hw_number_t hw)
  12. {
  13. struct sdw_bus *bus = h->host_data;
  14. irq_set_chip_data(virq, bus);
  15. irq_set_chip(virq, &bus->irq_chip);
  16. irq_set_nested_thread(virq, 1);
  17. irq_set_noprobe(virq);
  18. return 0;
  19. }
  20. static const struct irq_domain_ops sdw_domain_ops = {
  21. .map = sdw_irq_map,
  22. };
  23. int sdw_irq_create(struct sdw_bus *bus,
  24. struct fwnode_handle *fwnode)
  25. {
  26. bus->irq_chip.name = dev_name(bus->dev);
  27. bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES,
  28. &sdw_domain_ops, bus);
  29. if (!bus->domain) {
  30. dev_err(bus->dev, "Failed to add IRQ domain\n");
  31. return -EINVAL;
  32. }
  33. return 0;
  34. }
  35. void sdw_irq_delete(struct sdw_bus *bus)
  36. {
  37. irq_domain_remove(bus->domain);
  38. }
  39. void sdw_irq_create_mapping(struct sdw_slave *slave)
  40. {
  41. slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num);
  42. if (!slave->irq)
  43. dev_warn(&slave->dev, "Failed to map IRQ\n");
  44. }
  45. void sdw_irq_dispose_mapping(struct sdw_slave *slave)
  46. {
  47. irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num));
  48. }