ar71xx_chip.c revision 228450
12061Sjkh/*-
225980Sasami * Copyright (c) 2010 Adrian Chadd
32061Sjkh * All rights reserved.
42061Sjkh *
515603Smarkm * Redistribution and use in source and binary forms, with or without
63197Scsgr * modification, are permitted provided that the following conditions
720710Sasami * are met:
820710Sasami * 1. Redistributions of source code must retain the above copyright
93197Scsgr *    notice, this list of conditions and the following disclaimer.
102061Sjkh * 2. Redistributions in binary form must reproduce the above copyright
1112483Speter *    notice, this list of conditions and the following disclaimer in the
122160Scsgr *    documentation and/or other materials provided with the distribution.
132834Swollman *
142061Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152061Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162160Scsgr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1717308Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819320Sadam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1921536Sjmacd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2025399Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2125980Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221594Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2317308Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2417308Speter * SUCH DAMAGE.
2517308Speter */
2617308Speter
2717308Speter#include <sys/cdefs.h>
2817308Speter__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_chip.c 228450 2011-12-13 05:13:51Z adrian $");
2917308Speter
3019175Sbde#include "opt_ddb.h"
3119175Sbde
3219175Sbde#include <sys/param.h>
3319175Sbde#include <sys/conf.h>
3417308Speter#include <sys/kernel.h>
3525647Sbde#include <sys/systm.h>
3617308Speter#include <sys/bus.h>
372061Sjkh#include <sys/cons.h>
382061Sjkh#include <sys/kdb.h>
391594Srgrimes#include <sys/reboot.h>
4025313Sbde
4125313Sbde#include <vm/vm.h>
4225313Sbde#include <vm/vm_page.h>
4325313Sbde
4425313Sbde#include <net/ethernet.h>
4525313Sbde
4625313Sbde#include <machine/clock.h>
4725313Sbde#include <machine/cpu.h>
487407Srgrimes#include <machine/cpuregs.h>
497108Sphk#include <machine/hwfunc.h>
507108Sphk#include <machine/md_var.h>
517108Sphk#include <machine/trap.h>
527407Srgrimes#include <machine/vmparam.h>
537407Srgrimes
547407Srgrimes#include <mips/atheros/ar71xxreg.h>
557108Sphk#include <mips/atheros/ar71xx_chip.h>
562061Sjkh#include <mips/atheros/ar71xx_cpudef.h>
572061Sjkh
582061Sjkh#include <mips/sentry5/s5reg.h>
5917308Speter
602061Sjkh/* XXX these should replace the current definitions in ar71xxreg.h */
612061Sjkh/* XXX perhaps an ar71xx_chip.h header file? */
622061Sjkh#define AR71XX_PLL_REG_CPU_CONFIG       AR71XX_PLL_CPU_BASE + 0x00
632061Sjkh#define AR71XX_PLL_REG_SEC_CONFIG       AR71XX_PLL_CPU_BASE + 0x04
642061Sjkh#define AR71XX_PLL_REG_ETH0_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x10
653197Scsgr#define AR71XX_PLL_REG_ETH1_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x14
662626Scsgr
672626Scsgr#define AR71XX_PLL_DIV_SHIFT            3
682061Sjkh#define AR71XX_PLL_DIV_MASK             0x1f
692061Sjkh#define AR71XX_CPU_DIV_SHIFT            16
702061Sjkh#define AR71XX_CPU_DIV_MASK             0x3
712061Sjkh#define AR71XX_DDR_DIV_SHIFT            18
722061Sjkh#define AR71XX_DDR_DIV_MASK             0x3
732061Sjkh#define AR71XX_AHB_DIV_SHIFT            20
7419320Sadam#define AR71XX_AHB_DIV_MASK             0x7
752061Sjkh
762061Sjkh/* XXX these shouldn't be in here - this file is a per-chip file */
772061Sjkh/* XXX these should be in the top-level ar71xx type, not ar71xx -chip */
782061Sjkhuint32_t u_ar71xx_cpu_freq;
792061Sjkhuint32_t u_ar71xx_ahb_freq;
802061Sjkhuint32_t u_ar71xx_ddr_freq;
812061Sjkh
822061Sjkhstatic void
832061Sjkhar71xx_chip_detect_mem_size(void)
842061Sjkh{
852061Sjkh}
862834Swollman
872834Swollmanstatic void
882834Swollmanar71xx_chip_detect_sys_frequency(void)
892834Swollman{
902834Swollman	uint32_t pll;
912834Swollman	uint32_t freq;
921594Srgrimes	uint32_t div;
934486Sphk
944486Sphk	pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG);
954486Sphk
964486Sphk	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
974486Sphk	freq = div * AR71XX_BASE_FREQ;
982061Sjkh
992061Sjkh	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
10025979Sjkh	u_ar71xx_cpu_freq = freq / div;
10125979Sjkh
10225979Sjkh	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
10325979Sjkh	u_ar71xx_ddr_freq = freq / div;
1042061Sjkh
10525979Sjkh	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
1062061Sjkh	u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
1072061Sjkh}
10817308Speter
1092061Sjkh/*
1102061Sjkh * This does not lock the CPU whilst doing the work!
1112061Sjkh */
1122061Sjkhstatic void
1132061Sjkhar71xx_chip_device_stop(uint32_t mask)
11412483Speter{
11512483Speter	uint32_t reg;
11612483Speter
11712483Speter	reg = ATH_READ_REG(AR71XX_RST_RESET);
1182061Sjkh	ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask);
1192061Sjkh}
1208854Srgrimes
1212061Sjkhstatic void
1222061Sjkhar71xx_chip_device_start(uint32_t mask)
12312483Speter{
1242061Sjkh	uint32_t reg;
12518714Sache
12618714Sache	reg = ATH_READ_REG(AR71XX_RST_RESET);
12718714Sache	ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask);
12817308Speter}
12917308Speter
13017308Speterstatic int
13117308Speterar71xx_chip_device_stopped(uint32_t mask)
13221536Sjmacd{
13315603Smarkm	uint32_t reg;
13417308Speter
13517308Speter	reg = ATH_READ_REG(AR71XX_RST_RESET);
13617308Speter	return ((reg & mask) == mask);
13717308Speter}
13817308Speter
13917308Speter/* Speed is either 10, 100 or 1000 */
14017308Speterstatic void
14117308Speterar71xx_chip_set_pll_ge(int unit, int speed)
14217308Speter{
14318362Sjkh	uint32_t pll;
14419966Sache
14518362Sjkh	switch (speed) {
14617308Speter	case 10:
14717308Speter		pll = PLL_ETH_INT_CLK_10;
14817308Speter		break;
14917308Speter	case 100:
15017308Speter		pll = PLL_ETH_INT_CLK_100;
15117308Speter		break;
15216550Sjkh	case 1000:
1532061Sjkh		pll = PLL_ETH_INT_CLK_1000;
15417308Speter		break;
1552061Sjkh	default:
15617308Speter		printf("%s%d: invalid speed %d\n",
1572061Sjkh		    __func__, unit, speed);
15817308Speter		return;
15917308Speter	}
16017308Speter	switch (unit) {
16117308Speter	case 0:
16217308Speter		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
16317308Speter		    AR71XX_PLL_ETH_INT0_CLK, pll,
16417466Speter		    AR71XX_PLL_ETH0_SHIFT);
16517308Speter		break;
16617308Speter	case 1:
16717466Speter		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
16817308Speter		    AR71XX_PLL_ETH_INT1_CLK, pll,
16917308Speter		    AR71XX_PLL_ETH1_SHIFT);
17017308Speter		break;
17117308Speter	default:
17217466Speter		printf("%s: invalid PLL set for arge unit: %d\n",
17317308Speter		    __func__, unit);
17417308Speter		return;
17517308Speter	}
17617308Speter}
17717308Speter
17817308Speterstatic void
17917308Speterar71xx_chip_ddr_flush_ge(int unit)
18017308Speter{
18117308Speter
18217308Speter	switch (unit) {
18317308Speter	case 0:
18417308Speter		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0);
18517308Speter		break;
18617308Speter	case 1:
18717308Speter		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1);
18817308Speter		break;
18917308Speter	default:
19017308Speter		printf("%s: invalid DDR flush for arge unit: %d\n",
19117308Speter		    __func__, unit);
19217308Speter		return;
19317308Speter	}
19417308Speter}
19517308Speter
19617308Speterstatic void
19717308Speterar71xx_chip_ddr_flush_ip2(void)
19817308Speter{
19917308Speter	ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI);
20018392Speter}
20117308Speter
20217308Speterstatic uint32_t
20317308Speterar71xx_chip_get_eth_pll(unsigned int mac, int speed)
20417308Speter{
20517962Speter	return 0;
20617308Speter}
20717962Speter
20817962Speterstatic void
20917962Speterar71xx_chip_init_usb_peripheral(void)
21017962Speter{
21117962Speter
21217962Speter	ar71xx_device_stop(RST_RESET_USB_OHCI_DLL |
21317962Speter	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
21417962Speter	DELAY(1000);
21517962Speter
21617962Speter	ar71xx_device_start(RST_RESET_USB_OHCI_DLL |
21717962Speter	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
21817962Speter	DELAY(1000);
21917962Speter
22017962Speter	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
22117962Speter	    USB_CTRL_CONFIG_OHCI_DES_SWAP |
22217308Speter	    USB_CTRL_CONFIG_OHCI_BUF_SWAP |
22316550Sjkh	    USB_CTRL_CONFIG_EHCI_DES_SWAP |
22417308Speter	    USB_CTRL_CONFIG_EHCI_BUF_SWAP);
22517308Speter
22617308Speter	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
22717308Speter	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) |
22816550Sjkh	    (3 << USB_CTRL_FLADJ_A5_SHIFT));
22916550Sjkh
23017308Speter	DELAY(1000);
23117308Speter}
23219966Sache
23317962Speterstruct ar71xx_cpu_def ar71xx_chip_def = {
2342061Sjkh	&ar71xx_chip_detect_mem_size,
23517308Speter	&ar71xx_chip_detect_sys_frequency,
23617308Speter	&ar71xx_chip_device_stop,
23717308Speter	&ar71xx_chip_device_start,
23817308Speter	&ar71xx_chip_device_stopped,
23917308Speter	&ar71xx_chip_set_pll_ge,
24017308Speter	&ar71xx_chip_ddr_flush_ge,
24117308Speter	&ar71xx_chip_get_eth_pll,
24217308Speter	&ar71xx_chip_ddr_flush_ip2,
24312483Speter	&ar71xx_chip_init_usb_peripheral,
24417308Speter};
24512483Speter