ssb: cc: prepare clockmode support for cores rev 10+
authorRafał Miłecki <zajec5@gmail.com>
Wed, 27 Apr 2011 15:40:11 +0000 (17:40 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 2 May 2011 18:49:14 +0000 (14:49 -0400)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/ssb/driver_chipcommon.c

index b4b3733aefcf74a976cf7c42aea04648fb1abd8a..06d15b6f2215694b1c380c3891c4bedbf726858e 100644 (file)
@@ -46,40 +46,66 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
        if (!ccdev)
                return;
        bus = ccdev->bus;
+
+       /* We support SLOW only on 6..9 */
+       if (ccdev->id.revision >= 10 && mode == SSB_CLKMODE_SLOW)
+               mode = SSB_CLKMODE_DYNAMIC;
+
+       if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
+               return; /* PMU controls clockmode, separated function needed */
+       SSB_WARN_ON(ccdev->id.revision >= 20);
+
        /* chipcommon cores prior to rev6 don't support dynamic clock control */
        if (ccdev->id.revision < 6)
                return;
-       /* chipcommon cores rev10 are a whole new ball game */
+
+       /* ChipCommon cores rev10+ need testing */
        if (ccdev->id.revision >= 10)
                return;
+
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
                return;
 
        switch (mode) {
-       case SSB_CLKMODE_SLOW:
+       case SSB_CLKMODE_SLOW: /* For revs 6..9 only */
                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
                tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW;
                chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
                break;
        case SSB_CLKMODE_FAST:
-               ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */
-               tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
-               tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
-               tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL;
-               chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
+               if (ccdev->id.revision < 10) {
+                       ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */
+                       tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
+                       tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
+                       tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL;
+                       chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
+               } else {
+                       chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
+                               (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) |
+                                SSB_CHIPCO_SYSCLKCTL_FORCEHT));
+                       /* udelay(150); TODO: not available in early init */
+               }
                break;
        case SSB_CLKMODE_DYNAMIC:
-               tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
-               tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
-               tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL;
-               tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
-               if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL)
-                       tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
-               chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
-
-               /* for dynamic control, we have to release our xtal_pu "force on" */
-               if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL)
-                       ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);
+               if (ccdev->id.revision < 10) {
+                       tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
+                       tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
+                       tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL;
+                       tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
+                       if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) !=
+                           SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL)
+                               tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
+                       chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
+
+                       /* For dynamic control, we have to release our xtal_pu
+                        * "force on" */
+                       if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL)
+                               ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);
+               } else {
+                       chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
+                               (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) &
+                                ~SSB_CHIPCO_SYSCLKCTL_FORCEHT));
+               }
                break;
        default:
                SSB_WARN_ON(1);