aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/mt7621-pci/pci-mt7621.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/mt7621-pci/pci-mt7621.c')
-rw-r--r--drivers/staging/mt7621-pci/pci-mt7621.c64
1 files changed, 54 insertions, 10 deletions
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index f58e3a51fc71..f961b353c22e 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -55,7 +55,7 @@
#define RALINK_PCI_IOBASE 0x002C
/* PCICFG virtual bridges */
-#define PCIE_P2P_MAX 3
+#define PCIE_P2P_CNT 3
#define PCIE_P2P_BR_DEVNUM_SHIFT(p) (16 + (p) * 4)
#define PCIE_P2P_BR_DEVNUM0_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(0)
#define PCIE_P2P_BR_DEVNUM1_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(1)
@@ -97,6 +97,7 @@
* @pcie_rst: pointer to port reset control
* @gpio_rst: gpio reset
* @slot: port slot
+ * @irq: GIC irq
* @enabled: indicates if port is enabled
*/
struct mt7621_pcie_port {
@@ -107,6 +108,7 @@ struct mt7621_pcie_port {
struct reset_control *pcie_rst;
struct gpio_desc *gpio_rst;
u32 slot;
+ int irq;
bool enabled;
};
@@ -120,6 +122,7 @@ struct mt7621_pcie_port {
* @dev: Pointer to PCIe device
* @io_map_base: virtual memory base address for io
* @ports: pointer to PCIe port information
+ * @irq_map: irq mapping info according pcie link status
* @resets_inverted: depends on chip revision
* reset lines are inverted.
*/
@@ -135,6 +138,7 @@ struct mt7621_pcie {
} offset;
unsigned long io_map_base;
struct list_head ports;
+ int irq_map[PCIE_P2P_CNT];
bool resets_inverted;
};
@@ -279,6 +283,16 @@ static void setup_cm_memory_region(struct mt7621_pcie *pcie)
}
}
+static int mt7621_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ struct mt7621_pcie *pcie = pdev->bus->sysdata;
+ struct device *dev = pcie->dev;
+ int irq = pcie->irq_map[slot];
+
+ dev_info(dev, "bus=%d slot=%d irq=%d\n", pdev->bus->number, slot, irq);
+ return irq;
+}
+
static int mt7621_pci_parse_request_of_pci_ranges(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
@@ -330,6 +344,7 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
{
struct mt7621_pcie_port *port;
struct device *dev = pcie->dev;
+ struct platform_device *pdev = to_platform_device(dev);
struct device_node *pnode = dev->of_node;
struct resource regs;
char name[10];
@@ -371,6 +386,12 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
port->slot = slot;
port->pcie = pcie;
+ port->irq = platform_get_irq(pdev, slot);
+ if (port->irq < 0) {
+ dev_err(dev, "Failed to get IRQ for PCIe%d\n", slot);
+ return -ENXIO;
+ }
+
INIT_LIST_HEAD(&port->list);
list_add_tail(&port->list, &pcie->ports);
@@ -502,17 +523,25 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
mt7621_pcie_reset_ep_deassert(pcie);
+ tmp = NULL;
list_for_each_entry(port, &pcie->ports, list) {
u32 slot = port->slot;
if (!mt7621_pcie_port_is_linkup(port)) {
dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n",
slot);
- if (slot != 1)
- phy_power_off(port->phy);
mt7621_control_assert(port);
mt7621_pcie_port_clk_disable(port);
port->enabled = false;
+
+ if (slot == 0) {
+ tmp = port;
+ continue;
+ }
+
+ if (slot == 1 && tmp && !tmp->enabled)
+ phy_power_off(tmp->phy);
+
}
}
}
@@ -576,14 +605,16 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
{
u32 pcie_link_status = 0;
- u32 n;
- int i;
- u32 p2p_br_devnum[PCIE_P2P_MAX];
+ u32 n = 0;
+ int i = 0;
+ u32 p2p_br_devnum[PCIE_P2P_CNT];
+ int irqs[PCIE_P2P_CNT];
struct mt7621_pcie_port *port;
list_for_each_entry(port, &pcie->ports, list) {
u32 slot = port->slot;
+ irqs[i++] = port->irq;
if (port->enabled)
pcie_link_status |= BIT(slot);
}
@@ -591,12 +622,16 @@ static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
if (pcie_link_status == 0)
return -1;
- n = 0;
- for (i = 0; i < PCIE_P2P_MAX; i++)
+ /*
+ * Assign device numbers from zero to the enabled ports,
+ * then assigning remaining device numbers to any disabled
+ * ports.
+ */
+ for (i = 0; i < PCIE_P2P_CNT; i++)
if (pcie_link_status & BIT(i))
p2p_br_devnum[i] = n++;
- for (i = 0; i < PCIE_P2P_MAX; i++)
+ for (i = 0; i < PCIE_P2P_CNT; i++)
if ((pcie_link_status & BIT(i)) == 0)
p2p_br_devnum[i] = n++;
@@ -606,6 +641,15 @@ static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
(p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) |
(p2p_br_devnum[2] << PCIE_P2P_BR_DEVNUM2_SHIFT));
+ /* Assign IRQs */
+ n = 0;
+ for (i = 0; i < PCIE_P2P_CNT; i++)
+ if (pcie_link_status & BIT(i))
+ pcie->irq_map[n++] = irqs[i];
+
+ for (i = n; i < PCIE_P2P_CNT; i++)
+ pcie->irq_map[i] = -1;
+
return 0;
}
@@ -630,7 +674,7 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host,
host->busnr = pcie->busn.start;
host->dev.parent = pcie->dev;
host->ops = &mt7621_pci_ops;
- host->map_irq = of_irq_parse_and_map_pci;
+ host->map_irq = mt7621_map_irq;
host->swizzle_irq = pci_common_swizzle;
host->sysdata = pcie;