コード例 #1
0
ファイル: ar5312.c プロジェクト: lacombar/netbsd-alc
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);
}
コード例 #2
0
ファイル: ar5312.c プロジェクト: lacombar/netbsd-alc
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");
	}
}
コード例 #3
0
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;
}