All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
@ 2011-11-22 23:14 Gabor Juhos
  2011-11-22 23:14 ` [PATCH 01/12] MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c Gabor Juhos
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

This patch set fixes some errors in the AR724X specific
PCI code, and adds support for the PCI Host controller
of the AR71XX SoCs.

This set depends on v4 of the
'MIPS: ath79: cleanup AR724X PCI support code' patches.

Gabor Juhos (12):
  MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c
  MIPS: ath79: fix broken ar724x_pci_{read,write} functions
  MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs
  MIPS: ath79: fix a wrong IRQ number
  MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
  MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c
  MIPS: ath79: allow to use board specific pci_plat_dev_init functions
  MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs
  MIPS: ath79: allow to use SoC specific PCI IRQ maps
  MIPS: ath79: remove ar724x_pci_add_data function
  MIPS: ath79: register PCI controller on the PB44 board
  MIPS: ath79: update copyright headers of PCI related files

 arch/mips/ath79/Kconfig                |    1 +
 arch/mips/ath79/mach-pb44.c            |    2 +
 arch/mips/ath79/mach-ubnt-xm.c         |   42 ++++---
 arch/mips/ath79/pci.c                  |   97 ++++++++++++---
 arch/mips/ath79/pci.h                  |   19 ++-
 arch/mips/include/asm/mach-ath79/irq.h |    6 +-
 arch/mips/include/asm/mach-ath79/pci.h |   14 ++-
 arch/mips/pci/Makefile                 |    1 +
 arch/mips/pci/pci-ar724x.c             |  215 +++++++++++++++++++++++++++-----
 9 files changed, 318 insertions(+), 79 deletions(-)

-- 
1.7.2.1

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

* [PATCH 01/12] MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 02/12] MIPS: ath79: fix broken ar724x_pci_{read,write} functions Gabor Juhos
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The alignment of the 'where' parameters are checked
in the core PCI code already.

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

diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 22f5e5b..342bf4a 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -28,9 +28,6 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 	if (devfn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (where & (size - 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
 	base = ar724x_pci_devcfg_base;
 
 	spin_lock_irqsave(&ar724x_pci_lock, flags);
@@ -73,9 +70,6 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 	if (devfn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (where & (size - 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
 	base = ar724x_pci_devcfg_base;
 
 	spin_lock_irqsave(&ar724x_pci_lock, flags);
-- 
1.7.2.1

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

* [PATCH 02/12] MIPS: ath79: fix broken ar724x_pci_{read,write} functions
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
  2011-11-22 23:14 ` [PATCH 01/12] MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 03/12] MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs Gabor Juhos
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The current ar724x_pci_{read,write} functions are
broken. Due to that, pci_read_config_byte returns
with bogus values, and pci_write_config_{byte,word}
unconditionally clears the accessed PCI configuration
registers instead of changing the value of them.

The patch fixes the broken functions, thus the PCI
configuration space can be accessed correctly.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Output of 'lspci -vv' without the patch:

00:00.0 Network controller: Atheros Communications Inc. AR9285 Wireless
Network Adapter (PCI-Express) (rev 01)
        Subsystem: Atheros Communications Inc. Device a091
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 0
        Region 0: Memory at 10000000 (64-bit, non-prefetchable) [size=64K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold-)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit-
                Address: 00000000  Data: 0000
        Capabilities: [60] Express (v2) Legacy Endpoint, MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, Latency L0 <512ns, L1 <64us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-
                LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB

Output of 'lspci -vv' with the patch:

00:00.0 Network controller: Atheros Communications Inc. AR9285 Wireless
Network Adapter (PCI-Express) (rev 01)
        Subsystem: Atheros Communications Inc. Device a091
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 48
        Region 0: Memory at 10000000 (64-bit, non-prefetchable) [size=64K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold-)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit-
                Address: 00000000  Data: 0000
        Capabilities: [60] Express (v2) Legacy Endpoint, MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, Latency L0 <512ns, L1 <64us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-
                LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB
        Capabilities: [100 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [140 v1] Virtual Channel
                Caps:   LPEVC=0 RefClk=100ns PATEntryBits=1
                Arb:    Fixed- WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending- InProgress-
        Capabilities: [160 v1] Device Serial Number 00-15-17-ff-ff-24-14-12
        Capabilities: [170 v1] Power Budgeting <?>
---
 arch/mips/pci/pci-ar724x.c |   52 ++++++++++++++++++++++----------------------
 1 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 342bf4a..bb4f216 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -22,8 +22,9 @@ static void __iomem *ar724x_pci_devcfg_base;
 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 			    int size, uint32_t *value)
 {
-	unsigned long flags, addr, tval, mask;
+	unsigned long flags;
 	void __iomem *base;
+	u32 data;
 
 	if (devfn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -31,24 +32,22 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 	base = ar724x_pci_devcfg_base;
 
 	spin_lock_irqsave(&ar724x_pci_lock, flags);
+	data = __raw_readl(base + (where & ~3));
 
 	switch (size) {
 	case 1:
-		addr = where & ~3;
-		mask = 0xff000000 >> ((where % 4) * 8);
-		tval = __raw_readl(base + addr);
-		tval = tval & ~mask;
-		*value = (tval >> ((4 - (where % 4))*8));
+		if (where & 1)
+			data >>= 8;
+		if (where & 2)
+			data >>= 16;
+		data &= 0xff;
 		break;
 	case 2:
-		addr = where & ~3;
-		mask = 0xffff0000 >> ((where % 4)*8);
-		tval = __raw_readl(base + addr);
-		tval = tval & ~mask;
-		*value = (tval >> ((4 - (where % 4))*8));
+		if (where & 2)
+			data >>= 16;
+		data &= 0xffff;
 		break;
 	case 4:
-		*value = __raw_readl(base + where);
 		break;
 	default:
 		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
@@ -57,6 +56,7 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 	}
 
 	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
+	*value = data;
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -64,8 +64,10 @@ 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)
 {
-	unsigned long flags, tval, addr, mask;
+	unsigned long flags;
 	void __iomem *base;
+	u32 data;
+	int s;
 
 	if (devfn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -73,26 +75,21 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 	base = ar724x_pci_devcfg_base;
 
 	spin_lock_irqsave(&ar724x_pci_lock, flags);
+	data = __raw_readl(base + (where & ~3));
 
 	switch (size) {
 	case 1:
-		addr = where & ~3;
-		mask = 0xff000000 >> ((where % 4)*8);
-		tval = __raw_readl(base + addr);
-		tval = tval & ~mask;
-		tval |= (value << ((4 - (where % 4))*8)) & mask;
-		__raw_writel(tval, base + addr);
+		s = ((where & 3) * 8);
+		data &= ~(0xff << s);
+		data |= ((value & 0xff) << s);
 		break;
 	case 2:
-		addr = where & ~3;
-		mask = 0xffff0000 >> ((where % 4)*8);
-		tval = __raw_readl(base + addr);
-		tval = tval & ~mask;
-		tval |= (value << ((4 - (where % 4))*8)) & mask;
-		__raw_writel(tval, base + addr);
+		s = ((where & 2) * 8);
+		data &= ~(0xffff << s);
+		data |= ((value & 0xffff) << s);
 		break;
 	case 4:
-		__raw_writel(value, (base + where));
+		data = value;
 		break;
 	default:
 		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
@@ -100,6 +97,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 	}
 
+	__raw_writel(data, base + (where & ~3));
+	/* flush write */
+	__raw_readl(base + (where & ~3));
 	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
 
 	return PCIBIOS_SUCCESSFUL;
-- 
1.7.2.1

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

* [PATCH 03/12] MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
  2011-11-22 23:14 ` [PATCH 01/12] MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c Gabor Juhos
  2011-11-22 23:14 ` [PATCH 02/12] MIPS: ath79: fix broken ar724x_pci_{read,write} functions Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 04/12] MIPS: ath79: fix a wrong IRQ number Gabor Juhos
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The PCI controller of the AR724X SoCs has a hardware
bag. If the BAR0 register of the PCI device is set to
the proper base address, the memory address space of
the device is not accessible.

When the device driver tries to access the memory
address space of the PCI device, it leads to data
bus error, similiar to this:

Data bus error, epc == 801f69a0, ra == 801f698c
Oops[#1]:
Cpu 0
$ 0   : 00000000 00000061 deadbeef 000000ff
$ 4   : 00000000 000000ff 00000014 00000000
$ 8   : ff000000 fffffffc 00000000 00000000
$12   : 000001f5 00000006 00000000 6e637920
$16   : 81ca4000 81ca0260 81ca4000 804d70f0
$20   : fffffff4 0000002b 803ad4c4 00000000
$24   : 00000003 00000000
$28   : 81c20000 81c21c60 00000000 801f698c
Hi    : 00000000
Lo    : 00000000
epc   : 801f69a0 ath9k_hw_init+0xd0/0xa70
    Not tainted
ra    : 801f698c ath9k_hw_init+0xbc/0xa70
Status: 1000c103    KERNEL EXL IE
Cause : 1080001c
PrId  : 00019374 (MIPS 24Kc)
Modules linked in:
Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
Stack : 00000000 00000000 00000000 00000000 81c21c78 81ca0260 00000000 804d70f0
        81ca0260 81c21cc0 81ca0e80 81ca0260 81ca4000 804d70f0 fffffff4 0000002b
        803ad4c4 00000000 00000000 801e3ae8 81c9d080 81ca0e80 b0000000 800b9b9c
        00000008 81c9d000 8031aeb0 802d38a0 00000000 81c14c00 81c14c60 00000000
        81ca0e80 81ca0260 b0000000 801f08a4 81c9c820 81c21d48 81c9c820 80144320
        ...
Call Trace:
[<801f69a0>] ath9k_hw_init+0xd0/0xa70
[<801e3ae8>] ath9k_init_device+0x174/0x680
[<801f08a4>] ath_pci_probe+0x27c/0x380
[<8019e490>] pci_device_probe+0x74/0x9c
[<801bfadc>] driver_probe_device+0x9c/0x1b4
[<801bfcb0>] __driver_attach+0xbc/0xc4
[<801bea0c>] bus_for_each_dev+0x5c/0x98
[<801bf394>] bus_add_driver+0x1d0/0x2a4
[<801c0364>] driver_register+0x8c/0x16c
[<8019e72c>] __pci_register_driver+0x4c/0xe4
[<803d3d40>] ath9k_init+0x3c/0x88
[<80060930>] do_one_initcall+0x3c/0x1cc
[<803c297c>] kernel_init+0xa4/0x138
[<80063c04>] kernel_thread_helper+0x10/0x18

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

diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index bb4f216..cef6519 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/pci.h>
+#include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/pci.h>
 
 #define AR724X_PCI_CFG_BASE	0x14000000
@@ -16,9 +17,22 @@
 #define AR724X_PCI_MEM_BASE	0x10000000
 #define AR724X_PCI_MEM_SIZE	0x08000000
 
+#define AR724X_PCI_REG_INT_STATUS	0x4c
+#define AR724X_PCI_REG_INT_MASK		0x50
+
+#define AR724X_PCI_INT_DEV0		BIT(14)
+
+#define AR724X_PCI_IRQ_COUNT	1
+
+#define AR7240_BAR0_WAR_VALUE	0xffff
+#define AR724X_BAR0_WAR_VALUE	0x1000ffff
+
 static DEFINE_SPINLOCK(ar724x_pci_lock);
 static void __iomem *ar724x_pci_devcfg_base;
 
+static u32 ar724x_pci_bar0_value;
+static bool ar724x_pci_bar0_is_cached;
+
 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 			    int size, uint32_t *value)
 {
@@ -56,7 +70,14 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 	}
 
 	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
-	*value = data;
+
+	if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
+	    ar724x_pci_bar0_is_cached) {
+		/* use the cached value */
+		*value = ar724x_pci_bar0_value;
+	} else {
+		*value = data;
+	}
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -72,6 +93,30 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 	if (devfn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
+	if (where == PCI_BASE_ADDRESS_0 && size == 4) {
+		if (value != 0xffffffff) {
+			/*
+			 * WAR for a hw issue. If the BAR0 register of the
+			 * device is set to the proper base address, the
+			 * memory space of the device is not accessible.
+			 *
+			 * Cache the intended value so it can be read back,
+			 * and write a SoC specific constant value to the
+			 * BAR0 register in order to make the device memory
+			 * accessible.
+			 */
+			ar724x_pci_bar0_is_cached = true;
+			ar724x_pci_bar0_value = value;
+
+			if (soc_is_ar7240())
+				value = AR7240_BAR0_WAR_VALUE;
+			else
+				value = AR724X_BAR0_WAR_VALUE;
+		} else {
+			ar724x_pci_bar0_is_cached = false;
+		}
+	}
+
 	base = ar724x_pci_devcfg_base;
 
 	spin_lock_irqsave(&ar724x_pci_lock, flags);
-- 
1.7.2.1

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

* [PATCH 04/12] MIPS: ath79: fix a wrong IRQ number
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (2 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 03/12] MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 05/12] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs Gabor Juhos
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The Ubiquiti XM board setup code uses an invalid
IRQ number, because it if above of NR_IRQS. This
leads to failed 'request_irq' calls:

  ath9k 0000:00:00.0: request_irq failed
  ath9k: probe of 0000:00:00.0 failed with error -22

Preserve some IRQ numbers for the built-in IRQ
controller of PCI host controllers in the
AR71XX/AR724X SoCs, and use the correct IRQ
number in the board setup code.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

The IRQ controller code is also missing, that will be
added in a separate patch.
---
 arch/mips/ath79/mach-ubnt-xm.c         |    5 +++--
 arch/mips/include/asm/mach-ath79/irq.h |    6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index 3266ee0..0d95b67 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -17,6 +17,8 @@
 #include <linux/ath9k_platform.h>
 #endif /* CONFIG_PCI */
 
+#include <asm/mach-ath79/irq.h>
+
 #include "machtypes.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
@@ -33,7 +35,6 @@
 #define UBNT_XM_KEYS_POLL_INTERVAL	20
 #define UBNT_XM_KEYS_DEBOUNCE_INTERVAL	(3 * UBNT_XM_KEYS_POLL_INTERVAL)
 
-#define UBNT_XM_PCI_IRQ			48
 #define UBNT_XM_EEPROM_ADDR		(u8 *) KSEG1ADDR(0x1fff1000)
 
 static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
@@ -86,7 +87,7 @@ static struct ath9k_platform_data ubnt_xm_eeprom_data;
 
 static struct ar724x_pci_data ubnt_xm_pci_data[] = {
 	{
-		.irq	= UBNT_XM_PCI_IRQ,
+		.irq	= ATH79_PCI_IRQ(0),
 		.pdata	= &ubnt_xm_eeprom_data,
 	},
 };
diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h
index 519958f..6ae2646 100644
--- a/arch/mips/include/asm/mach-ath79/irq.h
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -10,11 +10,15 @@
 #define __ASM_MACH_ATH79_IRQ_H
 
 #define MIPS_CPU_IRQ_BASE	0
-#define NR_IRQS			40
+#define NR_IRQS			46
 
 #define ATH79_MISC_IRQ_BASE	8
 #define ATH79_MISC_IRQ_COUNT	32
 
+#define ATH79_PCI_IRQ_BASE	(ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
+#define ATH79_PCI_IRQ_COUNT	6
+#define ATH79_PCI_IRQ(_x)	(ATH79_PCI_IRQ_BASE + (_x))
+
 #define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
 #define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
 #define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
-- 
1.7.2.1

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

* [PATCH 05/12] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (3 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 04/12] MIPS: ath79: fix a wrong IRQ number Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 06/12] MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c Gabor Juhos
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The PCI Host Controller of the AR724x SoC has a
built-in IRQ controller. The current code does
not supports that, so the IRQ lines wired to this
controller are not usable. This leads to failed
'request_irq' calls:

  ath9k 0000:00:00.0: request_irq failed
  ath9k: probe of 0000:00:00.0 failed with error -89

