From d4a8a448fa131401b9150e6f93506e3fa92c08f4 Mon Sep 17 00:00:00 2001
From: hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Fri, 10 Feb 2012 17:22:26 +0000
Subject: [PATCH] brcm47xx: update bcm5354 support patch

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30423 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../brcm47xx/patches-3.2/220-bcm5354.patch    | 179 ++++++++++++++----
 1 file changed, 141 insertions(+), 38 deletions(-)

diff --git a/target/linux/brcm47xx/patches-3.2/220-bcm5354.patch b/target/linux/brcm47xx/patches-3.2/220-bcm5354.patch
index 84f7d6165..e8c7dde69 100644
--- a/target/linux/brcm47xx/patches-3.2/220-bcm5354.patch
+++ b/target/linux/brcm47xx/patches-3.2/220-bcm5354.patch
@@ -1,42 +1,145 @@
---- a/drivers/ssb/driver_chipcommon.c
-+++ b/drivers/ssb/driver_chipcommon.c
-@@ -318,6 +318,8 @@ void ssb_chipco_resume(struct ssb_chipco
- void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
-                              u32 *plltype, u32 *n, u32 *m)
- {
-+	if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
-+		return;
- 	*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
- 	*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
- 	switch (*plltype) {
-@@ -341,6 +343,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
- void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
- 				 u32 *plltype, u32 *n, u32 *m)
- {
-+	if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
-+		return;
- 	*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
- 	*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
- 	switch (*plltype) {
+From 6d174f732e198aae8583cc5414b11b988bfd37a9 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Mon, 30 Jan 2012 22:44:15 +0100
+Subject: [PATCH 4/4] ssb: add support for bcm5354
+
+This patch adds support the the BCM5354 SoC.
+It has a PMU and a constant not configurable clock.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/ssb/driver_chipcommon_pmu.c |   48 +++++++++++++++++++++++++++++++---
+ drivers/ssb/driver_mipscore.c       |    3 ++
+ drivers/ssb/main.c                  |    3 ++
+ drivers/ssb/ssb_private.h           |    4 +++
+ 4 files changed, 53 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
+index e5a2e0e..b58fef7 100644
+--- a/drivers/ssb/driver_chipcommon_pmu.c
++++ b/drivers/ssb/driver_chipcommon_pmu.c
+@@ -13,6 +13,9 @@
+ #include <linux/ssb/ssb_driver_chipcommon.h>
+ #include <linux/delay.h>
+ #include <linux/export.h>
++#ifdef CONFIG_BCM47XX
++#include <asm/mach-bcm47xx/nvram.h>
++#endif
+ 
+ #include "ssb_private.h"
+ 
+@@ -92,10 +95,6 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
+ 	u32 pmuctl, tmp, pllctl;
+ 	unsigned int i;
+ 
+-	if ((bus->chip_id == 0x5354) && !crystalfreq) {
+-		/* The 5354 crystal freq is 25MHz */
+-		crystalfreq = 25000;
+-	}
+ 	if (crystalfreq)
+ 		e = pmu0_plltab_find_entry(crystalfreq);
+ 	if (!e)
+@@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
+ 	u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
+ 
+ 	if (bus->bustype == SSB_BUSTYPE_SSB) {
+-		/* TODO: The user may override the crystal frequency. */
++#ifdef CONFIG_BCM47XX
++		char buf[20];
++		if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
++			crystalfreq = simple_strtoul(buf, NULL, 0);
++#endif
+ 	}
+ 
+ 	switch (bus->chip_id) {
+@@ -330,7 +333,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
+ 		ssb_pmu1_pllinit_r0(cc, crystalfreq);
+ 		break;
+ 	case 0x4328:
++		ssb_pmu0_pllinit_r0(cc, crystalfreq);
++		break;
+ 	case 0x5354:
++		if (crystalfreq == 0)
++			crystalfreq = 25000;
+ 		ssb_pmu0_pllinit_r0(cc, crystalfreq);
+ 		break;
+ 	case 0x4322:
+@@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
+ 
+ EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
+ EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
++
++u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
++{
++	struct ssb_bus *bus = cc->dev->bus;
++
++	switch (bus->chip_id) {
++	case 0x5354:
++		/* 5354 chip uses a non programmable PLL of frequency 240MHz */
++		return 240000000;
++	default:
++		ssb_printk(KERN_ERR PFX
++			   "ERROR: PMU cpu clock unknown for device %04X\n",
++			   bus->chip_id);
++		return 0;
++	}
++}
++
++u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
++{
++	struct ssb_bus *bus = cc->dev->bus;
++
++	switch (bus->chip_id) {
++	case 0x5354:
++		return 120000000;
++	default:
++		ssb_printk(KERN_ERR PFX
++			   "ERROR: PMU controlclock unknown for device %04X\n",
++			   bus->chip_id);
++		return 0;
++	}
++}
+diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
+index ced5015..d784ec8 100644
 --- a/drivers/ssb/driver_mipscore.c
 +++ b/drivers/ssb/driver_mipscore.c
-@@ -241,6 +241,8 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
- 
- 	if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
- 		rate = 200000000;
-+	} else if (bus->chip_id == 0x5354) {
-+		rate = 240000000;
- 	} else {
- 		rate = ssb_calc_clock_rate(pll_type, n, m);
- 	}
+@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
+ 	struct ssb_bus *bus = mcore->dev->bus;
+ 	u32 pll_type, n, m, rate = 0;
+ 
++	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
++	    	return ssb_pmu_get_cpu_clock(&bus->chipco);
++
+ 	if (bus->extif.dev) {
+ 		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+ 	} else if (bus->chipco.dev) {
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index bb6317f..d109cf0 100644
 --- a/drivers/ssb/main.c
 +++ b/drivers/ssb/main.c
-@@ -1105,6 +1105,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
- 
- 	if (bus->chip_id == 0x5365) {
- 		rate = 100000000;
-+	} else if (bus->chip_id == 0x5354) {
-+		rate = 120000000;
- 	} else {
- 		rate = ssb_calc_clock_rate(plltype, clkctl_n, clkctl_m);
- 		if (plltype == SSB_PLLTYPE_3) /* 25Mhz, 2 dividers */
+@@ -1094,6 +1094,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
+ 	u32 plltype;
+ 	u32 clkctl_n, clkctl_m;
+ 
++	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
++	    	return ssb_pmu_get_controlclock(&bus->chipco);
++
+ 	if (ssb_extif_available(&bus->extif))
+ 		ssb_extif_get_clockcontrol(&bus->extif, &plltype,
+ 					   &clkctl_n, &clkctl_m);
+diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
+index 7765301..a305550 100644
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_exit(void)
+ }
+ #endif /* CONFIG_SSB_B43_PCI_BRIDGE */
+ 
++/* driver_chipcommon_pmu.c */
++extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
++extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
++
+ #endif /* LINUX_SSB_PRIVATE_H_ */
+-- 
+1.7.5.4
+
-- 
2.20.1