[ARM] orion/kirkwood: reset PCIe unit on boot

Patch found in QNAPs vendor source package, with some cleanups
(proper defines, shortened max. timeout from 1s to 200ms).

Without this patch the PCIe SATA controller (Marvell 88sx7042/sata_mv)
in my QNAP TS-419P (Marvell 88f6281/Kirkwood) stops working after a
few minutes.

The symptomes are described in this thread:
http://marc.info/?l=linux-ide&m=124822863706181&w=2

[ Note: this is a workaround in need of a better analysis/solution -- NP ]

Acked-by: Saeed Bishara <saeed@marvell.com>
Tested-by: Bernhard R. Link <brl@pcpool00.mathematik.uni-freiburg.de>
Seconded-by: Martin Michlmayr <tbm@cyrius.com>
I'm_not_very_happy_with_it-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
This commit is contained in:
Olaf Rempel 2010-06-08 22:32:38 +02:00 committed by Nicolas Pitre
parent 6f2b186a0f
commit 21f0ba90a4

View file

@ -13,6 +13,7 @@
#include <linux/mbus.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
#include <linux/delay.h>
/*
* PCIe unit register offsets.
@ -46,6 +47,8 @@
#define PCIE_STAT_BUS_OFFS 8
#define PCIE_STAT_BUS_MASK 0xff
#define PCIE_STAT_LINK_DOWN 1
#define PCIE_DEBUG_CTRL 0x1a60
#define PCIE_DEBUG_SOFT_RESET (1<<20)
u32 __init orion_pcie_dev_id(void __iomem *base)
@ -85,6 +88,32 @@ void __init orion_pcie_set_local_bus_nr(void __iomem *base, int nr)
writel(stat, base + PCIE_STAT_OFF);
}
void __init orion_pcie_reset(void __iomem *base)
{
u32 reg;
int i;
/*
* MV-S104860-U0, Rev. C:
* PCI Express Unit Soft Reset
* When set, generates an internal reset in the PCI Express unit.
* This bit should be cleared after the link is re-established.
*/
reg = readl(base + PCIE_DEBUG_CTRL);
reg |= PCIE_DEBUG_SOFT_RESET;
writel(reg, base + PCIE_DEBUG_CTRL);
for (i = 0; i < 20; i++) {
mdelay(10);
if (orion_pcie_link_up(base))
break;
}
reg &= ~(PCIE_DEBUG_SOFT_RESET);
writel(reg, base + PCIE_DEBUG_CTRL);
}
/*
* Setup PCIE BARs and Address Decode Wins:
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
@ -152,6 +181,11 @@ void __init orion_pcie_setup(void __iomem *base,
u16 cmd;
u32 mask;
/*
* soft reset PCIe unit
*/
orion_pcie_reset(base);
/*
* Point PCIe unit MBUS decode windows to DRAM space.
*/