This patch adds support for the IRQ controller
in order to make PCI IRQs work.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/pci.c                  |    3 +-
 arch/mips/include/asm/mach-ath79/pci.h |    4 +-
 arch/mips/pci/pci-ar724x.c             |  111 +++++++++++++++++++++++++++++++-
 3 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 72281fb..14f981c2 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -10,6 +10,7 @@
 
 #include <linux/pci.h>
 #include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/irq.h>
 #include <asm/mach-ath79/pci.h>
 #include "pci.h"
 
@@ -50,7 +51,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 int __init ath79_register_pci(void)
 {
 	if (soc_is_ar724x())
-		return ar724x_pcibios_init();
+		return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
 
 	return -ENODEV;
 }
diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h
index 0aaf41f..a659e40 100644
--- a/arch/mips/include/asm/mach-ath79/pci.h
+++ b/arch/mips/include/asm/mach-ath79/pci.h
@@ -12,9 +12,9 @@
 #define __ASM_MACH_ATH79_PCI_H
 
 #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X)
-int ar724x_pcibios_init(void);
+int ar724x_pcibios_init(int irq);
 #else
-static inline int ar724x_pcibios_init(void) { return 0 };
+static inline int ar724x_pcibios_init(int irq) { return 0 };
 #endif
 
 #endif /* __ASM_MACH_ATH79_PCI_H */
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index cef6519..6a520a6 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -8,12 +8,17 @@
  *  by the Free Software Foundation.
  */
 
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
 #include <asm/mach-ath79/pci.h>
 
 #define AR724X_PCI_CFG_BASE	0x14000000
 #define AR724X_PCI_CFG_SIZE	0x1000
+#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000)
+#define AR724X_PCI_CTRL_SIZE	0x100
+
 #define AR724X_PCI_MEM_BASE	0x10000000
 #define AR724X_PCI_MEM_SIZE	0x08000000
 
@@ -29,6 +34,7 @@
 
 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;
@@ -175,14 +181,115 @@ static struct pci_controller ar724x_pci_controller = {
 	.mem_resource	= &ar724x_mem_resource,
 };
 
-int __init ar724x_pcibios_init(void)
+static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
+	void __iomem *base;
+	u32 pending;
+
+	base = ar724x_pci_ctrl_base;
+
+	pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
+		  __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+
+	if (pending & AR724X_PCI_INT_DEV0)
+		generic_handle_irq(ATH79_PCI_IRQ(0));
+
+	else
+		spurious_interrupt();
+}
+
+static void ar724x_pci_irq_unmask(struct irq_data *d)
+{
+	void __iomem *base;
+	u32 t;
+
+	base = ar724x_pci_ctrl_base;
+
+	switch (d->irq) {
+	case ATH79_PCI_IRQ(0):
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_MASK);
+	}
+}
+
+static void ar724x_pci_irq_mask(struct irq_data *d)
+{
+	void __iomem *base;
+	u32 t;
+
+	base = ar724x_pci_ctrl_base;
+
+	switch (d->irq) {
+	case ATH79_PCI_IRQ(0):
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_MASK);
+
+		t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_STATUS);
+
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_STATUS);
+	}
+}
+
+static struct irq_chip ar724x_pci_irq_chip = {
+	.name		= "AR724X PCI ",
+	.irq_mask	= ar724x_pci_irq_mask,
+	.irq_unmask	= ar724x_pci_irq_unmask,
+	.irq_mask_ack	= ar724x_pci_irq_mask,
+};
+
+static void __init ar724x_pci_irq_init(int irq)
+{
+	void __iomem *base;
+	int i;
+
+	base = ar724x_pci_ctrl_base;
+
+	__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);
+
+	for (i = ATH79_PCI_IRQ_BASE;
+	     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_chained_handler(irq, ar724x_pci_irq_handler);
+}
+
+int __init ar724x_pcibios_init(int irq)
+{
+	int ret;
+
+	ret = -ENOMEM;
+
 	ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
 					 AR724X_PCI_CFG_SIZE);
 	if (ar724x_pci_devcfg_base == NULL)
-		return -ENOMEM;
+		goto err;
 
+	ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE,
+				       AR724X_PCI_CTRL_SIZE);
+	if (ar724x_pci_ctrl_base == NULL)
+		goto err_unmap_devcfg;
+
+	ar724x_pci_irq_init(irq);
 	register_pci_controller(&ar724x_pci_controller);
 
 	return PCIBIOS_SUCCESSFUL;
+
+err_unmap_devcfg:
+	iounmap(ar724x_pci_devcfg_base);
+err:
+	return ret;
 }
-- 
1.7.2.1

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

* [PATCH 06/12] MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (4 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 05/12] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 07/12] MIPS: ath79: allow to use board specific pci_plat_dev_init functions Gabor Juhos
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

Remove a superfluous ifdef around an include. Also
reorganize the board setup code a bit, so another
ifdef can be removed.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/mach-ubnt-xm.c |   23 ++++++++++++-----------
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index 0d95b67..1e6b986 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -12,10 +12,7 @@
 
 #include <linux/init.h>
 #include <linux/pci.h>
-
-#ifdef CONFIG_PCI
 #include <linux/ath9k_platform.h>
-#endif /* CONFIG_PCI */
 
 #include <asm/mach-ath79/irq.h>
 
@@ -91,6 +88,17 @@ static struct ar724x_pci_data ubnt_xm_pci_data[] = {
 		.pdata	= &ubnt_xm_eeprom_data,
 	},
 };
+
+static void __init ubnt_xm_pci_init(void)
+{
+	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
+	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
+
+	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
+	ath79_register_pci();
+}
+#else
+static inline void ubnt_xm_pci_init(void) {}
 #endif /* CONFIG_PCI */
 
 static void __init ubnt_xm_init(void)
@@ -105,14 +113,7 @@ static void __init ubnt_xm_init(void)
 	ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
 			   ARRAY_SIZE(ubnt_xm_spi_info));
 
-#ifdef CONFIG_PCI
-	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
-	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
-
-	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
-#endif /* CONFIG_PCI */
-
-	ath79_register_pci();
+	ubnt_xm_pci_init();
 }
 
 MIPS_MACHINE(ATH79_MACH_UBNT_XM,
-- 
1.7.2.1

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

* [PATCH 07/12] MIPS: ath79: allow to use board specific pci_plat_dev_init functions
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (5 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 06/12] MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs Gabor Juhos
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

Th current implementation causes NULL pointer dereference
if 'pci_data' is not set:

pci 0000:00:00.0: BAR 0: assigned [mem 0x10000000-0x1000ffff 64bit]
pci 0000:00:00.0: BAR 0: set to [mem 0x10000000-0x1000ffff 64bit] (PCI
address [0x10000000-0x1000ffff])
CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 802daca0, ra == 802e78a4
Oops[#1]:
Cpu 0
$ 0   : 00000000 80420000 00000000 00000000
$ 4   : 00000000 00000000 00000001 00000001
$ 8   : 00000001 0000032c 81c54700 00000001
$12   : 0000032d 0000000f 00000000 ffffffff
$16   : 81c14c00 00000001 802dac74 80195f98
$20   : 802ea050 00000000 00000000 00000000
$24   : 00000003 800617f0
$28   : 81c20000 81c21e70 00000000 802e78a4
Hi    : 00000000
Lo    : 4190ab00
epc   : 802daca0 0x802daca0
    Not tainted
ra    : 802e78a4 0x802e78a4
Status: 1000c003    KERNEL EXL IE
Cause : 00800008
BadVA : 00000000
PrId  : 00019374 (MIPS 24Kc)
Modules linked in:
Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
Stack : 00000000 8027d5d8 802e8ae0 00000000 01000000 802e8b5c 81c50600 00000000
        802ff290 00000000 80420000 802ea0bc 00000000 00000000 80420000 802ff290
        80420000 80060930 33390000 00000000 00002308 80140a80 00000028 802d0000
        00000000 800ba024 802ff004 802ff0c8 802ff290 00000000 00000000 00000000
        00000000 802d897c 01234567 7f827068 00000000 0045f798 00460000 00000000

This can be avoided by calling the 'ar724x_pci_add_data'
function from the board specific setup code. However it
makes no sense to use that function for every board,
especially when the board does not needs to set the
platform_data field of any PCI device.

The patch allows the board setup code to specify a board
specific function if that is required.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
The pci_irq_map function can throw another NULL pointer
dereference, that will be fixed in a subsequent patch.
---
 arch/mips/ath79/mach-ubnt-xm.c |   13 ++++++++++++-
 arch/mips/ath79/pci.c          |   14 ++++++++------
 arch/mips/ath79/pci.h          |    4 +++-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index 1e6b986..ca47ba5 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -85,16 +85,27 @@ static struct ath9k_platform_data ubnt_xm_eeprom_data;
 static struct ar724x_pci_data ubnt_xm_pci_data[] = {
 	{
 		.irq	= ATH79_PCI_IRQ(0),
-		.pdata	= &ubnt_xm_eeprom_data,
 	},
 };
 
+static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev)
+{
+	switch (PCI_SLOT(dev->devfn)) {
+	case 0:
+		dev->dev.platform_data = &ubnt_xm_eeprom_data;
+		break;
+	}
+
+	return 0;
+}
+
 static void __init ubnt_xm_pci_init(void)
 {
 	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
 	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
 
 	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
+	ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init);
 	ath79_register_pci();
 }
 #else
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 14f981c2..2b4c730 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -14,6 +14,7 @@
 #include <asm/mach-ath79/pci.h>
 #include "pci.h"
 
+static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
 static struct ar724x_pci_data *pci_data;
 static int pci_data_size;
 
@@ -38,14 +39,15 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 
 int pcibios_plat_dev_init(struct pci_dev *dev)
 {
-	unsigned int devfn = dev->devfn;
-
-	if (devfn > pci_data_size - 1)
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (ath79_pci_plat_dev_init)
+		return ath79_pci_plat_dev_init(dev);
 
-	dev->dev.platform_data = pci_data[devfn].pdata;
+	return 0;
+}
 
-	return PCIBIOS_SUCCESSFUL;
+void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
+{
+	ath79_pci_plat_dev_init = func;
 }
 
 int __init ath79_register_pci(void)
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index e0601c4..de30e15 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -13,14 +13,16 @@
 
 struct ar724x_pci_data {
 	int irq;
-	void *pdata;
 };
 
 void ar724x_pci_add_data(struct ar724x_pci_data *data, int size);
 
 #ifdef CONFIG_PCI
+void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
 int ath79_register_pci(void);
 #else
+static inline void
+ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
 static inline int ath79_register_pci(void) { return 0; }
 #endif
 
-- 
1.7.2.1

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

* [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (6 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 07/12] MIPS: ath79: allow to use board specific pci_plat_dev_init functions Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-23  9:21   ` Sergei Shtylyov
  2011-11-22 23:14 ` [PATCH 09/12] MIPS: ath79: allow to use SoC specific PCI IRQ maps Gabor Juhos
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The Atheros AR71XX SoCs have a built-in PCI Host Controller.
This patch adds a driver for that, and modifies the relevant
files in order to allow to register the PCI controller from
board specific setup.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---
 arch/mips/ath79/Kconfig                |    1 +
 arch/mips/include/asm/mach-ath79/pci.h |    6 ++++++
 arch/mips/pci/Makefile                 |    1 +
 3 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index e0fae8f..bc6edad 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -52,6 +52,7 @@ endmenu
 config SOC_AR71XX
 	select USB_ARCH_HAS_EHCI
 	select USB_ARCH_HAS_OHCI
+	select HW_HAS_PCI
 	def_bool n
 
 config SOC_AR724X
diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h
index a659e40..a3d0655 100644
--- a/arch/mips/include/asm/mach-ath79/pci.h
+++ b/arch/mips/include/asm/mach-ath79/pci.h
@@ -11,6 +11,12 @@
 #ifndef __ASM_MACH_ATH79_PCI_H
 #define __ASM_MACH_ATH79_PCI_H
 
+#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR71XX)
+int ar71xx_pcibios_init(void);
+#else
+static inline int ar71xx_pcibios_init(void) { return 0 };
+#endif
+
 #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X)
 int ar724x_pcibios_init(int irq);
 #else
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 172277c..b1c0a1c 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
 obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
 					ops-bcm63xx.o
 obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
+obj-$(CONFIG_SOC_AR71XX)	+= pci-ar71xx.o
 obj-$(CONFIG_SOC_AR724X)	+= pci-ar724x.o
 
 #
-- 
1.7.2.1

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

* [PATCH 09/12] MIPS: ath79: allow to use SoC specific PCI IRQ maps
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (7 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 10/12] MIPS: ath79: remove ar724x_pci_add_data function Gabor Juhos
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The PCI controllers in the AR71XX and in the
AR724X SoCs are different, and both of them
uses different IRQ wiring.

The patch modifies the 'pcibios_map_irq' function
in order to allow to use different IRQ maps for
the different SoCs. The patch also adds a function,
which lets the board setup code to override the
default IRQ map.

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

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 2b4c730..365a8b6 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -8,6 +8,7 @@
  *  by the Free Software Foundation.
  */
 
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/irq.h>
@@ -15,9 +16,35 @@
 #include "pci.h"
 
 static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
+static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
+static unsigned ath79_pci_nr_irqs __initdata;
 static struct ar724x_pci_data *pci_data;
 static int pci_data_size;
 
+static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
+	{
+		.slot	= 17,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	}, {
+		.slot	= 18,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(1),
+	}, {
+		.slot	= 19,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(2),
+	}
+};
+
+static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
+	{
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	}
+};
+
 void ar724x_pci_add_data(struct ar724x_pci_data *data, int size)
 {
 	pci_data	= data;
@@ -26,13 +53,40 @@ void ar724x_pci_add_data(struct ar724x_pci_data *data, int size)
 
 int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 {
-	unsigned int devfn = dev->devfn;
 	int irq = -1;
+	int i;
+
+	if (ath79_pci_nr_irqs == 0 ||
+	    ath79_pci_irq_map == NULL) {
+		if (soc_is_ar71xx()) {
+			ath79_pci_irq_map = ar71xx_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map);
+		} else if (soc_is_ar724x()) {
+			ath79_pci_irq_map = ar724x_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map);
+		} else {
+			pr_crit("pci %s: invalid irq map\n",
+				pci_name((struct pci_dev *) dev));
+			return irq;
+		}
+	}
+
+	for (i = 0; i < ath79_pci_nr_irqs; i++) {
+		const struct ath79_pci_irq *entry;
 
-	if (devfn > pci_data_size - 1)
-		return irq;
+		entry = &ath79_pci_irq_map[i];
+		if (entry->slot == slot && entry->pin == pin) {
+			irq = entry->irq;
+			break;
+		}
+	}
 
-	irq = pci_data[devfn].irq;
+	if (irq < 0)
+		pr_crit("pci %s: no irq found for pin %u\n",
+			pci_name((struct pci_dev *) dev), pin);
+	else
+		pr_info("pci %s: using irq %d for pin %u\n",
+			pci_name((struct pci_dev *) dev), irq, pin);
 
 	return irq;
 }
@@ -45,6 +99,13 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 	return 0;
 }
 
+void __init ath79_pci_set_irq_map(unsigned nr_irqs,
+				  const struct ath79_pci_irq *map)
+{
+	ath79_pci_nr_irqs = nr_irqs;
+	ath79_pci_irq_map = map;
+}
+
 void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
 {
 	ath79_pci_plat_dev_init = func;
@@ -52,6 +113,9 @@ void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
 
 int __init ath79_register_pci(void)
 {
+	if (soc_is_ar71xx())
+		return ar71xx_pcibios_init();
+
 	if (soc_is_ar724x())
 		return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
 
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index de30e15..a5c4e58 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -15,13 +15,22 @@ struct ar724x_pci_data {
 	int irq;
 };
 
+struct ath79_pci_irq {
+	u8	slot;
+	u8	pin;
+	int	irq;
+};
+
 void ar724x_pci_add_data(struct ar724x_pci_data *data, int size);
 
 #ifdef CONFIG_PCI
+void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map);
 void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
 int ath79_register_pci(void);
 #else
 static inline void
+ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map) {}
+static inline void
 ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
 static inline int ath79_register_pci(void) { return 0; }
 #endif
