From 83983d6a761a3a07ddb6a6de12bd9000d06a84bd Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Mon, 2 Jul 2012 17:18:47 +0800 Subject: Add arch support for Vybrid platform Signed-off-by: TsiChung Liew --- arch/arm/cpu/armv7/vybrid-common/Makefile | 47 +++++ arch/arm/cpu/armv7/vybrid-common/cpu.c | 137 +++++++++++++ arch/arm/cpu/armv7/vybrid-common/speed.c | 41 ++++ arch/arm/cpu/armv7/vybrid-common/timer.c | 141 +++++++++++++ arch/arm/cpu/armv7/vybrid/Makefile | 46 +++++ arch/arm/cpu/armv7/vybrid/asm-offsets.c | 70 +++++++ arch/arm/cpu/armv7/vybrid/clock.c | 323 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/vybrid/iomux.c | 42 ++++ arch/arm/cpu/armv7/vybrid/lowlevel_init.S | 210 +++++++++++++++++++ arch/arm/cpu/armv7/vybrid/soc.c | 49 +++++ 10 files changed, 1106 insertions(+) create mode 100644 arch/arm/cpu/armv7/vybrid-common/Makefile create mode 100644 arch/arm/cpu/armv7/vybrid-common/cpu.c create mode 100644 arch/arm/cpu/armv7/vybrid-common/speed.c create mode 100644 arch/arm/cpu/armv7/vybrid-common/timer.c create mode 100644 arch/arm/cpu/armv7/vybrid/Makefile create mode 100644 arch/arm/cpu/armv7/vybrid/asm-offsets.c create mode 100644 arch/arm/cpu/armv7/vybrid/clock.c create mode 100644 arch/arm/cpu/armv7/vybrid/iomux.c create mode 100644 arch/arm/cpu/armv7/vybrid/lowlevel_init.S create mode 100644 arch/arm/cpu/armv7/vybrid/soc.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/vybrid-common/Makefile b/arch/arm/cpu/armv7/vybrid-common/Makefile new file mode 100644 index 0000000000..9ae8997873 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid-common/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright 2012 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)libvybrid-common.o + +COBJS = timer.o cpu.o speed.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/armv7/vybrid-common/cpu.c b/arch/arm/cpu/armv7/vybrid-common/cpu.c new file mode 100644 index 0000000000..865c01fc58 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid-common/cpu.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright 2012 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 +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_FSL_ESDHC +#include +#endif + +static char *get_reset_cause(void) +{ + char resetcause[32][64] = {"POR", + "Cortex A5 WDOG Timer Reset", + 0, + "CA5 WDOG reset", + "CM4 WDOG reset", + "JTAG HIGH-Z", + 0, + "External Reset", + "1.2V supply below 0.7V", + "HP regulator's LVD", + "ULP regulator's LVD", + "3.3V main supply is unstable", + "LP regulator's LVD", + 0, + 0, + 0, + "MDM-AP system reset request is set", + "Hard Fail State of System Security Monitor", + "SRC_SCR SW Reset is set", + "Platform's CSU alarm event", + 0, + 0, + 0, + 0, + "Anadig regulator 1.1V unstable", + "Anadig regulator 2.5V unstable", + "Anadig regulator 3.0V unstable", + "CMU even when FOSC freq less than 40MHz", + "CMU event when BUS freq is out of range", + "No clock is detected on FOSC", + "No clock is detected on SOSC", + "CM4 is in lockup"}; + char buf[512] = {0}, *pbuf; + u32 cause; + int i, bit; + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + + cause = readl(&src_regs->srsr); + writel(cause, &src_regs->srsr); + + pbuf = &buf[0]; + + for (i = 0; i < 32; i++) { + bit = 1 << i; + if ((cause & bit) == bit) { + if (resetcause[i][0] != NULL) + pbuf += sprintf(pbuf, "%s, ", resetcause[i]); + } + } + + if (buf[0] == NULL) + return 0; + + return &buf[0]; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 cpurev; + + cpurev = get_cpu_rev(); + printf("CPU: Freescale VyBrid %x family rev%d.%d at %d MHz\n", + (cpurev & 0xFFF000) >> 12, + (cpurev & 0x000F0) >> 4, + (cpurev & 0x0000F) >> 0, + vybrid_get_clock(VYBRID_ARM_CLK) / 1000000); + if (get_reset_cause() != NULL) + printf("Reset cause: %s\n", get_reset_cause()); + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + + rc = mcffec_initialize(bis); + + 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, WDOG_A5_BASE_ADDR); +} diff --git a/arch/arm/cpu/armv7/vybrid-common/speed.c b/arch/arm/cpu/armv7/vybrid-common/speed.c new file mode 100644 index 0000000000..df768b37e4 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid-common/speed.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright 2012 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 +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int get_clocks(void) +{ + gd->bus_clk = 66000000; + gd->ipg_clk = 66000000; +#ifdef CONFIG_FSL_ESDHC + gd->sdhc_clk = 132000000; +#endif + return 0; +} diff --git a/arch/arm/cpu/armv7/vybrid-common/timer.c b/arch/arm/cpu/armv7/vybrid-common/timer.c new file mode 100644 index 0000000000..6062a41e71 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid-common/timer.c @@ -0,0 +1,141 @@ +/* + * Copyright 2012 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 +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->tbl) +#define timerticks (gd->tbu) +#define lastinc (gd->lastinc) +static unsigned long ltmstamp = 0; + +#define CONFIG_TMR_USEPIT +#ifdef CONFIG_TMR_USEPIT + +unsigned long long _usec2ticks(unsigned long long usec); + +int timer_init(void) +{ + ulong usecs; + ulong ticks; + + timestamp = 0; + + /* + * nsecs conversion = (1/ipg_clk) * 10^9 + * equivalent to 1000 / (ipg_clk / 10^6) + */ + usecs = (gd->ipg_clk / 1000000); + ticks = 1000 / usecs; + + clrbits_le32(PIT_MCR, 2); /* enable PIT */ + + /* ticks per 10 us = 10000 us / usecs = cycles time */ + timerticks = (10 * 1000) / ticks; + + __raw_writel(0xFFFFFFFF, PIT_LDVAL1); + __raw_writel(0, PIT_TCTRL1); + __raw_writel(4, PIT_TCTRL1); + __raw_writel(5, PIT_TCTRL1); + __raw_writel(timerticks, PIT_LDVAL0); + __raw_writel(1, PIT_TCTRL0); + + lastinc = __raw_readl(PIT_LTMR64H); + + return 0; +} + +ulong get_timer(ulong base) +{ + unsigned long now, diff; + + now = __raw_readl(PIT_LTMR64H); + diff = -(now - lastinc); + ltmstamp += diff; + while (ltmstamp > 100) { + timestamp++; + ltmstamp -= 100; + } + lastinc = now; + + return timestamp - base; +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + ulong nsecs, tmp; + + /* + * nsecs conversion = (1/ipg_clk) * 10^9 + * equivalent to 1000 / (ipg_clk / 10^6) + */ + if (usec < 5) + usec = 10; + + nsecs = gd->ipg_clk / 1000000; + nsecs = 1000 / nsecs; + + /* 1 us per ticks = 1000 ns / nsecs = cycles time */ + while (usec > 0) { + if (usec > 65000) + tmp = 65000; + else + tmp = usec; + usec = usec - tmp; + + tmp = (tmp * 1000) / nsecs; + + __raw_writel(tmp, PIT_LDVAL2); + __raw_writel(1, PIT_TCTRL2); + + while ((__raw_readl(PIT_TFLG2) & 1) != 1) + ; + __raw_writel(0, PIT_TCTRL2); + __raw_writel(1, PIT_TFLG2); + } +} +#endif /* CONFIG_TMR_USEPIT */ + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long long _usec2ticks(unsigned long long usec) +{ + return usec; +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/arch/arm/cpu/armv7/vybrid/Makefile b/arch/arm/cpu/armv7/vybrid/Makefile new file mode 100644 index 0000000000..364e9a7c26 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).o + +COBJS = soc.o clock.o iomux.o +SOBJS = lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/armv7/vybrid/asm-offsets.c b/arch/arm/cpu/armv7/vybrid/asm-offsets.c new file mode 100644 index 0000000000..778c75b26f --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/asm-offsets.c @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Adapted from Linux v2.6.36 kernel: arch/powerpc/kernel/asm-offsets.c + * + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + * + * 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. + */ + +#include +#include + +#include + +int main(void) +{ + /* Round up to make sure size gives nice stack alignment */ + DEFINE(CLKCTL_CCR, offsetof(struct clkctl, ccr)); + DEFINE(CLKCTL_CSR, offsetof(struct clkctl, csr)); + DEFINE(CLKCTL_CCSR, offsetof(struct clkctl, ccsr)); + DEFINE(CLKCTL_CACRR, offsetof(struct clkctl, cacrr)); + DEFINE(CLKCTL_CSCMR1, offsetof(struct clkctl, cscmr1)); + DEFINE(CLKCTL_CSCDR1, offsetof(struct clkctl, cscdr1)); + DEFINE(CLKCTL_CSCDR2, offsetof(struct clkctl, cscdr2)); + DEFINE(CLKCTL_CSCDR3, offsetof(struct clkctl, cscdr3)); + DEFINE(CLKCTL_CSCMR2, offsetof(struct clkctl, cscmr2)); + DEFINE(CLKCTL_CSCDR4, offsetof(struct clkctl, cscdr4)); + DEFINE(CLKCTL_CTOR, offsetof(struct clkctl, ctor)); + DEFINE(CLKCTL_CLPCR, offsetof(struct clkctl, clpcr)); + DEFINE(CLKCTL_CISR, offsetof(struct clkctl, cisr)); + DEFINE(CLKCTL_CIMR, offsetof(struct clkctl, cimr)); + DEFINE(CLKCTL_CCOSR, offsetof(struct clkctl, ccosr)); + + DEFINE(CLKCTL_CGPR, offsetof(struct clkctl, cgpr)); + DEFINE(CLKCTL_CCGR0, offsetof(struct clkctl, ccgr0)); + DEFINE(CLKCTL_CCGR1, offsetof(struct clkctl, ccgr1)); + DEFINE(CLKCTL_CCGR2, offsetof(struct clkctl, ccgr2)); + DEFINE(CLKCTL_CCGR3, offsetof(struct clkctl, ccgr3)); + DEFINE(CLKCTL_CCGR4, offsetof(struct clkctl, ccgr4)); + DEFINE(CLKCTL_CCGR5, offsetof(struct clkctl, ccgr5)); + DEFINE(CLKCTL_CCGR6, offsetof(struct clkctl, ccgr6)); + DEFINE(CLKCTL_CCGR7, offsetof(struct clkctl, ccgr7)); + DEFINE(CLKCTL_CCGR8, offsetof(struct clkctl, ccgr8)); + DEFINE(CLKCTL_CCGR9, offsetof(struct clkctl, ccgr9)); + DEFINE(CLKCTL_CCGR10, offsetof(struct clkctl, ccgr10)); + DEFINE(CLKCTL_CCGR11, offsetof(struct clkctl, ccgr11)); + DEFINE(CLKCTL_CMEOR0, offsetof(struct clkctl, cmeor0)); + DEFINE(CLKCTL_CMEOR1, offsetof(struct clkctl, cmeor1)); + DEFINE(CLKCTL_CMEOR2, offsetof(struct clkctl, cmeor2)); + DEFINE(CLKCTL_CMEOR3, offsetof(struct clkctl, cmeor3)); + DEFINE(CLKCTL_CMEOR4, offsetof(struct clkctl, cmeor4)); + DEFINE(CLKCTL_CMEOR5, offsetof(struct clkctl, cmeor5)); + DEFINE(CLKCTL_CPPDSR, offsetof(struct clkctl, cppdsr)); + DEFINE(CLKCTL_CCOWR, offsetof(struct clkctl, ccowr)); + DEFINE(CLKCTL_CCPGR0, offsetof(struct clkctl, ccpgr0)); + DEFINE(CLKCTL_CCPGR1, offsetof(struct clkctl, ccpgr1)); + DEFINE(CLKCTL_CCPGR2, offsetof(struct clkctl, ccpgr2)); + DEFINE(CLKCTL_CCPGR3, offsetof(struct clkctl, ccpgr3)); + + return 0; +} diff --git a/arch/arm/cpu/armv7/vybrid/clock.c b/arch/arm/cpu/armv7/vybrid/clock.c new file mode 100644 index 0000000000..eea6af0f57 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/clock.c @@ -0,0 +1,323 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright 2012 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 +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum pll_clocks { + PLL1_CLOCK = 0, + PLL2_CLOCK, + PLL3_CLOCK, + PLL4_CLOCK, + PLL_CLOCKS, +}; + +struct mxc_pll_reg *vybridc_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 clkctl *ccm = (struct clkctl *)CCM_BASE_ADDR; + +/* Calculate the frequency of PLLn. */ +static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq) +{ +#if 0 + uint32_t ctrl, op, mfd, mfn, mfi, pdf, ret; + uint64_t refclk, temp; + int32_t mfn_abs; + + ctrl = readl(&pll->ctrl); + + if (ctrl & MXC_DPLLC_CTL_HFSM) { + mfn = __raw_readl(&pll->hfs_mfn); + mfd = __raw_readl(&pll->hfs_mfd); + op = __raw_readl(&pll->hfs_op); + } else { + mfn = __raw_readl(&pll->mfn); + mfd = __raw_readl(&pll->mfd); + op = __raw_readl(&pll->op); + } + + mfd &= MXC_DPLLC_MFD_MFD_MASK; + mfn &= MXC_DPLLC_MFN_MFN_MASK; + pdf = op & MXC_DPLLC_OP_PDF_MASK; + mfi = (op & MXC_DPLLC_OP_MFI_MASK) >> MXC_DPLLC_OP_MFI_OFFSET; + + /* 21.2.3 */ + if (mfi < 5) + mfi = 5; + + /* Sign extend */ + if (mfn >= 0x04000000) { + mfn |= 0xfc000000; + mfn_abs = -mfn; + } else + mfn_abs = mfn; + + refclk = infreq * 2; + if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN) + refclk *= 2; + + do_div(refclk, pdf + 1); + temp = refclk * mfn_abs; + do_div(temp, mfd + 1); + ret = refclk * mfi; + + if ((int)mfn < 0) + ret -= temp; + else + ret += temp; + + return ret; +#else + return 0; +#endif +} + +/* Get mcu main rate */ +u32 get_mcu_main_clk(void) +{ + u32 reg, freq; + + reg = __raw_readl(&ccm->cacrr) & 7; + freq = decode_pll(vybridc_plls[PLL1_CLOCK], CONFIG_SYS_VYBRID_HCLK); + return freq / (reg + 1); +} + +/* Get the rate of peripheral's root clock. */ +static u32 get_periph_clk(void) +{ +#if 0 + u32 reg; + + reg = __raw_readl(&mxc_ccm->cbcdr); + if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL)) + return decode_pll(vybridc_plls[PLL2_CLOCK], + CONFIG_SYS_VYBRID_HCLK); + 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(vybridc_plls[PLL1_CLOCK], + CONFIG_SYS_VYBRID_HCLK); + case 1: + return decode_pll(vybridc_plls[PLL3_CLOCK], + CONFIG_SYS_VYBRID_HCLK); + default: + return 0; + } + /* NOTREACHED */ +#else + return 0; +#endif +} + +/* Get the rate of ahb clock. */ +static u32 get_ahb_clk(void) +{ +#if 0 + uint32_t freq, div, reg; + + freq = get_periph_clk(); + + reg = __raw_readl(&mxc_ccm->cbcdr); + div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1; + + return freq / div; +#else + return 0; +#endif +} + +/* Get the rate of ipg clock. */ +static u32 get_ipg_clk(void) +{ +#if 0 + uint32_t freq, reg, div; + + freq = get_ahb_clk(); + + reg = __raw_readl(&mxc_ccm->cbcdr); + div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1; + + return freq / div; +#else + return 66000000; +#endif +} + +/* Get the rate of ipg_per clock. */ +static u32 get_ipg_per_clk(void) +{ +#if 0 + 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)); +#else + return 0; +#endif +} + +/* get cspi clock rate. */ +u32 vybrid_get_dspiclk(void) +{ +#if 0 + 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(vybridc_plls[PLL1_CLOCK], + CONFIG_SYS_VYBRID_HCLK) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case 1: + ret_val = decode_pll(vybridc_plls[PLL2_CLOCK], + CONFIG_SYS_VYBRID_HCLK) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case 2: + ret_val = decode_pll(vybridc_plls[PLL3_CLOCK], + CONFIG_SYS_VYBRID_HCLK) / + ((pre_pdf + 1) * (pdf + 1)); + break; + default: + ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1)); + break; + } + + return ret_val; +#else + return 0; +#endif +} + +/* The API of get vybrid clocks. */ +unsigned int vybrid_get_clock(enum vybrid_clock clk) +{ + switch (clk) { + case VYBRID_ARM_CLK: + return get_mcu_main_clk(); + case VYBRID_AHB_CLK: + return get_ahb_clk(); + case VYBRID_IPG_CLK: + return get_ipg_clk(); + case VYBRID_IPG_PERCLK: + return get_ipg_per_clk(); + case VYBRID_UART_CLK: + return vybrid_get_uartclk(); + case VYBRID_CSPI_CLK: + return vybrid_get_dspiclk(); + case VYBRID_FEC_CLK: +#if 0 + return decode_pll(vybridc_plls[PLL1_CLOCK], + CONFIG_SYS_VYBRID_HCLK); +#else + return 0; +#endif + + default: + break; + } + return -1; +} + +/* Get the rate of uart clk. */ +u32 vybrid_get_uartclk(void) +{ + return gd->ipg_clk; +} + +u32 vybrid_get_fecclk(void) +{ +#if 0 + return vybrid_get_clock(VYBRID_IPG_CLK); +#else + return 0; +#endif +} + +/* Dump some core clockes. */ +int do_vybrid_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ +#if 0 + u32 freq; + freq = decode_pll(vybridc_plls[PLL1_CLOCK], CONFIG_SYS_VYBRID_HCLK); + printf("PLL1 %8d MHz\n", freq / 1000000); + freq = decode_pll(vybridc_plls[PLL2_CLOCK], CONFIG_SYS_VYBRID_HCLK); + printf("PLL2 %8d MHz\n", freq / 1000000); + freq = decode_pll(vybridc_plls[PLL3_CLOCK], CONFIG_SYS_VYBRID_HCLK); + printf("PLL3 %8d MHz\n", freq / 1000000); +#endif + printf("\n"); + printf("AHB %8d kHz\n", + vybrid_get_clock(VYBRID_AHB_CLK) / 1000); + printf("IPG %8d kHz\n", + vybrid_get_clock(VYBRID_IPG_CLK) / 1000); + printf("IPG PERCLK %8d kHz\n", + vybrid_get_clock(VYBRID_IPG_PERCLK) / 1000); + + return 0; +} + +/***************************************************/ + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_vybrid_showclocks, + "display clocks", + "" +); diff --git a/arch/arm/cpu/armv7/vybrid/iomux.c b/arch/arm/cpu/armv7/vybrid/iomux.c new file mode 100644 index 0000000000..cecfddde71 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/iomux.c @@ -0,0 +1,42 @@ +/* + * Copyright 2012 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 +#include +#include +#include +#include +#include + +void pad_iomux_set(u32 pad_addr, pad_iomux_t *padio) +{ + u32 value; + + value = (((padio->mod & 7) << 20) | ((padio->spd & 3) << 12) | \ + ((padio->sre & 1) << 11) | ((padio->ode & 1) << 10) | \ + ((padio->hys & 1) << 9) | ((padio->dse & 7) << 6) | \ + ((padio->pus & 3) << 4) | ((padio->pke & 1) << 3) | \ + ((padio->pue & 1) << 2) | ((padio->obe & 1) << 1) | \ + ((padio->ibe & 1) << 0)); + + __raw_writel(pad_addr, value); +} diff --git a/arch/arm/cpu/armv7/vybrid/lowlevel_init.S b/arch/arm/cpu/armv7/vybrid/lowlevel_init.S new file mode 100644 index 0000000000..8c22e3c365 --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/lowlevel_init.S @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2007, Guennadi Liakhovetski + * + * Copyright 2012 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 +#include +#include + +/* VFPU setup/invalidation/disable */ +.macro init_vfpu + ldr r0, =(0xF << 20) + mcr p15, 0, r0, c1, c0, 2 + mov r3, #0x40000000 + .long 0xeee83a10 +/* vmsr FPEXC, r3 */ +.endm /* init_vfpu */ + +/* 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 */ + + ldr r1, =0x00000000 + ldr r3, [r1, #ROM_SI_REV] /* problem ********* */ + 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, =AIPS0_BASE_ADDR + ldr r1, =0x77777000 + str r1, [r0, #0x0] + str r1, [r0, #0x4] + ldr r0, =AIPS1_BASE_ADDR + str r1, [r0, #0x0] + str r1, [r0, #0x4] +.endm /* init_aips */ + +/* MAX (Multi-Layer AHB Crossbar Switch) setup */ +.macro init_max +.endm /* init_max */ + +/* M4IF setup */ +.macro init_m4if +.endm /* init_m4if */ + +/* DDR */ +.macro init_drive_strength +.endm /* init_drive_strength */ + +.macro setup_pll pll, freq +.endm + +.macro init_clock + ldr r0, =CCM_BASE_ADDR + + ldr r1, =CONFIG_SYS_CLKCTRL_CLPCR + str r1, [r0, #CLKCTL_CLPCR] + + /* Gate of clocks to the peripherals first */ + ldr r1, =CONFIG_SYS_CLKCTL_CCGR0 + str r1, [r0, #CLKCTL_CCGR0] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR1 + str r1, [r0, #CLKCTL_CCGR1] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR2 + str r1, [r0, #CLKCTL_CCGR2] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR3 + str r1, [r0, #CLKCTL_CCGR3] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR4 + str r1, [r0, #CLKCTL_CCGR4] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR5 + str r1, [r0, #CLKCTL_CCGR5] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR6 + str r1, [r0, #CLKCTL_CCGR6] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR7 + str r1, [r0, #CLKCTL_CCGR7] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR8 + str r1, [r0, #CLKCTL_CCGR8] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR9 + str r1, [r0, #CLKCTL_CCGR9] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR10 + str r1, [r0, #CLKCTL_CCGR10] + ldr r1, =CONFIG_SYS_CLKCTL_CCGR11 + str r1, [r0, #CLKCTL_CCGR11] + + ldr r2, =ANATOP_BASE_ADDR + ldr r1, =CONFIG_SYS_ANADIG_528_CTRL + str r1, [r2, #0x30] + ldr r1, =CONFIG_SYS_ANADIG_ENET_CTRL + str r1, [r2, #0xE0] + ldr r1, =CONFIG_SYS_ANADIG_SYS_CTRL + str r1, [r2, #0x270] + /* check for lock */ + + ldr r1, =CONFIG_SYS_CLKCTRL_CCR + str r1, [r0, #CLKCTL_CCR] + + ldr r1, =CONFIG_SYS_CLKCTRL_CCSR + str r1, [r0, #CLKCTL_CCSR] + + ldr r1, =CONFIG_SYS_CLKCTRL_CACRR + str r1, [r0, #CLKCTL_CACRR] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCMR1 + str r1, [r0, #CLKCTL_CSCMR1] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCDR1 + str r1, [r0, #CLKCTL_CSCDR1] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCDR2 + str r1, [r0, #CLKCTL_CSCDR2] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCDR3 + str r1, [r0, #CLKCTL_CSCDR3] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCMR2 + str r1, [r0, #CLKCTL_CSCMR2] + + ldr r1, =CONFIG_SYS_CLKCTRL_CSCDR4 + str r1, [r0, #CLKCTL_CSCDR4] +.endm + +.macro setup_wdog + ldr r0, =WDOG_A5_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] +*/ + /* ARM errata ID #468414 */ + mrc 15, 0, r1, c1, c0, 1 + orr r1, r1, #(1 << 5) /* enable L1NEON bit */ + mcr 15, 0, r1, c1, c0, 1 +/* + init_vfpu + + init_l2cc + + init_aips + + init_max + + init_m4if + + init_drive_strength +*/ + init_clock + + /* return from mxc_nand_load */ + /* b 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 diff --git a/arch/arm/cpu/armv7/vybrid/soc.c b/arch/arm/cpu/armv7/vybrid/soc.c new file mode 100644 index 0000000000..c8d1238dbe --- /dev/null +++ b/arch/arm/cpu/armv7/vybrid/soc.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright 2012 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 +#include +#include +#include + +#include +#include + +#if !(defined(CONFIG_VYBRID)) +#error "CPU_TYPE not defined" +#endif + +u32 get_cpu_rev(void) +{ + int system_rev = 0x600000; + int reg = __raw_readl(ROM_SI_REV); + + system_rev |= reg; + return system_rev; +} + +void set_chipselect_size(int const cs_size) +{ +} -- cgit v1.2.3