iosm_ipc_irq.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2020-21 Intel Corporation.
  4. */
  5. #include "iosm_ipc_pcie.h"
  6. #include "iosm_ipc_protocol.h"
  7. static void ipc_write_dbell_reg(struct iosm_pcie *ipc_pcie, int irq_n, u32 data)
  8. {
  9. void __iomem *write_reg;
  10. /* Select the first doorbell register, which is only currently needed
  11. * by CP.
  12. */
  13. write_reg = (void __iomem *)((u8 __iomem *)ipc_pcie->ipc_regs +
  14. ipc_pcie->doorbell_write +
  15. (irq_n * ipc_pcie->doorbell_reg_offset));
  16. /* Fire the doorbell irq by writing data on the doorbell write pointer
  17. * register.
  18. */
  19. iowrite32(data, write_reg);
  20. }
  21. void ipc_doorbell_fire(struct iosm_pcie *ipc_pcie, int irq_n, u32 data)
  22. {
  23. ipc_write_dbell_reg(ipc_pcie, irq_n, data);
  24. }
  25. /* Threaded Interrupt handler for MSI interrupts */
  26. static irqreturn_t ipc_msi_interrupt(int irq, void *dev_id)
  27. {
  28. struct iosm_pcie *ipc_pcie = dev_id;
  29. int instance = irq - ipc_pcie->pci->irq;
  30. /* Shift the MSI irq actions to the IPC tasklet. IRQ_NONE means the
  31. * irq was not from the IPC device or could not be served.
  32. */
  33. if (instance >= ipc_pcie->nvec)
  34. return IRQ_NONE;
  35. if (!test_bit(0, &ipc_pcie->suspend))
  36. ipc_imem_irq_process(ipc_pcie->imem, instance);
  37. return IRQ_HANDLED;
  38. }
  39. void ipc_release_irq(struct iosm_pcie *ipc_pcie)
  40. {
  41. struct pci_dev *pdev = ipc_pcie->pci;
  42. if (pdev->msi_enabled) {
  43. while (--ipc_pcie->nvec >= 0)
  44. free_irq(pdev->irq + ipc_pcie->nvec, ipc_pcie);
  45. }
  46. pci_free_irq_vectors(pdev);
  47. }
  48. int ipc_acquire_irq(struct iosm_pcie *ipc_pcie)
  49. {
  50. struct pci_dev *pdev = ipc_pcie->pci;
  51. int i, rc = -EINVAL;
  52. ipc_pcie->nvec = pci_alloc_irq_vectors(pdev, IPC_MSI_VECTORS,
  53. IPC_MSI_VECTORS, PCI_IRQ_MSI);
  54. if (ipc_pcie->nvec < 0) {
  55. rc = ipc_pcie->nvec;
  56. goto error;
  57. }
  58. if (!pdev->msi_enabled)
  59. goto error;
  60. for (i = 0; i < ipc_pcie->nvec; ++i) {
  61. rc = request_threaded_irq(pdev->irq + i, NULL,
  62. ipc_msi_interrupt, IRQF_ONESHOT,
  63. KBUILD_MODNAME, ipc_pcie);
  64. if (rc) {
  65. dev_err(ipc_pcie->dev, "unable to grab IRQ, rc=%d", rc);
  66. ipc_pcie->nvec = i;
  67. ipc_release_irq(ipc_pcie);
  68. goto error;
  69. }
  70. }
  71. error:
  72. return rc;
  73. }