-- 
1.7.2.1

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

* [PATCH 10/12] MIPS: ath79: remove ar724x_pci_add_data function
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (8 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 09/12] MIPS: ath79: allow to use SoC specific PCI IRQ maps Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 11/12] MIPS: ath79: register PCI controller on the PB44 board Gabor Juhos
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The variables set by this function are not used anymore.
Remove the function and the relevant variables as well.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/mach-ubnt-xm.c |    7 -------
 arch/mips/ath79/pci.c          |    8 --------
 arch/mips/ath79/pci.h          |    6 ------
 3 files changed, 0 insertions(+), 21 deletions(-)

diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index ca47ba5..4a3c606 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -82,12 +82,6 @@ static struct ath79_spi_platform_data ubnt_xm_spi_data = {
 #ifdef CONFIG_PCI
 static struct ath9k_platform_data ubnt_xm_eeprom_data;
 
-static struct ar724x_pci_data ubnt_xm_pci_data[] = {
-	{
-		.irq	= ATH79_PCI_IRQ(0),
-	},
-};
-
 static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev)
 {
 	switch (PCI_SLOT(dev->devfn)) {
@@ -104,7 +98,6 @@ static void __init ubnt_xm_pci_init(void)
 	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
 	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
 
-	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
 	ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init);
 	ath79_register_pci();
 }
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 365a8b6..253a382 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -18,8 +18,6 @@
 static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
 static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
 static unsigned ath79_pci_nr_irqs __initdata;
-static struct ar724x_pci_data *pci_data;
-static int pci_data_size;
 
 static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
 	{
@@ -45,12 +43,6 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
 	}
 };
 
-void ar724x_pci_add_data(struct ar724x_pci_data *data, int size)
-{
-	pci_data	= data;
-	pci_data_size	= size;
-}
-
 int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 {
 	int irq = -1;
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index a5c4e58..5ebed21 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -11,18 +11,12 @@
 #ifndef _ATH79_PCI_H
 #define _ATH79_PCI_H
 
-struct ar724x_pci_data {
-	int irq;
-};
-
 struct ath79_pci_irq {
 	u8	slot;
 	u8	pin;
 	int	irq;
 };
 
-void ar724x_pci_add_data(struct ar724x_pci_data *data, int size);
-
 #ifdef CONFIG_PCI
 void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map);
 void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
-- 
1.7.2.1

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

* [PATCH 11/12] MIPS: ath79: register PCI controller on the PB44 board
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (9 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 10/12] MIPS: ath79: remove ar724x_pci_add_data function Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-22 23:14 ` [PATCH 12/12] MIPS: ath79: update copyright headers of PCI related files Gabor Juhos
  2011-11-23 11:35 ` [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support René Bolldorf
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

The PB44 reference board has two miniPCI slots. Register
the PCI controller to make those usable.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 arch/mips/ath79/mach-pb44.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index fe9701a..c5f0ea5 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -19,6 +19,7 @@
 #include "dev-leds-gpio.h"
 #include "dev-spi.h"
 #include "dev-usb.h"
+#include "pci.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
@@ -114,6 +115,7 @@ static void __init pb44_init(void)
 	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
 			   ARRAY_SIZE(pb44_spi_info));
 	ath79_register_usb();
+	ath79_register_pci();
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
-- 
1.7.2.1

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

