ssb: get alp clock from devices with PMU
authorHauke Mehrtens <hauke@hauke-m.de>
Wed, 5 Dec 2012 17:46:03 +0000 (18:46 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 6 Dec 2012 19:58:57 +0000 (14:58 -0500)
If there is a PMU in the device, get the alp clock from that part and
do not assume 20000000.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/ssb/driver_chipcommon.c
drivers/ssb/driver_chipcommon_pmu.c
drivers/ssb/ssb_private.h

index e9d2ca11283b3e60fd8d63a31bf59b739135739e..603b63032e93053d7fda6acf8eb76af3f88cecea 100644 (file)
@@ -280,6 +280,14 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
        cc->fast_pwrup_delay = tmp;
 }
 
+static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc)
+{
+       if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
+               return ssb_pmu_get_alp_clock(cc);
+
+       return 20000000;
+}
+
 void ssb_chipcommon_init(struct ssb_chipcommon *cc)
 {
        if (!cc->dev)
@@ -473,12 +481,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
                                       chipco_read32(cc, SSB_CHIPCO_CORECTL)
                                       | SSB_CHIPCO_CORECTL_UARTCLK0);
                } else if ((ccrev >= 11) && (ccrev != 15)) {
-                       /* Fixed ALP clock */
-                       baud_base = 20000000;
-                       if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
-                               /* FIXME: baud_base is different for devices with a PMU */
-                               SSB_WARN_ON(1);
-                       }
+                       baud_base = ssb_chipco_alp_clock(cc);
                        div = 1;
                        if (ccrev >= 21) {
                                /* Turn off UART clock before switching clocksource. */
index d7d58044b4bc591fbce0b220ee1bec4ba587885c..a43415a7fbedfa7dd537d2dc48581904adbb3db9 100644 (file)
@@ -618,6 +618,33 @@ 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);
 
+static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
+{
+       u32 crystalfreq;
+       const struct pmu0_plltab_entry *e = NULL;
+
+       crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
+                     SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
+       e = pmu0_plltab_find_entry(crystalfreq);
+       BUG_ON(!e);
+       return e->freq * 1000;
+}
+
+u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
+{
+       struct ssb_bus *bus = cc->dev->bus;
+
+       switch (bus->chip_id) {
+       case 0x5354:
+               ssb_pmu_get_alp_clock_clk0(cc);
+       default:
+               ssb_printk(KERN_ERR PFX
+                          "ERROR: PMU alp clock unknown for device %04X\n",
+                          bus->chip_id);
+               return 0;
+       }
+}
+
 u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
 {
        struct ssb_bus *bus = cc->dev->bus;
index a305550b4b65ecce6c5e6e925c63c36667edd3b0..98b2915cd30baf1a7b18f82992d32b9cf857cd2e 100644 (file)
@@ -210,5 +210,6 @@ static inline void b43_pci_ssb_bridge_exit(void)
 /* 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);
+extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
 
 #endif /* LINUX_SSB_PRIVATE_H_ */