blob: f10664959446a94cd48452a5fcbbae416fb4b179 [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 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 cpu_pll_set(_mask, _val) \
set_val(AR934X_CPU_PLL_CONFIG, _mask, _val)
#define ddr_pll_set(_mask, _val) \
set_val(AR934X_DDR_PLL_CONFIG, _mask, _val)
#define cpu_ddr_control_set(_mask, _val) \
set_val(AR934X_CPU_DDR_CLOCK_CONTROL, _mask, _val)
/******************************************************************************
* 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 ar934x_lowlevel_init
.type ar934x_lowlevel_init, @function
.globl lowlevel_init
.type lowlevel_init, @function
.text
.align 4
ar934x_lowlevel_init:
lowlevel_init:
#if !defined(CONFIG_ATH_NAND_BR)
li t7, AR7240_REV_ID
lw t7, 0(t7)
andi t9, t7, 0xf
bne zero, t9, ar934x_1_dot_1_lowlevel_init
nop
li t5, KSEG1ADDR(WASP_BOOTSTRAP_REG);
li t6, WASP_REF_CLK_25
lw t7, 0(t5);
and t6, t7, t6
beq zero, t6, setup_ref25_val
nop
setup_ref40_val:
li t5, CPU_PLL_CONFIG_NINT_VAL_40
li t6, DDR_PLL_CONFIG_NINT_VAL_40
b 1f
nop
setup_ref25_val:
li t5, CPU_PLL_CONFIG_NINT_VAL_25
li t6, DDR_PLL_CONFIG_NINT_VAL_25
1:
li t4, (CPU_PLL_DITHER_DITHER_EN_SET(0) | \
CPU_PLL_DITHER_NFRAC_MAX_SET(0x3f) | \
CPU_PLL_NFRAC_MIN_SET | \
CPU_PLL_DITHER_NFRAC_STEP_SET(1) | \
CPU_PLL_DITHER_UPDATE_COUNT_SET(0xf));
#if 0
/*
* From: Ravi Subramanian
* Subject: Workaround for 5G RX reset-reset variation
* Date: Mon, 30 Aug 2010 12:53:49 +0530
*
* We are observing a reset to reset issue related to 5G RX
* performance (and EVM). As a workaround, pushing the DDR
* frequency from 400 MHz to 406 MHz, fixes this issue.
* Could you please give us a new u-boot with the following
* change?
*/
li t3, (DDR_PLL_DITHER_DITHER_EN_SET(1) | \
DDR_PLL_DITHER_NFRAC_MAX_SET(0x3ff) | \
DDR_PLL_DITHER_NFRAC_MIN_SET(0x200) | \
DDR_PLL_DITHER_NFRAC_STEP_SET(1) | \
DDR_PLL_DITHER_UPDATE_COUNT_SET(0xf));
#else
li t3, (DDR_PLL_DITHER_DITHER_EN_SET(0) | \
DDR_PLL_DITHER_NFRAC_MAX_SET(0x3ff) | \
DDR_PLL_DITHER_NFRAC_MIN_SET(0) | \
DDR_PLL_DITHER_NFRAC_STEP_SET(1) | \
DDR_PLL_DITHER_UPDATE_COUNT_SET(0xf));
#endif
li t7, PLL_CONFIG_VAL_F
lw t8, 0(t7)
li t7, PLL_MAGIC
beq t7, t8, read_from_flash
nop
j pll_bypass_set
nop
read_from_flash:
li t7, PLL_CONFIG_VAL_F + 4
lw t5, 0(t7)
lw t4, 4(t7)
lw t6, 8(t7)
lw t3, 12(t7)
pll_bypass_set:
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1));
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1));
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1));
init_cpu_pll:
li t7, KSEG1ADDR(AR934X_CPU_PLL_CONFIG);
li t8, (CPU_PLL_CONFIG_PLLPWD_SET(1) | \
CPU_PLL_CONFIG_REF_DIV_VAL | \
CPU_PLL_CONFIG_RANGE_VAL | \
CPU_PLL_CONFIG_OUT_DIV_VAL1);
or t8, t8, t5
sw t8, 0(t7);
init_ddr_pll:
li t7, KSEG1ADDR(AR934X_DDR_PLL_CONFIG);
li t8, (DDR_PLL_CONFIG_PLLPWD_SET(1) | \
DDR_PLL_CONFIG_REF_DIV_VAL | \
DDR_PLL_CONFIG_RANGE_VAL | \
DDR_PLL_CONFIG_OUT_DIV_VAL1);
or t8, t8, t6
sw t8, 0(t7);
init_ahb_pll:
li t7, KSEG1ADDR(AR934X_CPU_DDR_CLOCK_CONTROL);
li t8, (CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL | \
CPU_DDR_CLOCK_CONTROL_AHB_CLK_DDR | \
CPU_DDR_CLOCK_CONTROL_DDR_CLK_DDR | \
CPU_DDR_CLOCK_CONTROL_CPU_CLK_CPU | \
CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV | \
CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV | \
CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1) | \
CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1) | \
CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1));
sw t8, 0(t7);
pll_pwd_unset:
cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(0));
ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(0));
outdiv_unset:
cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL2);
ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL2);
pll_bypass_unset:
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(0));
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(0));
cpu_ddr_control_set (CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK, CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(0));
ddr_pll_dither_unset:
li t7, KSEG1ADDR(AR934X_DDR_PLL_DITHER);
sw t3, 0(t7);
cpu_pll_dither_unset:
li t7, KSEG1ADDR(AR934X_CPU_PLL_DITHER);
sw t4, 0(t7);
#endif
jr ra
nop