* [PATCH 12/12] MIPS: ath79: update copyright headers of PCI related files
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (10 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 11/12] MIPS: ath79: register PCI controller on the PB44 board Gabor Juhos
@ 2011-11-22 23:14 ` Gabor Juhos
  2011-11-23 11:35 ` [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support René Bolldorf
  12 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-22 23:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, René Bolldorf, Imre Kaloz, Gabor Juhos

Add copyright records according to the recent changes in
the PCI code. Also fix up the descriptions.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---
Just in case if someone is curious about why 2008 and 2009 years are
present in this change:

The recent PCI specific changes were based on an existing
code which can be found in the OpenWrt repository, and we
are working on that since 2008.
---
 arch/mips/ath79/pci.c                  |    4 ++++
 arch/mips/ath79/pci.h                  |    4 +++-
 arch/mips/include/asm/mach-ath79/pci.h |    4 +++-
 arch/mips/pci/pci-ar724x.c             |    3 ++-
 4 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 253a382..bc40070 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -2,6 +2,10 @@
  *  Atheros AR71XX/AR724X specific PCI setup code
  *
  *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License version 2 as published
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index 5ebed21..51c6625 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -1,7 +1,9 @@
 /*
- *  Atheros 724x PCI support
+ *  Atheros AR71XX/AR724X PCI support
  *
  *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License version 2 as published
diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h
index a3d0655..58d065f 100644
--- a/arch/mips/include/asm/mach-ath79/pci.h
+++ b/arch/mips/include/asm/mach-ath79/pci.h
@@ -1,7 +1,9 @@
 /*
- *  Atheros 724x PCI support
+ *  Atheros AR71XX/AR724X PCI support
  *
  *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License version 2 as published
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 6a520a6..2c2c34f 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -1,7 +1,8 @@
 /*
- *  Atheros 724x PCI support
+ *  Atheros AR724X PCI host controller driver
  *
  *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License version 2 as published
-- 
1.7.2.1

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

* Re: [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs
  2011-11-22 23:14 ` [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs Gabor Juhos
@ 2011-11-23  9:21   ` Sergei Shtylyov
  2011-11-23 12:04     ` Gabor Juhos
  0 siblings, 1 reply; 25+ messages in thread
From: Sergei Shtylyov @ 2011-11-23  9:21 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, René Bolldorf, Imre Kaloz

Hello.

On 23-11-2011 3:14, Gabor Juhos wrote:

> The Atheros AR71XX SoCs have a built-in PCI Host Controller.
> This patch adds a driver for that, and modifies the relevant
> files in order to allow to register the PCI controller from
> board specific setup.

> Signed-off-by: Gabor Juhos<juhosg@openwrt.org>
> Signed-off-by: Imre Kaloz<kaloz@openwrt.org>
[...]

> diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> index 172277c..b1c0a1c 100644
> --- a/arch/mips/pci/Makefile
> +++ b/arch/mips/pci/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
>   obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
>   					ops-bcm63xx.o
>   obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
> +obj-$(CONFIG_SOC_AR71XX)	+= pci-ar71xx.o

    OK, but where's pci_ar71xx.c file itself? Your whole patchset doesn't seem 
to include it...

WBR, Sergei

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
                   ` (11 preceding siblings ...)
  2011-11-22 23:14 ` [PATCH 12/12] MIPS: ath79: update copyright headers of PCI related files Gabor Juhos
@ 2011-11-23 11:35 ` René Bolldorf
  2011-11-23 14:08   ` Gabor Juhos
  12 siblings, 1 reply; 25+ messages in thread
From: René Bolldorf @ 2011-11-23 11:35 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

I don't know on which board you tested the patches,
but the pci read/write function are now broken.

-My patchset has the ability to use different irqs (see pci_data).
-I never hit the pci controller bug, any steps to replicate?

On Wed, Nov 23, 2011 at 12:14 AM, Gabor Juhos <juhosg@openwrt.org> wrote:
> This patch set fixes some errors in the AR724X specific
> PCI code, and adds support for the PCI Host controller
> of the AR71XX SoCs.
>
> This set depends on v4 of the
> 'MIPS: ath79: cleanup AR724X PCI support code' patches.
>
> Gabor Juhos (12):
>  MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c
>  MIPS: ath79: fix broken ar724x_pci_{read,write} functions
>  MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs
>  MIPS: ath79: fix a wrong IRQ number
>  MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
>  MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c
>  MIPS: ath79: allow to use board specific pci_plat_dev_init functions
>  MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs
>  MIPS: ath79: allow to use SoC specific PCI IRQ maps
>  MIPS: ath79: remove ar724x_pci_add_data function
>  MIPS: ath79: register PCI controller on the PB44 board
>  MIPS: ath79: update copyright headers of PCI related files
>
>  arch/mips/ath79/Kconfig                |    1 +
>  arch/mips/ath79/mach-pb44.c            |    2 +
>  arch/mips/ath79/mach-ubnt-xm.c         |   42 ++++---
>  arch/mips/ath79/pci.c                  |   97 ++++++++++++---
>  arch/mips/ath79/pci.h                  |   19 ++-
>  arch/mips/include/asm/mach-ath79/irq.h |    6 +-
>  arch/mips/include/asm/mach-ath79/pci.h |   14 ++-
>  arch/mips/pci/Makefile                 |    1 +
>  arch/mips/pci/pci-ar724x.c             |  215 +++++++++++++++++++++++++++-----
>  9 files changed, 318 insertions(+), 79 deletions(-)
>
> --
> 1.7.2.1
>
>

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

* Re: [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs
  2011-11-23  9:21   ` Sergei Shtylyov
@ 2011-11-23 12:04     ` Gabor Juhos
  0 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-23 12:04 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Ralf Baechle, linux-mips, René Bolldorf, Imre Kaloz

Hi Sergei,

>> @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)        += pci-bcm47xx.o
>>   obj-$(CONFIG_BCM63XX)        += pci-bcm63xx.o fixup-bcm63xx.o \
>>                       ops-bcm63xx.o
>>   obj-$(CONFIG_MIPS_ALCHEMY)    += pci-alchemy.o
>> +obj-$(CONFIG_SOC_AR71XX)    += pci-ar71xx.o
> 
>    OK, but where's pci_ar71xx.c file itself? Your whole patchset doesn't seem to
> include it...

You are correct, I forgot to add that. I have added that now, it will be in v2
of the patch-set.

Thanks,
Gabor

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 11:35 ` [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support René Bolldorf
@ 2011-11-23 14:08   ` Gabor Juhos
  2011-11-23 14:40     ` René Bolldorf
  0 siblings, 1 reply; 25+ messages in thread
From: Gabor Juhos @ 2011-11-23 14:08 UTC (permalink / raw)
  To: René Bolldorf; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

Hi René,

> I don't know on which board you tested the patches,

The patches were tested on an Ubiquiti Bullet 5M (AR7240), on a 
TP-Link TL-MR3420 (AR7241), and on an Atheros PB44 (AR7161) boards. 
You can find the bootlog of the Bullet 5M here: 
http://pastebin.com/p3UiU29M

> but the pci read/write function are now broken.

Here is a snippet from the original pci_read function:

	switch (size) {
	case 1:
		addr = where & ~3;
		mask = 0xff000000 >> ((where % 4) * 8);
		tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
		tval = tval & ~mask;
		*value = (tval >> ((4 - (where % 4))*8));
		break;

Say, we want to read four values from where={0,1,2,3} and with size=1. 
Because 'addr' will be zero, we will read the same 32 bits wide register 
in all cases, so I'm using 'tval = 0x12345678' for simplicity.

if where == 0:

mask = 0xff000000 >> ((0 % 4) * 8) = 0xff000000 >> (0 * 8) = 0xff000000 >> 0 = 0xff000000
tval = 0x12345678 & ~0xff000000 = 0x12345678 & 0x00ffffff = 0x00345678
*value = 0x00345678 >> ((4 - (0 % 4 )) * 8) = 0x00345678 >> ((4 - 0) * 8) = 0x00345678 >> (4 * 8) = 0x00345678 >> 32 = 0x00000000

Because shift is 32, the CPU will do nothing with the value, so it will 
return '0x00345678'. The value should be '0x78'.

if where == 1:

mask = 0xff000000 >> ((1 % 4) * 8) = 0xff000000 >> (1 * 8) = 0xff000000 >> 8 = 0x00ff0000
tval = 0x12345678 & ~0x00ff0000 = 0x12345678 & 0xff00ffff = 0x12005678
*value = 0x12005678 >> ((4 - (1 % 4 )) * 8) = 0x12005678 >> ((4 - 1) * 8) = 0x12005678 >> (3 * 8) = 0x12005678 >> 24 = 0x00000012

The value should be '0x56' instead of '0x00000012'.

if where = 2:

mask = 0xff000000 >> ((2 % 4) * 8) = 0xff000000 >> (2 * 8) = 0xff000000 >> 16 = 0x0000ff00
tval = 0x12345678 & ~0x0000ff00 = 0x12345678 & 0xffff00ff = 0x12340078
*value = 0x12340078 >> ((4 - (2 % 4 )) * 8) = 0x12340078 >> ((4 - 2) * 8) = 0x12340078 >> (2 * 8) = 0x12340078 >> 16 = 0x00001234

The value should be '0x34' instead of '0x00001234'.

if where = 3:

mask = 0xff000000 >> ((3 % 4) * 8) = 0xff000000 >> (3 * 8) = 0xff000000 >> 24 = 0x000000ff
tval = 0x12345678 & ~0x000000ff = 0x12345678 & 0xffffff00 = 0x12345600
*value = 0x12345600 >> ((4 - (3 % 4 )) * 8) = 0x12345600 >> ((4 - 3) * 8) = 0x12345600 >> (1 * 8) = 0x12345600 >> 8 = 0x00123456

The value should be '0x12' instead of '0x00123456'.

Due to this, and the other errors in the pci_write functions, 
Linux fails to assign the correct IRQ number for the device.
It can be noticed from the output of 'lspci -vv':

        Interrupt: pin A routed to IRQ 0
vs
        Interrupt: pin A routed to IRQ 48

I can show you the errors in the write functions, if you would 
like to see that as well.


I'm curious why do you think that it is broken now. 
You are getting a data bus error by any chance?

> -My patchset has the ability to use different irqs (see pci_data).

Yes, I know. You can set that from the board setup by calling the 
{ath,ar}724x_pci_add_data function. 

However that approach has some limitations:

1. It does not supports assigning a different IRQ for the different 
interrupt pins (A,B,C,D) of a PCI device. This is not a problem on the
AR724X boards, but that functionality is needed by some AR71xx based 
boards.

2. The devfn field of the struct pci_device is 0 on the AR724X based boards. 
However on AR71XX they are different. On the PB44 board, the devfn of a PCI 
device in the first miniPCI slot is 136, and it is 144 for the second slot. 
So if I want to define the pci_data for the PB44 board, I should write 
something like this:

static struct ath724x_pci_data pb44_pci_data[] = {
	[136] = { .irq	= PCI_IRQ_A },
	[144] = { .irq	= PCI_IRQ_B },
};

The array has 136+8 unused entries, which wastes the memory.

3. The {ath,ar}724x_pci_add_data function must be called from the 
setup code of each board. If the board setup code does not calls the 
function, the kernel will throw an oops due to a NULL pointer dereference.

> int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
> {
> 	unsigned int devfn = dev->devfn;
> 	int irq = -1;
> 

If the '{ath,ar}724x_pci_add_data' function is not called, pci_data_size = 0, 
and pci_data = NULL;

> 	if (devfn > pci_data_size - 1)
> 		return irq;

devfn is always >= 0, and (pci_data_size - 1) = -1 = 0xffffffff, so the 
condition in this if statement will be evaluated to false ...

> 	irq = pci_data[devfn].irq;

... and this line will cause the following oops:

CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 803c4cc8, ra == 803c4ca4
Oops[#1]:
Cpu 0
$ 0   : 00000000 80510000 00000000 00000000
$ 4   : 803b4128 00000a52 ffffffff 0000000a
$ 8   : 0000000a 00000000 00000001 00000000
$12   : 00000374 0000000f 00000001 ffffffff
$16   : 00000000 80510000 803c4c74 8019d838
$20   : 803d3fe0 00000000 00000000 00000000
$24   : 00000002 800617f0
$28   : 81c20000 81c21e50 00000000 803c4ca4
Hi    : 00000000
Lo    : 068e7780
epc   : 803c4cc8 pcibios_map_irq+0x54/0x6c
    Not tainted
ra    : 803c4ca4 pcibios_map_irq+0x30/0x6c
Status: 1000c003    KERNEL EXL IE
Cause : 00800008
BadVA : 00000000
PrId  : 00019374 (MIPS 24Kc)
Modules linked in:
Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
Stack : 81c21e58 00000000 ffffffff 00000001 00000000 81c14c00 00000001 803d1840
        00000000 80300ce8 803d2a7c 00000000 01000000 803d2af8 81c46800 00000000
        803e9584 00000000 80510000 803d404c 00000000 00000000 80510000 803e9584
        80510000 80060930 33390000 00000000 0000a498 80143058 00000028 803b0000
        00000000 800bc4e4 803e92d0 803e9394 803e9584 00000000 00000000 00000000
        ...
Call Trace:
[<803c4cc8>] pcibios_map_irq+0x54/0x6c
[<803d1840>] pci_fixup_irqs+0x78/0xc4
[<803d404c>] pcibios_init+0x6c/0x8c
[<80060930>] do_one_initcall+0x3c/0x1cc
[<803c297c>] kernel_init+0xa4/0x138
[<80063c44>] kernel_thread_helper+0x10/0x18

Code: 8c4250b4  001080c0  00508021 <8e020000> 8fbf001c  8fb10018  8fb00014  03e00008  27bd0020

> 
> 	return irq;
> }
> -I never hit the pci controller bug, any steps to replicate?

Hm, weird. Your devices are based on AR7240 or or AR7241?

Regards,
Gabor

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 14:08   ` Gabor Juhos
@ 2011-11-23 14:40     ` René Bolldorf
  2011-11-23 15:15       ` René Bolldorf
  2011-11-23 20:39       ` Gabor Juhos
  0 siblings, 2 replies; 25+ messages in thread
From: René Bolldorf @ 2011-11-23 14:40 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

Hi

2011/11/23 Gabor Juhos <juhosg@openwrt.org>:
> Hi René,
>
>> I don't know on which board you tested the patches,
>
> The patches were tested on an Ubiquiti Bullet 5M (AR7240), on a
> TP-Link TL-MR3420 (AR7241), and on an Atheros PB44 (AR7161) boards.
> You can find the bootlog of the Bullet 5M here:
> http://pastebin.com/p3UiU29M
>
>> but the pci read/write function are now broken.
>
> Here is a snippet from the original pci_read function:
>
>        switch (size) {
>        case 1:
>                addr = where & ~3;
>                mask = 0xff000000 >> ((where % 4) * 8);
>                tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
>                tval = tval & ~mask;
>                *value = (tval >> ((4 - (where % 4))*8));
>                break;
>
> Say, we want to read four values from where={0,1,2,3} and with size=1.
> Because 'addr' will be zero, we will read the same 32 bits wide register
> in all cases, so I'm using 'tval = 0x12345678' for simplicity.
>
> if where == 0:
>
> mask = 0xff000000 >> ((0 % 4) * 8) = 0xff000000 >> (0 * 8) = 0xff000000 >> 0 = 0xff000000
> tval = 0x12345678 & ~0xff000000 = 0x12345678 & 0x00ffffff = 0x00345678
> *value = 0x00345678 >> ((4 - (0 % 4 )) * 8) = 0x00345678 >> ((4 - 0) * 8) = 0x00345678 >> (4 * 8) = 0x00345678 >> 32 = 0x00000000
>
> Because shift is 32, the CPU will do nothing with the value, so it will
> return '0x00345678'. The value should be '0x78'.
>
> if where == 1:
>
> mask = 0xff000000 >> ((1 % 4) * 8) = 0xff000000 >> (1 * 8) = 0xff000000 >> 8 = 0x00ff0000
> tval = 0x12345678 & ~0x00ff0000 = 0x12345678 & 0xff00ffff = 0x12005678
> *value = 0x12005678 >> ((4 - (1 % 4 )) * 8) = 0x12005678 >> ((4 - 1) * 8) = 0x12005678 >> (3 * 8) = 0x12005678 >> 24 = 0x00000012
>
> The value should be '0x56' instead of '0x00000012'.
>
> if where = 2:
>
> mask = 0xff000000 >> ((2 % 4) * 8) = 0xff000000 >> (2 * 8) = 0xff000000 >> 16 = 0x0000ff00
> tval = 0x12345678 & ~0x0000ff00 = 0x12345678 & 0xffff00ff = 0x12340078
> *value = 0x12340078 >> ((4 - (2 % 4 )) * 8) = 0x12340078 >> ((4 - 2) * 8) = 0x12340078 >> (2 * 8) = 0x12340078 >> 16 = 0x00001234
>
> The value should be '0x34' instead of '0x00001234'.
>
> if where = 3:
>
> mask = 0xff000000 >> ((3 % 4) * 8) = 0xff000000 >> (3 * 8) = 0xff000000 >> 24 = 0x000000ff
> tval = 0x12345678 & ~0x000000ff = 0x12345678 & 0xffffff00 = 0x12345600
> *value = 0x12345600 >> ((4 - (3 % 4 )) * 8) = 0x12345600 >> ((4 - 3) * 8) = 0x12345600 >> (1 * 8) = 0x12345600 >> 8 = 0x00123456
>
> The value should be '0x12' instead of '0x00123456'.
>
> Due to this, and the other errors in the pci_write functions,
> Linux fails to assign the correct IRQ number for the device.
> It can be noticed from the output of 'lspci -vv':
>
>        Interrupt: pin A routed to IRQ 0
> vs
>        Interrupt: pin A routed to IRQ 48
>
> I can show you the errors in the write functions, if you would
> like to see that as well.
>
>
> I'm curious why do you think that it is broken now.
> You are getting a data bus error by any chance?
>

after a pci write, the pci read return bogus values.
However, I go through this tomorrow.

>> -My patchset has the ability to use different irqs (see pci_data).
>
> Yes, I know. You can set that from the board setup by calling the
> {ath,ar}724x_pci_add_data function.
>
> However that approach has some limitations:
>
> 1. It does not supports assigning a different IRQ for the different
> interrupt pins (A,B,C,D) of a PCI device. This is not a problem on the
> AR724X boards, but that functionality is needed by some AR71xx based
> boards.
>
> 2. The devfn field of the struct pci_device is 0 on the AR724X based boards.
> However on AR71XX they are different. On the PB44 board, the devfn of a PCI
> device in the first miniPCI slot is 136, and it is 144 for the second slot.
> So if I want to define the pci_data for the PB44 board, I should write
> something like this:
>
> static struct ath724x_pci_data pb44_pci_data[] = {
>        [136] = { .irq  = PCI_IRQ_A },
>        [144] = { .irq  = PCI_IRQ_B },
> };
>
> The array has 136+8 unused entries, which wastes the memory.
>
> 3. The {ath,ar}724x_pci_add_data function must be called from the
> setup code of each board. If the board setup code does not calls the
> function, the kernel will throw an oops due to a NULL pointer dereference.
>
>> int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
>> {
>>       unsigned int devfn = dev->devfn;
>>       int irq = -1;
>>
>
> If the '{ath,ar}724x_pci_add_data' function is not called, pci_data_size = 0,
> and pci_data = NULL;
>
>>       if (devfn > pci_data_size - 1)
>>               return irq;
>
> devfn is always >= 0, and (pci_data_size - 1) = -1 = 0xffffffff, so the
> condition in this if statement will be evaluated to false ...
>
>>       irq = pci_data[devfn].irq;
>
> ... and this line will cause the following oops:
>
> CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 803c4cc8, ra == 803c4ca4
> Oops[#1]:
> Cpu 0
> $ 0   : 00000000 80510000 00000000 00000000
> $ 4   : 803b4128 00000a52 ffffffff 0000000a
> $ 8   : 0000000a 00000000 00000001 00000000
> $12   : 00000374 0000000f 00000001 ffffffff
> $16   : 00000000 80510000 803c4c74 8019d838
> $20   : 803d3fe0 00000000 00000000 00000000
> $24   : 00000002 800617f0
> $28   : 81c20000 81c21e50 00000000 803c4ca4
> Hi    : 00000000
> Lo    : 068e7780
> epc   : 803c4cc8 pcibios_map_irq+0x54/0x6c
>    Not tainted
> ra    : 803c4ca4 pcibios_map_irq+0x30/0x6c
> Status: 1000c003    KERNEL EXL IE
> Cause : 00800008
> BadVA : 00000000
> PrId  : 00019374 (MIPS 24Kc)
> Modules linked in:
> Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
> Stack : 81c21e58 00000000 ffffffff 00000001 00000000 81c14c00 00000001 803d1840
>        00000000 80300ce8 803d2a7c 00000000 01000000 803d2af8 81c46800 00000000
>        803e9584 00000000 80510000 803d404c 00000000 00000000 80510000 803e9584
>        80510000 80060930 33390000 00000000 0000a498 80143058 00000028 803b0000
>        00000000 800bc4e4 803e92d0 803e9394 803e9584 00000000 00000000 00000000
>        ...
> Call Trace:
> [<803c4cc8>] pcibios_map_irq+0x54/0x6c
> [<803d1840>] pci_fixup_irqs+0x78/0xc4
> [<803d404c>] pcibios_init+0x6c/0x8c
> [<80060930>] do_one_initcall+0x3c/0x1cc
> [<803c297c>] kernel_init+0xa4/0x138
> [<80063c44>] kernel_thread_helper+0x10/0x18
>
> Code: 8c4250b4  001080c0  00508021 <8e020000> 8fbf001c  8fb10018  8fb00014  03e00008  27bd0020
>
>>
>>       return irq;
>> }

Ok

>> -I never hit the pci controller bug, any steps to replicate?
>
> Hm, weird. Your devices are based on AR7240 or or AR7241?
>
> Regards,
> Gabor
>

AR7241 AH-4A

Maybe it is better to split ar71xx and ar72xx pci support completly?

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 14:40     ` René Bolldorf
@ 2011-11-23 15:15       ` René Bolldorf
  2011-11-23 20:43         ` Gabor Juhos
  2011-11-23 20:39       ` Gabor Juhos
  1 sibling, 1 reply; 25+ messages in thread
From: René Bolldorf @ 2011-11-23 15:15 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

It seems your board is a older one.
Can you remove the heatsink and post the revision from the SoC?

2011/11/23 René Bolldorf <xsecute@googlemail.com>:
> Hi
>
> 2011/11/23 Gabor Juhos <juhosg@openwrt.org>:
>> Hi René,
>>
>>> I don't know on which board you tested the patches,
>>
>> The patches were tested on an Ubiquiti Bullet 5M (AR7240), on a
>> TP-Link TL-MR3420 (AR7241), and on an Atheros PB44 (AR7161) boards.
>> You can find the bootlog of the Bullet 5M here:
>> http://pastebin.com/p3UiU29M
>>
>>> but the pci read/write function are now broken.
>>
>> Here is a snippet from the original pci_read function:
>>
>>        switch (size) {
>>        case 1:
>>                addr = where & ~3;
>>                mask = 0xff000000 >> ((where % 4) * 8);
>>                tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
>>                tval = tval & ~mask;
>>                *value = (tval >> ((4 - (where % 4))*8));
>>                break;
>>
>> Say, we want to read four values from where={0,1,2,3} and with size=1.
>> Because 'addr' will be zero, we will read the same 32 bits wide register
>> in all cases, so I'm using 'tval = 0x12345678' for simplicity.
>>
>> if where == 0:
>>
>> mask = 0xff000000 >> ((0 % 4) * 8) = 0xff000000 >> (0 * 8) = 0xff000000 >> 0 = 0xff000000
>> tval = 0x12345678 & ~0xff000000 = 0x12345678 & 0x00ffffff = 0x00345678
>> *value = 0x00345678 >> ((4 - (0 % 4 )) * 8) = 0x00345678 >> ((4 - 0) * 8) = 0x00345678 >> (4 * 8) = 0x00345678 >> 32 = 0x00000000
>>
>> Because shift is 32, the CPU will do nothing with the value, so it will
>> return '0x00345678'. The value should be '0x78'.
>>
>> if where == 1:
>>
>> mask = 0xff000000 >> ((1 % 4) * 8) = 0xff000000 >> (1 * 8) = 0xff000000 >> 8 = 0x00ff0000
>> tval = 0x12345678 & ~0x00ff0000 = 0x12345678 & 0xff00ffff = 0x12005678
>> *value = 0x12005678 >> ((4 - (1 % 4 )) * 8) = 0x12005678 >> ((4 - 1) * 8) = 0x12005678 >> (3 * 8) = 0x12005678 >> 24 = 0x00000012
>>
>> The value should be '0x56' instead of '0x00000012'.
>>
>> if where = 2:
>>
>> mask = 0xff000000 >> ((2 % 4) * 8) = 0xff000000 >> (2 * 8) = 0xff000000 >> 16 = 0x0000ff00
>> tval = 0x12345678 & ~0x0000ff00 = 0x12345678 & 0xffff00ff = 0x12340078
>> *value = 0x12340078 >> ((4 - (2 % 4 )) * 8) = 0x12340078 >> ((4 - 2) * 8) = 0x12340078 >> (2 * 8) = 0x12340078 >> 16 = 0x00001234
>>
>> The value should be '0x34' instead of '0x00001234'.
>>
>> if where = 3:
>>
>> mask = 0xff000000 >> ((3 % 4) * 8) = 0xff000000 >> (3 * 8) = 0xff000000 >> 24 = 0x000000ff
>> tval = 0x12345678 & ~0x000000ff = 0x12345678 & 0xffffff00 = 0x12345600
>> *value = 0x12345600 >> ((4 - (3 % 4 )) * 8) = 0x12345600 >> ((4 - 3) * 8) = 0x12345600 >> (1 * 8) = 0x12345600 >> 8 = 0x00123456
>>
>> The value should be '0x12' instead of '0x00123456'.
>>
>> Due to this, and the other errors in the pci_write functions,
>> Linux fails to assign the correct IRQ number for the device.
>> It can be noticed from the output of 'lspci -vv':
>>
>>        Interrupt: pin A routed to IRQ 0
>> vs
>>        Interrupt: pin A routed to IRQ 48
>>
>> I can show you the errors in the write functions, if you would
>> like to see that as well.
>>
>>
>> I'm curious why do you think that it is broken now.
>> You are getting a data bus error by any chance?
>>
>
> after a pci write, the pci read return bogus values.
> However, I go through this tomorrow.
>
>>> -My patchset has the ability to use different irqs (see pci_data).
>>
>> Yes, I know. You can set that from the board setup by calling the
>> {ath,ar}724x_pci_add_data function.
>>
>> However that approach has some limitations:
>>
>> 1. It does not supports assigning a different IRQ for the different
>> interrupt pins (A,B,C,D) of a PCI device. This is not a problem on the
>> AR724X boards, but that functionality is needed by some AR71xx based
>> boards.
>>
>> 2. The devfn field of the struct pci_device is 0 on the AR724X based boards.
>> However on AR71XX they are different. On the PB44 board, the devfn of a PCI
>> device in the first miniPCI slot is 136, and it is 144 for the second slot.
>> So if I want to define the pci_data for the PB44 board, I should write
>> something like this:
>>
>> static struct ath724x_pci_data pb44_pci_data[] = {
>>        [136] = { .irq  = PCI_IRQ_A },
>>        [144] = { .irq  = PCI_IRQ_B },
>> };
>>
>> The array has 136+8 unused entries, which wastes the memory.
>>
>> 3. The {ath,ar}724x_pci_add_data function must be called from the
>> setup code of each board. If the board setup code does not calls the
>> function, the kernel will throw an oops due to a NULL pointer dereference.
>>
>>> int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
>>> {
>>>       unsigned int devfn = dev->devfn;
>>>       int irq = -1;
>>>
>>
>> If the '{ath,ar}724x_pci_add_data' function is not called, pci_data_size = 0,
>> and pci_data = NULL;
>>
>>>       if (devfn > pci_data_size - 1)
>>>               return irq;
>>
>> devfn is always >= 0, and (pci_data_size - 1) = -1 = 0xffffffff, so the
>> condition in this if statement will be evaluated to false ...
>>
>>>       irq = pci_data[devfn].irq;
>>
>> ... and this line will cause the following oops:
>>
>> CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 803c4cc8, ra == 803c4ca4
>> Oops[#1]:
>> Cpu 0
>> $ 0   : 00000000 80510000 00000000 00000000
>> $ 4   : 803b4128 00000a52 ffffffff 0000000a
>> $ 8   : 0000000a 00000000 00000001 00000000
>> $12   : 00000374 0000000f 00000001 ffffffff
>> $16   : 00000000 80510000 803c4c74 8019d838
>> $20   : 803d3fe0 00000000 00000000 00000000
>> $24   : 00000002 800617f0
>> $28   : 81c20000 81c21e50 00000000 803c4ca4
>> Hi    : 00000000
>> Lo    : 068e7780
>> epc   : 803c4cc8 pcibios_map_irq+0x54/0x6c
>>    Not tainted
>> ra    : 803c4ca4 pcibios_map_irq+0x30/0x6c
>> Status: 1000c003    KERNEL EXL IE
>> Cause : 00800008
>> BadVA : 00000000
>> PrId  : 00019374 (MIPS 24Kc)
>> Modules linked in:
>> Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
>> Stack : 81c21e58 00000000 ffffffff 00000001 00000000 81c14c00 00000001 803d1840
>>        00000000 80300ce8 803d2a7c 00000000 01000000 803d2af8 81c46800 00000000
>>        803e9584 00000000 80510000 803d404c 00000000 00000000 80510000 803e9584
>>        80510000 80060930 33390000 00000000 0000a498 80143058 00000028 803b0000
>>        00000000 800bc4e4 803e92d0 803e9394 803e9584 00000000 00000000 00000000
>>        ...
>> Call Trace:
>> [<803c4cc8>] pcibios_map_irq+0x54/0x6c
>> [<803d1840>] pci_fixup_irqs+0x78/0xc4
>> [<803d404c>] pcibios_init+0x6c/0x8c
>> [<80060930>] do_one_initcall+0x3c/0x1cc
>> [<803c297c>] kernel_init+0xa4/0x138
>> [<80063c44>] kernel_thread_helper+0x10/0x18
>>
>> Code: 8c4250b4  001080c0  00508021 <8e020000> 8fbf001c  8fb10018  8fb00014  03e00008  27bd0020
>>
>>>
>>>       return irq;
>>> }
>
> Ok
>
>>> -I never hit the pci controller bug, any steps to replicate?
>>
>> Hm, weird. Your devices are based on AR7240 or or AR7241?
>>
>> Regards,
>> Gabor
>>
>
> AR7241 AH-4A
>
> Maybe it is better to split ar71xx and ar72xx pci support completly?
>

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 14:40     ` René Bolldorf
  2011-11-23 15:15       ` René Bolldorf
@ 2011-11-23 20:39       ` Gabor Juhos
  1 sibling, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-23 20:39 UTC (permalink / raw)
  To: René Bolldorf; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

Hi,

<...>

>> I'm curious why do you think that it is broken now.
>> You are getting a data bus error by any chance?
>>
> 
> after a pci write, the pci read return bogus values.

Can you be more specific please? The new code reads bogus values from every
configuration registers or only from some of them?

> However, I go through this tomorrow.

Ok.

<...>

>>> -I never hit the pci controller bug, any steps to replicate?
>>
>> Hm, weird. Your devices are based on AR7240 or or AR7241?
>>
>> Regards,
>> Gabor
>>
> 
> AR7241 AH-4A

Yeah, that is different, my Bullet 5M uses an AR7240. I have retested the code
with and without the workaround on an AR7241 based board and it is working in
both cases. So it seems that the AR7241 is not affected. I will change the patch
to use the workaround only if the kernel is running on AR7240.

> Maybe it is better to split ar71xx and ar72xx pci support completly?

Sorry, what do you mean? It is separated already. The common functions are
'pcibios_map_irq', 'pcibios_plat_dev_init' and 'ath79_register_pci'. None of
these functions are related to accessing of the PCI devices. Additionally, the
'ath79_register_pci' function calls the appropriate 'ar7{1x,24}x_pcibios_init'
depending on the actual SoC, so the AR71XX specific PCI controller code never
runs on AR724X.

-Gabor

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 15:15       ` René Bolldorf
@ 2011-11-23 20:43         ` Gabor Juhos
  2011-11-24 10:37           ` René Bolldorf
  0 siblings, 1 reply; 25+ messages in thread
From: Gabor Juhos @ 2011-11-23 20:43 UTC (permalink / raw)
  To: René Bolldorf; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

2011.11.23. 16:15 keltezéssel, René Bolldorf írta:
> It seems your board is a older one.

Yes, it uses AR7240.

> Can you remove the heatsink and post the revision from the SoC?

Sorry, I can't remove the heatsink. It is glued onto the SoC, and I don't want
to brick the board. However the kernel shows this:

SoC: Atheros AR7240 rev 2
Clocks: CPU:400.000MHz, DDR:400.000MHz, AHB:200.000MHz, Ref:5.000MHz

On the TL-MR3420:

SoC: Atheros AR7241 rev 1
Clocks: CPU:400.000MHz, DDR:400.000MHz, AHB:200.000MHz, Ref:5.000MHz

-Gabor

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-23 20:43         ` Gabor Juhos
@ 2011-11-24 10:37           ` René Bolldorf
  2011-11-24 15:06             ` Gabor Juhos
  0 siblings, 1 reply; 25+ messages in thread
From: René Bolldorf @ 2011-11-24 10:37 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

Sorry Gabor for the following patch, but it seems your patchset was
against a other tree? Because of the many failures I rebase'ed
against 09521577ca7718b6c of the linus tree and written anything from scratch.

- The ar724x pci build only then SOC_AR724X and AR724X_PCI is set.
(new symbol AR724X_PCI)
- We have a shared PCI header file for both controllers. (Only AR724x
is included atm)
- We have a default irq map if the board pass no other map with
ar724x_pci_add_data.
- I added the fix for the 7240 controller bug, hopefully right.

Gabor, can you please test the patch?

René

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 4770741..e763661 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -23,6 +23,16 @@ config ATH79_MACH_PB44
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros PB44 reference board.

+config ATH79_MACH_UBNT_XM
+	bool "Ubiquiti Networks XM (rev 1.0) board"
+	select SOC_AR724X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Ubiquiti Networks XM (rev 1.0) board.
+
 endmenu

 config SOC_AR71XX
@@ -33,6 +43,7 @@ config SOC_AR71XX
 config SOC_AR724X
 	select USB_ARCH_HAS_EHCI
 	select USB_ARCH_HAS_OHCI
+	select HW_HAS_PCI
 	def_bool n

 config SOC_AR913X
@@ -52,4 +63,8 @@ config ATH79_DEV_LEDS_GPIO
 config ATH79_DEV_SPI
 	def_bool n

+config AR724X_PCI
+	depends on PCI
+	def_bool y
+
 endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index c33d465..ac9f375 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
 #
 obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
 obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
+obj-$(CONFIG_ATH79_MACH_UBNT_XM)	+= mach-ubnt-xm.o
diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
new file mode 100644
index 0000000..6fadd0b
--- /dev/null
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -0,0 +1,121 @@
+/*
+ *  Ubiquiti Networks XM (rev 1.0) board support
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *
+ *  Derived from: mach-pb44.c
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_PCI
+#include <linux/ath9k_platform.h>
+#include <asm/mach-ath79/pci.h>
+#include <asm/mach-ath79/irq.h>
+#endif /* CONFIG_PCI */
+
+#include "machtypes.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-spi.h"
+
+#define UBNT_XM_GPIO_LED_L1		0
+#define UBNT_XM_GPIO_LED_L2		1
+#define UBNT_XM_GPIO_LED_L3		11
+#define UBNT_XM_GPIO_LED_L4		7
+
+#define UBNT_XM_GPIO_BTN_RESET		12
+
+#define UBNT_XM_KEYS_POLL_INTERVAL	20
+#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL	(3 * UBNT_XM_KEYS_POLL_INTERVAL)
+
+#define UBNT_XM_EEPROM_ADDR		(u8 *) KSEG1ADDR(0x1fff1000)
+
+static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
+	{
+		.name		= "ubnt-xm:red:link1",
+		.gpio		= UBNT_XM_GPIO_LED_L1,
+		.active_low	= 0,
+	}, {
+		.name		= "ubnt-xm:orange:link2",
+		.gpio		= UBNT_XM_GPIO_LED_L2,
+		.active_low	= 0,
+	}, {
+		.name		= "ubnt-xm:green:link3",
+		.gpio		= UBNT_XM_GPIO_LED_L3,
+		.active_low	= 0,
+	}, {
+		.name		= "ubnt-xm:green:link4",
+		.gpio		= UBNT_XM_GPIO_LED_L4,
+		.active_low	= 0,
+	},
+};
+
+static struct gpio_keys_button ubnt_xm_gpio_keys[] __initdata = {
+	{
+		.desc			= "reset",
+		.type			= EV_KEY,
+		.code			= KEY_RESTART,
+		.debounce_interval	= UBNT_XM_KEYS_DEBOUNCE_INTERVAL,
+		.gpio			= UBNT_XM_GPIO_BTN_RESET,
+		.active_low		= 1,
+	}
+};
+
+static struct spi_board_info ubnt_xm_spi_info[] = {
+	{
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 25000000,
+		.modalias	= "mx25l6405d",
+	}
+};
+
+static struct ath79_spi_platform_data ubnt_xm_spi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 1,
+};
+
+#ifdef CONFIG_PCI
+static struct ath9k_platform_data ubnt_xm_eeprom_data;
+
+static struct ath79_pci_data ubnt_xm_pci_data[] = {
+	{
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+		.pdata	= &ubnt_xm_eeprom_data,
+	},
+};
+#endif /* CONFIG_PCI */
+
+static void __init ubnt_xm_init(void)
+{
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio),
+				 ubnt_xm_leds_gpio);
+
+	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(ubnt_xm_gpio_keys),
+					ubnt_xm_gpio_keys);
+
+	ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
+			   ARRAY_SIZE(ubnt_xm_spi_info));
+
+#ifdef CONFIG_PCI
+	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
+	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
+
+	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
+#endif /* CONFIG_PCI */
+
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_XM,
+	     "UBNT-XM",
+	     "Ubiquiti Networks XM (rev 1.0) board",
+	     ubnt_xm_init);
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
index 3940fe4..35d5d5c 100644
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
@@ -18,6 +18,7 @@ enum ath79_mach_type {
 	ATH79_MACH_GENERIC = 0,
 	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
 	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
+	ATH79_MACH_UBNT_XM,		/* Ubiquiti Networks XM board rev 1.0 */
 };

 #endif /* _ATH79_MACHTYPE_H */
