From b97f8ef70b5ac2844b8dd6afbb247e80b2bf7787 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Thu, 22 Mar 2007 20:23:17 +0000
Subject: [PATCH] add brcm47xx-2.6 fixes from #1496

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@6639 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../brcm47xx-2.6/files/drivers/ssb/core.c     |  2 +-
 .../ssb/driver_chipcommon/chipcommon.c        | 29 +++++++++++++++++++
 .../files/drivers/ssb/driver_mips/mips.c      | 11 ++++---
 .../files/drivers/ssb/driver_pci/pcicore.c    |  3 ++
 .../include/linux/ssb/ssb_driver_chipcommon.h |  2 ++
 5 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/target/linux/brcm47xx-2.6/files/drivers/ssb/core.c b/target/linux/brcm47xx-2.6/files/drivers/ssb/core.c
index a3fbaca9d..2ee13d2d3 100644
--- a/target/linux/brcm47xx-2.6/files/drivers/ssb/core.c
+++ b/target/linux/brcm47xx-2.6/files/drivers/ssb/core.c
@@ -235,6 +235,7 @@ static int ssb_attach_queued_buses(void)
 	int i, err;
 
 	list_for_each_entry_safe(bus, n, &attach_queue, list) {
+		ssb_pcicore_init(&bus->pcicore);
 		for (i = 0; i < bus->nr_devices; i++) {
 			dev = &(bus->devices[i]);
 
@@ -350,7 +351,6 @@ static int ssb_bus_register(struct ssb_bus *bus,
 	/* Initialize basic system devices (if available) */
 	ssb_chipcommon_init(&bus->chipco);
 	ssb_mipscore_init(&bus->mipscore);
-	ssb_pcicore_init(&bus->pcicore);
 
 	/* Queue it for attach */
 	list_add_tail(&bus->list, &attach_queue);
diff --git a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_chipcommon/chipcommon.c b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_chipcommon/chipcommon.c
index 6d3412b58..a17910947 100644
--- a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_chipcommon/chipcommon.c
+++ b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_chipcommon/chipcommon.c
@@ -266,6 +266,35 @@ void ssb_chipco_resume(struct ssb_chipcommon *cc)
 	chipco_powercontrol_init(cc);
 }
 
+void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, u32 chip_id, u32 *rate,
+			     u32 *plltype, u32 *n, u32 *m)
+{
+	*rate = 0;
+	*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
+	*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
+	switch (*plltype) {
+		case SSB_PLLTYPE_2:
+		case SSB_PLLTYPE_4:
+		case SSB_PLLTYPE_6:
+		case SSB_PLLTYPE_7:
+			*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
+			break;
+		case SSB_PLLTYPE_5:
+			*rate = 200000000;
+			break;
+		case SSB_PLLTYPE_3:
+			/* 5350 uses m2 to control mips */
+			*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
+			break;
+		default:
+			*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
+			break;
+	}
+
+	if (*rate == 0 && chip_id == 0x5365)
+		*rate = 200000000;
+}
+
 void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
 				 u32 *plltype, u32 *n, u32 *m)
 {
diff --git a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_mips/mips.c b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_mips/mips.c
index 65916b17b..7b3880ab0 100644
--- a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_mips/mips.c
+++ b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_mips/mips.c
@@ -215,15 +215,14 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
 	if (bus->extif.dev) {
 		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
 	} else if (bus->chipco.dev) {
-		if (bus->chip_id == 0x5365)
-			/* FIXME: is this override really necessary? */
-			return 200000000;
-
-		ssb_chipco_get_clockcontrol(&bus->chipco, &pll_type, &n, &m);
+		ssb_chipco_get_clockcpu(&bus->chipco, bus->chip_id, &rate,
+			&pll_type, &n, &m);
 	} else
 		return 0;
 
-	rate = ssb_calc_clock_rate(pll_type, n, m);
+	if (rate == 0)
+		rate = ssb_calc_clock_rate(pll_type, n, m);
+
 	if (pll_type == SSB_PLLTYPE_6)
 		rate *= 2;
 
diff --git a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_pci/pcicore.c b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_pci/pcicore.c
index 9800ce66e..e02583495 100644
--- a/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_pci/pcicore.c
+++ b/target/linux/brcm47xx-2.6/files/drivers/ssb/driver_pci/pcicore.c
@@ -303,6 +303,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	udelay(150);
 	val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
 	pcicore_write32(pc, SSB_PCICORE_CTL, val);
+	val = SSB_PCICORE_ARBCTL_INTERN;
+	pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); 
 	udelay(1);
 
 	//TODO cardbus mode
@@ -329,6 +331,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	 * The following needs change, if we want to port hostmode
 	 * to non-MIPS platform. */
 	set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
+	mdelay(300);
 	register_pci_controller(&ssb_pcicore_controller);
 }
 
diff --git a/target/linux/brcm47xx-2.6/files/include/linux/ssb/ssb_driver_chipcommon.h b/target/linux/brcm47xx-2.6/files/include/linux/ssb/ssb_driver_chipcommon.h
index ba0b8702c..e0c0e61b8 100644
--- a/target/linux/brcm47xx-2.6/files/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/target/linux/brcm47xx-2.6/files/include/linux/ssb/ssb_driver_chipcommon.h
@@ -364,6 +364,8 @@ extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
 extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
 extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
 
+extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, u32 chip_id,
+	u32 *rate, u32 *plltype, u32 *n, u32 *m);
 extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
 					u32 *plltype, u32 *n, u32 *m);
 extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
-- 
2.20.1