Exemplo n.º 1
0
static int
ar5312_enable_device(const struct atheros_device *adv)
{
	const struct ar531x_boarddata * const info = atheros_get_board_info();

	if (info != NULL
	    && adv->adv_mask && ((adv->adv_mask & info->config) == 0)) {
		return -1;
	}
	if (adv->adv_reset) {
		/* put device into reset */
		PUTSYSREG(AR5312_SYSREG_RESETCTL,
		    GETSYSREG(AR5312_SYSREG_RESETCTL) | adv->adv_reset);

		delay(15000);	/* XXX: tsleep? */

		/* take it out of reset */
		PUTSYSREG(AR5312_SYSREG_RESETCTL,
		    GETSYSREG(AR5312_SYSREG_RESETCTL) & ~adv->adv_reset);

		delay(25);
	}
	if (adv->adv_enable) {
		PUTSYSREG(AR5312_SYSREG_ENABLE,
		    GETSYSREG(AR5312_SYSREG_ENABLE) | adv->adv_enable);
	}
	return 0;
}
Exemplo n.º 2
0
int
ar531x_enable_device(const struct ar531x_device *dev)
{
	const struct ar531x_boarddata *info;

	info = ar531x_board_info();
	if (dev->mask && ((dev->mask & info->config) == 0)) {
		return -1;
	}
	if (dev->reset) {
		/* put device into reset */
		PUTSYSREG(AR5312_SYSREG_RESETCTL,
		    GETSYSREG(AR5312_SYSREG_RESETCTL) | dev->reset);

		delay(15000);	/* XXX: tsleep? */

		/* take it out of reset */
		PUTSYSREG(AR5312_SYSREG_RESETCTL,
		    GETSYSREG(AR5312_SYSREG_RESETCTL) & ~dev->reset);

		delay(25);
	}
	if (dev->enable) {
		PUTSYSREG(AR5312_SYSREG_ENABLE,
		    GETSYSREG(AR5312_SYSREG_ENABLE) | dev->enable);
	}
	return 0;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
static void
ar5312_bus_init(void)
{
	/*
	 * Clear previous AHB errors
	 */
	GETSYSREG(AR5312_SYSREG_AHBPERR);
	GETSYSREG(AR5312_SYSREG_AHBDMAE);
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
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");
	}
}
Exemplo n.º 7
0
void
ar531x_device_register(struct device *dev, void *aux) 
{
	struct arbus_attach_args *aa = aux;
	const struct ar531x_boarddata *info;

	info = ar531x_board_info();
	if (info == NULL) {
		/* nothing known about this board! */
		return;
	}

	/*
	 * We don't ever know the boot device.  But that's because the
	 * firmware only loads from the network.
	 */

	/* Fetch the MAC addresses. */
	if (device_is_a(dev, "ae")) {
		const uint8_t *enet;

		if (aa->aa_addr == AR5312_ENET0_BASE)
			enet = info->enet0Mac;
		else if (aa->aa_addr == AR5312_ENET1_BASE)
			enet = info->enet1Mac;
		else
			return;

		addprop_data(dev, "mac-addr", enet, ETHER_ADDR_LEN);
	}

	if (device_is_a(dev, "ath")) {
		const uint8_t *enet;

		if (aa->aa_addr == AR5312_WLAN0_BASE)
			enet = info->wlan0Mac;
		else if (aa->aa_addr == AR5312_WLAN1_BASE)
			enet = info->wlan1Mac;
		else
			return;

		addprop_data(dev, "mac-addr", enet, ETHER_ADDR_LEN);

		addprop_integer(dev, "wmac-rev",
		    AR5312_REVISION_WMAC(GETSYSREG(AR5312_SYSREG_REVISION)));

	}

	if (device_is_a(dev, "com")) {
		addprop_integer(dev, "frequency", ar531x_cpu_freq() / 4);
	}

	if (device_is_a(dev, "argpio")) {
		if (info->config & BD_RSTFACTORY) {
			addprop_integer(dev, "reset-pin",
			    info->resetConfigGpio);
		}
		if (info->config & BD_SYSLED) {
			addprop_integer(dev, "sysled-pin",
			    info->sysLedGpio);
		}
	}
}