diff --git a/arch/mips/include/asm/mach-ath79/irq.h
b/arch/mips/include/asm/mach-ath79/irq.h
index 189bc6e..eb68e79 100644
--- a/arch/mips/include/asm/mach-ath79/irq.h
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -10,11 +10,15 @@
 #define __ASM_MACH_ATH79_IRQ_H

 #define MIPS_CPU_IRQ_BASE	0
-#define NR_IRQS			16
+#define NR_IRQS			22

 #define ATH79_MISC_IRQ_BASE	8
 #define ATH79_MISC_IRQ_COUNT	8

+#define ATH79_PCI_IRQ_BASE	(ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
+#define ATH79_PCI_IRQ_COUNT	6
+#define ATH79_PCI_IRQ(_x)	(ATH79_PCI_IRQ_BASE + (_x))
+
 #define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
 #define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
 #define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
diff --git a/arch/mips/include/asm/mach-ath79/pci.h
b/arch/mips/include/asm/mach-ath79/pci.h
new file mode 100644
index 0000000..f671174
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/pci.h
@@ -0,0 +1,24 @@
+/*
+ *  Atheros 71xx/724x PCI support
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_ATH79_PCI_H
+#define __ASM_MACH_ATH79_PCI_H
+
+struct ath79_pci_data {
+	uint8_t slot;
+	uint8_t pin;
+	int irq;
+	void *pdata;
+};
+
+void ar724x_pci_add_data(struct ath79_pci_data *data, int size);
+
+#endif /* __ASM_MACH_ATH79_PCI_H */
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index bb82cbd..6603594 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
 obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
 					ops-bcm63xx.o
 obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
