mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 00:11:13 +00:00
206 lines
5.6 KiB
Diff
206 lines
5.6 KiB
Diff
|
From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001
|
||
|
From: John Crispin <john@phrozen.org>
|
||
|
Date: Sat, 23 Jun 2018 15:07:37 +0200
|
||
|
Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF
|
||
|
|
||
|
With the ath79 target getting converted to pure OF, we can drop all the
|
||
|
platform data code and add the missing OF bits to the driver. We also add
|
||
|
a irq domain for the PCI/e controllers cascade, thus making it usable from
|
||
|
dts files.
|
||
|
|
||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||
|
---
|
||
|
arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------
|
||
|
1 file changed, 42 insertions(+), 46 deletions(-)
|
||
|
|
||
|
--- a/arch/mips/pci/pci-ar724x.c
|
||
|
+++ b/arch/mips/pci/pci-ar724x.c
|
||
|
@@ -14,8 +14,11 @@
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/platform_device.h>
|
||
|
+#include <linux/irqchip/chained_irq.h>
|
||
|
#include <asm/mach-ath79/ath79.h>
|
||
|
#include <asm/mach-ath79/ar71xx_regs.h>
|
||
|
+#include <linux/of_irq.h>
|
||
|
+#include <linux/of_pci.h>
|
||
|
|
||
|
#define AR724X_PCI_REG_APP 0x00
|
||
|
#define AR724X_PCI_REG_RESET 0x18
|
||
|
@@ -45,17 +48,20 @@ struct ar724x_pci_controller {
|
||
|
void __iomem *crp_base;
|
||
|
|
||
|
int irq;
|
||
|
- int irq_base;
|
||
|
|
||
|
bool link_up;
|
||
|
bool bar0_is_cached;
|
||
|
u32 bar0_value;
|
||
|
|
||
|
+ struct device_node *np;
|
||
|
struct pci_controller pci_controller;
|
||
|
+ struct irq_domain *domain;
|
||
|
struct resource io_res;
|
||
|
struct resource mem_res;
|
||
|
};
|
||
|
|
||
|
+static struct irq_chip ar724x_pci_irq_chip;
|
||
|
+
|
||
|
static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
|
||
|
{
|
||
|
u32 reset;
|
||
|
@@ -231,35 +237,31 @@ static struct pci_ops ar724x_pci_ops = {
|
||
|
|
||
|
static void ar724x_pci_irq_handler(struct irq_desc *desc)
|
||
|
{
|
||
|
- struct ar724x_pci_controller *apc;
|
||
|
- void __iomem *base;
|
||
|
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
||
|
+ struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc);
|
||
|
u32 pending;
|
||
|
|
||
|
- apc = irq_desc_get_handler_data(desc);
|
||
|
- base = apc->ctrl_base;
|
||
|
-
|
||
|
- pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
|
||
|
- __raw_readl(base + AR724X_PCI_REG_INT_MASK);
|
||
|
+ chained_irq_enter(chip, desc);
|
||
|
+ pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) &
|
||
|
+ __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK);
|
||
|
|
||
|
if (pending & AR724X_PCI_INT_DEV0)
|
||
|
- generic_handle_irq(apc->irq_base + 0);
|
||
|
-
|
||
|
+ generic_handle_irq(irq_linear_revmap(apc->domain, 1));
|
||
|
else
|
||
|
spurious_interrupt();
|
||
|
+ chained_irq_exit(chip, desc);
|
||
|
}
|
||
|
|
||
|
static void ar724x_pci_irq_unmask(struct irq_data *d)
|
||
|
{
|
||
|
struct ar724x_pci_controller *apc;
|
||
|
void __iomem *base;
|
||
|
- int offset;
|
||
|
u32 t;
|
||
|
|
||
|
apc = irq_data_get_irq_chip_data(d);
|
||
|
base = apc->ctrl_base;
|
||
|
- offset = apc->irq_base - d->irq;
|
||
|
|
||
|
- switch (offset) {
|
||
|
+ switch (irq_linear_revmap(apc->domain, d->irq)) {
|
||
|
case 0:
|
||
|
t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
|
||
|
__raw_writel(t | AR724X_PCI_INT_DEV0,
|
||
|
@@ -273,14 +275,12 @@ static void ar724x_pci_irq_mask(struct i
|
||
|
{
|
||
|
struct ar724x_pci_controller *apc;
|
||
|
void __iomem *base;
|
||
|
- int offset;
|
||
|
u32 t;
|
||
|
|
||
|
apc = irq_data_get_irq_chip_data(d);
|
||
|
base = apc->ctrl_base;
|
||
|
- offset = apc->irq_base - d->irq;
|
||
|
|
||
|
- switch (offset) {
|
||
|
+ switch (irq_linear_revmap(apc->domain, d->irq)) {
|
||
|
case 0:
|
||
|
t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
|
||
|
__raw_writel(t & ~AR724X_PCI_INT_DEV0,
|
||
|
@@ -305,26 +305,34 @@ static struct irq_chip ar724x_pci_irq_ch
|
||
|
.irq_mask_ack = ar724x_pci_irq_mask,
|
||
|
};
|
||
|
|
||
|
+static int ar724x_pci_irq_map(struct irq_domain *d,
|
||
|
+ unsigned int irq, irq_hw_number_t hw)
|
||
|
+{
|
||
|
+ struct ar724x_pci_controller *apc = d->host_data;
|
||
|
+
|
||
|
+ irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq);
|
||
|
+ irq_set_chip_data(irq, apc);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct irq_domain_ops ar724x_pci_domain_ops = {
|
||
|
+ .xlate = irq_domain_xlate_onecell,
|
||
|
+ .map = ar724x_pci_irq_map,
|
||
|
+};
|
||
|
+
|
||
|
static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
|
||
|
int id)
|
||
|
{
|
||
|
void __iomem *base;
|
||
|
- int i;
|
||
|
|
||
|
base = apc->ctrl_base;
|
||
|
|
||
|
__raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
|
||
|
__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
|
||
|
|
||
|
- apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
|
||
|
-
|
||
|
- for (i = apc->irq_base;
|
||
|
- i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
|
||
|
- irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
|
||
|
- handle_level_irq);
|
||
|
- irq_set_chip_data(i, apc);
|
||
|
- }
|
||
|
-
|
||
|
+ apc->domain = irq_domain_add_linear(apc->np, 2,
|
||
|
+ &ar724x_pci_domain_ops, apc);
|
||
|
irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
|
||
|
apc);
|
||
|
}
|
||
|
@@ -394,29 +402,11 @@ static int ar724x_pci_probe(struct platf
|
||
|
if (apc->irq < 0)
|
||
|
return -EINVAL;
|
||
|
|
||
|
- res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
|
||
|
- if (!res)
|
||
|
- return -EINVAL;
|
||
|
-
|
||
|
- apc->io_res.parent = res;
|
||
|
- apc->io_res.name = "PCI IO space";
|
||
|
- apc->io_res.start = res->start;
|
||
|
- apc->io_res.end = res->end;
|
||
|
- apc->io_res.flags = IORESOURCE_IO;
|
||
|
-
|
||
|
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
|
||
|
- if (!res)
|
||
|
- return -EINVAL;
|
||
|
-
|
||
|
- apc->mem_res.parent = res;
|
||
|
- apc->mem_res.name = "PCI memory space";
|
||
|
- apc->mem_res.start = res->start;
|
||
|
- apc->mem_res.end = res->end;
|
||
|
- apc->mem_res.flags = IORESOURCE_MEM;
|
||
|
-
|
||
|
+ apc->np = pdev->dev.of_node;
|
||
|
apc->pci_controller.pci_ops = &ar724x_pci_ops;
|
||
|
apc->pci_controller.io_resource = &apc->io_res;
|
||
|
apc->pci_controller.mem_resource = &apc->mem_res;
|
||
|
+ pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node);
|
||
|
|
||
|
/*
|
||
|
* Do the full PCIE Root Complex Initialization Sequence if the PCIe
|
||
|
@@ -438,10 +428,16 @@ static int ar724x_pci_probe(struct platf
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static const struct of_device_id ar724x_pci_ids[] = {
|
||
|
+ { .compatible = "qcom,ar7240-pci" },
|
||
|
+ {},
|
||
|
+};
|
||
|
+
|
||
|
static struct platform_driver ar724x_pci_driver = {
|
||
|
.probe = ar724x_pci_probe,
|
||
|
.driver = {
|
||
|
.name = "ar724x-pci",
|
||
|
+ .of_match_table = of_match_ptr(ar724x_pci_ids),
|
||
|
},
|
||
|
};
|
||
|
|