uint32_t ar531x_cpu_freq(void) { static uint32_t cpufreq; uint32_t wisoc = GETSYSREG(AR5312_SYSREG_REVISION); uint32_t predivmask; uint32_t predivshift; uint32_t multmask; uint32_t multshift; uint32_t doublermask; uint32_t divisor; uint32_t multiplier; uint32_t clockctl; const int predivide_table[4] = { 1, 2, 4, 5 }; /* XXX: in theory we might be able to get clock from bootrom */ /* * This logic looks at the clock control register and * determines the actual CPU frequency. These parts lack any * kind of real-time clock on them, but the cpu clocks should * be very accurate -- WiFi requires usec resolution timers. */ if (cpufreq) { return cpufreq; } if (AR5312_REVISION_MAJOR(wisoc) == AR5312_REVISION_MAJ_AR2313) { predivmask = AR2313_CLOCKCTL_PREDIVIDE_MASK; predivshift = AR2313_CLOCKCTL_PREDIVIDE_SHIFT; multmask = AR2313_CLOCKCTL_MULTIPLIER_MASK; multshift = AR2313_CLOCKCTL_MULTIPLIER_SHIFT; doublermask = AR2313_CLOCKCTL_DOUBLER_MASK; } else { predivmask = AR5312_CLOCKCTL_PREDIVIDE_MASK; predivshift = AR5312_CLOCKCTL_PREDIVIDE_SHIFT; multmask = AR5312_CLOCKCTL_MULTIPLIER_MASK; multshift = AR5312_CLOCKCTL_MULTIPLIER_SHIFT; doublermask = AR5312_CLOCKCTL_DOUBLER_MASK; } /* * Note that the source clock involved here is a 40MHz. */ clockctl = GETSYSREG(AR5312_SYSREG_CLOCKCTL); divisor = predivide_table[(clockctl & predivmask) >> predivshift]; multiplier = (clockctl & multmask) >> multshift; if (clockctl & doublermask) multiplier <<= 1; cpufreq = (40000000 / divisor) * multiplier; return (cpufreq); }
const char * ar531x_cpuname(void) { uint32_t revision; revision = GETSYSREG(AR5312_SYSREG_REVISION); switch (AR5312_REVISION_MAJOR(revision)) { case AR5312_REVISION_MAJ_AR5311: return ("Atheros AR5311"); case AR5312_REVISION_MAJ_AR5312: return ("Atheros AR5312"); case AR5312_REVISION_MAJ_AR2313: return ("Atheros AR2313"); case AR5312_REVISION_MAJ_AR5315: return ("Atheros AR5315"); default: return ("Atheros AR531X"); } }
static void ar5312_get_freqs(struct arfreqs *freqs) { const uint32_t wisoc = GETSYSREG(AR5312_SYSREG_REVISION); uint32_t predivisor; uint32_t multiplier; /* * This logic looks at the clock control register and * determines the actual CPU frequency. These parts lack any * kind of real-time clock on them, but the cpu clocks should * be very accurate -- WiFi requires usec resolution timers. */ const uint32_t clockctl = GETSYSREG(AR5312_SYSREG_CLOCKCTL); if (AR5312_REVISION_MAJOR(wisoc) == AR5312_REVISION_MAJ_AR2313) { predivisor = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_PREDIVIDE); multiplier = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_MULTIPLIER); } else { predivisor = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_PREDIVIDE); multiplier = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_MULTIPLIER); if (clockctl & AR5312_CLOCKCTL_DOUBLER) multiplier <<= 1; } /* * Note that the source clock involved here is a 40MHz. */ const uint32_t divisor = (0x5421 >> (predivisor * 4)) & 15; const uint32_t cpufreq = (40000000 / divisor) * multiplier; freqs->freq_cpu = cpufreq; freqs->freq_bus = cpufreq / 4; freqs->freq_mem = 0; freqs->freq_ref = 40000000; freqs->freq_pll = 40000000; }