+obj-$(CONFIG_AR724X_PCI)	+= pci-ar724x.o

 #
 # These are still pretty much in the old state, watch, go blind.
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
new file mode 100644
index 0000000..66974fa
--- /dev/null
+++ b/arch/mips/pci/pci-ar724x.c
@@ -0,0 +1,284 @@
+/*
+ *  Atheros 724x PCI support
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/pci.h>
+#include <asm/mach-ath79/irq.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#define AR724X_PCI_CFG_BASE	0x14000000
+#define AR724X_PCI_CFG_SIZE	0x1000
+#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000)
+#define AR724X_PCI_CTRL_SIZE	0x100
+
+#define AR724X_PCI_MEM_BASE	0x10000000
+#define AR724X_PCI_MEM_SIZE	0x08000000
+
+#define AR724X_PCI_REG_INT_STATUS	0x4c
+#define AR724X_PCI_REG_INT_MASK		0x50
+#define AR724X_PCI_INT_DEV0		BIT(14)
+
+#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 struct ath79_pci_data *pci_data;
+static int pci_data_size = -1;
+
+static u32 ar724x_pci_bar0_value;
+static bool ar724x_pci_bar0_is_cached;
+
+static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+			    int size, uint32_t *value)
+{
+	unsigned long flags;
+	void __iomem *base;
+
+	if (devfn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = ar724x_pci_devcfg_base;
+
+	spin_lock_irqsave(&ar724x_pci_lock, flags);
+
+	switch (size) {
+	case 1:
+		*value = (__raw_readl(base + (where & ~3)) & 0xff);
+		break;
+	case 2:
+		*value = (__raw_readl(base + (where & ~3)) & 0xffff);
+		break;
+	case 4:
+		if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 &&
+		    ar724x_pci_bar0_is_cached)
+			/* use the cached value */
+			*value = ar724x_pci_bar0_value;
+		else
+			*value = __raw_readl(base + where);
+		break;
+	default:
+		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
+
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+			     int size, uint32_t value)
+{
+	unsigned long flags;
+	void __iomem *base;
+
+	if (devfn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
+		if (value != 0xffffffff) {
+			/*
+			 * WAR for a hw issue. If the BAR0 register of the
+			 * device is set to the proper base address, the
+			 * memory space of the device is not accessible.
+			 *
+			 * Cache the intended value so it can be read back,
+			 * and write a SoC specific constant value to the
+			 * BAR0 register in order to make the device memory
+			 * accessible.
+			 */
+			ar724x_pci_bar0_is_cached = true;
+			ar724x_pci_bar0_value = value;
+			value = AR7240_BAR0_WAR_VALUE;
+		} else {
+			ar724x_pci_bar0_is_cached = false;
+		}
+	}
+
+	base = ar724x_pci_devcfg_base;
+
+	spin_lock_irqsave(&ar724x_pci_lock, flags);
+
+	switch (size) {
+	case 1:
+		value = (__raw_readl(base + (where & ~3)) & 0xff);
+		__raw_writel(value, base + (where & ~3));
+		break;
+	case 2:
+		value = (__raw_readl(base + (where & ~3)) & 0xffff);
+		__raw_writel(value, base + (where & ~3));
+		break;
+	case 4:
+		__raw_writel(value, (base + where));
+		break;
+	default:
+		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
+
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops ar724x_pci_ops = {
+	.read	= ar724x_pci_read,
+	.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 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_mask(struct irq_data *data)
+{
+	void __iomem *base;
+	u32 t;
+
+	base = ar724x_pci_ctrl_base;
+
+	switch (data->irq) {
+	case ATH79_PCI_IRQ(0):
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+
+		t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_STATUS);
+	}
+}
+
+static void ar724x_pci_irq_unmask(struct irq_data *data)
+{
+	void __iomem *base;
+	u32 t;
+
+	base = ar724x_pci_ctrl_base;
+
+	switch (data->irq) {
+	case ATH79_PCI_IRQ(0):
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+	}
+}
+
+static struct irq_chip ar724x_pci_irq_chip = {
+	.name		= "AR724X PCI",
+	.irq_mask	= ar724x_pci_irq_mask,
+	.irq_unmask	= ar724x_pci_irq_unmask,
+	.irq_mask_ack	= ar724x_pci_irq_mask,
+};
+
+static __initconst struct ath79_pci_data ar724x_default_pci_data[] = {
+	{
+		.slot = 0,
+		.pin  = 1,
+		.irq  = ATH79_PCI_IRQ(0),
+	},
+};
+
+void ar724x_pci_add_data(struct ath79_pci_data *data, int size)
+{
+	pci_data	= data;
+	pci_data_size	= size;
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot,
uint8_t pin)
+{
+	int irq = -1;
+	int i;
+
+	if (pci_data_size == -1)
+		return irq;
+
+	for (i = 0; i < pci_data_size; i++) {
+		if ((pci_data[i].slot == slot) && (pci_data[i].pin == pin)) {
+			if (pci_data[i].irq != 0)
+				irq = pci_data[i].irq;
+		break;
+		}
+	}
+
+	return irq;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	int i;
+
+	if (pci_data_size == -1)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	for (i = 0; i < pci_data_size; i++) {
+		if (pci_data[i].slot == PCI_SLOT(dev->devfn)) {
+			if (pci_data[i].pdata != NULL)
+				dev->dev.platform_data = pci_data[i].pdata;
+		break;
+		}
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __init ar724x_pcibios_init(void)
+{
+	int i;
+
+	ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE,
+						 AR724X_PCI_CFG_SIZE);
+	if (ar724x_pci_devcfg_base == NULL)
+		return -ENOMEM;
+
+	ar724x_pci_ctrl_base = ioremap_nocache(AR724X_PCI_CTRL_BASE,
+						  AR724X_PCI_CTRL_SIZE);
+	if (ar724x_pci_ctrl_base == NULL)
+		return -ENOMEM;
+
+	if (pci_data == NULL)
+		pci_data = ar724x_default_pci_data;
+		pci_data_size = ARRAY_SIZE(ar724x_default_pci_data);
+
+	for (i = ATH79_PCI_IRQ_BASE;
+	     i < ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
+					 handle_level_irq);
+
+	register_pci_controller(&ar724x_pci_controller);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+arch_initcall(ar724x_pcibios_init);

2011/11/23 Gabor Juhos <juhosg@openwrt.org>:
> 2011.11.23. 16:15 keltezéssel, René Bolldorf írta:
>> It seems your board is a older one.
>
> Yes, it uses AR7240.
>
>> Can you remove the heatsink and post the revision from the SoC?
>
> Sorry, I can't remove the heatsink. It is glued onto the SoC, and I don't want
> to brick the board. However the kernel shows this:
>
> SoC: Atheros AR7240 rev 2
> Clocks: CPU:400.000MHz, DDR:400.000MHz, AHB:200.000MHz, Ref:5.000MHz
>
> On the TL-MR3420:
>
> SoC: Atheros AR7241 rev 1
> Clocks: CPU:400.000MHz, DDR:400.000MHz, AHB:200.000MHz, Ref:5.000MHz
>
> -Gabor
>

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-24 10:37           ` René Bolldorf
@ 2011-11-24 15:06             ` Gabor Juhos
  2011-11-24 15:54               ` René Bolldorf
  0 siblings, 1 reply; 25+ messages in thread
From: Gabor Juhos @ 2011-11-24 15:06 UTC (permalink / raw)
  To: René Bolldorf; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

Hi René,

> Sorry Gabor for the following patch, but it seems your patchset was
> against a other tree? 

Both of my patch sets was based on the 'mips-for-linux-next' branch of Ralf's
'upstream-sfr' tree:

git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git

> Because of the many failures I rebase'ed against 09521577ca7718b6c of the
> linus tree and written anything from scratch.

That was waste of time. The ath79 platform got a pile of changes recently, and
those changes are not yet available in Linus' tree. If you were unsure about the
tree, you should have asked earlier.

> - The ar724x pci build only then SOC_AR724X and AR724X_PCI is set.
> (new symbol AR724X_PCI)
> - We have a shared PCI header file for both controllers. (Only AR724x
> is included atm)
> - We have a default irq map if the board pass no other map with
> ar724x_pci_add_data.
> - I added the fix for the 7240 controller bug, hopefully right.

> Gabor, can you please test the patch?

I can tell without testing that this is not working, see below.

> 
> René
> 
> diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
> index 4770741..e763661 100644
> --- a/arch/mips/ath79/Kconfig
> +++ b/arch/mips/ath79/Kconfig
> @@ -23,6 +23,16 @@ config ATH79_MACH_PB44
>  	  Say 'Y' here if you want your kernel to support the
>  	  Atheros PB44 reference board.
> 
> +config ATH79_MACH_UBNT_XM
> +	bool "Ubiquiti Networks XM (rev 1.0) board"
> +	select SOC_AR724X
> +	select ATH79_DEV_GPIO_BUTTONS
> +	select ATH79_DEV_LEDS_GPIO
> +	select ATH79_DEV_SPI
> +	help
> +	  Say 'Y' here if you want your kernel to support the
> +	  Ubiquiti Networks XM (rev 1.0) board.
> +
>  endmenu
> 
>  config SOC_AR71XX
> @@ -33,6 +43,7 @@ config SOC_AR71XX
>  config SOC_AR724X
>  	select USB_ARCH_HAS_EHCI
>  	select USB_ARCH_HAS_OHCI
> +	select HW_HAS_PCI
>  	def_bool n
> 
>  config SOC_AR913X
> @@ -52,4 +63,8 @@ config ATH79_DEV_LEDS_GPIO
>  config ATH79_DEV_SPI
>  	def_bool n
> 
> +config AR724X_PCI
> +	depends on PCI
> +	def_bool y
> +
>  endif

Why would we have to add yet another Kconfig symbol? The AR724X specific code is
only build when both PCI and SOC_AR724X is selected (in Ralf's tree, and in
linux-next).

> diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
> index c33d465..ac9f375 100644
> --- a/arch/mips/ath79/Makefile
> +++ b/arch/mips/ath79/Makefile
> @@ -26,3 +26,4 @@ obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
>  #
>  obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
>  obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
> +obj-$(CONFIG_ATH79_MACH_UBNT_XM)	+= mach-ubnt-xm.o
> diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
> new file mode 100644
> index 0000000..6fadd0b
> --- /dev/null
> +++ b/arch/mips/ath79/mach-ubnt-xm.c
> @@ -0,0 +1,121 @@
> +/*
> + *  Ubiquiti Networks XM (rev 1.0) board support
> + *
> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
> + *
> + *  Derived from: mach-pb44.c
> + *
> + *  This program is free software; you can redistribute it and/or modify it
> + *  under the terms of the GNU General Public License version 2 as published
> + *  by the Free Software Foundation.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +
> +#ifdef CONFIG_PCI
> +#include <linux/ath9k_platform.h>
> +#include <asm/mach-ath79/pci.h>
> +#include <asm/mach-ath79/irq.h>
> +#endif /* CONFIG_PCI */
> +
> +#include "machtypes.h"
> +#include "dev-gpio-buttons.h"
> +#include "dev-leds-gpio.h"
> +#include "dev-spi.h"
> +
> +#define UBNT_XM_GPIO_LED_L1		0
> +#define UBNT_XM_GPIO_LED_L2		1
> +#define UBNT_XM_GPIO_LED_L3		11
> +#define UBNT_XM_GPIO_LED_L4		7
> +
> +#define UBNT_XM_GPIO_BTN_RESET		12
> +
> +#define UBNT_XM_KEYS_POLL_INTERVAL	20
> +#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL	(3 * UBNT_XM_KEYS_POLL_INTERVAL)
> +
> +#define UBNT_XM_EEPROM_ADDR		(u8 *) KSEG1ADDR(0x1fff1000)
> +
> +static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
> +	{
> +		.name		= "ubnt-xm:red:link1",
> +		.gpio		= UBNT_XM_GPIO_LED_L1,
> +		.active_low	= 0,
> +	}, {
> +		.name		= "ubnt-xm:orange:link2",
> +		.gpio		= UBNT_XM_GPIO_LED_L2,
> +		.active_low	= 0,
> +	}, {
> +		.name		= "ubnt-xm:green:link3",
> +		.gpio		= UBNT_XM_GPIO_LED_L3,
> +		.active_low	= 0,
> +	}, {
> +		.name		= "ubnt-xm:green:link4",
> +		.gpio		= UBNT_XM_GPIO_LED_L4,
> +		.active_low	= 0,
> +	},
> +};
> +
> +static struct gpio_keys_button ubnt_xm_gpio_keys[] __initdata = {
> +	{
> +		.desc			= "reset",
> +		.type			= EV_KEY,
> +		.code			= KEY_RESTART,
> +		.debounce_interval	= UBNT_XM_KEYS_DEBOUNCE_INTERVAL,
> +		.gpio			= UBNT_XM_GPIO_BTN_RESET,
> +		.active_low		= 1,
> +	}
> +};
> +
> +static struct spi_board_info ubnt_xm_spi_info[] = {
> +	{
> +		.bus_num	= 0,
> +		.chip_select	= 0,
> +		.max_speed_hz	= 25000000,
> +		.modalias	= "mx25l6405d",
> +	}
> +};
> +
> +static struct ath79_spi_platform_data ubnt_xm_spi_data = {
> +	.bus_num		= 0,
> +	.num_chipselect		= 1,
> +};
> +
> +#ifdef CONFIG_PCI
> +static struct ath9k_platform_data ubnt_xm_eeprom_data;
> +
> +static struct ath79_pci_data ubnt_xm_pci_data[] = {
> +	{
> +		.slot	= 0,
> +		.pin	= 1,
> +		.irq	= ATH79_PCI_IRQ(0),
> +		.pdata	= &ubnt_xm_eeprom_data,
> +	},
> +};
> +#endif /* CONFIG_PCI */
> +
> +static void __init ubnt_xm_init(void)
> +{
> +	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio),
> +				 ubnt_xm_leds_gpio);
> +
> +	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
> +					ARRAY_SIZE(ubnt_xm_gpio_keys),
> +					ubnt_xm_gpio_keys);
> +
> +	ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
> +			   ARRAY_SIZE(ubnt_xm_spi_info));
> +
> +#ifdef CONFIG_PCI
> +	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
> +	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
> +
> +	ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
> +#endif /* CONFIG_PCI */
> +
> +}
> +
> +MIPS_MACHINE(ATH79_MACH_UBNT_XM,
> +	     "UBNT-XM",
> +	     "Ubiquiti Networks XM (rev 1.0) board",
> +	     ubnt_xm_init);
> diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
> index 3940fe4..35d5d5c 100644
> --- a/arch/mips/ath79/machtypes.h
> +++ b/arch/mips/ath79/machtypes.h
> @@ -18,6 +18,7 @@ enum ath79_mach_type {
>  	ATH79_MACH_GENERIC = 0,
>  	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
>  	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
> +	ATH79_MACH_UBNT_XM,		/* Ubiquiti Networks XM board rev 1.0 */
>  };
> 
>  #endif /* _ATH79_MACHTYPE_H */
> diff --git a/arch/mips/include/asm/mach-ath79/irq.h
> b/arch/mips/include/asm/mach-ath79/irq.h
> index 189bc6e..eb68e79 100644
> --- a/arch/mips/include/asm/mach-ath79/irq.h
> +++ b/arch/mips/include/asm/mach-ath79/irq.h
> @@ -10,11 +10,15 @@
>  #define __ASM_MACH_ATH79_IRQ_H
> 
>  #define MIPS_CPU_IRQ_BASE	0
> -#define NR_IRQS			16
> +#define NR_IRQS			22
> 

This will conflict with other changes already in linux-next.

>  #define ATH79_MISC_IRQ_BASE	8
>  #define ATH79_MISC_IRQ_COUNT	8
> 
> +#define ATH79_PCI_IRQ_BASE	(ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
> +#define ATH79_PCI_IRQ_COUNT	6
> +#define ATH79_PCI_IRQ(_x)	(ATH79_PCI_IRQ_BASE + (_x))
> +
>  #define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
>  #define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
>  #define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
> diff --git a/arch/mips/include/asm/mach-ath79/pci.h
> b/arch/mips/include/asm/mach-ath79/pci.h
> new file mode 100644
> index 0000000..f671174
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ath79/pci.h
> @@ -0,0 +1,24 @@
> +/*
> + *  Atheros 71xx/724x PCI support
> + *
> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
> + *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
> + *
> + *  This program is free software; you can redistribute it and/or modify it
> + *  under the terms of the GNU General Public License version 2 as published
> + *  by the Free Software Foundation.
> + */
> +
> +#ifndef __ASM_MACH_ATH79_PCI_H
> +#define __ASM_MACH_ATH79_PCI_H
> +
> +struct ath79_pci_data {
> +	uint8_t slot;
> +	uint8_t pin;
> +	int irq;
> +	void *pdata;
> +};
> +
> +void ar724x_pci_add_data(struct ath79_pci_data *data, int size);
> +
> +#endif /* __ASM_MACH_ATH79_PCI_H */
> diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> index bb82cbd..6603594 100644
> --- a/arch/mips/pci/Makefile
> +++ b/arch/mips/pci/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
>  obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
>  					ops-bcm63xx.o
>  obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
> +obj-$(CONFIG_AR724X_PCI)	+= pci-ar724x.o
> 
>  #
>  # These are still pretty much in the old state, watch, go blind.
> diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
> new file mode 100644
> index 0000000..66974fa
> --- /dev/null
> +++ b/arch/mips/pci/pci-ar724x.c
> @@ -0,0 +1,284 @@
> +/*
> + *  Atheros 724x PCI support
> + *
> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
> + *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
> + *
> + *  This program is free software; you can redistribute it and/or modify it
> + *  under the terms of the GNU General Public License version 2 as published
> + *  by the Free Software Foundation.
> + */
> +
> +#include <linux/pci.h>
> +#include <linux/irq.h>
> +#include <asm/mach-ath79/ath79.h>
> +#include <asm/mach-ath79/pci.h>
> +#include <asm/mach-ath79/irq.h>
> +#include <asm/mach-ath79/ar71xx_regs.h>
> +
> +#define AR724X_PCI_CFG_BASE	0x14000000
> +#define AR724X_PCI_CFG_SIZE	0x1000
> +#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000)
> +#define AR724X_PCI_CTRL_SIZE	0x100
> +
> +#define AR724X_PCI_MEM_BASE	0x10000000
> +#define AR724X_PCI_MEM_SIZE	0x08000000
> +
> +#define AR724X_PCI_REG_INT_STATUS	0x4c
> +#define AR724X_PCI_REG_INT_MASK		0x50
> +#define AR724X_PCI_INT_DEV0		BIT(14)
> +
> +#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 struct ath79_pci_data *pci_data;
> +static int pci_data_size = -1;
> +
> +static u32 ar724x_pci_bar0_value;
> +static bool ar724x_pci_bar0_is_cached;
> +
> +static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
> +			    int size, uint32_t *value)
> +{
> +	unsigned long flags;
> +	void __iomem *base;
> +
> +	if (devfn)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	base = ar724x_pci_devcfg_base;
> +
> +	spin_lock_irqsave(&ar724x_pci_lock, flags);
> +
> +	switch (size) {
> +	case 1:
> +		*value = (__raw_readl(base + (where & ~3)) & 0xff);

This is wrong. This will always return the least significant byte, instead of
the right one. And the outermost parens are not needed.

> +		break;
> +	case 2:
> +		*value = (__raw_readl(base + (where & ~3)) & 0xffff);

This is wrong as well.

> +		break;
> +	case 4:
> +		if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 &&
> +		    ar724x_pci_bar0_is_cached)
> +			/* use the cached value */
> +			*value = ar724x_pci_bar0_value;
> +		else
> +			*value = __raw_readl(base + where);
> +		break;
> +	default:
> +		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
> +
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +	}
> +
> +	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
> +			     int size, uint32_t value)
> +{
> +	unsigned long flags;
> +	void __iomem *base;
> +
> +	if (devfn)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
> +		if (value != 0xffffffff) {
> +			/*
> +			 * WAR for a hw issue. If the BAR0 register of the
> +			 * device is set to the proper base address, the
> +			 * memory space of the device is not accessible.
> +			 *
> +			 * Cache the intended value so it can be read back,
> +			 * and write a SoC specific constant value to the
> +			 * BAR0 register in order to make the device memory
> +			 * accessible.
> +			 */
> +			ar724x_pci_bar0_is_cached = true;
> +			ar724x_pci_bar0_value = value;
> +			value = AR7240_BAR0_WAR_VALUE;
> +		} else {
> +			ar724x_pci_bar0_is_cached = false;
> +		}
> +	}
> +
> +	base = ar724x_pci_devcfg_base;
> +
> +	spin_lock_irqsave(&ar724x_pci_lock, flags);
> +
> +	switch (size) {
> +	case 1:
> +		value = (__raw_readl(base + (where & ~3)) & 0xff);
> +		__raw_writel(value, base + (where & ~3));

Wrong. This reads the register, and masks out everything but the least
significant byte, and writes the results back to the same register. It must
modify the right byte intead.

> +		break;
> +	case 2:
> +		value = (__raw_readl(base + (where & ~3)) & 0xffff);
> +		__raw_writel(value, base + (where & ~3));

Also wrong (with words instead of bytes).

> +		break;
> +	case 4:
> +		__raw_writel(value, (base + where));
> +		break;
> +	default:
> +		spin_unlock_irqrestore(&ar724x_pci_lock, flags);
> +
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +	}
> +
> +	spin_unlock_irqrestore(&ar724x_pci_lock, flags);
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static struct pci_ops ar724x_pci_ops = {
> +	.read	= ar724x_pci_read,
> +	.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 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_mask(struct irq_data *data)
> +{
> +	void __iomem *base;
> +	u32 t;
> +
> +	base = ar724x_pci_ctrl_base;
> +
> +	switch (data->irq) {
> +	case ATH79_PCI_IRQ(0):
> +		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
> +		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
> +			     base + AR724X_PCI_REG_INT_MASK);

A __raw_readl is missing.

> +
> +		t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
> +		__raw_writel(t | AR724X_PCI_INT_DEV0,
> +			     base + AR724X_PCI_REG_INT_STATUS);

Here too.

> +	}
> +}
> +
> +static void ar724x_pci_irq_unmask(struct irq_data *data)
> +{
> +	void __iomem *base;
> +	u32 t;
> +
> +	base = ar724x_pci_ctrl_base;
> +
> +	switch (data->irq) {
> +	case ATH79_PCI_IRQ(0):
> +		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
> +		__raw_writel(t | AR724X_PCI_INT_DEV0,
> +			     base + AR724X_PCI_REG_INT_MASK);

And here also.

> +	}
> +}
> +
> +static struct irq_chip ar724x_pci_irq_chip = {
> +	.name		= "AR724X PCI",
> +	.irq_mask	= ar724x_pci_irq_mask,
> +	.irq_unmask	= ar724x_pci_irq_unmask,
> +	.irq_mask_ack	= ar724x_pci_irq_mask,
> +};
> +
> +static __initconst struct ath79_pci_data ar724x_default_pci_data[] = {

__initconst must be placed after [].

> +	{
> +		.slot = 0,
> +		.pin  = 1,
> +		.irq  = ATH79_PCI_IRQ(0),
> +	},
> +};
> +
> +void ar724x_pci_add_data(struct ath79_pci_data *data, int size)
> +{
> +	pci_data	= data;
> +	pci_data_size	= size;
> +}
> +
> +int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot,
> uint8_t pin)
> +{
> +	int irq = -1;
> +	int i;
> +
> +	if (pci_data_size == -1)
> +		return irq;
> +
> +	for (i = 0; i < pci_data_size; i++) {
> +		if ((pci_data[i].slot == slot) && (pci_data[i].pin == pin)) {
> +			if (pci_data[i].irq != 0)
> +				irq = pci_data[i].irq;
> +		break;

Wrong indentation for the break statement.

> +		}
> +	}
> +
> +	return irq;
> +}
> +
> +int pcibios_plat_dev_init(struct pci_dev *dev)
> +{
> +	int i;
> +
> +	if (pci_data_size == -1)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	for (i = 0; i < pci_data_size; i++) {
> +		if (pci_data[i].slot == PCI_SLOT(dev->devfn)) {
> +			if (pci_data[i].pdata != NULL)
> +				dev->dev.platform_data = pci_data[i].pdata;
> +		break;

Ditto.

> +		}
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int __init ar724x_pcibios_init(void)
> +{
> +	int i;
> +
> +	ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE,
> +						 AR724X_PCI_CFG_SIZE);

ioremap can be used instead of ioremap_nocache.

> +	if (ar724x_pci_devcfg_base == NULL)
> +		return -ENOMEM;
> +
> +	ar724x_pci_ctrl_base = ioremap_nocache(AR724X_PCI_CTRL_BASE,
> +						  AR724X_PCI_CTRL_SIZE);
> +	if (ar724x_pci_ctrl_base == NULL)
> +		return -ENOMEM;

ar724x_pci_devcfg_base must be unmapped if the second iomap call fails.

> +
> +	if (pci_data == NULL)
> +		pci_data = ar724x_default_pci_data;
> +		pci_data_size = ARRAY_SIZE(ar724x_default_pci_data);

Braces are missing from this if statement.

The AR724X_PCI_IRQ_REG_INT_{MASK,STATUS} registers must be cleared here.

> +
> +	for (i = ATH79_PCI_IRQ_BASE;
> +	     i < ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT; i++)
> +		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
> +					 handle_level_irq);

The 'irq_set_chained_handler' call is missing here. And the
ar724x_pci_irq_handler function is completely missing from the patch.

> +
> +	register_pci_controller(&ar724x_pci_controller);
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +arch_initcall(ar724x_pcibios_init);

Regards,
Gabor

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-24 15:06             ` Gabor Juhos
@ 2011-11-24 15:54               ` René Bolldorf
  2011-11-24 18:39                 ` Gabor Juhos
  0 siblings, 1 reply; 25+ messages in thread
From: René Bolldorf @ 2011-11-24 15:54 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

2011/11/24 Gabor Juhos <juhosg@openwrt.org>:
> Hi René,
>
>> Sorry Gabor for the following patch, but it seems your patchset was
>> against a other tree?
>
> Both of my patch sets was based on the 'mips-for-linux-next' branch of Ralf's
> 'upstream-sfr' tree:
>
> git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git
>
>> Because of the many failures I rebase'ed against 09521577ca7718b6c of the
>> linus tree and written anything from scratch.
>
> That was waste of time. The ath79 platform got a pile of changes recently, and
> those changes are not yet available in Linus' tree. If you were unsure about the
> tree, you should have asked earlier.
>

Alright. I don't play with all trees now.
I wait for the next merge.

>> - The ar724x pci build only then SOC_AR724X and AR724X_PCI is set.
>> (new symbol AR724X_PCI)
>> - We have a shared PCI header file for both controllers. (Only AR724x
>> is included atm)
>> - We have a default irq map if the board pass no other map with
>> ar724x_pci_add_data.
>> - I added the fix for the 7240 controller bug, hopefully right.
>
>> Gabor, can you please test the patch?
>
> I can tell without testing that this is not working, see below.
>
>>
>> René
>>
>> diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
>> index 4770741..e763661 100644
>> --- a/arch/mips/ath79/Kconfig
>> +++ b/arch/mips/ath79/Kconfig
>> @@ -23,6 +23,16 @@ config ATH79_MACH_PB44
>>         Say 'Y' here if you want your kernel to support the
>>         Atheros PB44 reference board.
>>
>> +config ATH79_MACH_UBNT_XM
>> +     bool "Ubiquiti Networks XM (rev 1.0) board"
>> +     select SOC_AR724X
>> +     select ATH79_DEV_GPIO_BUTTONS
>> +     select ATH79_DEV_LEDS_GPIO
>> +     select ATH79_DEV_SPI
>> +     help
>> +       Say 'Y' here if you want your kernel to support the
>> +       Ubiquiti Networks XM (rev 1.0) board.
>> +
>>  endmenu
>>
>>  config SOC_AR71XX
>> @@ -33,6 +43,7 @@ config SOC_AR71XX
>>  config SOC_AR724X
>>       select USB_ARCH_HAS_EHCI
>>       select USB_ARCH_HAS_OHCI
>> +     select HW_HAS_PCI
>>       def_bool n
>>
>>  config SOC_AR913X
>> @@ -52,4 +63,8 @@ config ATH79_DEV_LEDS_GPIO
>>  config ATH79_DEV_SPI
>>       def_bool n
>>
>> +config AR724X_PCI
>> +     depends on PCI
>> +     def_bool y
>> +
>>  endif
>
> Why would we have to add yet another Kconfig symbol? The AR724X specific code is
> only build when both PCI and SOC_AR724X is selected (in Ralf's tree, and in
> linux-next).
>
>> diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
>> index c33d465..ac9f375 100644
>> --- a/arch/mips/ath79/Makefile
>> +++ b/arch/mips/ath79/Makefile
>> @@ -26,3 +26,4 @@ obj-$(CONFIG_ATH79_DEV_SPI)         += dev-spi.o
>>  #
>>  obj-$(CONFIG_ATH79_MACH_AP81)                += mach-ap81.o
>>  obj-$(CONFIG_ATH79_MACH_PB44)                += mach-pb44.o
>> +obj-$(CONFIG_ATH79_MACH_UBNT_XM)     += mach-ubnt-xm.o
>> diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
>> new file mode 100644
>> index 0000000..6fadd0b
>> --- /dev/null
>> +++ b/arch/mips/ath79/mach-ubnt-xm.c
>> @@ -0,0 +1,121 @@
>> +/*
>> + *  Ubiquiti Networks XM (rev 1.0) board support
>> + *
>> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
>> + *
>> + *  Derived from: mach-pb44.c
>> + *
>> + *  This program is free software; you can redistribute it and/or modify it
>> + *  under the terms of the GNU General Public License version 2 as published
>> + *  by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/pci.h>
>> +
>> +#ifdef CONFIG_PCI
>> +#include <linux/ath9k_platform.h>
>> +#include <asm/mach-ath79/pci.h>
>> +#include <asm/mach-ath79/irq.h>
>> +#endif /* CONFIG_PCI */
>> +
>> +#include "machtypes.h"
>> +#include "dev-gpio-buttons.h"
>> +#include "dev-leds-gpio.h"
>> +#include "dev-spi.h"
>> +
>> +#define UBNT_XM_GPIO_LED_L1          0
>> +#define UBNT_XM_GPIO_LED_L2          1
>> +#define UBNT_XM_GPIO_LED_L3          11
>> +#define UBNT_XM_GPIO_LED_L4          7
>> +
>> +#define UBNT_XM_GPIO_BTN_RESET               12
>> +
>> +#define UBNT_XM_KEYS_POLL_INTERVAL   20
>> +#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL       (3 * UBNT_XM_KEYS_POLL_INTERVAL)
>> +
>> +#define UBNT_XM_EEPROM_ADDR          (u8 *) KSEG1ADDR(0x1fff1000)
>> +
>> +static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
>> +     {
>> +             .name           = "ubnt-xm:red:link1",
>> +             .gpio           = UBNT_XM_GPIO_LED_L1,
>> +             .active_low     = 0,
>> +     }, {
>> +             .name           = "ubnt-xm:orange:link2",
>> +             .gpio           = UBNT_XM_GPIO_LED_L2,
>> +             .active_low     = 0,
>> +     }, {
>> +             .name           = "ubnt-xm:green:link3",
>> +             .gpio           = UBNT_XM_GPIO_LED_L3,
>> +             .active_low     = 0,
>> +     }, {
>> +             .name           = "ubnt-xm:green:link4",
>> +             .gpio           = UBNT_XM_GPIO_LED_L4,
>> +             .active_low     = 0,
>> +     },
>> +};
>> +
>> +static struct gpio_keys_button ubnt_xm_gpio_keys[] __initdata = {
>> +     {
>> +             .desc                   = "reset",
>> +             .type                   = EV_KEY,
>> +             .code                   = KEY_RESTART,
>> +             .debounce_interval      = UBNT_XM_KEYS_DEBOUNCE_INTERVAL,
>> +             .gpio                   = UBNT_XM_GPIO_BTN_RESET,
>> +             .active_low             = 1,
>> +     }
>> +};
>> +
>> +static struct spi_board_info ubnt_xm_spi_info[] = {
>> +     {
>> +             .bus_num        = 0,
>> +             .chip_select    = 0,
>> +             .max_speed_hz   = 25000000,
>> +             .modalias       = "mx25l6405d",
>> +     }
>> +};
>> +
>> +static struct ath79_spi_platform_data ubnt_xm_spi_data = {
>> +     .bus_num                = 0,
>> +     .num_chipselect         = 1,
>> +};
>> +
>> +#ifdef CONFIG_PCI
>> +static struct ath9k_platform_data ubnt_xm_eeprom_data;
>> +
>> +static struct ath79_pci_data ubnt_xm_pci_data[] = {
>> +     {
>> +             .slot   = 0,
>> +             .pin    = 1,
>> +             .irq    = ATH79_PCI_IRQ(0),
>> +             .pdata  = &ubnt_xm_eeprom_data,
>> +     },
>> +};
>> +#endif /* CONFIG_PCI */
>> +
>> +static void __init ubnt_xm_init(void)
>> +{
>> +     ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio),
>> +                              ubnt_xm_leds_gpio);
>> +
>> +     ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
>> +                                     ARRAY_SIZE(ubnt_xm_gpio_keys),
>> +                                     ubnt_xm_gpio_keys);
>> +
>> +     ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
>> +                        ARRAY_SIZE(ubnt_xm_spi_info));
>> +
>> +#ifdef CONFIG_PCI
>> +     memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
>> +            sizeof(ubnt_xm_eeprom_data.eeprom_data));
>> +
>> +     ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
>> +#endif /* CONFIG_PCI */
>> +
>> +}
>> +
>> +MIPS_MACHINE(ATH79_MACH_UBNT_XM,
>> +          "UBNT-XM",
>> +          "Ubiquiti Networks XM (rev 1.0) board",
>> +          ubnt_xm_init);
>> diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
>> index 3940fe4..35d5d5c 100644
>> --- a/arch/mips/ath79/machtypes.h
>> +++ b/arch/mips/ath79/machtypes.h
>> @@ -18,6 +18,7 @@ enum ath79_mach_type {
>>       ATH79_MACH_GENERIC = 0,
>>       ATH79_MACH_AP81,                /* Atheros AP81 reference board */
>>       ATH79_MACH_PB44,                /* Atheros PB44 reference board */
>> +     ATH79_MACH_UBNT_XM,             /* Ubiquiti Networks XM board rev 1.0 */
>>  };
>>
>>  #endif /* _ATH79_MACHTYPE_H */
>> diff --git a/arch/mips/include/asm/mach-ath79/irq.h
>> b/arch/mips/include/asm/mach-ath79/irq.h
>> index 189bc6e..eb68e79 100644
>> --- a/arch/mips/include/asm/mach-ath79/irq.h
>> +++ b/arch/mips/include/asm/mach-ath79/irq.h
>> @@ -10,11 +10,15 @@
>>  #define __ASM_MACH_ATH79_IRQ_H
>>
>>  #define MIPS_CPU_IRQ_BASE    0
>> -#define NR_IRQS                      16
>> +#define NR_IRQS                      22
>>
>
> This will conflict with other changes already in linux-next.
>
>>  #define ATH79_MISC_IRQ_BASE  8
>>  #define ATH79_MISC_IRQ_COUNT 8
>>
>> +#define ATH79_PCI_IRQ_BASE   (ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
>> +#define ATH79_PCI_IRQ_COUNT  6
>> +#define ATH79_PCI_IRQ(_x)    (ATH79_PCI_IRQ_BASE + (_x))
>> +
>>  #define ATH79_CPU_IRQ_IP2    (MIPS_CPU_IRQ_BASE + 2)
>>  #define ATH79_CPU_IRQ_USB    (MIPS_CPU_IRQ_BASE + 3)
>>  #define ATH79_CPU_IRQ_GE0    (MIPS_CPU_IRQ_BASE + 4)
>> diff --git a/arch/mips/include/asm/mach-ath79/pci.h
>> b/arch/mips/include/asm/mach-ath79/pci.h
>> new file mode 100644
>> index 0000000..f671174
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-ath79/pci.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + *  Atheros 71xx/724x PCI support
>> + *
>> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
>> + *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
>> + *
>> + *  This program is free software; you can redistribute it and/or modify it
>> + *  under the terms of the GNU General Public License version 2 as published
>> + *  by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __ASM_MACH_ATH79_PCI_H
>> +#define __ASM_MACH_ATH79_PCI_H
>> +
>> +struct ath79_pci_data {
>> +     uint8_t slot;
>> +     uint8_t pin;
>> +     int irq;
>> +     void *pdata;
>> +};
>> +
>> +void ar724x_pci_add_data(struct ath79_pci_data *data, int size);
>> +
>> +#endif /* __ASM_MACH_ATH79_PCI_H */
>> diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
>> index bb82cbd..6603594 100644
>> --- a/arch/mips/pci/Makefile
>> +++ b/arch/mips/pci/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX)               += pci-bcm47xx.o
>>  obj-$(CONFIG_BCM63XX)                += pci-bcm63xx.o fixup-bcm63xx.o \
>>                                       ops-bcm63xx.o
>>  obj-$(CONFIG_MIPS_ALCHEMY)   += pci-alchemy.o
>> +obj-$(CONFIG_AR724X_PCI)     += pci-ar724x.o
>>
>>  #
>>  # These are still pretty much in the old state, watch, go blind.
>> diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
>> new file mode 100644
>> index 0000000..66974fa
>> --- /dev/null
>> +++ b/arch/mips/pci/pci-ar724x.c
>> @@ -0,0 +1,284 @@
>> +/*
>> + *  Atheros 724x PCI support
>> + *
>> + *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
>> + *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
>> + *
>> + *  This program is free software; you can redistribute it and/or modify it
>> + *  under the terms of the GNU General Public License version 2 as published
>> + *  by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/pci.h>
>> +#include <linux/irq.h>
>> +#include <asm/mach-ath79/ath79.h>
>> +#include <asm/mach-ath79/pci.h>
>> +#include <asm/mach-ath79/irq.h>
>> +#include <asm/mach-ath79/ar71xx_regs.h>
>> +
>> +#define AR724X_PCI_CFG_BASE  0x14000000
>> +#define AR724X_PCI_CFG_SIZE  0x1000
>> +#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000)
>> +#define AR724X_PCI_CTRL_SIZE 0x100
>> +
>> +#define AR724X_PCI_MEM_BASE  0x10000000
>> +#define AR724X_PCI_MEM_SIZE  0x08000000
>> +
>> +#define AR724X_PCI_REG_INT_STATUS    0x4c
>> +#define AR724X_PCI_REG_INT_MASK              0x50
>> +#define AR724X_PCI_INT_DEV0          BIT(14)
>> +
>> +#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 struct ath79_pci_data *pci_data;
>> +static int pci_data_size = -1;
>> +
>> +static u32 ar724x_pci_bar0_value;
>> +static bool ar724x_pci_bar0_is_cached;
>> +
>> +static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
>> +                         int size, uint32_t *value)
>> +{
>> +     unsigned long flags;
>> +     void __iomem *base;
>> +
>> +     if (devfn)
>> +             return PCIBIOS_DEVICE_NOT_FOUND;
>> +
>> +     base = ar724x_pci_devcfg_base;
>> +
>> +     spin_lock_irqsave(&ar724x_pci_lock, flags);
>> +
>> +     switch (size) {
>> +     case 1:
>> +             *value = (__raw_readl(base + (where & ~3)) & 0xff);
>
> This is wrong. This will always return the least significant byte, instead of
> the right one. And the outermost parens are not needed.
>
>> +             break;
>> +     case 2:
>> +             *value = (__raw_readl(base + (where & ~3)) & 0xffff);
>
> This is wrong as well.
>
>> +             break;
>> +     case 4:
>> +             if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 &&
>> +                 ar724x_pci_bar0_is_cached)
>> +                     /* use the cached value */
>> +                     *value = ar724x_pci_bar0_value;
>> +             else
>> +                     *value = __raw_readl(base + where);
>> +             break;
>> +     default:
>> +             spin_unlock_irqrestore(&ar724x_pci_lock, flags);
>> +
>> +             return PCIBIOS_BAD_REGISTER_NUMBER;
>> +     }
>> +
>> +     spin_unlock_irqrestore(&ar724x_pci_lock, flags);
>> +
>> +     return PCIBIOS_SUCCESSFUL;
>> +}
>> +
>> +static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
>> +                          int size, uint32_t value)
>> +{
>> +     unsigned long flags;
>> +     void __iomem *base;
>> +
>> +     if (devfn)
>> +             return PCIBIOS_DEVICE_NOT_FOUND;
>> +
>> +     if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
>> +             if (value != 0xffffffff) {
>> +                     /*
>> +                      * WAR for a hw issue. If the BAR0 register of the
>> +                      * device is set to the proper base address, the
>> +                      * memory space of the device is not accessible.
>> +                      *
>> +                      * Cache the intended value so it can be read back,
>> +                      * and write a SoC specific constant value to the
>> +                      * BAR0 register in order to make the device memory
>> +                      * accessible.
>> +                      */
>> +                     ar724x_pci_bar0_is_cached = true;
>> +                     ar724x_pci_bar0_value = value;
>> +                     value = AR7240_BAR0_WAR_VALUE;
>> +             } else {
>> +                     ar724x_pci_bar0_is_cached = false;
>> +             }
>> +     }
>> +
>> +     base = ar724x_pci_devcfg_base;
>> +
>> +     spin_lock_irqsave(&ar724x_pci_lock, flags);
>> +
>> +     switch (size) {
>> +     case 1:
>> +             value = (__raw_readl(base + (where & ~3)) & 0xff);
>> +             __raw_writel(value, base + (where & ~3));
>
> Wrong. This reads the register, and masks out everything but the least
> significant byte, and writes the results back to the same register. It must
> modify the right byte intead.
>
>> +             break;
>> +     case 2:
>> +             value = (__raw_readl(base + (where & ~3)) & 0xffff);
>> +             __raw_writel(value, base + (where & ~3));
>
> Also wrong (with words instead of bytes).
>
>> +             break;
>> +     case 4:
>> +             __raw_writel(value, (base + where));
>> +             break;
>> +     default:
>> +             spin_unlock_irqrestore(&ar724x_pci_lock, flags);
>> +
>> +             return PCIBIOS_BAD_REGISTER_NUMBER;
>> +     }
>> +
>> +     spin_unlock_irqrestore(&ar724x_pci_lock, flags);
>> +
>> +     return PCIBIOS_SUCCESSFUL;
>> +}
>> +
>> +static struct pci_ops ar724x_pci_ops = {
>> +     .read   = ar724x_pci_read,
>> +     .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 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_mask(struct irq_data *data)
>> +{
>> +     void __iomem *base;
>> +     u32 t;
>> +
>> +     base = ar724x_pci_ctrl_base;
>> +
>> +     switch (data->irq) {
>> +     case ATH79_PCI_IRQ(0):
>> +             t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
>> +             __raw_writel(t & ~AR724X_PCI_INT_DEV0,
>> +                          base + AR724X_PCI_REG_INT_MASK);
>
> A __raw_readl is missing.
>
>> +
>> +             t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
>> +             __raw_writel(t | AR724X_PCI_INT_DEV0,
>> +                          base + AR724X_PCI_REG_INT_STATUS);
>
> Here too.
>
>> +     }
>> +}
>> +
>> +static void ar724x_pci_irq_unmask(struct irq_data *data)
>> +{
>> +     void __iomem *base;
>> +     u32 t;
>> +
>> +     base = ar724x_pci_ctrl_base;
>> +
>> +     switch (data->irq) {
>> +     case ATH79_PCI_IRQ(0):
>> +             t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
>> +             __raw_writel(t | AR724X_PCI_INT_DEV0,
>> +                          base + AR724X_PCI_REG_INT_MASK);
>
> And here also.
>
>> +     }
>> +}
>> +
>> +static struct irq_chip ar724x_pci_irq_chip = {
>> +     .name           = "AR724X PCI",
>> +     .irq_mask       = ar724x_pci_irq_mask,
>> +     .irq_unmask     = ar724x_pci_irq_unmask,
>> +     .irq_mask_ack   = ar724x_pci_irq_mask,
>> +};
>> +
>> +static __initconst struct ath79_pci_data ar724x_default_pci_data[] = {
>
> __initconst must be placed after [].
>
>> +     {
>> +             .slot = 0,
>> +             .pin  = 1,
>> +             .irq  = ATH79_PCI_IRQ(0),
>> +     },
>> +};
>> +
>> +void ar724x_pci_add_data(struct ath79_pci_data *data, int size)
>> +{
>> +     pci_data        = data;
>> +     pci_data_size   = size;
>> +}
>> +
>> +int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot,
>> uint8_t pin)
>> +{
>> +     int irq = -1;
>> +     int i;
>> +
>> +     if (pci_data_size == -1)
>> +             return irq;
>> +
>> +     for (i = 0; i < pci_data_size; i++) {
>> +             if ((pci_data[i].slot == slot) && (pci_data[i].pin == pin)) {
>> +                     if (pci_data[i].irq != 0)
>> +                             irq = pci_data[i].irq;
>> +             break;
>
> Wrong indentation for the break statement.
>
>> +             }
>> +     }
>> +
>> +     return irq;
>> +}
>> +
>> +int pcibios_plat_dev_init(struct pci_dev *dev)
>> +{
>> +     int i;
>> +
>> +     if (pci_data_size == -1)
>> +             return PCIBIOS_DEVICE_NOT_FOUND;
>> +
>> +     for (i = 0; i < pci_data_size; i++) {
>> +             if (pci_data[i].slot == PCI_SLOT(dev->devfn)) {
>> +                     if (pci_data[i].pdata != NULL)
>> +                             dev->dev.platform_data = pci_data[i].pdata;
>> +             break;
>
> Ditto.
>
>> +             }
>> +     }
>> +
>> +     return PCIBIOS_SUCCESSFUL;
>> +}
>> +
>> +static int __init ar724x_pcibios_init(void)
>> +{
>> +     int i;
>> +
>> +     ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE,
>> +                                              AR724X_PCI_CFG_SIZE);
>
> ioremap can be used instead of ioremap_nocache.
>
>> +     if (ar724x_pci_devcfg_base == NULL)
>> +             return -ENOMEM;
>> +
>> +     ar724x_pci_ctrl_base = ioremap_nocache(AR724X_PCI_CTRL_BASE,
>> +                                               AR724X_PCI_CTRL_SIZE);
>> +     if (ar724x_pci_ctrl_base == NULL)
>> +             return -ENOMEM;
>
> ar724x_pci_devcfg_base must be unmapped if the second iomap call fails.
>
>> +
>> +     if (pci_data == NULL)
>> +             pci_data = ar724x_default_pci_data;
>> +             pci_data_size = ARRAY_SIZE(ar724x_default_pci_data);
>
> Braces are missing from this if statement.
>
> The AR724X_PCI_IRQ_REG_INT_{MASK,STATUS} registers must be cleared here.
>
>> +
>> +     for (i = ATH79_PCI_IRQ_BASE;
>> +          i < ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT; i++)
>> +             irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
>> +                                      handle_level_irq);
>
> The 'irq_set_chained_handler' call is missing here. And the
> ar724x_pci_irq_handler function is completely missing from the patch.
>
>> +
>> +     register_pci_controller(&ar724x_pci_controller);
>> +
>> +     return PCIBIOS_SUCCESSFUL;
>> +}
>> +
>> +arch_initcall(ar724x_pcibios_init);
>
> Regards,
> Gabor
>

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

