The patch add initial support for the Freescale i.MX51 processor (family arm cortex_a8). Signed-off-by: Stefano Babic <sbabic@denx.de> Signed-off-by: Fred Fan <fanyefeng@gmail.com>master
parent
18ba012b9b
commit
64fdf452a8
@ -0,0 +1,48 @@ |
||||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# (C) Copyright 2009 Freescale Semiconductor, 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 $(TOPDIR)/config.mk |
||||
|
||||
LIB = $(obj)lib$(SOC).a
|
||||
|
||||
COBJS = soc.o clock.o iomux.o timer.o
|
||||
SOBJS = lowlevel_init.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
all: $(obj).depend $(LIB) |
||||
|
||||
$(LIB): $(OBJS) |
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk |
||||
|
||||
sinclude $(obj).depend |
||||
|
||||
#########################################################################
|
@ -0,0 +1,293 @@ |
||||
/*
|
||||
* (C) Copyright 2007 |
||||
* Sascha Hauer, Pengutronix |
||||
* |
||||
* (C) Copyright 2009 Freescale Semiconductor, 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 <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/errno.h> |
||||
#include <asm/arch/imx-regs.h> |
||||
#include <asm/arch/crm_regs.h> |
||||
|
||||
enum pll_clocks { |
||||
PLL1_CLOCK = 0, |
||||
PLL2_CLOCK, |
||||
PLL3_CLOCK, |
||||
PLL_CLOCKS, |
||||
}; |
||||
|
||||
struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = { |
||||
[PLL1_CLOCK] = (struct mxc_pll_reg *)PLL1_BASE_ADDR, |
||||
[PLL2_CLOCK] = (struct mxc_pll_reg *)PLL2_BASE_ADDR, |
||||
[PLL3_CLOCK] = (struct mxc_pll_reg *)PLL3_BASE_ADDR, |
||||
}; |
||||
|
||||
struct mxc_ccm_reg *mxc_ccm = MXC_CCM_BASE; |
||||
|
||||
/*
|
||||
* Calculate the frequency of this pll. |
||||
*/ |
||||
static u32 decode_pll(struct mxc_pll_reg *pll, u32 infreq) |
||||
{ |
||||
u32 mfi, mfn, mfd, pd; |
||||
|
||||
mfn = __raw_readl(&pll->mfn); |
||||
mfd = __raw_readl(&pll->mfd) + 1; |
||||
mfi = __raw_readl(&pll->op); |
||||
pd = (mfi & 0xF) + 1; |
||||
mfi = (mfi >> 4) & 0xF; |
||||
mfi = (mfi >= 5) ? mfi : 5; |
||||
|
||||
return ((4 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; |
||||
} |
||||
|
||||
/*
|
||||
* Get mcu main rate |
||||
*/ |
||||
u32 get_mcu_main_clk(void) |
||||
{ |
||||
u32 reg, freq; |
||||
|
||||
reg = (__raw_readl(&mxc_ccm->cacrr) & MXC_CCM_CACRR_ARM_PODF_MASK) >> |
||||
MXC_CCM_CACRR_ARM_PODF_OFFSET; |
||||
freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
return freq / (reg + 1); |
||||
} |
||||
|
||||
/*
|
||||
* Get the rate of peripheral's root clock. |
||||
*/ |
||||
static u32 get_periph_clk(void) |
||||
{ |
||||
u32 reg; |
||||
|
||||
reg = __raw_readl(&mxc_ccm->cbcdr); |
||||
if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL)) |
||||
return decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
reg = __raw_readl(&mxc_ccm->cbcmr); |
||||
switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> |
||||
MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) { |
||||
case 0: |
||||
return decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
case 1: |
||||
return decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
default: |
||||
return 0; |
||||
} |
||||
/* NOTREACHED */ |
||||
} |
||||
|
||||
/*
|
||||
* Get the rate of ipg clock. |
||||
*/ |
||||
static u32 get_ipg_clk(void) |
||||
{ |
||||
u32 ahb_podf, ipg_podf; |
||||
|
||||
ahb_podf = __raw_readl(&mxc_ccm->cbcdr); |
||||
ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >> |
||||
MXC_CCM_CBCDR_IPG_PODF_OFFSET; |
||||
ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >> |
||||
MXC_CCM_CBCDR_AHB_PODF_OFFSET; |
||||
return get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1)); |
||||
} |
||||
|
||||
/*
|
||||
* Get the rate of ipg_per clock. |
||||
*/ |
||||
static u32 get_ipg_per_clk(void) |
||||
{ |
||||
u32 pred1, pred2, podf; |
||||
|
||||
if (__raw_readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) |
||||
return get_ipg_clk(); |
||||
/* Fixme: not handle what about lpm*/ |
||||
podf = __raw_readl(&mxc_ccm->cbcdr); |
||||
pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> |
||||
MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET; |
||||
pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> |
||||
MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET; |
||||
podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> |
||||
MXC_CCM_CBCDR_PERCLK_PODF_OFFSET; |
||||
|
||||
return get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); |
||||
} |
||||
|
||||
/*
|
||||
* Get the rate of uart clk. |
||||
*/ |
||||
static u32 get_uart_clk(void) |
||||
{ |
||||
unsigned int freq, reg, pred, podf; |
||||
|
||||
reg = __raw_readl(&mxc_ccm->cscmr1); |
||||
switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >> |
||||
MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) { |
||||
case 0x0: |
||||
freq = decode_pll(mxc_plls[PLL1_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ); |
||||
break; |
||||
case 0x1: |
||||
freq = decode_pll(mxc_plls[PLL2_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ); |
||||
break; |
||||
case 0x2: |
||||
freq = decode_pll(mxc_plls[PLL3_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ); |
||||
break; |
||||
default: |
||||
return 66500000; |
||||
} |
||||
|
||||
reg = __raw_readl(&mxc_ccm->cscdr1); |
||||
|
||||
pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> |
||||
MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET; |
||||
|
||||
podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> |
||||
MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; |
||||
freq /= (pred + 1) * (podf + 1); |
||||
|
||||
return freq; |
||||
} |
||||
|
||||
/*
|
||||
* This function returns the low power audio clock. |
||||
*/ |
||||
u32 get_lp_apm(void) |
||||
{ |
||||
u32 ret_val = 0; |
||||
u32 ccsr = __raw_readl(&mxc_ccm->ccsr); |
||||
|
||||
if (((ccsr >> 9) & 1) == 0) |
||||
ret_val = CONFIG_MX51_HCLK_FREQ; |
||||
else |
||||
ret_val = ((32768 * 1024)); |
||||
|
||||
return ret_val; |
||||
} |
||||
|
||||
/*
|
||||
* get cspi clock rate. |
||||
*/ |
||||
u32 imx_get_cspiclk(void) |
||||
{ |
||||
u32 ret_val = 0, pdf, pre_pdf, clk_sel; |
||||
u32 cscmr1 = __raw_readl(&mxc_ccm->cscmr1); |
||||
u32 cscdr2 = __raw_readl(&mxc_ccm->cscdr2); |
||||
|
||||
pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \
|
||||
>> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET; |
||||
pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \
|
||||
>> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET; |
||||
clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \
|
||||
>> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; |
||||
|
||||
switch (clk_sel) { |
||||
case 0: |
||||
ret_val = decode_pll(mxc_plls[PLL1_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ) / |
||||
((pre_pdf + 1) * (pdf + 1)); |
||||
break; |
||||
case 1: |
||||
ret_val = decode_pll(mxc_plls[PLL2_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ) / |
||||
((pre_pdf + 1) * (pdf + 1)); |
||||
break; |
||||
case 2: |
||||
ret_val = decode_pll(mxc_plls[PLL3_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ) / |
||||
((pre_pdf + 1) * (pdf + 1)); |
||||
break; |
||||
default: |
||||
ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1)); |
||||
break; |
||||
} |
||||
|
||||
return ret_val; |
||||
} |
||||
|
||||
/*
|
||||
* The API of get mxc clockes. |
||||
*/ |
||||
unsigned int mxc_get_clock(enum mxc_clock clk) |
||||
{ |
||||
switch (clk) { |
||||
case MXC_ARM_CLK: |
||||
return get_mcu_main_clk(); |
||||
case MXC_AHB_CLK: |
||||
break; |
||||
case MXC_IPG_CLK: |
||||
return get_ipg_clk(); |
||||
case MXC_IPG_PERCLK: |
||||
return get_ipg_per_clk(); |
||||
case MXC_UART_CLK: |
||||
return get_uart_clk(); |
||||
case MXC_CSPI_CLK: |
||||
return imx_get_cspiclk(); |
||||
case MXC_FEC_CLK: |
||||
return decode_pll(mxc_plls[PLL1_CLOCK], |
||||
CONFIG_MX51_HCLK_FREQ); |
||||
default: |
||||
break; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
u32 imx_get_uartclk(void) |
||||
{ |
||||
return get_uart_clk(); |
||||
} |
||||
|
||||
|
||||
u32 imx_get_fecclk(void) |
||||
{ |
||||
return mxc_get_clock(MXC_IPG_CLK); |
||||
} |
||||
|
||||
/*
|
||||
* Dump some core clockes. |
||||
*/ |
||||
int do_mx51_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
||||
{ |
||||
u32 freq; |
||||
|
||||
freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
printf("mx51 pll1: %dMHz\n", freq / 1000000); |
||||
freq = decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
printf("mx51 pll2: %dMHz\n", freq / 1000000); |
||||
freq = decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_MX51_HCLK_FREQ); |
||||
printf("mx51 pll3: %dMHz\n", freq / 1000000); |
||||
printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK)); |
||||
printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK)); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/***************************************************/ |
||||
|
||||
U_BOOT_CMD( |
||||
clockinfo, CONFIG_SYS_MAXARGS, 1, do_mx51_showclocks, |
||||
"display mx51 clocks\n", |
||||
"" |
||||
); |
@ -0,0 +1,165 @@ |
||||
/*
|
||||
* (C) Copyright 2009 Freescale Semiconductor, 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 <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/imx-regs.h> |
||||
#include <asm/arch/mx51_pins.h> |
||||
#include <asm/arch/iomux.h> |
||||
|
||||
/* IOMUX register (base) addresses */ |
||||
enum iomux_reg_addr { |
||||
IOMUXGPR0 = IOMUXC_BASE_ADDR, |
||||
IOMUXGPR1 = IOMUXC_BASE_ADDR + 0x004, |
||||
IOMUXSW_MUX_CTL = IOMUXC_BASE_ADDR, |
||||
IOMUXSW_MUX_END = IOMUXC_BASE_ADDR + MUX_I_END, |
||||
IOMUXSW_PAD_CTL = IOMUXC_BASE_ADDR + PAD_I_START, |
||||
IOMUXSW_INPUT_CTL = IOMUXC_BASE_ADDR, |
||||
}; |
||||
|
||||
#define MUX_PIN_NUM_MAX (((MUX_I_END - MUX_I_START) >> 2) + 1) |
||||
|
||||
/* Get the iomux register address of this pin */ |
||||
static inline u32 get_mux_reg(iomux_pin_name_t pin) |
||||
{ |
||||
u32 mux_reg = PIN_TO_IOMUX_MUX(pin); |
||||
|
||||
if (is_soc_rev(CHIP_REV_2_0) < 0) { |
||||
/*
|
||||
* Fixup register address: |
||||
* i.MX51 TO1 has offset with the register |
||||
* which is define as TO2. |
||||
*/ |
||||
if ((pin == MX51_PIN_NANDF_RB5) || |
||||
(pin == MX51_PIN_NANDF_RB6) || |
||||
(pin == MX51_PIN_NANDF_RB7)) |
||||
; /* Do nothing */ |
||||
else if (mux_reg >= 0x2FC) |
||||
mux_reg += 8; |
||||
else if (mux_reg >= 0x130) |
||||
mux_reg += 0xC; |
||||
} |
||||
mux_reg += IOMUXSW_MUX_CTL; |
||||
return mux_reg; |
||||
} |
||||
|
||||
/* Get the pad register address of this pin */ |
||||
static inline u32 get_pad_reg(iomux_pin_name_t pin) |
||||
{ |
||||
u32 pad_reg = PIN_TO_IOMUX_PAD(pin); |
||||
|
||||
if (is_soc_rev(CHIP_REV_2_0) < 0) { |
||||
/*
|
||||
* Fixup register address: |
||||
* i.MX51 TO1 has offset with the register |
||||
* which is define as TO2. |
||||
*/ |
||||
if ((pin == MX51_PIN_NANDF_RB5) || |
||||
(pin == MX51_PIN_NANDF_RB6) || |
||||
(pin == MX51_PIN_NANDF_RB7)) |
||||
; /* Do nothing */ |
||||
else if (pad_reg == 0x4D0 - PAD_I_START) |
||||
pad_reg += 0x4C; |
||||
else if (pad_reg == 0x860 - PAD_I_START) |
||||
pad_reg += 0x9C; |
||||
else if (pad_reg >= 0x804 - PAD_I_START) |
||||
pad_reg += 0xB0; |
||||
else if (pad_reg >= 0x7FC - PAD_I_START) |
||||
pad_reg += 0xB4; |
||||
else if (pad_reg >= 0x4E4 - PAD_I_START) |
||||
pad_reg += 0xCC; |
||||
else |
||||
pad_reg += 8; |
||||
} |
||||
pad_reg += IOMUXSW_PAD_CTL; |
||||
return pad_reg; |
||||
} |
||||
|
||||
/* Get the last iomux register address */ |
||||
static inline u32 get_mux_end(void) |
||||
{ |
||||
if (is_soc_rev(CHIP_REV_2_0) < 0) |
||||
return IOMUXC_BASE_ADDR + (0x3F8 - 4); |
||||
else |
||||
return IOMUXC_BASE_ADDR + (0x3F0 - 4); |
||||
} |
||||
|
||||
/*
|
||||
* This function is used to configure a pin through the IOMUX module. |
||||
* @param pin a pin number as defined in iomux_pin_name_t |
||||
* @param cfg an output function as defined in iomux_pin_cfg_t |
||||
* |
||||
* @return 0 if successful; Non-zero otherwise |
||||
*/ |
||||
static void iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) |
||||
{ |
||||
u32 mux_reg = get_mux_reg(pin); |
||||
|
||||
if ((mux_reg > get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL)) |
||||
return ; |
||||
if (cfg == IOMUX_CONFIG_GPIO) |
||||
writel(PIN_TO_ALT_GPIO(pin), mux_reg); |
||||
else |
||||
writel(cfg, mux_reg); |
||||
} |
||||
|
||||
/*
|
||||
* Request ownership for an IO pin. This function has to be the first one |
||||
* being called before that pin is used. The caller has to check the |
||||
* return value to make sure it returns 0. |
||||
* |
||||
* @param pin a name defined by iomux_pin_name_t |
||||
* @param cfg an input function as defined in iomux_pin_cfg_t |
||||
* |
||||
*/ |
||||
void mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) |
||||
{ |
||||
iomux_config_mux(pin, cfg); |
||||
} |
||||
|
||||
/*
|
||||
* Release ownership for an IO pin |
||||
* |
||||
* @param pin a name defined by iomux_pin_name_t |
||||
* @param cfg an input function as defined in iomux_pin_cfg_t |
||||
*/ |
||||
void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) |
||||
{ |
||||
} |
||||
|
||||
/*
|
||||
* This function configures the pad value for a IOMUX pin. |
||||
* |
||||
* @param pin a pin number as defined in iomux_pin_name_t |
||||
* @param config the ORed value of elements defined in iomux_pad_config_t |
||||
*/ |
||||
void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) |
||||
{ |
||||
u32 pad_reg = get_pad_reg(pin); |
||||
writel(config, pad_reg); |
||||
} |
||||
|
||||
unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin) |
||||
{ |
||||
u32 pad_reg = get_pad_reg(pin); |
||||
return readl(pad_reg); |
||||
} |
@ -0,0 +1,289 @@ |
||||
/* |
||||
* Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
|
||||
* |
||||
* (C) Copyright 2009 Freescale Semiconductor, Inc. |
||||
* |
||||
* 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 <asm/arch/imx-regs.h> |
||||
#include <asm/arch/asm-offsets.h> |
||||
|
||||
/* |
||||
* L2CC Cache setup/invalidation/disable |
||||
*/ |
||||
.macro init_l2cc
|
||||
/* explicitly disable L2 cache */ |
||||
mrc 15, 0, r0, c1, c0, 1 |
||||
bic r0, r0, #0x2 |
||||
mcr 15, 0, r0, c1, c0, 1 |
||||
|
||||
/* reconfigure L2 cache aux control reg */ |
||||
mov r0, #0xC0 /* tag RAM */ |
||||
add r0, r0, #0x4 /* data RAM */ |
||||
orr r0, r0, #(1 << 24) /* disable write allocate delay */ |
||||
orr r0, r0, #(1 << 23) /* disable write allocate combine */ |
||||
orr r0, r0, #(1 << 22) /* disable write allocate */ |
||||
|
||||
cmp r3, #0x10 /* r3 contains the silicon rev */ |
||||
|
||||
/* disable write combine for TO 2 and lower revs */ |
||||
orrls r0, r0, #(1 << 25) |
||||
|
||||
mcr 15, 1, r0, c9, c0, 2 |
||||
.endm /* init_l2cc */ |
||||
|
||||
/* AIPS setup - Only setup MPROTx registers. |
||||
* The PACR default values are good.*/ |
||||
.macro init_aips
|
||||
/* |
||||
* Set all MPROTx to be non-bufferable, trusted for R/W, |
||||
* not forced to user-mode. |
||||
*/ |
||||
ldr r0, =AIPS1_BASE_ADDR |
||||
ldr r1, =0x77777777 |
||||
str r1, [r0, #0x0] |
||||
str r1, [r0, #0x4] |
||||
ldr r0, =AIPS2_BASE_ADDR |
||||
str r1, [r0, #0x0] |
||||
str r1, [r0, #0x4] |
||||
/* |
||||
* Clear the on and off peripheral modules Supervisor Protect bit |
||||
* for SDMA to access them. Did not change the AIPS control registers |
||||
* (offset 0x20) access type |
||||
*/ |
||||
.endm /* init_aips */ |
||||
|
||||
/* M4IF setup */ |
||||
.macro init_m4if
|
||||
/* VPU and IPU given higher priority (0x4) |
||||
* IPU accesses with ID=0x1 given highest priority (=0xA) |
||||
*/ |
||||
ldr r0, =M4IF_BASE_ADDR |
||||
|
||||
ldr r1, =0x00000203 |
||||
str r1, [r0, #0x40] |
||||
|
||||
ldr r1, =0x0 |
||||
str r1, [r0, #0x44] |
||||
|
||||
ldr r1, =0x00120125 |
||||
str r1, [r0, #0x9C] |
||||
|
||||
ldr r1, =0x001901A3 |
||||
str r1, [r0, #0x48] |
||||
|
||||
.endm /* init_m4if */ |
||||
|
||||
.macro setup_pll pll, freq |
||||
ldr r2, =\pll |
||||
ldr r1, =0x00001232 |
||||
str r1, [r2, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */ |
||||
mov r1, #0x2 |
||||
str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ |
||||
|
||||
str r3, [r2, #PLL_DP_OP] |
||||
str r3, [r2, #PLL_DP_HFS_OP] |
||||
|
||||
str r4, [r2, #PLL_DP_MFD] |
||||
str r4, [r2, #PLL_DP_HFS_MFD] |
||||
|
||||
str r5, [r2, #PLL_DP_MFN] |
||||
str r5, [r2, #PLL_DP_HFS_MFN] |
||||
|
||||
ldr r1, =0x00001232 |
||||
str r1, [r2, #PLL_DP_CTL] |
||||
1: ldr r1, [r2, #PLL_DP_CTL] |
||||
ands r1, r1, #0x1 |
||||
beq 1b |
||||
.endm |
||||
|
||||
.macro init_clock
|
||||
ldr r0, =CCM_BASE_ADDR |
||||
|
||||
/* Gate of clocks to the peripherals first */ |
||||
ldr r1, =0x3FFFFFFF |
||||
str r1, [r0, #CLKCTL_CCGR0] |
||||
ldr r1, =0x0 |
||||
str r1, [r0, #CLKCTL_CCGR1] |
||||
str r1, [r0, #CLKCTL_CCGR2] |
||||
str r1, [r0, #CLKCTL_CCGR3] |
||||
|
||||
ldr r1, =0x00030000 |
||||
str r1, [r0, #CLKCTL_CCGR4] |
||||
ldr r1, =0x00FFF030 |
||||
str r1, [r0, #CLKCTL_CCGR5] |
||||
ldr r1, =0x00000300 |
||||
str r1, [r0, #CLKCTL_CCGR6] |
||||
|
||||
/* Disable IPU and HSC dividers */ |
||||
mov r1, #0x60000 |
||||
str r1, [r0, #CLKCTL_CCDR] |
||||
|
||||
/* Make sure to switch the DDR away from PLL 1 */ |
||||
ldr r1, =0x19239145 |
||||
str r1, [r0, #CLKCTL_CBCDR] |
||||
/* make sure divider effective */ |
||||
1: ldr r1, [r0, #CLKCTL_CDHIPR] |
||||
cmp r1, #0x0 |
||||
bne 1b |
||||
|
||||
/* Switch ARM to step clock */ |
||||
mov r1, #0x4 |
||||
str r1, [r0, #CLKCTL_CCSR] |
||||
mov r3, #DP_OP_800 |
||||
mov r4, #DP_MFD_800 |
||||
mov r5, #DP_MFN_800 |
||||
setup_pll PLL1_BASE_ADDR |
||||
|
||||
mov r3, #DP_OP_665 |
||||
mov r4, #DP_MFD_665 |
||||
mov r5, #DP_MFN_665 |
||||
setup_pll PLL3_BASE_ADDR |
||||
|
||||
/* Switch peripheral to PLL 3 */ |
||||
ldr r0, =CCM_BASE_ADDR |
||||
ldr r1, =0x000010C0 |
||||
str r1, [r0, #CLKCTL_CBCMR] |
||||
ldr r1, =0x13239145 |
||||
str r1, [r0, #CLKCTL_CBCDR] |
||||
mov r3, #DP_OP_665 |
||||
mov r4, #DP_MFD_665 |
||||
mov r5, #DP_MFN_665 |
||||
setup_pll PLL2_BASE_ADDR |
||||
|
||||
/* Switch peripheral to PLL2 */ |
||||
ldr r0, =CCM_BASE_ADDR |
||||
ldr r1, =0x19239145 |
||||
str r1, [r0, #CLKCTL_CBCDR] |
||||
ldr r1, =0x000020C0 |
||||
str r1, [r0, #CLKCTL_CBCMR] |
||||
|
||||
mov r3, #DP_OP_216 |
||||
mov r4, #DP_MFD_216 |
||||
mov r5, #DP_MFN_216 |
||||
setup_pll PLL3_BASE_ADDR |
||||
|
||||
|
||||
/* Set the platform clock dividers */ |
||||
ldr r0, =ARM_BASE_ADDR |
||||
ldr r1, =0x00000725 |
||||
str r1, [r0, #0x14] |
||||
|
||||
ldr r0, =CCM_BASE_ADDR |
||||
|
||||
/* Run 3.0 at Full speed, for other TO's wait till we increase VDDGP */ |
||||
ldr r1, =0x0 |
||||
ldr r3, [r1, #ROM_SI_REV] |
||||
cmp r3, #0x10 |
||||
movls r1, #0x1 |
||||
movhi r1, #0 |
||||
str r1, [r0, #CLKCTL_CACRR] |
||||
|
||||
/* Switch ARM back to PLL 1 */ |
||||
mov r1, #0 |
||||
str r1, [r0, #CLKCTL_CCSR] |
||||
|
||||
/* setup the rest */ |
||||
/* Use lp_apm (24MHz) source for perclk */ |
||||
ldr r1, =0x000020C2 |
||||
str r1, [r0, #CLKCTL_CBCMR] |
||||
/* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */ |
||||
ldr r1, =0x59E35100 |
||||
str r1, [r0, #CLKCTL_CBCDR] |
||||
|
||||
/* Restore the default values in the Gate registers */ |
||||
ldr r1, =0xFFFFFFFF |
||||
str r1, [r0, #CLKCTL_CCGR0] |
||||
str r1, [r0, #CLKCTL_CCGR1] |
||||
str r1, [r0, #CLKCTL_CCGR2] |
||||
str r1, [r0, #CLKCTL_CCGR3] |
||||
str r1, [r0, #CLKCTL_CCGR4] |
||||
str r1, [r0, #CLKCTL_CCGR5] |
||||
str r1, [r0, #CLKCTL_CCGR6] |
||||
|
||||
/* Use PLL 2 for UART's, get 66.5MHz from it */ |
||||
ldr r1, =0xA5A2A020 |
||||
str r1, [r0, #CLKCTL_CSCMR1] |
||||
ldr r1, =0x00C30321 |
||||
str r1, [r0, #CLKCTL_CSCDR1] |
||||
|
||||
/* make sure divider effective */ |
||||
1: ldr r1, [r0, #CLKCTL_CDHIPR] |
||||
cmp r1, #0x0 |
||||
bne 1b |
||||
|
||||
mov r1, #0x0 |
||||
str r1, [r0, #CLKCTL_CCDR] |
||||
|
||||
/* for cko - for ARM div by 8 */ |
||||
mov r1, #0x000A0000 |
||||
add r1, r1, #0x00000F0 |
||||
str r1, [r0, #CLKCTL_CCOSR] |
||||
.endm |
||||
|
||||
.macro setup_wdog
|
||||
ldr r0, =WDOG1_BASE_ADDR |
||||
mov r1, #0x30 |
||||
strh r1, [r0] |
||||
.endm |
||||
|
||||
.section ".text.init", "x" |
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init: |
||||
ldr r0, =GPIO1_BASE_ADDR |
||||
ldr r1, [r0, #0x0] |
||||
orr r1, r1, #(1 << 23) |
||||
str r1, [r0, #0x0] |
||||
ldr r1, [r0, #0x4] |
||||
orr r1, r1, #(1 << 23) |
||||
str r1, [r0, #0x4] |
||||
|
||||
#ifdef ENABLE_IMPRECISE_ABORT |
||||
mrs r1, spsr /* save old spsr */ |
||||
mrs r0, cpsr /* read out the cpsr */ |
||||
bic r0, r0, #0x100 /* clear the A bit */ |
||||
msr spsr, r0 /* update spsr */ |
||||
add lr, pc, #0x8 /* update lr */ |
||||
movs pc, lr /* update cpsr */ |
||||
nop |
||||
nop |
||||
nop |
||||
nop |
||||
msr spsr, r1 /* restore old spsr */ |
||||
#endif |
||||
|
||||
init_l2cc |
||||
|
||||
init_aips |
||||
|
||||
init_m4if |
||||
|
||||
init_clock |
||||
|
||||
/* return from mxc_nand_load */ |
||||
/* r12 saved upper lr*/ |
||||
mov pc,lr |
||||
|
||||
/* Board level setting value */ |
||||
DDR_PERCHARGE_CMD: .word 0x04008008 |
||||
DDR_REFRESH_CMD: .word 0x00008010 |
||||
DDR_LMR1_W: .word 0x00338018 |
||||
DDR_LMR_CMD: .word 0xB2220000 |
||||
DDR_TIMING_W: .word 0xB02567A9 |
||||
DDR_MISC_W: .word 0x000A0104 |
@ -0,0 +1,109 @@ |
||||
/*
|
||||
* (C) Copyright 2007 |
||||
* Sascha Hauer, Pengutronix |
||||
* |
||||
* (C) Copyright 2009 Freescale Semiconductor, 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 <common.h> |
||||
#include <asm/arch/imx-regs.h> |
||||
#include <asm/errno.h> |
||||
#include <asm/io.h> |
||||
|
||||
u32 get_cpu_rev(void) |
||||
{ |
||||
int reg; |
||||
int system_rev; |
||||
|
||||
reg = __raw_readl(ROM_SI_REV); |
||||
switch (reg) { |
||||
case 0x02: |
||||
system_rev = 0x51000 | CHIP_REV_1_1; |
||||
break; |
||||
case 0x10: |
||||
if ((__raw_readl(GPIO1_BASE_ADDR + 0x0) & (0x1 << 22)) == 0) |
||||
system_rev = 0x51000 | CHIP_REV_2_5; |
||||
else |
||||
system_rev = 0x51000 | CHIP_REV_2_0; |
||||
break; |
||||
case 0x20: |
||||
system_rev = 0x51000 | CHIP_REV_3_0; |
||||
break; |
||||
return system_rev; |
||||
default: |
||||
system_rev = 0x51000 | CHIP_REV_1_0; |
||||
break; |
||||
} |
||||
return system_rev; |
||||
} |
||||
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO) |
||||
int print_cpuinfo(void) |
||||
{ |
||||
u32 cpurev; |
||||
|
||||
cpurev = get_cpu_rev(); |
||||
printf("CPU: Freescale i.MX51 family %d.%dV at %d MHz\n", |
||||
(cpurev & 0xF0) >> 4, |
||||
(cpurev & 0x0F) >> 4, |
||||
get_mcu_main_clk() / 1000000); |
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
/*
|
||||
* Initializes on-chip ethernet controllers. |
||||
* to override, implement board_eth_init() |
||||
*/ |
||||
#if defined(CONFIG_FEC_MXC) |
||||
extern int fecmxc_initialize(bd_t *bis); |
||||
#endif |
||||
|
||||
int cpu_eth_init(bd_t *bis) |
||||
{ |
||||
int rc = -ENODEV; |
||||
|
||||
#if defined(CONFIG_FEC_MXC) |
||||
rc = fecmxc_initialize(bis); |
||||
#endif |
||||
|
||||
return rc; |
||||
} |
||||
|
||||
/*
|
||||
* Initializes on-chip MMC controllers. |
||||
* to override, implement board_mmc_init() |
||||
*/ |
||||
int cpu_mmc_init(bd_t *bis) |
||||
{ |
||||
#ifdef CONFIG_FSL_ESDHC |
||||
return fsl_esdhc_mmc_init(bis); |
||||
#else |
||||
return 0; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
void reset_cpu(ulong addr) |
||||
{ |
||||
__raw_writew(4, WDOG1_BASE_ADDR); |
||||
} |
@ -0,0 +1,119 @@ |
||||
/*
|
||||
* (C) Copyright 2007 |
||||
* Sascha Hauer, Pengutronix |
||||
* |
||||
* (C) Copyright 2009 Freescale Semiconductor, 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 <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/imx-regs.h> |
||||
|
||||
/* General purpose timers registers */ |
||||
struct mxc_gpt { |
||||
unsigned int control; |
||||
unsigned int prescaler; |
||||
unsigned int status; |
||||
unsigned int nouse[6]; |
||||
unsigned int counter; |
||||
}; |
||||
|
||||
static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR; |
||||
|
||||
/* General purpose timers bitfields */ |
||||
#define GPTCR_SWR (1<<15) /* Software reset */ |
||||
#define GPTCR_FRR (1<<9) /* Freerun / restart */ |
||||
#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ |
||||
#define GPTCR_TEN (1) /* Timer enable */ |
||||
|
||||
static ulong timestamp; |
||||
static ulong lastinc; |
||||
|
||||
int timer_init(void) |
||||
{ |
||||
int i; |
||||
|
||||
/* setup GP Timer 1 */ |
||||
__raw_writel(GPTCR_SWR, &cur_gpt->control); |
||||
|
||||
/* We have no udelay by now */ |
||||
for (i = 0; i < 100; i++) |
||||
__raw_writel(0, &cur_gpt->control); |
||||
|
||||
__raw_writel(0, &cur_gpt->prescaler); /* 32Khz */ |
||||
|
||||
/* Freerun Mode, PERCLK1 input */ |
||||
i = __raw_readl(&cur_gpt->control); |
||||
__raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control); |
||||
reset_timer_masked(); |
||||
return 0; |
||||
} |
||||
|
||||
void reset_timer(void) |
||||
{ |
||||
reset_timer_masked(); |
||||
} |
||||
|
||||
void reset_timer_masked(void) |
||||
{ |
||||
ulong val = __raw_readl(&cur_gpt->counter); |
||||
lastinc = val / (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ); |
||||
timestamp = 0; |
||||
} |
||||
|
||||
ulong get_timer_masked(void) |
||||
{ |
||||
ulong val = __raw_readl(&cur_gpt->counter); |
||||
val /= (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ); |
||||
if (val >= lastinc) |
||||
timestamp += (val - lastinc); |
||||
else |
||||
timestamp += ((0xFFFFFFFF / (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ)) |
||||
- lastinc) + val; |
||||
lastinc = val; |
||||
return val; |
||||
} |
||||
|
||||
ulong get_timer(ulong base) |
||||
{ |
||||
return get_timer_masked() - base; |
||||
} |
||||
|
||||
void set_timer(ulong t) |
||||
{ |
||||
timestamp = t; |
||||
} |
||||
|
||||
/* delay x useconds AND perserve advance timstamp value */ |
||||
void __udelay(unsigned long usec) |
||||
{ |
||||
unsigned long now, start, tmo; |
||||
tmo = usec * (CONFIG_MX51_CLK32 / 1000) / 1000; |
||||
|
||||
if (!tmo) |
||||
tmo = 1; |
||||
|
||||
now = start = readl(&cur_gpt->counter); |
||||
|
||||
while ((now - start) < tmo) |
||||
now = readl(&cur_gpt->counter); |
||||
|
||||
} |
@ -0,0 +1,61 @@ |
||||
/* |
||||
* January 2004 - Changed to support H4 device |
||||
* Copyright (c) 2004 Texas Instruments |
||||
* |
||||
* (C) Copyright 2002 |
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de> |
||||
* |
||||
* (C) Copyright 2009 Freescale Semiconductor, 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 |
||||
*/ |
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") |
||||
OUTPUT_ARCH(arm) |
||||
ENTRY(_start) |
||||
SECTIONS |
||||
{ |
||||
. = 0x00000000; |
||||
|
||||
. = ALIGN(4); |
||||
.text : |
||||
{ |
||||
cpu/arm_cortexa8/start.o |
||||
*(.text) |
||||
} |
||||
|
||||
. = ALIGN(4); |
||||
.rodata : { *(.rodata) } |
||||
|
||||
. = ALIGN(4); |
||||
.data : { *(.data) } |
||||
|
||||
. = ALIGN(4); |
||||
.got : { *(.got) } |
||||
|
||||
. = .; |
||||
__u_boot_cmd_start = .; |
||||
.u_boot_cmd : { *(.u_boot_cmd) } |
||||
__u_boot_cmd_end = .; |
||||
|
||||
. = ALIGN(4); |
||||
__bss_start = .; |
||||
.bss : { *(.bss) } |
||||
_end = .; |
||||
} |
@ -0,0 +1,31 @@ |
||||
/*
|
||||
* (C) Copyright 2009 |
||||
* Stefano Babic, DENX Software Engineering, sbabic@denx.de. |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
#ifndef __ASM_ARCH_CLOCK_H |
||||
#define __ASM_ARCH_CLOCK_H |
||||
unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref); |
||||
|
||||
ulong imx_get_uartclk(void); |
||||
ulong imx_get_fecclk(void); |
||||
|
||||
#endif /* __ASM_ARCH_CLOCK_H */ |
Loading…
Reference in new issue