blob: 5f0b874fbee98e7fa79f1b35b90cba1fe81e46e3 [file] [log] [blame]
/*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <version.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <ar7240_soc.h>
/*
* Helper macros.
* These Clobber t7, t8 and t9
*/
#define clear_mask(_reg, _mask) \
li t7, KSEG1ADDR(_reg); \
lw t8, 0(t7); \
li t9, ~_mask; \
and t8, t8, t9; \
sw t8, 0(t7)
#define set_val(_reg, _mask, _val) \
li t7, KSEG1ADDR(_reg); \
lw t8, 0(t7); \
li t9, ~_mask; \
and t8, t8, t9; \
li t9, _val; \
or t8, t8, t9; \
sw t8, 0(t7)
#define set_val_f(_reg, _mask, _val) \
li t7, KSEG1ADDR(_reg); \
lw t8, 0(t7); \
li t9, ~_mask; \
and t8, t8, t9; \
li t6, KSEG1ADDR(_val); \
lw t9, 0(t6); \
or t8, t8, t9; \
sw t8, 0(t7)
#define get_val(_reg, _mask, _shift, _res_reg) \
li t7, KSEG1ADDR(_reg); \
lw t8, 0(t7); \
li t9, _mask; \
and t8, t8, t9; \
srl _res_reg, t8, _shift \
#define pll_clr(_mask) \
clear_mask(AR7240_CPU_PLL_CONFIG, _mask)
#define pll_set(_mask, _val) \
set_val(AR7240_CPU_PLL_CONFIG, _mask, _val)
#define pll_set_f(_mask, _val) \
set_val_f(AR7240_CPU_PLL_CONFIG, _mask, _val)
#define pll_get(_mask, _shift, _res_reg) \
get_val(AR7240_CPU_PLL_CONFIG, _mask, _shift, _res_reg)
#define clk_clr(_mask) \
clear_mask(AR7240_CPU_CLOCK_CONTROL, _mask)
#define clk_set(_mask, _val) \
set_val(AR7240_CPU_CLOCK_CONTROL, _mask, _val)
#define clk_get(_mask, _shift, _res_reg) \
get_val(AR7240_CPU_CLOCK_CONTROL, _mask, _shift, _res_reg)
/******************************************************************************
* first level initialization:
*
* 0) If clock cntrl reset switch is already set, we're recovering from
* "divider reset"; goto 3.
* 1) Setup divide ratios.
* 2) Reset.
* 3) Setup pll's, wait for lock.
*
*****************************************************************************/
.globl lowlevel_init
lowlevel_init:
/*
* The code below is for the real chip. Wont work on FPGA
*/
/* jr ra */
#if !defined(CONFIG_AR7240_EMU) && defined(CONFIG_WASP_SUPPORT)
#if !defined(CONFIG_ATH_NAND_BR)
b ar934x_lowlevel_init
#endif
#else
#ifndef CONFIG_HORNET_EMU
#if defined(CONFIG_MACH_HORNET)
b hornet_pll_init
#else
wdt_reset:
#ifndef CONFIG_AR7240_EMU
li $3, -1207566336 # 0xffffffffb8060000
ori $4, $3, 0x8
lw $2, 0($4)
bltz $2, $L6
nop
ori $5, $3, 0xc
li $3, 300 # 0x4
sw $3, 0($5)
li $3, 3 # 0x3
sw $3, 0($4)
$L3:
b $L3
nop
#endif
$L6:
nop
nop
#ifndef CONFIG_AR7240_EMU
#ifndef COMPRESSED_UBOOT
/*
* WAR for the bug#55574: Set the CKE (bit 7 in DDR_CONFIG2 register)
* to low initially
*/
li t7, KSEG1ADDR(AR7240_DDR_CONFIG2);
lw t8, 0(t7);
li t9, 0xffffff7f;
and t8, t8, t9;
sw t8, 0(t7);
#endif
/*
* Check if the PLL is already set and CPU is Reset
*/
clk_get(CLOCK_CONTROL_RST_SWITCH_MASK, CLOCK_CONTROL_RST_SWITCH_SHIFT, t6)
bne zero, t6, initialize_pll
nop
init_pll_values:
li a2,PLL_CONFIG_VAL_F # 0xffffffffbf040000
lw a0,0(a2)
li v1,PLL_MAGIC # 0xffffffffaabb0000
beq a0,v1,read_pll_from_flash
nop
#ifdef CONFIG_SUPPORT_AR7241
li t7, KSEG1ADDR(AR7240_REV_ID)
lw t8, 0(t7)
li t9, AR7240_REV_ID_MASK
and t8, t8, t9
li v1, AR7241_REV_1_0
beq t8,v1,init_7241_pll
nop
li v1, AR7242_REV_1_0
beq t8,v1,init_7241_pll
nop
bne t8,v1,init_default
init_7241_pll:
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
pll_set( (PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,( PLL_7241_CONFIG_PLL_REF_DIV_VAL|PLL_7241_CONFIG_PLL_DIV_VAL|PLL_7241_CONFIG_AHB_DIV_VAL|PLL_7241_CONFIG_DDR_DIV_VAL|PLL_CONFIG_PLL_NOPWD_VAL))
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
b wait_for_pll_update
nop
init_default:
#endif
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
pll_set( (PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,( PLL_CONFIG_PLL_REF_DIV_VAL|PLL_CONFIG_PLL_DIV_VAL|PLL_CONFIG_AHB_DIV_VAL|PLL_CONFIG_DDR_DIV_VAL|PLL_CONFIG_PLL_NOPWD_VAL))
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
b wait_for_pll_update
nop
read_pll_from_flash:
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
pll_set_f((PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,((PLL_CONFIG_VAL_F + 4) | PLL_CONFIG_PLL_NOPWD_VAL))
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
b wait_for_pll_update
nop
wait_for_pll_update:
pll_get(PLL_CONFIG_PLL_UPDATE_MASK, PLL_CONFIG_PLL_UPDATE_SHIFT, t6)
bne zero, t6, wait_for_pll_update
nop
/*
* Will cause a reset
* The RESET_SWITCH need to be set first and then
* set the CLOCK_SWITCH for the CPU to boot properly
* after RESET.
*/
pll_locked:
clk_set(CLOCK_CONTROL_RST_SWITCH_MASK, 0x2)
clk_set(CLOCK_CONTROL_CLOCK_SWITCH_MASK, 0x1)
nop
/*
* When the PLL is already set and CPU is RESET
* The code will jump here
*/
initialize_pll:
clk_clr(CLOCK_CONTROL_RST_SWITCH_MASK)
clk_clr(CLOCK_CONTROL_CLOCK_SWITCH_MASK)
#endif
#endif /* CONFIG_MACH_HORNET */
#endif /* CONFIG_HORNET_EMU */
#endif /* CONFIG_MAC_WASP */
jr ra
nop