* Re: [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support
  2011-11-24 15:54               ` René Bolldorf
@ 2011-11-24 18:39                 ` Gabor Juhos
  0 siblings, 0 replies; 25+ messages in thread
From: Gabor Juhos @ 2011-11-24 18:39 UTC (permalink / raw)
  To: René Bolldorf; +Cc: Ralf Baechle, linux-mips, Imre Kaloz

2011.11.24. 16:54 keltezéssel, René Bolldorf írta:
> 2011/11/24 Gabor Juhos <juhosg@openwrt.org>:
>> Hi René,
>>
>>> Sorry Gabor for the following patch, but it seems your patchset was
>>> against a other tree?
>>
>> Both of my patch sets was based on the 'mips-for-linux-next' branch of Ralf's
>> 'upstream-sfr' tree:
>>
>> git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git
>>
>>> Because of the many failures I rebase'ed against 09521577ca7718b6c of the
>>> linus tree and written anything from scratch.
>>
>> That was waste of time. The ath79 platform got a pile of changes recently, and
>> those changes are not yet available in Linus' tree. If you were unsure about the
>> tree, you should have asked earlier.
>>
> 
> Alright. I don't play with all trees now.

Why if not indiscreet?

> I wait for the next merge.

If you mean Linus' tree, the new codes will not be merged into that before the
release of 3.2. You would have to wait for a few weeks probably.

-Gabor

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

end of thread, other threads:[~2011-11-24 18:39 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-22 23:14 [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support Gabor Juhos
2011-11-22 23:14 ` [PATCH 01/12] MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c Gabor Juhos
2011-11-22 23:14 ` [PATCH 02/12] MIPS: ath79: fix broken ar724x_pci_{read,write} functions Gabor Juhos
2011-11-22 23:14 ` [PATCH 03/12] MIPS: ath79: add a workaround for a PCI controller bug in AR724X SoCs Gabor Juhos
2011-11-22 23:14 ` [PATCH 04/12] MIPS: ath79: fix a wrong IRQ number Gabor Juhos
2011-11-22 23:14 ` [PATCH 05/12] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs Gabor Juhos
2011-11-22 23:14 ` [PATCH 06/12] MIPS: ath79: get rid of some ifdefs in mach-ubnt-xm.c Gabor Juhos
2011-11-22 23:14 ` [PATCH 07/12] MIPS: ath79: allow to use board specific pci_plat_dev_init functions Gabor Juhos
2011-11-22 23:14 ` [PATCH 08/12] MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs Gabor Juhos
2011-11-23  9:21   ` Sergei Shtylyov
2011-11-23 12:04     ` Gabor Juhos
2011-11-22 23:14 ` [PATCH 09/12] MIPS: ath79: allow to use SoC specific PCI IRQ maps Gabor Juhos
2011-11-22 23:14 ` [PATCH 10/12] MIPS: ath79: remove ar724x_pci_add_data function Gabor Juhos
2011-11-22 23:14 ` [PATCH 11/12] MIPS: ath79: register PCI controller on the PB44 board Gabor Juhos
2011-11-22 23:14 ` [PATCH 12/12] MIPS: ath79: update copyright headers of PCI related files Gabor Juhos
2011-11-23 11:35 ` [PATCH 00/12] MIPS: ath79: AR724X PCI fixes and AR71XX PCI support René Bolldorf
2011-11-23 14:08   ` Gabor Juhos
2011-11-23 14:40     ` René Bolldorf
2011-11-23 15:15       ` René Bolldorf
2011-11-23 20:43         ` Gabor Juhos
2011-11-24 10:37           ` René Bolldorf
2011-11-24 15:06             ` Gabor Juhos
2011-11-24 15:54               ` René Bolldorf
2011-11-24 18:39                 ` Gabor Juhos
2011-11-23 20:39       ` Gabor Juhos

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.