diff options
Diffstat (limited to 'target/linux/ar71xx/patches-3.6/149-MIPS-pci-ar724x-use-dynamically-allocated-PCI-contro.patch')
-rw-r--r-- | target/linux/ar71xx/patches-3.6/149-MIPS-pci-ar724x-use-dynamically-allocated-PCI-contro.patch | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/target/linux/ar71xx/patches-3.6/149-MIPS-pci-ar724x-use-dynamically-allocated-PCI-contro.patch b/target/linux/ar71xx/patches-3.6/149-MIPS-pci-ar724x-use-dynamically-allocated-PCI-contro.patch new file mode 100644 index 0000000000..3a67cae2d2 --- /dev/null +++ b/target/linux/ar71xx/patches-3.6/149-MIPS-pci-ar724x-use-dynamically-allocated-PCI-contro.patch @@ -0,0 +1,307 @@ +From 242aedf3246dc5085271aca56134ac455bfb64b5 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos <juhosg@openwrt.org> +Date: Sun, 24 Jun 2012 11:51:34 +0200 +Subject: [PATCH 10/34] MIPS: pci-ar724x: use dynamically allocated PCI controller structure + +Signed-off-by: Gabor Juhos <juhosg@openwrt.org> +--- + arch/mips/pci/pci-ar724x.c | 129 ++++++++++++++++++++++++++++---------------- + 1 files changed, 82 insertions(+), 47 deletions(-) + +--- a/arch/mips/pci/pci-ar724x.c ++++ b/arch/mips/pci/pci-ar724x.c +@@ -9,6 +9,7 @@ + * by the Free Software Foundation. + */ + ++#include <linux/spinlock.h> + #include <linux/irq.h> + #include <linux/pci.h> + #include <linux/module.h> +@@ -28,38 +29,56 @@ + + #define AR7240_BAR0_WAR_VALUE 0xffff + +-static DEFINE_SPINLOCK(ar724x_pci_lock); +-static void __iomem *ar724x_pci_devcfg_base; +-static void __iomem *ar724x_pci_ctrl_base; +- +-static u32 ar724x_pci_bar0_value; +-static bool ar724x_pci_bar0_is_cached; +-static bool ar724x_pci_link_up; ++struct ar724x_pci_controller { ++ void __iomem *devcfg_base; ++ void __iomem *ctrl_base; + +-static inline bool ar724x_pci_check_link(void) ++ int irq; ++ ++ bool link_up; ++ bool bar0_is_cached; ++ u32 bar0_value; ++ ++ spinlock_t lock; ++ ++ struct pci_controller pci_controller; ++}; ++ ++static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc) + { + u32 reset; + +- reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET); ++ reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET); + return reset & AR724X_PCI_RESET_LINK_UP; + } + ++static inline struct ar724x_pci_controller * ++pci_bus_to_ar724x_controller(struct pci_bus *bus) ++{ ++ struct pci_controller *hose; ++ ++ hose = (struct pci_controller *) bus->sysdata; ++ return container_of(hose, struct ar724x_pci_controller, pci_controller); ++} ++ + static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t *value) + { ++ struct ar724x_pci_controller *apc; + unsigned long flags; + void __iomem *base; + u32 data; + +- if (!ar724x_pci_link_up) ++ apc = pci_bus_to_ar724x_controller(bus); ++ if (!apc->link_up) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + +- base = ar724x_pci_devcfg_base; ++ base = apc->devcfg_base; + +- spin_lock_irqsave(&ar724x_pci_lock, flags); ++ spin_lock_irqsave(&apc->lock, flags); + data = __raw_readl(base + (where & ~3)); + + switch (size) { +@@ -78,17 +97,17 @@ static int ar724x_pci_read(struct pci_bu + case 4: + break; + default: +- spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++ spin_unlock_irqrestore(&apc->lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + +- spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++ spin_unlock_irqrestore(&apc->lock, flags); + + if (where == PCI_BASE_ADDRESS_0 && size == 4 && +- ar724x_pci_bar0_is_cached) { ++ apc->bar0_is_cached) { + /* use the cached value */ +- *value = ar724x_pci_bar0_value; ++ *value = apc->bar0_value; + } else { + *value = data; + } +@@ -99,12 +118,14 @@ static int ar724x_pci_read(struct pci_bu + static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t value) + { ++ struct ar724x_pci_controller *apc; + unsigned long flags; + void __iomem *base; + u32 data; + int s; + +- if (!ar724x_pci_link_up) ++ apc = pci_bus_to_ar724x_controller(bus); ++ if (!apc->link_up) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (devfn) +@@ -122,18 +143,18 @@ static int ar724x_pci_write(struct pci_b + * BAR0 register in order to make the device memory + * accessible. + */ +- ar724x_pci_bar0_is_cached = true; +- ar724x_pci_bar0_value = value; ++ apc->bar0_is_cached = true; ++ apc->bar0_value = value; + + value = AR7240_BAR0_WAR_VALUE; + } else { +- ar724x_pci_bar0_is_cached = false; ++ apc->bar0_is_cached = false; + } + } + +- base = ar724x_pci_devcfg_base; ++ base = apc->devcfg_base; + +- spin_lock_irqsave(&ar724x_pci_lock, flags); ++ spin_lock_irqsave(&apc->lock, flags); + data = __raw_readl(base + (where & ~3)); + + switch (size) { +@@ -151,7 +172,7 @@ static int ar724x_pci_write(struct pci_b + data = value; + break; + default: +- spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++ spin_unlock_irqrestore(&apc->lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } +@@ -159,7 +180,7 @@ static int ar724x_pci_write(struct pci_b + __raw_writel(data, base + (where & ~3)); + /* flush write */ + __raw_readl(base + (where & ~3)); +- spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++ spin_unlock_irqrestore(&apc->lock, flags); + + return PCIBIOS_SUCCESSFUL; + } +@@ -183,18 +204,14 @@ static struct resource ar724x_mem_resour + .flags = IORESOURCE_MEM, + }; + +-static struct pci_controller ar724x_pci_controller = { +- .pci_ops = &ar724x_pci_ops, +- .io_resource = &ar724x_io_resource, +- .mem_resource = &ar724x_mem_resource, +-}; +- + static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) + { ++ struct ar724x_pci_controller *apc; + void __iomem *base; + u32 pending; + +- base = ar724x_pci_ctrl_base; ++ apc = irq_get_handler_data(irq); ++ base = apc->ctrl_base; + + pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & + __raw_readl(base + AR724X_PCI_REG_INT_MASK); +@@ -208,10 +225,12 @@ static void ar724x_pci_irq_handler(unsig + + static void ar724x_pci_irq_unmask(struct irq_data *d) + { ++ struct ar724x_pci_controller *apc; + void __iomem *base; + u32 t; + +- base = ar724x_pci_ctrl_base; ++ apc = irq_data_get_irq_chip_data(d); ++ base = apc->ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): +@@ -225,10 +244,12 @@ static void ar724x_pci_irq_unmask(struct + + static void ar724x_pci_irq_mask(struct irq_data *d) + { ++ struct ar724x_pci_controller *apc; + void __iomem *base; + u32 t; + +- base = ar724x_pci_ctrl_base; ++ apc = irq_data_get_irq_chip_data(d); ++ base = apc->ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): +@@ -255,12 +276,12 @@ static struct irq_chip ar724x_pci_irq_ch + .irq_mask_ack = ar724x_pci_irq_mask, + }; + +-static void __devinit ar724x_pci_irq_init(int irq) ++static void __devinit ar724x_pci_irq_init(struct ar724x_pci_controller *apc) + { + void __iomem *base; + int i; + +- base = ar724x_pci_ctrl_base; ++ base = apc->ctrl_base; + + __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); + __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); +@@ -268,45 +289,59 @@ static void __devinit ar724x_pci_irq_ini + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT); + + for (i = ATH79_PCI_IRQ_BASE; +- i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) ++ i < ATH79_PCI_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); ++ } + +- irq_set_chained_handler(irq, ar724x_pci_irq_handler); ++ irq_set_handler_data(apc->irq, apc); ++ irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler); + } + + static int __devinit ar724x_pci_probe(struct platform_device *pdev) + { ++ struct ar724x_pci_controller *apc; + struct resource *res; +- int irq; ++ ++ apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller), ++ GFP_KERNEL); ++ if (!apc) ++ return -ENOMEM; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base"); + if (!res) + return -EINVAL; + +- ar724x_pci_ctrl_base = devm_request_and_ioremap(&pdev->dev, res); +- if (ar724x_pci_ctrl_base == NULL) ++ apc->ctrl_base = devm_request_and_ioremap(&pdev->dev, res); ++ if (apc->ctrl_base == NULL) + return -EBUSY; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); + if (!res) + return -EINVAL; + +- ar724x_pci_devcfg_base = devm_request_and_ioremap(&pdev->dev, res); +- if (!ar724x_pci_devcfg_base) ++ apc->devcfg_base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!apc->devcfg_base) + return -EBUSY; + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) ++ apc->irq = platform_get_irq(pdev, 0); ++ if (apc->irq < 0) + return -EINVAL; + +- ar724x_pci_link_up = ar724x_pci_check_link(); +- if (!ar724x_pci_link_up) ++ spin_lock_init(&apc->lock); ++ ++ apc->pci_controller.pci_ops = &ar724x_pci_ops; ++ apc->pci_controller.io_resource = &ar724x_io_resource; ++ apc->pci_controller.mem_resource = &ar724x_mem_resource; ++ ++ apc->link_up = ar724x_pci_check_link(apc); ++ if (!apc->link_up) + dev_warn(&pdev->dev, "PCIe link is down\n"); + +- ar724x_pci_irq_init(irq); ++ ar724x_pci_irq_init(apc); + +- register_pci_controller(&ar724x_pci_controller); ++ register_pci_controller(&apc->pci_controller); + + return 0; + } |