1211498Sadrian/*- 2211498Sadrian * Copyright (c) 2010 Adrian Chadd 3211498Sadrian * All rights reserved. 4211498Sadrian * 5211498Sadrian * Redistribution and use in source and binary forms, with or without 6211498Sadrian * modification, are permitted provided that the following conditions 7211498Sadrian * are met: 8211498Sadrian * 1. Redistributions of source code must retain the above copyright 9211498Sadrian * notice, this list of conditions and the following disclaimer. 10211498Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11211498Sadrian * notice, this list of conditions and the following disclaimer in the 12211498Sadrian * documentation and/or other materials provided with the distribution. 13211498Sadrian * 14211498Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15211498Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16211498Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17211498Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18211498Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19211498Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20211498Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21211498Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22211498Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23211498Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24211498Sadrian * SUCH DAMAGE. 25211498Sadrian */ 26211498Sadrian 27211476Sadrian#include <sys/cdefs.h> 28211476Sadrian__FBSDID("$FreeBSD$"); 29211476Sadrian 30211476Sadrian#include "opt_ddb.h" 31211476Sadrian 32211476Sadrian#include <sys/param.h> 33211476Sadrian#include <sys/conf.h> 34211476Sadrian#include <sys/kernel.h> 35211476Sadrian#include <sys/systm.h> 36211476Sadrian#include <sys/bus.h> 37211476Sadrian#include <sys/cons.h> 38211476Sadrian#include <sys/kdb.h> 39211476Sadrian#include <sys/reboot.h> 40228450Sadrian 41211476Sadrian#include <vm/vm.h> 42211476Sadrian#include <vm/vm_page.h> 43228450Sadrian 44211476Sadrian#include <net/ethernet.h> 45228450Sadrian 46211476Sadrian#include <machine/clock.h> 47211476Sadrian#include <machine/cpu.h> 48223562Skevlo#include <machine/cpuregs.h> 49211476Sadrian#include <machine/hwfunc.h> 50211476Sadrian#include <machine/md_var.h> 51211476Sadrian#include <machine/trap.h> 52211476Sadrian#include <machine/vmparam.h> 53228450Sadrian 54211476Sadrian#include <mips/atheros/ar71xxreg.h> 55211476Sadrian#include <mips/atheros/ar71xx_chip.h> 56211476Sadrian#include <mips/atheros/ar71xx_cpudef.h> 57211476Sadrian 58223562Skevlo#include <mips/sentry5/s5reg.h> 59223562Skevlo 60211476Sadrian/* XXX these should replace the current definitions in ar71xxreg.h */ 61211476Sadrian/* XXX perhaps an ar71xx_chip.h header file? */ 62211476Sadrian#define AR71XX_PLL_REG_CPU_CONFIG AR71XX_PLL_CPU_BASE + 0x00 63211476Sadrian#define AR71XX_PLL_REG_SEC_CONFIG AR71XX_PLL_CPU_BASE + 0x04 64211476Sadrian#define AR71XX_PLL_REG_ETH0_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x10 65211476Sadrian#define AR71XX_PLL_REG_ETH1_INT_CLOCK AR71XX_PLL_CPU_BASE + 0x14 66211476Sadrian 67211476Sadrian#define AR71XX_PLL_DIV_SHIFT 3 68211476Sadrian#define AR71XX_PLL_DIV_MASK 0x1f 69211476Sadrian#define AR71XX_CPU_DIV_SHIFT 16 70211476Sadrian#define AR71XX_CPU_DIV_MASK 0x3 71211476Sadrian#define AR71XX_DDR_DIV_SHIFT 18 72211476Sadrian#define AR71XX_DDR_DIV_MASK 0x3 73211476Sadrian#define AR71XX_AHB_DIV_SHIFT 20 74211476Sadrian#define AR71XX_AHB_DIV_MASK 0x7 75211476Sadrian 76211476Sadrian/* XXX these shouldn't be in here - this file is a per-chip file */ 77211476Sadrian/* XXX these should be in the top-level ar71xx type, not ar71xx -chip */ 78211476Sadrianuint32_t u_ar71xx_cpu_freq; 79211476Sadrianuint32_t u_ar71xx_ahb_freq; 80211476Sadrianuint32_t u_ar71xx_ddr_freq; 81253508Sadrianuint32_t u_ar71xx_uart_freq; 82253508Sadrianuint32_t u_ar71xx_wdt_freq; 83248781Sadrianuint32_t u_ar71xx_refclk; 84211476Sadrian 85211476Sadrianstatic void 86211476Sadrianar71xx_chip_detect_mem_size(void) 87211476Sadrian{ 88211476Sadrian} 89211476Sadrian 90211476Sadrianstatic void 91211476Sadrianar71xx_chip_detect_sys_frequency(void) 92211476Sadrian{ 93211476Sadrian uint32_t pll; 94211476Sadrian uint32_t freq; 95211476Sadrian uint32_t div; 96211476Sadrian 97248781Sadrian u_ar71xx_refclk = AR71XX_BASE_FREQ; 98248781Sadrian 99211476Sadrian pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG); 100211476Sadrian 101211476Sadrian div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; 102211476Sadrian freq = div * AR71XX_BASE_FREQ; 103211476Sadrian 104211476Sadrian div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 105211476Sadrian u_ar71xx_cpu_freq = freq / div; 106211476Sadrian 107211476Sadrian div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 108211476Sadrian u_ar71xx_ddr_freq = freq / div; 109211476Sadrian 110211476Sadrian div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 111211476Sadrian u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div; 112253508Sadrian u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div; 113253508Sadrian u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div; 114211476Sadrian} 115211476Sadrian 116211476Sadrian/* 117211476Sadrian * This does not lock the CPU whilst doing the work! 118211476Sadrian */ 119211476Sadrianstatic void 120211476Sadrianar71xx_chip_device_stop(uint32_t mask) 121211476Sadrian{ 122211476Sadrian uint32_t reg; 123211476Sadrian 124211476Sadrian reg = ATH_READ_REG(AR71XX_RST_RESET); 125211476Sadrian ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask); 126211476Sadrian} 127211476Sadrian 128211476Sadrianstatic void 129211476Sadrianar71xx_chip_device_start(uint32_t mask) 130211476Sadrian{ 131211476Sadrian uint32_t reg; 132211476Sadrian 133211476Sadrian reg = ATH_READ_REG(AR71XX_RST_RESET); 134211476Sadrian ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask); 135211476Sadrian} 136211476Sadrian 137211476Sadrianstatic int 138211476Sadrianar71xx_chip_device_stopped(uint32_t mask) 139211476Sadrian{ 140211476Sadrian uint32_t reg; 141211476Sadrian 142211476Sadrian reg = ATH_READ_REG(AR71XX_RST_RESET); 143228450Sadrian return ((reg & mask) == mask); 144211476Sadrian} 145211476Sadrian 146234326Sadrianvoid 147233081Sadrianar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed) 148233081Sadrian{ 149233081Sadrian uint32_t val, reg, ctrl; 150233081Sadrian 151233081Sadrian switch (unit) { 152233081Sadrian case 0: 153233081Sadrian reg = AR71XX_MII0_CTRL; 154233081Sadrian break; 155233081Sadrian case 1: 156233081Sadrian reg = AR71XX_MII1_CTRL; 157233081Sadrian break; 158233081Sadrian default: 159233081Sadrian printf("%s: invalid MII unit set for arge unit: %d\n", 160233081Sadrian __func__, unit); 161233081Sadrian return; 162233081Sadrian } 163233081Sadrian 164233081Sadrian switch (speed) { 165233081Sadrian case 10: 166233081Sadrian ctrl = MII_CTRL_SPEED_10; 167233081Sadrian break; 168233081Sadrian case 100: 169233081Sadrian ctrl = MII_CTRL_SPEED_100; 170233081Sadrian break; 171233081Sadrian case 1000: 172233081Sadrian ctrl = MII_CTRL_SPEED_1000; 173233081Sadrian break; 174233081Sadrian default: 175233081Sadrian printf("%s: invalid MII speed (%d) set for arge unit: %d\n", 176233081Sadrian __func__, speed, unit); 177233081Sadrian return; 178233081Sadrian } 179233081Sadrian 180233081Sadrian val = ATH_READ_REG(reg); 181233081Sadrian val &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT); 182233081Sadrian val |= (ctrl & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT; 183233081Sadrian ATH_WRITE_REG(reg, val); 184233081Sadrian} 185233081Sadrian 186234906Sadrianvoid 187234906Sadrianar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_mode) 188234906Sadrian{ 189234906Sadrian uint32_t val, reg, mii_if; 190234906Sadrian 191234906Sadrian switch (unit) { 192234906Sadrian case 0: 193234906Sadrian reg = AR71XX_MII0_CTRL; 194234906Sadrian if (mii_mode == AR71XX_MII_MODE_GMII) 195234906Sadrian mii_if = MII0_CTRL_IF_GMII; 196234906Sadrian else if (mii_mode == AR71XX_MII_MODE_MII) 197234906Sadrian mii_if = MII0_CTRL_IF_MII; 198234906Sadrian else if (mii_mode == AR71XX_MII_MODE_RGMII) 199234906Sadrian mii_if = MII0_CTRL_IF_RGMII; 200234906Sadrian else if (mii_mode == AR71XX_MII_MODE_RMII) 201234906Sadrian mii_if = MII0_CTRL_IF_RMII; 202234941Sadrian else { 203234906Sadrian printf("%s: invalid MII mode (%d) for unit %d\n", 204234906Sadrian __func__, mii_mode, unit); 205234906Sadrian return; 206234941Sadrian } 207234906Sadrian break; 208234906Sadrian case 1: 209234906Sadrian reg = AR71XX_MII1_CTRL; 210234906Sadrian if (mii_mode == AR71XX_MII_MODE_RGMII) 211234906Sadrian mii_if = MII1_CTRL_IF_RGMII; 212234941Sadrian else if (mii_mode == AR71XX_MII_MODE_RMII) 213234906Sadrian mii_if = MII1_CTRL_IF_RMII; 214234941Sadrian else { 215234906Sadrian printf("%s: invalid MII mode (%d) for unit %d\n", 216234906Sadrian __func__, mii_mode, unit); 217234906Sadrian return; 218234941Sadrian } 219234906Sadrian break; 220234906Sadrian default: 221234906Sadrian printf("%s: invalid MII unit set for arge unit: %d\n", 222234906Sadrian __func__, unit); 223234906Sadrian return; 224234906Sadrian } 225234906Sadrian 226234906Sadrian val = ATH_READ_REG(reg); 227234906Sadrian val &= ~(MII_CTRL_IF_MASK << MII_CTRL_IF_SHIFT); 228234906Sadrian val |= (mii_if & MII_CTRL_IF_MASK) << MII_CTRL_IF_SHIFT; 229234906Sadrian ATH_WRITE_REG(reg, val); 230234906Sadrian} 231234906Sadrian 232211510Sadrian/* Speed is either 10, 100 or 1000 */ 233211476Sadrianstatic void 234234907Sadrianar71xx_chip_set_pll_ge(int unit, int speed, uint32_t pll) 235211476Sadrian{ 236211510Sadrian 237228018Sray switch (unit) { 238228018Sray case 0: 239228018Sray ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG, 240228018Sray AR71XX_PLL_ETH_INT0_CLK, pll, 241228018Sray AR71XX_PLL_ETH0_SHIFT); 242228018Sray break; 243228018Sray case 1: 244228018Sray ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG, 245228018Sray AR71XX_PLL_ETH_INT1_CLK, pll, 246228018Sray AR71XX_PLL_ETH1_SHIFT); 247228018Sray break; 248228018Sray default: 249228018Sray printf("%s: invalid PLL set for arge unit: %d\n", 250228018Sray __func__, unit); 251228018Sray return; 252228018Sray } 253211476Sadrian} 254211476Sadrian 255211476Sadrianstatic void 256228018Srayar71xx_chip_ddr_flush_ge(int unit) 257211476Sadrian{ 258228450Sadrian 259228018Sray switch (unit) { 260228018Sray case 0: 261228018Sray ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0); 262228018Sray break; 263228018Sray case 1: 264228018Sray ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1); 265228018Sray break; 266228018Sray default: 267228018Sray printf("%s: invalid DDR flush for arge unit: %d\n", 268228018Sray __func__, unit); 269228018Sray return; 270211510Sadrian } 271211476Sadrian} 272211476Sadrian 273211476Sadrianstatic void 274221240Sadrianar71xx_chip_ddr_flush_ip2(void) 275221240Sadrian{ 276221240Sadrian ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI); 277221240Sadrian} 278221240Sadrian 279211476Sadrianstatic uint32_t 280211476Sadrianar71xx_chip_get_eth_pll(unsigned int mac, int speed) 281211476Sadrian{ 282234907Sadrian uint32_t pll; 283234907Sadrian 284234907Sadrian switch (speed) { 285234907Sadrian case 10: 286234907Sadrian pll = PLL_ETH_INT_CLK_10; 287234907Sadrian break; 288234907Sadrian case 100: 289234907Sadrian pll = PLL_ETH_INT_CLK_100; 290234907Sadrian break; 291234907Sadrian case 1000: 292234907Sadrian pll = PLL_ETH_INT_CLK_1000; 293234907Sadrian break; 294234907Sadrian default: 295234907Sadrian printf("%s%d: invalid speed %d\n", __func__, mac, speed); 296234907Sadrian pll = 0; 297234907Sadrian } 298234907Sadrian 299234907Sadrian return (pll); 300211476Sadrian} 301211476Sadrian 302211476Sadrianstatic void 303211476Sadrianar71xx_chip_init_usb_peripheral(void) 304211476Sadrian{ 305228450Sadrian 306228450Sadrian ar71xx_device_stop(RST_RESET_USB_OHCI_DLL | 307228450Sadrian RST_RESET_USB_HOST | RST_RESET_USB_PHY); 308211476Sadrian DELAY(1000); 309211476Sadrian 310228450Sadrian ar71xx_device_start(RST_RESET_USB_OHCI_DLL | 311228450Sadrian RST_RESET_USB_HOST | RST_RESET_USB_PHY); 312211476Sadrian DELAY(1000); 313211476Sadrian 314211476Sadrian ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG, 315228450Sadrian USB_CTRL_CONFIG_OHCI_DES_SWAP | 316228450Sadrian USB_CTRL_CONFIG_OHCI_BUF_SWAP | 317228450Sadrian USB_CTRL_CONFIG_EHCI_DES_SWAP | 318228450Sadrian USB_CTRL_CONFIG_EHCI_BUF_SWAP); 319211476Sadrian 320211476Sadrian ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ, 321228450Sadrian (32 << USB_CTRL_FLADJ_HOST_SHIFT) | 322228450Sadrian (3 << USB_CTRL_FLADJ_A5_SHIFT)); 323211476Sadrian 324211476Sadrian DELAY(1000); 325211476Sadrian} 326211476Sadrian 327211476Sadrianstruct ar71xx_cpu_def ar71xx_chip_def = { 328211476Sadrian &ar71xx_chip_detect_mem_size, 329211476Sadrian &ar71xx_chip_detect_sys_frequency, 330211476Sadrian &ar71xx_chip_device_stop, 331211476Sadrian &ar71xx_chip_device_start, 332211476Sadrian &ar71xx_chip_device_stopped, 333228018Sray &ar71xx_chip_set_pll_ge, 334233081Sadrian &ar71xx_chip_set_mii_speed, 335234906Sadrian &ar71xx_chip_set_mii_if, 336228018Sray &ar71xx_chip_ddr_flush_ge, 337211476Sadrian &ar71xx_chip_get_eth_pll, 338221240Sadrian &ar71xx_chip_ddr_flush_ip2, 339211476Sadrian &ar71xx_chip_init_usb_peripheral, 340211476Sadrian}; 341