diff options
Diffstat (limited to 'drivers/ssb/driver_chipcommon.c')
| -rw-r--r-- | drivers/ssb/driver_chipcommon.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 7c031fdc8205..06d15b6f2215 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
| @@ -46,40 +46,66 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, | |||
| 46 | if (!ccdev) | 46 | if (!ccdev) |
| 47 | return; | 47 | return; |
| 48 | bus = ccdev->bus; | 48 | bus = ccdev->bus; |
| 49 | |||
| 50 | /* We support SLOW only on 6..9 */ | ||
| 51 | if (ccdev->id.revision >= 10 && mode == SSB_CLKMODE_SLOW) | ||
| 52 | mode = SSB_CLKMODE_DYNAMIC; | ||
| 53 | |||
| 54 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) | ||
| 55 | return; /* PMU controls clockmode, separated function needed */ | ||
| 56 | SSB_WARN_ON(ccdev->id.revision >= 20); | ||
| 57 | |||
| 49 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | 58 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ |
| 50 | if (ccdev->id.revision < 6) | 59 | if (ccdev->id.revision < 6) |
| 51 | return; | 60 | return; |
| 52 | /* chipcommon cores rev10 are a whole new ball game */ | 61 | |
| 62 | /* ChipCommon cores rev10+ need testing */ | ||
| 53 | if (ccdev->id.revision >= 10) | 63 | if (ccdev->id.revision >= 10) |
| 54 | return; | 64 | return; |
| 65 | |||
| 55 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) | 66 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) |
| 56 | return; | 67 | return; |
| 57 | 68 | ||
| 58 | switch (mode) { | 69 | switch (mode) { |
| 59 | case SSB_CLKMODE_SLOW: | 70 | case SSB_CLKMODE_SLOW: /* For revs 6..9 only */ |
| 60 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | 71 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); |
| 61 | tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW; | 72 | tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW; |
| 62 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | 73 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); |
| 63 | break; | 74 | break; |
| 64 | case SSB_CLKMODE_FAST: | 75 | case SSB_CLKMODE_FAST: |
| 65 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ | 76 | if (ccdev->id.revision < 10) { |
| 66 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | 77 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ |
| 67 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; | 78 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); |
| 68 | tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; | 79 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; |
| 69 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | 80 | tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; |
| 81 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | ||
| 82 | } else { | ||
| 83 | chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, | ||
| 84 | (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) | | ||
| 85 | SSB_CHIPCO_SYSCLKCTL_FORCEHT)); | ||
| 86 | /* udelay(150); TODO: not available in early init */ | ||
| 87 | } | ||
| 70 | break; | 88 | break; |
| 71 | case SSB_CLKMODE_DYNAMIC: | 89 | case SSB_CLKMODE_DYNAMIC: |
| 72 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | 90 | if (ccdev->id.revision < 10) { |
| 73 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; | 91 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); |
| 74 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; | 92 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; |
| 75 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; | 93 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; |
| 76 | if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) | 94 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; |
| 77 | tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; | 95 | if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != |
| 78 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | 96 | SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) |
| 79 | 97 | tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; | |
| 80 | /* for dynamic control, we have to release our xtal_pu "force on" */ | 98 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); |
| 81 | if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) | 99 | |
| 82 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); | 100 | /* For dynamic control, we have to release our xtal_pu |
| 101 | * "force on" */ | ||
| 102 | if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) | ||
| 103 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); | ||
| 104 | } else { | ||
| 105 | chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, | ||
| 106 | (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) & | ||
| 107 | ~SSB_CHIPCO_SYSCLKCTL_FORCEHT)); | ||
| 108 | } | ||
| 83 | break; | 109 | break; |
| 84 | default: | 110 | default: |
| 85 | SSB_WARN_ON(1); | 111 | SSB_WARN_ON(1); |
| @@ -260,6 +286,12 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
| 260 | if (cc->dev->id.revision >= 11) | 286 | if (cc->dev->id.revision >= 11) |
| 261 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); | 287 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); |
| 262 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); | 288 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); |
| 289 | |||
| 290 | if (cc->dev->id.revision >= 20) { | ||
| 291 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); | ||
| 292 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLDOWN, 0); | ||
| 293 | } | ||
| 294 | |||
| 263 | ssb_pmu_init(cc); | 295 | ssb_pmu_init(cc); |
| 264 | chipco_powercontrol_init(cc); | 296 | chipco_powercontrol_init(cc); |
| 265 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); | 297 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); |
