diff options
Diffstat (limited to 'drivers/spi/spi-pci1xxxx.c')
-rw-r--r-- | drivers/spi/spi-pci1xxxx.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index fc98979eba48..e27642c4dea4 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -685,6 +685,17 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) return pci1xxxx_spi_isr_io(irq, dev); } +static irqreturn_t pci1xxxx_spi_shared_isr(int irq, void *dev) +{ + struct pci1xxxx_spi *par = dev; + u8 i = 0; + + for (i = 0; i < par->total_hw_instances; i++) + pci1xxxx_spi_isr(irq, par->spi_int[i]); + + return IRQ_HANDLED; +} + static bool pci1xxxx_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) @@ -702,6 +713,7 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * struct device *dev = &pdev->dev; struct pci1xxxx_spi *spi_bus; struct spi_controller *spi_host; + int num_vector = 0; u32 regval; int ret; @@ -741,21 +753,19 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * if (ret) return -ENOMEM; - ret = pci_request_regions(pdev, DRV_NAME); + ret = pcim_request_all_regions(pdev, DRV_NAME); if (ret) return -ENOMEM; spi_bus->reg_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0)); - if (!spi_bus->reg_base) { - ret = -EINVAL; - goto error; - } + if (!spi_bus->reg_base) + return -EINVAL; - ret = pci_alloc_irq_vectors(pdev, hw_inst_cnt, hw_inst_cnt, - PCI_IRQ_ALL_TYPES); - if (ret < 0) { + num_vector = pci_alloc_irq_vectors(pdev, 1, hw_inst_cnt, + PCI_IRQ_INTX | PCI_IRQ_MSI); + if (num_vector < 0) { dev_err(&pdev->dev, "Error allocating MSI vectors\n"); - goto error; + return num_vector; } init_completion(&spi_sub_ptr->spi_xfer_done); @@ -767,19 +777,24 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * SPI_MST_EVENT_MASK_REG_OFFSET(spi_sub_ptr->hw_inst)); spi_sub_ptr->irq = pci_irq_vector(pdev, 0); - ret = devm_request_irq(&pdev->dev, spi_sub_ptr->irq, - pci1xxxx_spi_isr, PCI1XXXX_IRQ_FLAGS, - pci_name(pdev), spi_sub_ptr); + if (num_vector >= hw_inst_cnt) + ret = devm_request_irq(&pdev->dev, spi_sub_ptr->irq, + pci1xxxx_spi_isr, PCI1XXXX_IRQ_FLAGS, + pci_name(pdev), spi_sub_ptr); + else + ret = devm_request_irq(&pdev->dev, spi_sub_ptr->irq, + pci1xxxx_spi_shared_isr, + PCI1XXXX_IRQ_FLAGS | IRQF_SHARED, + pci_name(pdev), spi_bus); if (ret < 0) { dev_err(&pdev->dev, "Unable to request irq : %d", spi_sub_ptr->irq); - ret = -ENODEV; - goto error; + return -ENODEV; } ret = pci1xxxx_spi_dma_init(spi_bus, spi_sub_ptr->irq); if (ret && ret != -EOPNOTSUPP) - goto error; + return ret; /* This register is only applicable for 1st instance */ regval = readl(spi_bus->reg_base + SPI_PCI_CTRL_REG_OFFSET(0)); @@ -801,15 +816,16 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * regval &= ~SPI_INTR; writel(regval, spi_bus->reg_base + SPI_MST_EVENT_MASK_REG_OFFSET(spi_sub_ptr->hw_inst)); - spi_sub_ptr->irq = pci_irq_vector(pdev, iter); - ret = devm_request_irq(&pdev->dev, spi_sub_ptr->irq, - pci1xxxx_spi_isr, PCI1XXXX_IRQ_FLAGS, - pci_name(pdev), spi_sub_ptr); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to request irq : %d", - spi_sub_ptr->irq); - ret = -ENODEV; - goto error; + if (num_vector >= hw_inst_cnt) { + spi_sub_ptr->irq = pci_irq_vector(pdev, iter); + ret = devm_request_irq(&pdev->dev, spi_sub_ptr->irq, + pci1xxxx_spi_isr, PCI1XXXX_IRQ_FLAGS, + pci_name(pdev), spi_sub_ptr); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to request irq : %d", + spi_sub_ptr->irq); + return -ENODEV; + } } } @@ -828,15 +844,11 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * spi_controller_set_devdata(spi_host, spi_sub_ptr); ret = devm_spi_register_controller(dev, spi_host); if (ret) - goto error; + return ret; } pci_set_drvdata(pdev, spi_bus); return 0; - -error: - pci_release_regions(pdev); - return ret; } static void store_restore_config(struct pci1xxxx_spi *spi_ptr, |