Linux MIPS Architecture development
 help / color / mirror / Atom feed
* [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps
@ 2013-02-03 10:58 Gabor Juhos
  2013-02-03 10:58 ` [PATCH 2/4] MIPS: pci-ar724x: use dynamically allocated PCI controller structure Gabor Juhos
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 10:58 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Gabor Juhos

This is needed for multiple PCI bus support.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/pci.c |    4 +++-
 arch/mips/ath79/pci.h |    1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index c94bcec..d90e071 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -75,7 +75,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 		const struct ath79_pci_irq *entry;
 
 		entry = &ath79_pci_irq_map[i];
-		if (entry->slot == slot && entry->pin == pin) {
+		if (entry->bus == dev->bus->number &&
+		    entry->slot == slot &&
+		    entry->pin == pin) {
 			irq = entry->irq;
 			break;
 		}
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index 51c6625..1d00a38 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -14,6 +14,7 @@
 #define _ATH79_PCI_H
 
 struct ath79_pci_irq {
+	int	bus;
 	u8	slot;
 	u8	pin;
 	int	irq;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] MIPS: pci-ar724x: use dynamically allocated PCI controller structure
  2013-02-03 10:58 [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps Gabor Juhos
@ 2013-02-03 10:58 ` Gabor Juhos
  2013-02-03 10:59 ` [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources Gabor Juhos
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 10:58 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Gabor Juhos

The current code uses static variables to store the
PCI controller specific data. This works if the system
contains one PCI controller only, however it becomes
impractical when multiple PCI controllers are present.

Move the variables into a dynamically allocated controller
specific structure, and use that instead of the static
variables.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/pci/pci-ar724x.c |  129 ++++++++++++++++++++++++++++----------------
 1 file changed, 82 insertions(+), 47 deletions(-)

diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 8f008d9..93ab877 100644
--- 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;
+struct ar724x_pci_controller {
+	void __iomem *devcfg_base;
+	void __iomem *ctrl_base;
 
-static u32 ar724x_pci_bar0_value;
-static bool ar724x_pci_bar0_is_cached;
-static bool ar724x_pci_link_up;
+	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(void)
+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_bus *bus, unsigned int devfn, int where,
 	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_bus *bus, unsigned int devfn, int where,
 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_bus *bus, unsigned int devfn, int where,
 			 * 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_bus *bus, unsigned int devfn, int where,
 		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_bus *bus, unsigned int devfn, int where,
 	__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_resource = {
 	.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(unsigned int irq, struct irq_desc *desc)
 
 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 irq_data *d)
 
 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_chip = {
 	.irq_mask_ack	= ar724x_pci_irq_mask,
 };
 
-static void ar724x_pci_irq_init(int irq)
+static void 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 ar724x_pci_irq_init(int irq)
 	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 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;
 }
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources
  2013-02-03 10:58 [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps Gabor Juhos
  2013-02-03 10:58 ` [PATCH 2/4] MIPS: pci-ar724x: use dynamically allocated PCI controller structure Gabor Juhos
@ 2013-02-03 10:59 ` Gabor Juhos
  2013-02-03 11:18   ` Sergei Shtylyov
  2013-02-03 11:00 ` [PATCH 4/4] MIPS: pci-ar724x: use per-controller IRQ base Gabor Juhos
  2013-02-03 15:52 ` [PATCH 5/4] MIPS: pci-ar724x: setup command register of the PCI controller Gabor Juhos
  3 siblings, 1 reply; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 10:59 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Gabor Juhos

Static resources become impractical when multiple
PCI controllers are present. Move the resources
into the platform device registration code and
change the probe routine to get those from there
platform device's resources.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/pci.c      |   21 ++++++++++++++++++++-
 arch/mips/pci/pci-ar724x.c |   40 ++++++++++++++++++++++++----------------
 2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index d90e071..45d1112 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -139,10 +139,13 @@ static struct platform_device *
 ath79_register_pci_ar724x(int id,
 			  unsigned long cfg_base,
 			  unsigned long ctrl_base,
+			  unsigned long mem_base,
+			  unsigned long mem_size,
+			  unsigned long io_base,
 			  int irq)
 {
 	struct platform_device *pdev;
-	struct resource res[3];
+	struct resource res[5];
 
 	memset(res, 0, sizeof(res));
 
@@ -160,6 +163,16 @@ ath79_register_pci_ar724x(int id,
 	res[2].start = irq;
 	res[2].end = irq;
 
+	res[3].name = "mem_base";
+	res[3].flags = IORESOURCE_MEM;
+	res[3].start = mem_base;
+	res[3].end = mem_base + mem_size - 1;
+
+	res[4].name = "io_base";
+	res[4].flags = IORESOURCE_IO;
+	res[4].start = io_base;
+	res[4].end = io_base;
+
 	pdev = platform_device_register_simple("ar724x-pci", id,
 					       res, ARRAY_SIZE(res));
 	return pdev;
@@ -175,6 +188,9 @@ int __init ath79_register_pci(void)
 		pdev = ath79_register_pci_ar724x(-1,
 						 AR724X_PCI_CFG_BASE,
 						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_MEM_BASE,
+						 AR724X_PCI_MEM_SIZE,
+						 0,
 						 ATH79_CPU_IRQ_IP2);
 	} else if (soc_is_ar9342() ||
 		   soc_is_ar9344()) {
@@ -187,6 +203,9 @@ int __init ath79_register_pci(void)
 		pdev = ath79_register_pci_ar724x(-1,
 						 AR724X_PCI_CFG_BASE,
 						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_MEM_BASE,
+						 AR724X_PCI_MEM_SIZE,
+						 0,
 						 ATH79_IP2_IRQ(0));
 	} else {
 		/* No PCI support */
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 93ab877..d0d707d 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -42,6 +42,8 @@ struct ar724x_pci_controller {
 	spinlock_t lock;
 
 	struct pci_controller pci_controller;
+	struct resource io_res;
+	struct resource mem_res;
 };
 
 static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
@@ -190,20 +192,6 @@ static struct pci_ops ar724x_pci_ops = {
 	.write	= ar724x_pci_write,
 };
 
-static struct resource ar724x_io_resource = {
-	.name   = "PCI IO space",
-	.start  = 0,
-	.end    = 0,
-	.flags  = IORESOURCE_IO,
-};
-
-static struct resource ar724x_mem_resource = {
-	.name   = "PCI memory space",
-	.start  = AR724X_PCI_MEM_BASE,
-	.end    = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
 static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct ar724x_pci_controller *apc;
@@ -331,9 +319,29 @@ static int ar724x_pci_probe(struct platform_device *pdev)
 
 	spin_lock_init(&apc->lock);
 
+	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->pci_controller.pci_ops = &ar724x_pci_ops;
-	apc->pci_controller.io_resource = &ar724x_io_resource;
-	apc->pci_controller.mem_resource = &ar724x_mem_resource;
+	apc->pci_controller.io_resource = &apc->io_res;
+	apc->pci_controller.mem_resource = &apc->mem_res;
 
 	apc->link_up = ar724x_pci_check_link(apc);
 	if (!apc->link_up)
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] MIPS: pci-ar724x: use per-controller IRQ base
  2013-02-03 10:58 [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps Gabor Juhos
  2013-02-03 10:58 ` [PATCH 2/4] MIPS: pci-ar724x: use dynamically allocated PCI controller structure Gabor Juhos
  2013-02-03 10:59 ` [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources Gabor Juhos
@ 2013-02-03 11:00 ` Gabor Juhos
  2013-02-03 15:52 ` [PATCH 5/4] MIPS: pci-ar724x: setup command register of the PCI controller Gabor Juhos
  3 siblings, 0 replies; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 11:00 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Gabor Juhos

Change to the code to use per-controller IRQ base.
This is needed for multiple PCI controller support.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/pci/pci-ar724x.c |   31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index d0d707d..0440d88 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -34,6 +34,7 @@ struct ar724x_pci_controller {
 	void __iomem *ctrl_base;
 
 	int irq;
+	int irq_base;
 
 	bool link_up;
 	bool bar0_is_cached;
@@ -205,7 +206,7 @@ static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
 		  __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 
 	if (pending & AR724X_PCI_INT_DEV0)
-		generic_handle_irq(ATH79_PCI_IRQ(0));
+		generic_handle_irq(apc->irq_base + 0);
 
 	else
 		spurious_interrupt();
@@ -215,13 +216,15 @@ 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 (d->irq) {
-	case ATH79_PCI_IRQ(0):
+	switch (offset) {
+	case 0:
 		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 		__raw_writel(t | AR724X_PCI_INT_DEV0,
 			     base + AR724X_PCI_REG_INT_MASK);
@@ -234,13 +237,15 @@ static void ar724x_pci_irq_mask(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 (d->irq) {
-	case ATH79_PCI_IRQ(0):
+	switch (offset) {
+	case 0:
 		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
 			     base + AR724X_PCI_REG_INT_MASK);
@@ -264,7 +269,8 @@ static struct irq_chip ar724x_pci_irq_chip = {
 	.irq_mask_ack	= ar724x_pci_irq_mask,
 };
 
-static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc)
+static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
+				int id)
 {
 	void __iomem *base;
 	int i;
@@ -274,10 +280,10 @@ static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc)
 	__raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
 	__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
 
-	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
+	apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
 
-	for (i = ATH79_PCI_IRQ_BASE;
-	     i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) {
+	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);
@@ -291,6 +297,11 @@ static int ar724x_pci_probe(struct platform_device *pdev)
 {
 	struct ar724x_pci_controller *apc;
 	struct resource *res;
+	int id;
+
+	id = pdev->id;
+	if (id == -1)
+		id = 0;
 
 	apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller),
 			    GFP_KERNEL);
@@ -347,7 +358,7 @@ static int ar724x_pci_probe(struct platform_device *pdev)
 	if (!apc->link_up)
 		dev_warn(&pdev->dev, "PCIe link is down\n");
 
-	ar724x_pci_irq_init(apc);
+	ar724x_pci_irq_init(apc, id);
 
 	register_pci_controller(&apc->pci_controller);
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources
  2013-02-03 10:59 ` [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources Gabor Juhos
@ 2013-02-03 11:18   ` Sergei Shtylyov
  2013-02-03 12:31     ` Gabor Juhos
  0 siblings, 1 reply; 9+ messages in thread
From: Sergei Shtylyov @ 2013-02-03 11:18 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, John Crispin

Hello.

On 03-02-2013 14:59, Gabor Juhos wrote:

> Static resources become impractical when multiple
> PCI controllers are present. Move the resources
> into the platform device registration code and
> change the probe routine to get those from there
> platform device's resources.

> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> ---
>   arch/mips/ath79/pci.c      |   21 ++++++++++++++++++++-
>   arch/mips/pci/pci-ar724x.c |   40 ++++++++++++++++++++++++----------------
>   2 files changed, 44 insertions(+), 17 deletions(-)

> diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
> index d90e071..45d1112 100644
> --- a/arch/mips/ath79/pci.c
> +++ b/arch/mips/ath79/pci.c
> @@ -139,10 +139,13 @@ static struct platform_device *
>   ath79_register_pci_ar724x(int id,
>   			  unsigned long cfg_base,
>   			  unsigned long ctrl_base,
> +			  unsigned long mem_base,
> +			  unsigned long mem_size,
> +			  unsigned long io_base,
>   			  int irq)
>   {
>   	struct platform_device *pdev;
> -	struct resource res[3];
> +	struct resource res[5];
>
>   	memset(res, 0, sizeof(res));
>
> @@ -160,6 +163,16 @@ ath79_register_pci_ar724x(int id,
>   	res[2].start = irq;
>   	res[2].end = irq;
>
> +	res[3].name = "mem_base";
> +	res[3].flags = IORESOURCE_MEM;
> +	res[3].start = mem_base;
> +	res[3].end = mem_base + mem_size - 1;
> +
> +	res[4].name = "io_base";
> +	res[4].flags = IORESOURCE_IO;
> +	res[4].start = io_base;
> +	res[4].end = io_base;

    One I/O port, hm? What is it good for?

WBR, Sergei

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources
  2013-02-03 11:18   ` Sergei Shtylyov
@ 2013-02-03 12:31     ` Gabor Juhos
  2013-02-04 12:13       ` Sergei Shtylyov
  0 siblings, 1 reply; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 12:31 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Ralf Baechle, linux-mips, John Crispin

2013.02.03. 12:18 keltezéssel, Sergei Shtylyov írta:

>> @@ -160,6 +163,16 @@ ath79_register_pci_ar724x(int id,
>>       res[2].start = irq;
>>       res[2].end = irq;
>>
>> +    res[3].name = "mem_base";
>> +    res[3].flags = IORESOURCE_MEM;
>> +    res[3].start = mem_base;
>> +    res[3].end = mem_base + mem_size - 1;
>> +
>> +    res[4].name = "io_base";
>> +    res[4].flags = IORESOURCE_IO;
>> +    res[4].start = io_base;
>> +    res[4].end = io_base;
> 
>    One I/O port, hm? What is it good for?

Strictly speaking it is not good for anything. This is a PCIe controller and it
does not support IO requests at all. However the whole PCI code assumes that
each PCI controller have an IO resource and uses the hose->io_resource pointer
unconditionally.

Additionally, this matches with the removed static resource:

> -static struct resource ar724x_io_resource = {
> -	.name   = "PCI IO space",
> -	.start  = 0,
> -	.end    = 0,
> -	.flags  = IORESOURCE_IO,
> -};
> -

Thank you for the review.

-Gabor

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/4] MIPS: pci-ar724x: setup command register of the PCI controller
  2013-02-03 10:58 [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps Gabor Juhos
                   ` (2 preceding siblings ...)
  2013-02-03 11:00 ` [PATCH 4/4] MIPS: pci-ar724x: use per-controller IRQ base Gabor Juhos
@ 2013-02-03 15:52 ` Gabor Juhos
  3 siblings, 0 replies; 9+ messages in thread
From: Gabor Juhos @ 2013-02-03 15:52 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Gabor Juhos

The command register of the PCI controller is
not initialized correctly by the bootloader on
some boards and this leads to non working PCI
bus.

Add code to initialize the command register
from the Linux code to avoid this.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Sorry for the confusing patch number. This belongs to the 
previous 'pci-ar724x' series but I forgot to add it there.

Gabor


 arch/mips/ath79/pci.c                          |   10 +++-
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h |    2 +
 arch/mips/pci/pci-ar724x.c                     |   63 ++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 45d1112..942e3f9 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -139,13 +139,14 @@ static struct platform_device *
 ath79_register_pci_ar724x(int id,
 			  unsigned long cfg_base,
 			  unsigned long ctrl_base,
+			  unsigned long crp_base,
 			  unsigned long mem_base,
 			  unsigned long mem_size,
 			  unsigned long io_base,
 			  int irq)
 {
 	struct platform_device *pdev;
-	struct resource res[5];
+	struct resource res[6];
 
 	memset(res, 0, sizeof(res));
 
@@ -173,6 +174,11 @@ ath79_register_pci_ar724x(int id,
 	res[4].start = io_base;
 	res[4].end = io_base;
 
+	res[5].name = "crp_base";
+	res[5].flags = IORESOURCE_MEM;
+	res[5].start = crp_base;
+	res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1;
+
 	pdev = platform_device_register_simple("ar724x-pci", id,
 					       res, ARRAY_SIZE(res));
 	return pdev;
@@ -188,6 +194,7 @@ int __init ath79_register_pci(void)
 		pdev = ath79_register_pci_ar724x(-1,
 						 AR724X_PCI_CFG_BASE,
 						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_CRP_BASE,
 						 AR724X_PCI_MEM_BASE,
 						 AR724X_PCI_MEM_SIZE,
 						 0,
@@ -203,6 +210,7 @@ int __init ath79_register_pci(void)
 		pdev = ath79_register_pci_ar724x(-1,
 						 AR724X_PCI_CFG_BASE,
 						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_CRP_BASE,
 						 AR724X_PCI_MEM_BASE,
 						 AR724X_PCI_MEM_SIZE,
 						 0,
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 7c87bfe..a77f6ee 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -67,6 +67,8 @@
 
 #define AR724X_PCI_CFG_BASE	0x14000000
 #define AR724X_PCI_CFG_SIZE	0x1000
+#define AR724X_PCI_CRP_BASE	(AR71XX_APB_BASE + 0x000c0000)
+#define AR724X_PCI_CRP_SIZE	0x1000
 #define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000)
 #define AR724X_PCI_CTRL_SIZE	0x100
 
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 0440d88..8a0700d 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -29,9 +29,17 @@
 
 #define AR7240_BAR0_WAR_VALUE	0xffff
 
+#define AR724X_PCI_CMD_INIT	(PCI_COMMAND_MEMORY |		\
+				 PCI_COMMAND_MASTER |		\
+				 PCI_COMMAND_INVALIDATE |	\
+				 PCI_COMMAND_PARITY |		\
+				 PCI_COMMAND_SERR |		\
+				 PCI_COMMAND_FAST_BACK)
+
 struct ar724x_pci_controller {
 	void __iomem *devcfg_base;
 	void __iomem *ctrl_base;
+	void __iomem *crp_base;
 
 	int irq;
 	int irq_base;
@@ -64,6 +72,51 @@ pci_bus_to_ar724x_controller(struct pci_bus *bus)
 	return container_of(hose, struct ar724x_pci_controller, pci_controller);
 }
 
+static int ar724x_pci_local_write(struct ar724x_pci_controller *apc,
+				  int where, int size, u32 value)
+{
+	unsigned long flags;
+	void __iomem *base;
+	u32 data;
+	int s;
+
+	WARN_ON(where & (size - 1));
+
+	if (!apc->link_up)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = apc->crp_base;
+
+	spin_lock_irqsave(&apc->lock, flags);
+	data = __raw_readl(base + (where & ~3));
+
+	switch (size) {
+	case 1:
+		s = ((where & 3) * 8);
+		data &= ~(0xff << s);
+		data |= ((value & 0xff) << s);
+		break;
+	case 2:
+		s = ((where & 2) * 8);
+		data &= ~(0xffff << s);
+		data |= ((value & 0xffff) << s);
+		break;
+	case 4:
+		data = value;
+		break;
+	default:
+		spin_unlock_irqrestore(&apc->lock, flags);
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	__raw_writel(data, base + (where & ~3));
+	/* flush write */
+	__raw_readl(base + (where & ~3));
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 			    int size, uint32_t *value)
 {
@@ -324,6 +377,14 @@ static int ar724x_pci_probe(struct platform_device *pdev)
 	if (!apc->devcfg_base)
 		return -EBUSY;
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->crp_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (apc->crp_base == NULL)
+		return -EBUSY;
+
 	apc->irq = platform_get_irq(pdev, 0);
 	if (apc->irq < 0)
 		return -EINVAL;
@@ -360,6 +421,8 @@ static int ar724x_pci_probe(struct platform_device *pdev)
 
 	ar724x_pci_irq_init(apc, id);
 
+	ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT);
+
 	register_pci_controller(&apc->pci_controller);
 
 	return 0;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources
  2013-02-03 12:31     ` Gabor Juhos
@ 2013-02-04 12:13       ` Sergei Shtylyov
  2013-02-04 13:14         ` Gabor Juhos
  0 siblings, 1 reply; 9+ messages in thread
From: Sergei Shtylyov @ 2013-02-04 12:13 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, John Crispin

Hello.

On 03-02-2013 16:31, Gabor Juhos wrote:

>>> @@ -160,6 +163,16 @@ ath79_register_pci_ar724x(int id,
>>>        res[2].start = irq;
>>>        res[2].end = irq;
>>>
>>> +    res[3].name = "mem_base";
>>> +    res[3].flags = IORESOURCE_MEM;
>>> +    res[3].start = mem_base;
>>> +    res[3].end = mem_base + mem_size - 1;
>>> +
>>> +    res[4].name = "io_base";
>>> +    res[4].flags = IORESOURCE_IO;
>>> +    res[4].start = io_base;
>>> +    res[4].end = io_base;
>>
>>     One I/O port, hm? What is it good for?

> Strictly speaking it is not good for anything. This is a PCIe controller and it
> does not support IO requests at all.

    Is this the case with every PCIe controller or only this particular one?

> However the whole PCI code assumes that
> each PCI controller have an IO resource and uses the hose->io_resource pointer
> unconditionally.

> Additionally, this matches with the removed static resource:

>> -static struct resource ar724x_io_resource = {
>> -	.name   = "PCI IO space",
>> -	.start  = 0,
>> -	.end    = 0,
>> -	.flags  = IORESOURCE_IO,
>> -};
>> -

    Since you seems to always pass 0, maybe you don't need 'io_base' parameter 
to the function above?

> -Gabor

WBR, Sergei

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources
  2013-02-04 12:13       ` Sergei Shtylyov
@ 2013-02-04 13:14         ` Gabor Juhos
  0 siblings, 0 replies; 9+ messages in thread
From: Gabor Juhos @ 2013-02-04 13:14 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Ralf Baechle, linux-mips, John Crispin

2013.02.04. 13:13 keltezéssel, Sergei Shtylyov írta:
> Hello.
> 
> On 03-02-2013 16:31, Gabor Juhos wrote:
> 
>>>> @@ -160,6 +163,16 @@ ath79_register_pci_ar724x(int id,
>>>>        res[2].start = irq;
>>>>        res[2].end = irq;
>>>>
>>>> +    res[3].name = "mem_base";
>>>> +    res[3].flags = IORESOURCE_MEM;
>>>> +    res[3].start = mem_base;
>>>> +    res[3].end = mem_base + mem_size - 1;
>>>> +
>>>> +    res[4].name = "io_base";
>>>> +    res[4].flags = IORESOURCE_IO;
>>>> +    res[4].start = io_base;
>>>> +    res[4].end = io_base;
>>>
>>>     One I/O port, hm? What is it good for?
> 
>> Strictly speaking it is not good for anything. This is a PCIe controller and it
>> does not support IO requests at all.
> 
>    Is this the case with every PCIe controller or only this particular one?

It is a limitation of this controller.

> 
>> However the whole PCI code assumes that
>> each PCI controller have an IO resource and uses the hose->io_resource pointer
>> unconditionally.
> 
>> Additionally, this matches with the removed static resource:
> 
>>> -static struct resource ar724x_io_resource = {
>>> -    .name   = "PCI IO space",
>>> -    .start  = 0,
>>> -    .end    = 0,
>>> -    .flags  = IORESOURCE_IO,
>>> -};
>>> -
> 
>    Since you seems to always pass 0, maybe you don't need 'io_base' parameter to
> the function above?

The AR724x SoCs SoCs have one PCIe controller only. However newer chips have
more than one PCIe controllers, and each of those controllers needs a different
io_base value to avoid resource conflicts. I'm preparing patches for newer SoCs
and if everything goes well I will send those today.

-GAbor

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-02-04 13:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-03 10:58 [PATCH 1/4] MIPS: ath79: allow to specify bus number in PCI IRQ maps Gabor Juhos
2013-02-03 10:58 ` [PATCH 2/4] MIPS: pci-ar724x: use dynamically allocated PCI controller structure Gabor Juhos
2013-02-03 10:59 ` [PATCH 3/4] MIPS: pci-ar724x: remove static PCI IO/MEM resources Gabor Juhos
2013-02-03 11:18   ` Sergei Shtylyov
2013-02-03 12:31     ` Gabor Juhos
2013-02-04 12:13       ` Sergei Shtylyov
2013-02-04 13:14         ` Gabor Juhos
2013-02-03 11:00 ` [PATCH 4/4] MIPS: pci-ar724x: use per-controller IRQ base Gabor Juhos
2013-02-03 15:52 ` [PATCH 5/4] MIPS: pci-ar724x: setup command register of the PCI controller Gabor Juhos

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox