| 1 | From 6d174f732e198aae8583cc5414b11b988bfd37a9 Mon Sep 17 00:00:00 2001 |
| 2 | From: Hauke Mehrtens <hauke@hauke-m.de> |
| 3 | Date: Mon, 30 Jan 2012 22:44:15 +0100 |
| 4 | Subject: [PATCH 4/4] ssb: add support for bcm5354 |
| 5 | |
| 6 | This patch adds support the the BCM5354 SoC. |
| 7 | It has a PMU and a constant not configurable clock. |
| 8 | |
| 9 | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> |
| 10 | --- |
| 11 | drivers/ssb/driver_chipcommon_pmu.c | 48 +++++++++++++++++++++++++++++++--- |
| 12 | drivers/ssb/driver_mipscore.c | 3 ++ |
| 13 | drivers/ssb/main.c | 3 ++ |
| 14 | drivers/ssb/ssb_private.h | 4 +++ |
| 15 | 4 files changed, 53 insertions(+), 5 deletions(-) |
| 16 | |
| 17 | --- a/drivers/ssb/driver_chipcommon_pmu.c |
| 18 | +++ b/drivers/ssb/driver_chipcommon_pmu.c |
| 19 | @@ -13,6 +13,9 @@ |
| 20 | #include <linux/ssb/ssb_driver_chipcommon.h> |
| 21 | #include <linux/delay.h> |
| 22 | #include <linux/export.h> |
| 23 | +#ifdef CONFIG_BCM47XX |
| 24 | +#include <asm/mach-bcm47xx/nvram.h> |
| 25 | +#endif |
| 26 | |
| 27 | #include "ssb_private.h" |
| 28 | |
| 29 | @@ -92,10 +95,6 @@ static void ssb_pmu0_pllinit_r0(struct s |
| 30 | u32 pmuctl, tmp, pllctl; |
| 31 | unsigned int i; |
| 32 | |
| 33 | - if ((bus->chip_id == 0x5354) && !crystalfreq) { |
| 34 | - /* The 5354 crystal freq is 25MHz */ |
| 35 | - crystalfreq = 25000; |
| 36 | - } |
| 37 | if (crystalfreq) |
| 38 | e = pmu0_plltab_find_entry(crystalfreq); |
| 39 | if (!e) |
| 40 | @@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_ |
| 41 | u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ |
| 42 | |
| 43 | if (bus->bustype == SSB_BUSTYPE_SSB) { |
| 44 | - /* TODO: The user may override the crystal frequency. */ |
| 45 | +#ifdef CONFIG_BCM47XX |
| 46 | + char buf[20]; |
| 47 | + if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) |
| 48 | + crystalfreq = simple_strtoul(buf, NULL, 0); |
| 49 | +#endif |
| 50 | } |
| 51 | |
| 52 | switch (bus->chip_id) { |
| 53 | @@ -330,7 +333,11 @@ static void ssb_pmu_pll_init(struct ssb_ |
| 54 | ssb_pmu1_pllinit_r0(cc, crystalfreq); |
| 55 | break; |
| 56 | case 0x4328: |
| 57 | + ssb_pmu0_pllinit_r0(cc, crystalfreq); |
| 58 | + break; |
| 59 | case 0x5354: |
| 60 | + if (crystalfreq == 0) |
| 61 | + crystalfreq = 25000; |
| 62 | ssb_pmu0_pllinit_r0(cc, crystalfreq); |
| 63 | break; |
| 64 | case 0x4322: |
| 65 | @@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch |
| 66 | |
| 67 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); |
| 68 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); |
| 69 | + |
| 70 | +u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) |
| 71 | +{ |
| 72 | + struct ssb_bus *bus = cc->dev->bus; |
| 73 | + |
| 74 | + switch (bus->chip_id) { |
| 75 | + case 0x5354: |
| 76 | + /* 5354 chip uses a non programmable PLL of frequency 240MHz */ |
| 77 | + return 240000000; |
| 78 | + default: |
| 79 | + ssb_printk(KERN_ERR PFX |
| 80 | + "ERROR: PMU cpu clock unknown for device %04X\n", |
| 81 | + bus->chip_id); |
| 82 | + return 0; |
| 83 | + } |
| 84 | +} |
| 85 | + |
| 86 | +u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) |
| 87 | +{ |
| 88 | + struct ssb_bus *bus = cc->dev->bus; |
| 89 | + |
| 90 | + switch (bus->chip_id) { |
| 91 | + case 0x5354: |
| 92 | + return 120000000; |
| 93 | + default: |
| 94 | + ssb_printk(KERN_ERR PFX |
| 95 | + "ERROR: PMU controlclock unknown for device %04X\n", |
| 96 | + bus->chip_id); |
| 97 | + return 0; |
| 98 | + } |
| 99 | +} |
| 100 | --- a/drivers/ssb/driver_mipscore.c |
| 101 | +++ b/drivers/ssb/driver_mipscore.c |
| 102 | @@ -232,6 +232,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m |
| 103 | struct ssb_bus *bus = mcore->dev->bus; |
| 104 | u32 pll_type, n, m, rate = 0; |
| 105 | |
| 106 | + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) |
| 107 | + return ssb_pmu_get_cpu_clock(&bus->chipco); |
| 108 | + |
| 109 | if (bus->extif.dev) { |
| 110 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); |
| 111 | } else if (bus->chipco.dev) { |
| 112 | --- a/drivers/ssb/main.c |
| 113 | +++ b/drivers/ssb/main.c |
| 114 | @@ -1094,6 +1094,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) |
| 115 | u32 plltype; |
| 116 | u32 clkctl_n, clkctl_m; |
| 117 | |
| 118 | + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) |
| 119 | + return ssb_pmu_get_controlclock(&bus->chipco); |
| 120 | + |
| 121 | if (ssb_extif_available(&bus->extif)) |
| 122 | ssb_extif_get_clockcontrol(&bus->extif, &plltype, |
| 123 | &clkctl_n, &clkctl_m); |
| 124 | --- a/drivers/ssb/ssb_private.h |
| 125 | +++ b/drivers/ssb/ssb_private.h |
| 126 | @@ -211,4 +211,8 @@ static inline void b43_pci_ssb_bridge_ex |
| 127 | } |
| 128 | #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ |
| 129 | |
| 130 | +/* driver_chipcommon_pmu.c */ |
| 131 | +extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); |
| 132 | +extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); |
| 133 | + |
| 134 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
| 135 | |