diff options
Diffstat (limited to 'arch/arm/cpu')
| -rw-r--r-- | arch/arm/cpu/arm1136/cpu.c | 1 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1136/start.S | 4 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/cpu.c | 3 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/start.S | 65 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/Makefile | 44 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/aemif.c | 93 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/clock.c | 451 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/init.c | 37 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S | 25 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/mux.c | 334 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/timer.c | 122 | ||||
| -rw-r--r-- | arch/arm/cpu/arm1176/tnetv107x/wdt.c | 180 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/board.c | 34 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/emif4.c | 168 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/mem.c | 90 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/sdrc.c | 202 | ||||
| -rw-r--r-- | arch/arm/cpu/arm_cortexa8/omap3/sys_info.c | 41 | 
18 files changed, 1711 insertions, 188 deletions
| diff --git a/arch/arm/cpu/arm1136/cpu.c b/arch/arm/cpu/arm1136/cpu.c index ade7f4680..2b9163173 100644 --- a/arch/arm/cpu/arm1136/cpu.c +++ b/arch/arm/cpu/arm1136/cpu.c @@ -71,6 +71,7 @@ static void cache_flush(void)  {  	unsigned long i = 0; +	asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */  	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));  /* invalidate both caches and flush btb */  	asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */  } diff --git a/arch/arm/cpu/arm1136/start.S b/arch/arm/cpu/arm1136/start.S index 957f4389b..922d01cb7 100644 --- a/arch/arm/cpu/arm1136/start.S +++ b/arch/arm/cpu/arm1136/start.S @@ -226,8 +226,8 @@ cpu_init_crit:  	 * flush v4 I/D caches  	 */  	mov	r0, #0 -	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */ -	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */ +	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */ +	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */  	/*  	 * disable MMU stuff and caches diff --git a/arch/arm/cpu/arm1176/cpu.c b/arch/arm/cpu/arm1176/cpu.c index befa0cdcc..c0fd114e1 100644 --- a/arch/arm/cpu/arm1176/cpu.c +++ b/arch/arm/cpu/arm1176/cpu.c @@ -33,9 +33,6 @@  #include <common.h>  #include <command.h> -#ifdef CONFIG_S3C64XX -#include <asm/arch/s3c6400.h> -#endif  #include <asm/system.h>  static void cache_flush (void); diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S index e2b6c9b08..a540edbfb 100644 --- a/arch/arm/cpu/arm1176/start.S +++ b/arch/arm/cpu/arm1176/start.S @@ -1,5 +1,5 @@  /* - *  armboot - Startup Code for S3C6400/ARM1176 CPU-core + *  armboot - Startup Code for ARM1176 CPU-core   *   * Copyright (c) 2007	Samsung Electronics   * @@ -35,9 +35,6 @@  #ifdef CONFIG_ENABLE_MMU  #include <asm/proc/domain.h>  #endif -#ifdef CONFIG_S3C64XX -#include <asm/arch/s3c6400.h> -#endif  #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)  #define CONFIG_SYS_PHY_UBOOT_BASE	CONFIG_SYS_UBOOT_BASE @@ -172,14 +169,10 @@ cpu_init_crit:  	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)  	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align  	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache +  	/* Prepare to disable the MMU */ -	adr	r1, mmu_disable_phys -	/* We presume we're within the first 1024 bytes */ -	and	r1, r1, #0x3fc -	ldr	r2, _TEXT_PHY_BASE -	ldr	r3, =0xfff00000 -	and	r2, r2, r3 -	orr	r2, r2, r1 +	adr	r2, mmu_disable_phys +	sub	r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - TEXT_BASE)  	b	mmu_disable  	.align 5 @@ -189,14 +182,30 @@ mmu_disable:  	nop  	nop  	mov	pc, r2 +mmu_disable_phys: + +#ifdef CONFIG_DISABLE_TCM +	/* +	 * Disable the TCMs +	 */ +	mrc	p15, 0, r0, c0, c0, 2	/* Return TCM details */ +	cmp	r0, #0 +	beq	skip_tcmdisable +	mov	r1, #0 +	mov	r2, #1 +	tst	r0, r2 +	mcrne	p15, 0, r1, c9, c1, 1	/* Disable Instruction TCM if present*/ +	tst	r0, r2, LSL #16 +	mcrne	p15, 0, r1, c9, c1, 0	/* Disable Data TCM if present*/ +skip_tcmdisable: +#endif  #endif -mmu_disable_phys: -#ifdef CONFIG_S3C64XX +#ifdef CONFIG_PERIPORT_REMAP  	/* Peri port setup */ -	ldr	r0, =0x70000000 -	orr	r0, r0, #0x13 -	mcr	p15,0,r0,c15,c2,4       @ 256M (0x70000000 - 0x7fffffff) +	ldr	r0, =CONFIG_PERIPORT_BASE +	orr	r0, r0, #CONFIG_PERIPORT_SIZE +	mcr	p15,0,r0,c15,c2,4  #endif  	/* @@ -204,7 +213,25 @@ mmu_disable_phys:  	 */  	bl	lowlevel_init		/* go setup pll,mux,memory */ -after_copy: +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate:				/* relocate U-Boot to RAM	    */ +	adr	r0, _start		/* r0 <- current position of code   */ +	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */ +	cmp     r0, r1                  /* don't reloc during debug         */ +	beq     stack_setup + +	ldr	r2, _armboot_start +	ldr	r3, _bss_start +	sub	r2, r3, r2		/* r2 <- size of armboot            */ +	add	r2, r0, r2		/* r2 <- source end address         */ + +copy_loop: +	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */ +	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */ +	cmp	r0, r2			/* until source end addreee [r2]    */ +	ble	copy_loop +#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */ +  #ifdef CONFIG_ENABLE_MMU  enable_mmu:  	/* enable domain access */ @@ -240,9 +267,9 @@ mmu_enable:  	nop  	nop  	mov	pc, r2 +skip_hw_init:  #endif -skip_hw_init:  	/* Set up the stack						    */  stack_setup:  	ldr	r0, =CONFIG_SYS_UBOOT_BASE	/* base of copy in DRAM	    */ @@ -310,6 +337,8 @@ phy_last_jump:  	mov	r0, #0  	mov	pc, r9  #endif + +  /*   *************************************************************************   * diff --git a/arch/arm/cpu/arm1176/tnetv107x/Makefile b/arch/arm/cpu/arm1176/tnetv107x/Makefile new file mode 100644 index 000000000..fe9d8a0dc --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/Makefile @@ -0,0 +1,44 @@ +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +include $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(SOC).a + +COBJS	+= aemif.o clock.o init.o mux.o timer.o wdt.o +SOBJS	+= lowlevel_init.o + +SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) + +OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) +START	:= $(addprefix $(obj),$(START)) + +all:	$(obj).depend $(LIB) + +$(LIB):	$(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/arm1176/tnetv107x/aemif.c b/arch/arm/cpu/arm1176/tnetv107x/aemif.c new file mode 100644 index 000000000..172f583bc --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/aemif.c @@ -0,0 +1,93 @@ +/* + * TNETV107X: Asynchronous EMIF Configuration + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/mux.h> + +#define ASYNC_EMIF_BASE			TNETV107X_ASYNC_EMIF_CNTRL_BASE +#define ASYNC_EMIF_CONFIG(cs)		(ASYNC_EMIF_BASE+0x10+(cs)*4) +#define ASYNC_EMIF_ONENAND_CONTROL	(ASYNC_EMIF_BASE+0x5c) +#define ASYNC_EMIF_NAND_CONTROL		(ASYNC_EMIF_BASE+0x60) +#define ASYNC_EMIF_WAITCYCLE_CONFIG	(ASYNC_EMIF_BASE+0x4) + +#define CONFIG_SELECT_STROBE(v)		((v) ? 1 << 31 : 0) +#define CONFIG_EXTEND_WAIT(v)		((v) ? 1 << 30 : 0) +#define CONFIG_WR_SETUP(v)		(((v) & 0x0f) << 26) +#define CONFIG_WR_STROBE(v)		(((v) & 0x3f) << 20) +#define CONFIG_WR_HOLD(v)		(((v) & 0x07) << 17) +#define CONFIG_RD_SETUP(v)		(((v) & 0x0f) << 13) +#define CONFIG_RD_STROBE(v)		(((v) & 0x3f) << 7) +#define CONFIG_RD_HOLD(v)		(((v) & 0x07) << 4) +#define CONFIG_TURN_AROUND(v)		(((v) & 0x03) << 2) +#define CONFIG_WIDTH(v)			(((v) & 0x03) << 0) + +#define NUM_CS				4 + +#define set_config_field(reg, field, val)			\ +	do {							\ +		if (val != -1) {				\ +			reg &= ~CONFIG_##field(0xffffffff);	\ +			reg |=	CONFIG_##field(val);		\ +		}						\ +	} while (0) + +void configure_async_emif(int cs, struct async_emif_config *cfg) +{ +	unsigned long tmp; + +	if (cfg->mode == ASYNC_EMIF_MODE_NAND) { +		tmp = __raw_readl(ASYNC_EMIF_NAND_CONTROL); +		tmp |= (1 << cs); +		__raw_writel(tmp, ASYNC_EMIF_NAND_CONTROL); + +	} else if (cfg->mode == ASYNC_EMIF_MODE_ONENAND) { +		tmp = __raw_readl(ASYNC_EMIF_ONENAND_CONTROL); +		tmp |= (1 << cs); +		__raw_writel(tmp, ASYNC_EMIF_ONENAND_CONTROL); +	} + +	tmp = __raw_readl(ASYNC_EMIF_CONFIG(cs)); + +	set_config_field(tmp, SELECT_STROBE,	cfg->select_strobe); +	set_config_field(tmp, EXTEND_WAIT,	cfg->extend_wait); +	set_config_field(tmp, WR_SETUP,		cfg->wr_setup); +	set_config_field(tmp, WR_STROBE,	cfg->wr_strobe); +	set_config_field(tmp, WR_HOLD,		cfg->wr_hold); +	set_config_field(tmp, RD_SETUP,		cfg->rd_setup); +	set_config_field(tmp, RD_STROBE,	cfg->rd_strobe); +	set_config_field(tmp, RD_HOLD,		cfg->rd_hold); +	set_config_field(tmp, TURN_AROUND,	cfg->turn_around); +	set_config_field(tmp, WIDTH,		cfg->width); + +	__raw_writel(tmp, ASYNC_EMIF_CONFIG(cs)); +} + +void init_async_emif(int num_cs, struct async_emif_config *config) +{ +	int cs; + +	clk_enable(TNETV107X_LPSC_AEMIF); + +	for (cs = 0; cs < num_cs; cs++) +		configure_async_emif(cs, config + cs); +} diff --git a/arch/arm/cpu/arm1176/tnetv107x/clock.c b/arch/arm/cpu/arm1176/tnetv107x/clock.c new file mode 100644 index 000000000..e26fec1f9 --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/clock.c @@ -0,0 +1,451 @@ +/* + * TNETV107X: Clock management APIs + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm-generic/errno.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/clock.h> + +#define CLOCK_BASE		TNETV107X_CLOCK_CONTROL_BASE +#define PSC_BASE		TNETV107X_PSC_BASE + +#define BIT(x)			(1 << (x)) + +#define MAX_PREDIV		64 +#define MAX_POSTDIV		8 +#define MAX_MULT		512 +#define MAX_DIV			(MAX_PREDIV * MAX_POSTDIV) + +/* LPSC registers */ +#define PSC_PTCMD		0x120 +#define PSC_PTSTAT		0x128 +#define PSC_MDSTAT(n)		(0x800 + (n) * 4) +#define PSC_MDCTL(n)		(0xA00 + (n) * 4) + +#define PSC_MDCTL_LRSTZ		BIT(8) + +#define psc_reg_read(reg)	__raw_readl((u32 *)(PSC_BASE + (reg))) +#define psc_reg_write(reg, val)	__raw_writel(val, (u32 *)(PSC_BASE + (reg))) + +/* SSPLL registers */ +struct sspll_regs { +	u32	modes; +	u32	postdiv; +	u32	prediv; +	u32	mult_factor; +	u32	divider_range; +	u32	bw_divider; +	u32	spr_amount; +	u32	spr_rate_div; +	u32	diag; +}; + +/* SSPLL base addresses */ +static struct sspll_regs *sspll_regs[] = { +	(struct sspll_regs *)(CLOCK_BASE + 0x040), +	(struct sspll_regs *)(CLOCK_BASE + 0x080), +	(struct sspll_regs *)(CLOCK_BASE + 0x0c0), +}; + +#define sspll_reg(pll, reg)		(&(sspll_regs[pll]->reg)) +#define sspll_reg_read(pll, reg)	__raw_readl(sspll_reg(pll, reg)) +#define sspll_reg_write(pll, reg, val)	__raw_writel(val, sspll_reg(pll, reg)) + + +/* PLL Control Registers */ +struct pllctl_regs { +	u32	ctl;		/* 00 */ +	u32	ocsel;		/* 04 */ +	u32	secctl;		/* 08 */ +	u32	__pad0; +	u32	mult;		/* 10 */ +	u32	prediv;		/* 14 */ +	u32	div1;		/* 18 */ +	u32	div2;		/* 1c */ +	u32	div3;		/* 20 */ +	u32	oscdiv1;	/* 24 */ +	u32	postdiv;	/* 28 */ +	u32	bpdiv;		/* 2c */ +	u32	wakeup;		/* 30 */ +	u32	__pad1; +	u32	cmd;		/* 38 */ +	u32	stat;		/* 3c */ +	u32	alnctl;		/* 40 */ +	u32	dchange;	/* 44 */ +	u32	cken;		/* 48 */ +	u32	ckstat;		/* 4c */ +	u32	systat;		/* 50 */ +	u32	ckctl;		/* 54 */ +	u32	__pad2[2]; +	u32	div4;		/* 60 */ +	u32	div5;		/* 64 */ +	u32	div6;		/* 68 */ +	u32	div7;		/* 6c */ +	u32	div8;		/* 70 */ +}; + +struct lpsc_map { +	int	pll, div; +}; + +static struct pllctl_regs *pllctl_regs[] = { +	(struct pllctl_regs *)(CLOCK_BASE + 0x700), +	(struct pllctl_regs *)(CLOCK_BASE + 0x300), +	(struct pllctl_regs *)(CLOCK_BASE + 0x500), +}; + +#define pllctl_reg(pll, reg)		(&(pllctl_regs[pll]->reg)) +#define pllctl_reg_read(pll, reg)	__raw_readl(pllctl_reg(pll, reg)) +#define pllctl_reg_write(pll, reg, val)	__raw_writel(val, pllctl_reg(pll, reg)) + +#define pllctl_reg_rmw(pll, reg, mask, val)			\ +	pllctl_reg_write(pll, reg,				\ +		(pllctl_reg_read(pll, reg) & ~(mask)) | val) + +#define pllctl_reg_setbits(pll, reg, mask)			\ +	pllctl_reg_rmw(pll, reg, 0, mask) + +#define pllctl_reg_clrbits(pll, reg, mask)			\ +	pllctl_reg_rmw(pll, reg, mask, 0) + +/* PLLCTL Bits */ +#define PLLCTL_CLKMODE		BIT(8) +#define PLLCTL_PLLSELB		BIT(7) +#define PLLCTL_PLLENSRC		BIT(5) +#define PLLCTL_PLLDIS		BIT(4) +#define PLLCTL_PLLRST		BIT(3) +#define PLLCTL_PLLPWRDN		BIT(1) +#define PLLCTL_PLLEN		BIT(0) + +#define PLLDIV_ENABLE		BIT(15) + +static int pll_div_offset[] = { +#define div_offset(reg)	offsetof(struct pllctl_regs, reg) +	div_offset(div1), div_offset(div2), div_offset(div3), +	div_offset(div4), div_offset(div5), div_offset(div6), +	div_offset(div7), div_offset(div8), +}; + +static unsigned long pll_bypass_mask[] = { 1, 4, 2 }; +static unsigned long pll_div_mask[] = { 0x01ff, 0x00ff, 0x00ff }; + +/* Mappings from PLL+DIV to subsystem clocks */ +#define sys_arm1176_clk		{SYS_PLL, 0} +#define sys_dsp_clk		{SYS_PLL, 1} +#define sys_ddr_clk		{SYS_PLL, 2} +#define sys_full_clk		{SYS_PLL, 3} +#define sys_lcd_clk		{SYS_PLL, 4} +#define sys_vlynq_ref_clk	{SYS_PLL, 5} +#define sys_tsc_clk		{SYS_PLL, 6} +#define sys_half_clk		{SYS_PLL, 7} + +#define eth_clk_5		{ETH_PLL, 0} +#define eth_clk_50		{ETH_PLL, 1} +#define eth_clk_125		{ETH_PLL, 2} +#define eth_clk_250		{ETH_PLL, 3} +#define eth_clk_25		{ETH_PLL, 4} + +#define tdm_clk			{TDM_PLL, 0} +#define tdm_extra_clk		{TDM_PLL, 1} +#define tdm1_clk		{TDM_PLL, 2} + +/* Optimization barrier */ +#define barrier()	\ +	__asm__ __volatile__("mov r0, r0\n" : : : "memory"); + +static const struct lpsc_map lpsc_clk_map[] = { +	[TNETV107X_LPSC_ARM]			= sys_arm1176_clk, +	[TNETV107X_LPSC_GEM]			= sys_dsp_clk, +	[TNETV107X_LPSC_DDR2_PHY]		= sys_ddr_clk, +	[TNETV107X_LPSC_TPCC]			= sys_full_clk, +	[TNETV107X_LPSC_TPTC0]			= sys_full_clk, +	[TNETV107X_LPSC_TPTC1]			= sys_full_clk, +	[TNETV107X_LPSC_RAM]			= sys_full_clk, +	[TNETV107X_LPSC_MBX_LITE]		= sys_arm1176_clk, +	[TNETV107X_LPSC_LCD]			= sys_lcd_clk, +	[TNETV107X_LPSC_ETHSS]			= eth_clk_125, +	[TNETV107X_LPSC_AEMIF]			= sys_full_clk, +	[TNETV107X_LPSC_CHIP_CFG]		= sys_half_clk, +	[TNETV107X_LPSC_TSC]			= sys_tsc_clk, +	[TNETV107X_LPSC_ROM]			= sys_half_clk, +	[TNETV107X_LPSC_UART2]			= sys_half_clk, +	[TNETV107X_LPSC_PKTSEC]			= sys_half_clk, +	[TNETV107X_LPSC_SECCTL]			= sys_half_clk, +	[TNETV107X_LPSC_KEYMGR]			= sys_half_clk, +	[TNETV107X_LPSC_KEYPAD]			= sys_half_clk, +	[TNETV107X_LPSC_GPIO]			= sys_half_clk, +	[TNETV107X_LPSC_MDIO]			= sys_half_clk, +	[TNETV107X_LPSC_SDIO0]			= sys_half_clk, +	[TNETV107X_LPSC_UART0]			= sys_half_clk, +	[TNETV107X_LPSC_UART1]			= sys_half_clk, +	[TNETV107X_LPSC_TIMER0]			= sys_half_clk, +	[TNETV107X_LPSC_TIMER1]			= sys_half_clk, +	[TNETV107X_LPSC_WDT_ARM]		= sys_half_clk, +	[TNETV107X_LPSC_WDT_DSP]		= sys_half_clk, +	[TNETV107X_LPSC_SSP]			= sys_half_clk, +	[TNETV107X_LPSC_TDM0]			= tdm_clk, +	[TNETV107X_LPSC_VLYNQ]			= sys_vlynq_ref_clk, +	[TNETV107X_LPSC_MCDMA]			= sys_half_clk, +	[TNETV107X_LPSC_USB0]			= sys_half_clk, +	[TNETV107X_LPSC_TDM1]			= tdm1_clk, +	[TNETV107X_LPSC_DEBUGSS]		= sys_half_clk, +	[TNETV107X_LPSC_ETHSS_RGMII]		= eth_clk_250, +	[TNETV107X_LPSC_SYSTEM]			= sys_half_clk, +	[TNETV107X_LPSC_IMCOP]			= sys_dsp_clk, +	[TNETV107X_LPSC_SPARE]			= sys_half_clk, +	[TNETV107X_LPSC_SDIO1]			= sys_half_clk, +	[TNETV107X_LPSC_USB1]			= sys_half_clk, +	[TNETV107X_LPSC_USBSS]			= sys_half_clk, +	[TNETV107X_LPSC_DDR2_EMIF1_VRST]	= sys_ddr_clk, +	[TNETV107X_LPSC_DDR2_EMIF2_VCTL_RST]	= sys_ddr_clk, +}; + +static const unsigned long pll_ext_freq[] = { +	[SYS_PLL] = CONFIG_PLL_SYS_EXT_FREQ, +	[ETH_PLL] = CONFIG_PLL_ETH_EXT_FREQ, +	[TDM_PLL] = CONFIG_PLL_TDM_EXT_FREQ, +}; + +static unsigned long pll_freq_get(int pll) +{ +	unsigned long mult = 1, prediv = 1, postdiv = 1; +	unsigned long ref = CONFIG_SYS_INT_OSC_FREQ; +	unsigned long ret; +	u32 bypass; + +	bypass = __raw_readl((u32 *)(CLOCK_BASE)); +	if (!(bypass & pll_bypass_mask[pll])) { +		mult	= sspll_reg_read(pll, mult_factor); +		prediv	= sspll_reg_read(pll, prediv) + 1; +		postdiv	= sspll_reg_read(pll, postdiv) + 1; +	} + +	if (pllctl_reg_read(pll, ctl) & PLLCTL_CLKMODE) +		ref = pll_ext_freq[pll]; + +	if (!(pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN)) +		return ref; + +	ret = (unsigned long)(ref + ((unsigned long long)ref * mult) / 256); +	ret /= (prediv * postdiv); + +	return ret; +} + +static unsigned long __pll_div_freq_get(int pll, unsigned int fpll, +					int div) +{ +	int divider = 1; +	unsigned long divreg; + +	divreg = __raw_readl((void *)pllctl_regs[pll] + pll_div_offset[div]); + +	if (divreg & PLLDIV_ENABLE) +		divider = (divreg & pll_div_mask[pll]) + 1; + +	return fpll / divider; +} + +static unsigned long pll_div_freq_get(int pll, int div) +{ +	unsigned int fpll = pll_freq_get(pll); + +	return __pll_div_freq_get(pll, fpll, div); +} + +static void __pll_div_freq_set(int pll, unsigned int fpll, int div, +			       unsigned long hz) +{ +	int divider = (fpll / hz - 1); + +	divider &= pll_div_mask[pll]; +	divider |= PLLDIV_ENABLE; + +	__raw_writel(divider, (void *)pllctl_regs[pll] + pll_div_offset[div]); +	pllctl_reg_setbits(pll, alnctl, (1 << div)); +	pllctl_reg_setbits(pll, dchange, (1 << div)); +} + +static unsigned long pll_div_freq_set(int pll, int div, unsigned long hz) +{ +	unsigned int fpll = pll_freq_get(pll); + +	__pll_div_freq_set(pll, fpll, div, hz); + +	pllctl_reg_write(pll, cmd, 1); + +	/* Wait until new divider takes effect */ +	while (pllctl_reg_read(pll, stat) & 0x01); + +	return __pll_div_freq_get(pll, fpll, div); +} + +unsigned long clk_get_rate(unsigned int clk) +{ +	return pll_div_freq_get(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div); +} + +unsigned long clk_round_rate(unsigned int clk, unsigned long hz) +{ +	unsigned long fpll, divider, pll; + +	pll = lpsc_clk_map[clk].pll; +	fpll = pll_freq_get(pll); +	divider = (fpll / hz - 1); +	divider &= pll_div_mask[pll]; + +	return fpll / (divider + 1); +} + +int clk_set_rate(unsigned int clk, unsigned long _hz) +{ +	unsigned long hz; + +	hz = clk_round_rate(clk, _hz); +	if (hz != _hz) +		return -EINVAL;	/* Cannot set to target freq */ + +	pll_div_freq_set(lpsc_clk_map[clk].pll, lpsc_clk_map[clk].div, hz); +	return 0; +} + +void lpsc_control(int mod, unsigned long state, int lrstz) +{ +	u32 mdctl; + +	mdctl = psc_reg_read(PSC_MDCTL(mod)); +	mdctl &= ~0x1f; +	mdctl |= state; + +	if (lrstz == 0) +		mdctl &= ~PSC_MDCTL_LRSTZ; +	else if (lrstz == 1) +		mdctl |= PSC_MDCTL_LRSTZ; + +	psc_reg_write(PSC_MDCTL(mod), mdctl); + +	psc_reg_write(PSC_PTCMD, 1); + +	/* wait for power domain transition to end */ +	while (psc_reg_read(PSC_PTSTAT) & 1); + +	/* Wait for module state change */ +	while ((psc_reg_read(PSC_MDSTAT(mod)) & 0x1f) != state); +} + +int lpsc_status(unsigned int id) +{ +	return psc_reg_read(PSC_MDSTAT(id)) & 0x1f; +} + +static void init_pll(const struct pll_init_data *data) +{ +	unsigned long fpll; +	unsigned long best_pre = 0, best_post = 0, best_mult = 0; +	unsigned long div, prediv, postdiv, mult; +	unsigned long delta, actual; +	long best_delta = -1; +	int i; +	u32 tmp; + +	if (data->pll == SYS_PLL) +		return; /* cannot reconfigure system pll on the fly */ + +	tmp = pllctl_reg_read(data->pll, ctl); +	if (data->internal_osc) { +		tmp &= ~PLLCTL_CLKMODE; +		fpll = CONFIG_SYS_INT_OSC_FREQ; +	} else { +		tmp |= PLLCTL_CLKMODE; +		fpll = pll_ext_freq[data->pll]; +	} +	pllctl_reg_write(data->pll, ctl, tmp); + +	mult = data->pll_freq / fpll; +	for (mult = MAX(mult, 1); mult <= MAX_MULT; mult++) { +		div = (fpll * mult) / data->pll_freq; +		if (div < 1 || div > MAX_DIV) +			continue; + +		for (postdiv = 1; postdiv <= min(div, MAX_POSTDIV); postdiv++) { +			prediv = div / postdiv; +			if (prediv < 1 || prediv > MAX_PREDIV) +				continue; + +			actual = (fpll / prediv) * (mult / postdiv); +			delta = (actual - data->pll_freq); +			if (delta < 0) +				delta = -delta; +			if ((delta < best_delta) || (best_delta == -1)) { +				best_delta = delta; +				best_mult = mult; +				best_pre = prediv; +				best_post = postdiv; +				if (delta == 0) +					goto done; +			} +		} +	} +done: + +	if (best_delta == -1) { +		printf("pll cannot derive %lu from %lu\n", +				data->pll_freq, fpll); +		return; +	} + +	fpll = fpll * best_mult; +	fpll /= best_pre * best_post; + +	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLENSRC); +	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN); + +	pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST); + +	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN); +	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLDIS); + +	sspll_reg_write(data->pll, mult_factor,	(best_mult - 1) << 8); +	sspll_reg_write(data->pll, prediv,	best_pre - 1); +	sspll_reg_write(data->pll, postdiv,	best_post - 1); + +	for (i = 0; i < 10; i++) +		if (data->div_freq[i]) +			__pll_div_freq_set(data->pll, fpll, i, +					   data->div_freq[i]); + +	pllctl_reg_write(data->pll, cmd, 1); + +	/* Wait until pll "go" operation completes */ +	while (pllctl_reg_read(data->pll, stat) & 0x01); + +	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST); +	pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN); +} + +void init_plls(int num_pll, struct pll_init_data *config) +{ +	int i; + +	for (i = 0; i < num_pll; i++) +		init_pll(&config[i]); +} diff --git a/arch/arm/cpu/arm1176/tnetv107x/init.c b/arch/arm/cpu/arm1176/tnetv107x/init.c new file mode 100644 index 000000000..ce3a02550 --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/init.c @@ -0,0 +1,37 @@ +/* + * TNETV107X: Architecture initialization + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> + +void chip_configuration_unlock(void) +{ +       __raw_writel(TNETV107X_KICK0_MAGIC, TNETV107X_KICK0); +       __raw_writel(TNETV107X_KICK1_MAGIC, TNETV107X_KICK1); +} + +int arch_cpu_init(void) +{ +       icache_enable(); +       chip_configuration_unlock(); + +       return 0; +} diff --git a/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S b/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S new file mode 100644 index 000000000..3ee32ef96 --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/lowlevel_init.S @@ -0,0 +1,25 @@ +/* + * TNETV107X: Low-level pre-relocation initialization + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +.globl lowlevel_init +lowlevel_init: +	/* nothing for now, maybe needed for more exotic boot modes */ +	mov	pc, lr diff --git a/arch/arm/cpu/arm1176/tnetv107x/mux.c b/arch/arm/cpu/arm1176/tnetv107x/mux.c new file mode 100644 index 000000000..ccc53141f --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/mux.c @@ -0,0 +1,334 @@ +/* + * TNETV107X: Pinmux configuration + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/mux.h> + +#define MUX_MODE_1		0x00 +#define MUX_MODE_2		0x04 +#define MUX_MODE_3		0x0c +#define MUX_MODE_4		0x1c + +#define MUX_DEBUG		0 + +static const struct pin_config pin_table[] = { +	/*		  reg	shift	mode	*/ +	TNETV107X_MUX_CFG(0,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(0,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(0,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(0,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(0,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(0,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(0,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(1,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(1,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(2,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(2,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(3,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(3,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	10,	MUX_MODE_4), +	TNETV107X_MUX_CFG(3,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(3,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	20,	MUX_MODE_4), +	TNETV107X_MUX_CFG(3,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(3,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(3,	25,	MUX_MODE_4), +	TNETV107X_MUX_CFG(4,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(4,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(4,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(4,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	20,	MUX_MODE_3), +	TNETV107X_MUX_CFG(4,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(4,	25,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	10,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	20,	MUX_MODE_4), +	TNETV107X_MUX_CFG(5,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(5,	25,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	10,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	20,	MUX_MODE_4), +	TNETV107X_MUX_CFG(6,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(6,	25,	MUX_MODE_4), +	TNETV107X_MUX_CFG(7,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(7,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(7,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	10,	MUX_MODE_4), +	TNETV107X_MUX_CFG(7,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(7,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(7,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(7,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(8,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(8,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(8,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(8,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(8,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(8,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(8,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(9,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	0,	MUX_MODE_4), +	TNETV107X_MUX_CFG(9,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(9,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	5,	MUX_MODE_4), +	TNETV107X_MUX_CFG(9,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(9,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	10,	MUX_MODE_4), +	TNETV107X_MUX_CFG(9,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(9,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(9,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(9,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(9,	20,	MUX_MODE_4), +	TNETV107X_MUX_CFG(10,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(10,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(10,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(10,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(10,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(10,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(10,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(11,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(11,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(12,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(13,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(13,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(13,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(13,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(14,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(15,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(15,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(15,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(16,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(16,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(16,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(16,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(16,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(16,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(16,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(17,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(17,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(17,	0,	MUX_MODE_3), +	TNETV107X_MUX_CFG(17,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(17,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(17,	5,	MUX_MODE_3), +	TNETV107X_MUX_CFG(17,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(17,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(17,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(17,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(17,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(17,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(18,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(18,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(18,	0,	MUX_MODE_3), +	TNETV107X_MUX_CFG(18,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(18,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(18,	5,	MUX_MODE_3), +	TNETV107X_MUX_CFG(18,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(18,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(18,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(18,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(18,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(18,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(19,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(19,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(19,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(19,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(19,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(19,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(20,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(20,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(21,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	5,	MUX_MODE_3), +	TNETV107X_MUX_CFG(22,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(22,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(22,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(22,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	20,	MUX_MODE_3), +	TNETV107X_MUX_CFG(22,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(22,	25,	MUX_MODE_3), +	TNETV107X_MUX_CFG(23,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(23,	0,	MUX_MODE_3), +	TNETV107X_MUX_CFG(23,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(23,	5,	MUX_MODE_3), +	TNETV107X_MUX_CFG(23,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(23,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(24,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(24,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(24,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(24,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(24,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(24,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(24,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(24,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(24,	25,	MUX_MODE_2), +	TNETV107X_MUX_CFG(25,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(25,	0,	MUX_MODE_2), +	TNETV107X_MUX_CFG(25,	0,	MUX_MODE_3), +	TNETV107X_MUX_CFG(25,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(25,	5,	MUX_MODE_2), +	TNETV107X_MUX_CFG(25,	5,	MUX_MODE_3), +	TNETV107X_MUX_CFG(25,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(25,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(25,	10,	MUX_MODE_3), +	TNETV107X_MUX_CFG(25,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(25,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(25,	15,	MUX_MODE_3), +	TNETV107X_MUX_CFG(25,	15,	MUX_MODE_4), +	TNETV107X_MUX_CFG(26,	0,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	5,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	10,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	10,	MUX_MODE_2), +	TNETV107X_MUX_CFG(26,	15,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	15,	MUX_MODE_2), +	TNETV107X_MUX_CFG(26,	20,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	20,	MUX_MODE_2), +	TNETV107X_MUX_CFG(26,	25,	MUX_MODE_1), +	TNETV107X_MUX_CFG(26,	25,	MUX_MODE_2), +}; + +const int pin_table_size = sizeof(pin_table) / sizeof(pin_table[0]); + +int mux_select_pin(short index) +{ +	const struct pin_config *cfg; +	unsigned long mask, mode, reg; + +	if (index >= pin_table_size) +		return 0; + +	cfg = &pin_table[index]; + +	mask = 0x1f << cfg->mask_offset; +	mode = cfg->mode << cfg->mask_offset; + +	reg = __raw_readl(TNETV107X_PINMUX(cfg->reg_index)); +	reg = (reg & ~mask) | mode; +	__raw_writel(reg, TNETV107X_PINMUX(cfg->reg_index)); + +	return 1; +} + +int mux_select_pins(const short *pins) +{ +	int i, ret = 1; + +	for (i = 0; pins[i] >= 0; i++) +		ret &= mux_select_pin(pins[i]); + +	return ret; +} diff --git a/arch/arm/cpu/arm1176/tnetv107x/timer.c b/arch/arm/cpu/arm1176/tnetv107x/timer.c new file mode 100644 index 000000000..a7a400d1e --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/timer.c @@ -0,0 +1,122 @@ +/* + * TNETV107X: Timer implementation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> + +struct timer_regs { +	u_int32_t pid12; +	u_int32_t pad[3]; +	u_int32_t tim12; +	u_int32_t tim34; +	u_int32_t prd12; +	u_int32_t prd34; +	u_int32_t tcr; +	u_int32_t tgcr; +	u_int32_t wdtcr; +}; + +#define regs ((struct timer_regs *)CONFIG_SYS_TIMERBASE) + +#define TIMER_LOAD_VAL	(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) +#define TIM_CLK_DIV	16 + +static ulong timestamp; +static ulong lastinc; + +int timer_init(void) +{ +	clk_enable(TNETV107X_LPSC_TIMER0); + +	lastinc = timestamp = 0; + +	/* We are using timer34 in unchained 32-bit mode, full speed */ +	__raw_writel(0x0, ®s->tcr); +	__raw_writel(0x0, ®s->tgcr); +	__raw_writel(0x06 | ((TIM_CLK_DIV - 1) << 8), ®s->tgcr); +	__raw_writel(0x0, ®s->tim34); +	__raw_writel(TIMER_LOAD_VAL, ®s->prd34); +	__raw_writel(2 << 22, ®s->tcr); + +	return 0; +} + +void reset_timer(void) +{ +	lastinc = timestamp = 0; + +	__raw_writel(0,		®s->tcr); +	__raw_writel(0,		®s->tim34); +	__raw_writel(2 << 22,	®s->tcr); +} + +static ulong get_timer_raw(void) +{ +	ulong now = __raw_readl(®s->tim34); + +	if (now >= lastinc) +		timestamp += now - lastinc; +	else +		timestamp += now + TIMER_LOAD_VAL - lastinc; + +	lastinc = now; + +	return timestamp; +} + +ulong get_timer(ulong base) +{ +	return (get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base; +} + +void set_timer(ulong t) +{ +	timestamp = t; +} + +unsigned long long get_ticks(void) +{ +	return get_timer(0); +} + +void __udelay(unsigned long usec) +{ +	ulong tmo; +	ulong endtime; +	signed long diff; + +	tmo = CONFIG_SYS_HZ_CLOCK / 1000; +	tmo *= usec; +	tmo /= (1000 * TIM_CLK_DIV); + +	endtime = get_timer_raw() + tmo; + +	do { +		ulong now = get_timer_raw(); +		diff = endtime - now; +	} while (diff >= 0); +} + +ulong get_tbclk(void) +{ +	return CONFIG_SYS_HZ; +} diff --git a/arch/arm/cpu/arm1176/tnetv107x/wdt.c b/arch/arm/cpu/arm1176/tnetv107x/wdt.c new file mode 100644 index 000000000..18aadb0c6 --- /dev/null +++ b/arch/arm/cpu/arm1176/tnetv107x/wdt.c @@ -0,0 +1,180 @@ +/* + * TNETV107X: Watchdog timer implementation (for reset) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> + +#define MAX_DIV		0xFFFE0001 + +struct wdt_regs { +	u32 kick_lock; +#define KICK_LOCK_1	0x5555 +#define KICK_LOCK_2	0xaaaa +	u32 kick; + +	u32 change_lock; +#define CHANGE_LOCK_1	0x6666 +#define CHANGE_LOCK_2	0xbbbb +	u32 change; + +	u32 disable_lock; +#define DISABLE_LOCK_1	0x7777 +#define DISABLE_LOCK_2	0xcccc +#define DISABLE_LOCK_3	0xdddd +	u32 disable; + +	u32 prescale_lock; +#define PRESCALE_LOCK_1	0x5a5a +#define PRESCALE_LOCK_2	0xa5a5 +	u32 prescale; +}; + +static struct wdt_regs* regs = (struct wdt_regs *)TNETV107X_WDT0_ARM_BASE; + +#define wdt_reg_read(reg)	__raw_readl(®s->reg) +#define wdt_reg_write(reg, val)	__raw_writel((val), ®s->reg) + +static int write_prescale_reg(unsigned long prescale_value) +{ +	wdt_reg_write(prescale_lock, PRESCALE_LOCK_1); +	if ((wdt_reg_read(prescale_lock) & 0x3) != 0x1) +		return -1; + +	wdt_reg_write(prescale_lock, PRESCALE_LOCK_2); +	if ((wdt_reg_read(prescale_lock) & 0x3) != 0x3) +		return -1; + +	wdt_reg_write(prescale, prescale_value); + +	return 0; +} + +static int write_change_reg(unsigned long initial_timer_value) +{ +	wdt_reg_write(change_lock, CHANGE_LOCK_1); +	if ((wdt_reg_read(change_lock) & 0x3) != 0x1) +		return -1; + +	wdt_reg_write(change_lock, CHANGE_LOCK_2); +	if ((wdt_reg_read(change_lock) & 0x3) != 0x3) +		return -1; + +	wdt_reg_write(change, initial_timer_value); + +	return 0; +} + +static int wdt_control(unsigned long disable_value) +{ +	wdt_reg_write(disable_lock, DISABLE_LOCK_1); +	if ((wdt_reg_read(disable_lock) & 0x3) != 0x1) +		return -1; + +	wdt_reg_write(disable_lock, DISABLE_LOCK_2); +	if ((wdt_reg_read(disable_lock) & 0x3) != 0x2) +		return -1; + +	wdt_reg_write(disable_lock, DISABLE_LOCK_3); +	if ((wdt_reg_read(disable_lock) & 0x3) != 0x3) +		return -1; + +	wdt_reg_write(disable, disable_value); +	return 0; +} + +static int wdt_set_period(unsigned long msec) +{ +	unsigned long change_value, count_value; +	unsigned long prescale_value = 1; +	unsigned long refclk_khz, maxdiv; +	int ret; + +	refclk_khz = clk_get_rate(TNETV107X_LPSC_WDT_ARM); +	maxdiv = (MAX_DIV / refclk_khz); + +	if ((!msec) || (msec > maxdiv)) +		return -1; + +	count_value = refclk_khz * msec; +	if (count_value > 0xffff) { +		change_value = count_value / 0xffff + 1; +		prescale_value = count_value / change_value; +	} else { +		change_value = count_value; +	} + +	ret = write_prescale_reg(prescale_value - 1); +	if (ret) +		return ret; + +	ret = write_change_reg(change_value); +	if (ret) +		return ret; + +	return 0; +} + +unsigned long last_wdt = -1; + +int wdt_start(unsigned long msecs) +{ +	int ret; +	ret = wdt_control(0); +	if (ret) +		return ret; +	ret = wdt_set_period(msecs); +	if (ret) +		return ret; +	ret = wdt_control(1); +	if (ret) +		return ret; +	ret = wdt_kick(); +	last_wdt = msecs; +	return ret; +} + +int wdt_stop(void) +{ +	last_wdt = -1; +	return wdt_control(0); +} + +int wdt_kick(void) +{ +	wdt_reg_write(kick_lock, KICK_LOCK_1); +	if ((wdt_reg_read(kick_lock) & 0x3) != 0x1) +		return -1; + +	wdt_reg_write(kick_lock, KICK_LOCK_2); +	if ((wdt_reg_read(kick_lock) & 0x3) != 0x3) +		return -1; + +	wdt_reg_write(kick, 1); +	return 0; +} + +void reset_cpu(ulong addr) +{ +	clk_enable(TNETV107X_LPSC_WDT_ARM); +	wdt_start(1); +	wdt_kick(); +} diff --git a/arch/arm/cpu/arm_cortexa8/omap3/Makefile b/arch/arm/cpu/arm_cortexa8/omap3/Makefile index 136b163ad..7d63c6bec 100644 --- a/arch/arm/cpu/arm_cortexa8/omap3/Makefile +++ b/arch/arm/cpu/arm_cortexa8/omap3/Makefile @@ -37,8 +37,11 @@ COBJS	+= syslib.o  COBJS	+= sys_info.o  COBJS	+= timer.o +COBJS-$(CONFIG_EMIF4)	+= emif4.o +COBJS-$(CONFIG_SDRC)	+= sdrc.o +  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) +OBJS	:= $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS))  all:	 $(obj).depend $(LIB) diff --git a/arch/arm/cpu/arm_cortexa8/omap3/board.c b/arch/arm/cpu/arm_cortexa8/omap3/board.c index 7b78fa448..d2500ca3b 100644 --- a/arch/arm/cpu/arm_cortexa8/omap3/board.c +++ b/arch/arm/cpu/arm_cortexa8/omap3/board.c @@ -40,8 +40,6 @@  extern omap3_sysinfo sysinfo; -extern u32 is_mem_sdr(void); -  /******************************************************************************   * Routine: delay   * Description: spinning delay to use before udelay works @@ -233,7 +231,7 @@ void s_init(void)  	per_clocks_enable();  	if (!in_sdram) -		sdrc_init(); +		mem_init();  }  /****************************************************************************** @@ -274,36 +272,6 @@ void watchdog_init(void)  }  /****************************************************************************** - * Routine: dram_init - * Description: sets uboots idea of sdram size - *****************************************************************************/ -int dram_init(void) -{ -	DECLARE_GLOBAL_DATA_PTR; -	unsigned int size0 = 0, size1 = 0; - -	/* -	 * If a second bank of DDR is attached to CS1 this is -	 * where it can be started.  Early init code will init -	 * memory on CS0. -	 */ -	if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) { -		do_sdrc_init(CS1, NOT_EARLY); -		make_cs1_contiguous(); -	} - -	size0 = get_sdr_cs_size(CS0); -	size1 = get_sdr_cs_size(CS1); - -	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; -	gd->bd->bi_dram[0].size = size0; -	gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); -	gd->bd->bi_dram[1].size = size1; - -	return 0; -} - -/******************************************************************************   * Dummy function to handle errors for EABI incompatibility   *****************************************************************************/  void abort(void) diff --git a/arch/arm/cpu/arm_cortexa8/omap3/emif4.c b/arch/arm/cpu/arm_cortexa8/omap3/emif4.c new file mode 100644 index 000000000..fae5b1161 --- /dev/null +++ b/arch/arm/cpu/arm_cortexa8/omap3/emif4.c @@ -0,0 +1,168 @@ +/* + * Author : + *     Vaibhav Hiremath <hvaibhav@ti.com> + * + * Based on mem.c and sdrc.c + * + * Copyright (C) 2010 + * Texas Instruments Incorporated - http://www.ti.com/ + * + * 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/mem.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/emif4.h> + +extern omap3_sysinfo sysinfo; + +static emif4_t *emif4_base = (emif4_t *)OMAP34XX_SDRC_BASE; + +/* + * is_mem_sdr - + *  - Return 1 if mem type in use is SDR + */ +u32 is_mem_sdr(void) +{ +	return 0; +} + +/* + * get_sdr_cs_size - + *  - Get size of chip select 0/1 + */ +u32 get_sdr_cs_size(u32 cs) +{ +	u32 size; + +	/* TODO: Calculate the size based on EMIF4 configuration */ +	size = CONFIG_SYS_CS0_SIZE; + +	return size; +} + +/* + * get_sdr_cs_offset - + *  - Get offset of cs from cs0 start + */ +u32 get_sdr_cs_offset(u32 cs) +{ +	u32 offset = 0; + +	return offset; +} + +/* + * do_emif4_init - + *  - Init the emif4 module for DDR access + *  - Early init routines, called from flash or SRAM. + */ +void do_emif4_init(void) +{ +	unsigned int regval; +	/* Set the DDR PHY parameters in PHY ctrl registers */ +	regval = (EMIF4_DDR1_READ_LAT | EMIF4_DDR1_PWRDN_DIS | +		EMIF4_DDR1_EXT_STRB_DIS); +	writel(regval, &emif4_base->ddr_phyctrl1); +	writel(regval, &emif4_base->ddr_phyctrl1_shdw); +	writel(0, &emif4_base->ddr_phyctrl2); + +	/* Reset the DDR PHY and wait till completed */ +	regval = readl(&emif4_base->sdram_iodft_tlgc); +	regval |= (1<<10); +	writel(regval, &emif4_base->sdram_iodft_tlgc); +	/*Wait till that bit clears*/ +	while ((readl(&emif4_base->sdram_iodft_tlgc) & (1<<10)) == 0x1); +	/*Re-verify the DDR PHY status*/ +	while ((readl(&emif4_base->sdram_sts) & (1<<2)) == 0x0); + +	regval |= (1<<0); +	writel(regval, &emif4_base->sdram_iodft_tlgc); +	/* Set SDR timing registers */ +	regval = (EMIF4_TIM1_T_WTR | EMIF4_TIM1_T_RRD | +		EMIF4_TIM1_T_RC | EMIF4_TIM1_T_RAS | +		EMIF4_TIM1_T_WR | EMIF4_TIM1_T_RCD | +		EMIF4_TIM1_T_RP); +	writel(regval, &emif4_base->sdram_time1); +	writel(regval, &emif4_base->sdram_time1_shdw); + +	regval = (EMIF4_TIM2_T_CKE | EMIF4_TIM2_T_RTP | +		EMIF4_TIM2_T_XSRD | EMIF4_TIM2_T_XSNR | +		EMIF4_TIM2_T_ODT | EMIF4_TIM2_T_XP); +	writel(regval, &emif4_base->sdram_time2); +	writel(regval, &emif4_base->sdram_time2_shdw); + +	regval = (EMIF4_TIM3_T_RAS_MAX | EMIF4_TIM3_T_RFC); +	writel(regval, &emif4_base->sdram_time3); +	writel(regval, &emif4_base->sdram_time3_shdw); + +	/* Set the PWR control register */ +	regval = (EMIF4_PWR_PM_TIM | EMIF4_PWR_LP_MODE | +		EMIF4_PWR_DPD_DIS | EMIF4_PWR_IDLE_MODE); +	writel(regval, &emif4_base->sdram_pwr_mgmt); +	writel(regval, &emif4_base->sdram_pwr_mgmt_shdw); + +	/* Set the DDR refresh rate control register */ +	regval = (EMIF4_REFRESH_RATE | EMIF4_INITREF_DIS); +	writel(regval, &emif4_base->sdram_refresh_ctrl); +	writel(regval, &emif4_base->sdram_refresh_ctrl_shdw); + +	/* set the SDRAM configuration register */ +	regval = (EMIF4_CFG_PGSIZE | EMIF4_CFG_EBANK | +		EMIF4_CFG_IBANK | EMIF4_CFG_ROWSIZE | +		EMIF4_CFG_CL | EMIF4_CFG_NARROW_MD | +		EMIF4_CFG_SDR_DRV | EMIF4_CFG_DDR_DIS_DLL | +		EMIF4_CFG_DDR2_DDQS | EMIF4_CFG_DDR_TERM | +		EMIF4_CFG_IBANK_POS | EMIF4_CFG_SDRAM_TYP); +	writel(regval, &emif4_base->sdram_config); +} + +/* + * dram_init - + *  - Sets uboots idea of sdram size + */ +int dram_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	unsigned int size0 = 0, size1 = 0; + +	size0 = get_sdr_cs_size(CS0); +	/* +	 * If a second bank of DDR is attached to CS1 this is +	 * where it can be started.  Early init code will init +	 * memory on CS0. +	 */ +	if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) +		size1 = get_sdr_cs_size(CS1); + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = size0; +	gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); +	gd->bd->bi_dram[1].size = size1; + +	return 0; +} + +/* + * mem_init() - + *  - Initialize memory subsystem + */ +void mem_init(void) +{ +	do_emif4_init(); +} diff --git a/arch/arm/cpu/arm_cortexa8/omap3/mem.c b/arch/arm/cpu/arm_cortexa8/omap3/mem.c index dfb7e4c2a..bd914b0ee 100644 --- a/arch/arm/cpu/arm_cortexa8/omap3/mem.c +++ b/arch/arm/cpu/arm_cortexa8/omap3/mem.c @@ -79,26 +79,6 @@ static const u32 gpmc_onenand[GPMC_MAX_REG] = {  #endif -static struct sdrc *sdrc_base = (struct sdrc *)OMAP34XX_SDRC_BASE; - -/************************************************************************** - * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow - *  command line mem=xyz use all memory with out discontinuous support - *  compiled in.  Could do it at the ATAG, but there really is two banks... - * Called as part of 2nd phase DDR init. - **************************************************************************/ -void make_cs1_contiguous(void) -{ -	u32 size, a_add_low, a_add_high; - -	size = get_sdr_cs_size(CS0); -	size >>= 25;	/* divide by 32 MiB to find size to offset CS1 */ -	a_add_high = (size & 3) << 8;	/* set up low field */ -	a_add_low = (size & 0x3C) >> 2;	/* set up high field */ -	writel((a_add_high | a_add_low), &sdrc_base->cs_cfg); - -} -  /********************************************************   *  mem_ok() - test used to see if timings are correct   *             for a part. Helps in guessing which part @@ -123,76 +103,6 @@ u32 mem_ok(u32 cs)  		return 1;  } -/******************************************************** - *  sdrc_init() - init the sdrc chip selects CS0 and CS1 - *  - early init routines, called from flash or - *  SRAM. - *******************************************************/ -void sdrc_init(void) -{ -	/* only init up first bank here */ -	do_sdrc_init(CS0, EARLY_INIT); -} - -/************************************************************************* - * do_sdrc_init(): initialize the SDRAM for use. - *  -code sets up SDRAM basic SDRC timings for CS0 - *  -optimal settings can be placed here, or redone after i2c - *      inspection of board info - * - *  - code called once in C-Stack only context for CS0 and a possible 2nd - *      time depending on memory configuration from stack+global context - **************************************************************************/ - -void do_sdrc_init(u32 cs, u32 early) -{ -	struct sdrc_actim *sdrc_actim_base; - -	if(cs) -		sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE; -	else -		sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE; - -	if (early) { -		/* reset sdrc controller */ -		writel(SOFTRESET, &sdrc_base->sysconfig); -		wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status, -			      12000000); -		writel(0, &sdrc_base->sysconfig); - -		/* setup sdrc to ball mux */ -		writel(SDRC_SHARING, &sdrc_base->sharing); - -		/* Disable Power Down of CKE cuz of 1 CKE on combo part */ -		writel(WAKEUPPROC | PWDNEN | SRFRONRESET | PAGEPOLICY_HIGH, -				&sdrc_base->power); - -		writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); -		sdelay(0x20000); -	} - -	writel(RASWIDTH_13BITS | CASWIDTH_10BITS | ADDRMUXLEGACY | -		RAMSIZE_128 | BANKALLOCATION | B32NOT16 | B32NOT16 | -		DEEPPD | DDR_SDRAM, &sdrc_base->cs[cs].mcfg); -	writel(ARCV | ARE_ARCV_1, &sdrc_base->cs[cs].rfr_ctrl); -	writel(V_ACTIMA_165, &sdrc_actim_base->ctrla); -	writel(V_ACTIMB_165, &sdrc_actim_base->ctrlb); - -	writel(CMD_NOP, &sdrc_base ->cs[cs].manual); -	writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual); -	writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); -	writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); - -	/* -	 * CAS latency 3, Write Burst = Read Burst, Serial Mode, -	 * Burst length = 4 -	 */ -	writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); - -	if (!mem_ok(cs)) -		writel(0, &sdrc_base->cs[cs].mcfg); -} -  void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,  			u32 size)  { diff --git a/arch/arm/cpu/arm_cortexa8/omap3/sdrc.c b/arch/arm/cpu/arm_cortexa8/omap3/sdrc.c new file mode 100644 index 000000000..96fd990c7 --- /dev/null +++ b/arch/arm/cpu/arm_cortexa8/omap3/sdrc.c @@ -0,0 +1,202 @@ +/* + * Functions related to OMAP3 SDRC. + * + * This file has been created after exctracting and consolidating + * the SDRC related content from mem.c and board.c, also created + * generic init function (mem_init). + * + * Copyright (C) 2004-2010 + * Texas Instruments Incorporated - http://www.ti.com/ + * + * Author : + *     Vaibhav Hiremath <hvaibhav@ti.com> + * + * Original implementation by (mem.c, board.c) : + *      Sunil Kumar <sunilsaini05@gmail.com> + *      Shashi Ranjan <shashiranjanmca05@gmail.com> + *      Manikandan Pillai <mani.pillai@ti.com> + * + * 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/mem.h> +#include <asm/arch/sys_proto.h> + +extern omap3_sysinfo sysinfo; + +static struct sdrc *sdrc_base = (struct sdrc *)OMAP34XX_SDRC_BASE; + +/* + * is_mem_sdr - + *  - Return 1 if mem type in use is SDR + */ +u32 is_mem_sdr(void) +{ +	if (readl(&sdrc_base->cs[CS0].mr) == SDRC_MR_0_SDR) +		return 1; +	return 0; +} + +/* + * make_cs1_contiguous - + *  - For es2 and above remap cs1 behind cs0 to allow command line + *    mem=xyz use all memory with out discontinuous support compiled in. + *    Could do it at the ATAG, but there really is two banks... + *  - Called as part of 2nd phase DDR init. + */ +void make_cs1_contiguous(void) +{ +	u32 size, a_add_low, a_add_high; + +	size = get_sdr_cs_size(CS0); +	size >>= 25;	/* divide by 32 MiB to find size to offset CS1 */ +	a_add_high = (size & 3) << 8;	/* set up low field */ +	a_add_low = (size & 0x3C) >> 2;	/* set up high field */ +	writel((a_add_high | a_add_low), &sdrc_base->cs_cfg); + +} + + +/* + * get_sdr_cs_size - + *  - Get size of chip select 0/1 + */ +u32 get_sdr_cs_size(u32 cs) +{ +	u32 size; + +	/* get ram size field */ +	size = readl(&sdrc_base->cs[cs].mcfg) >> 8; +	size &= 0x3FF;		/* remove unwanted bits */ +	size <<= 21;		/* multiply by 2 MiB to find size in MB */ +	return size; +} + +/* + * get_sdr_cs_offset - + *  - Get offset of cs from cs0 start + */ +u32 get_sdr_cs_offset(u32 cs) +{ +	u32 offset; + +	if (!cs) +		return 0; + +	offset = readl(&sdrc_base->cs_cfg); +	offset = (offset & 15) << 27 | (offset & 0x30) >> 17; + +	return offset; +} + +/* + * do_sdrc_init - + *  - Initialize the SDRAM for use. + *  - Sets up SDRC timings for CS0 + *  - code called once in C-Stack only context for CS0 and a possible 2nd + *    time depending on memory configuration from stack+global context + */ +void do_sdrc_init(u32 cs, u32 early) +{ +	struct sdrc_actim *sdrc_actim_base; + +	if (cs) +		sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE; +	else +		sdrc_actim_base = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE; + +	if (early) { +		/* reset sdrc controller */ +		writel(SOFTRESET, &sdrc_base->sysconfig); +		wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status, +				12000000); +		writel(0, &sdrc_base->sysconfig); + +		/* setup sdrc to ball mux */ +		writel(SDRC_SHARING, &sdrc_base->sharing); + +		/* Disable Power Down of CKE cuz of 1 CKE on combo part */ +		writel(WAKEUPPROC | SRFRONRESET | PAGEPOLICY_HIGH, +				&sdrc_base->power); + +		writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); +		sdelay(0x20000); +	} + +	writel(RASWIDTH_13BITS | CASWIDTH_10BITS | ADDRMUXLEGACY | +			RAMSIZE_128 | BANKALLOCATION | B32NOT16 | B32NOT16 | +			DEEPPD | DDR_SDRAM, &sdrc_base->cs[cs].mcfg); +	writel(ARCV | ARE_ARCV_1, &sdrc_base->cs[cs].rfr_ctrl); +	writel(V_ACTIMA_165, &sdrc_actim_base->ctrla); +	writel(V_ACTIMB_165, &sdrc_actim_base->ctrlb); + +	writel(CMD_NOP, &sdrc_base->cs[cs].manual); +	writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual); +	writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); +	writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); + +	/* +	 * CAS latency 3, Write Burst = Read Burst, Serial Mode, +	 * Burst length = 4 +	 */ +	writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); + +	if (!mem_ok(cs)) +		writel(0, &sdrc_base->cs[cs].mcfg); +} + +/* + * dram_init - + *  - Sets uboots idea of sdram size + */ +int dram_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	unsigned int size0 = 0, size1 = 0; + +	size0 = get_sdr_cs_size(CS0); +	/* +	 * If a second bank of DDR is attached to CS1 this is +	 * where it can be started.  Early init code will init +	 * memory on CS0. +	 */ +	if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) { +		do_sdrc_init(CS1, NOT_EARLY); +		make_cs1_contiguous(); + +		size1 = get_sdr_cs_size(CS1); +	} + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = size0; +	gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); +	gd->bd->bi_dram[1].size = size1; + +	return 0; +} + +/* + * mem_init - + *  - Init the sdrc chip, + *  - Selects CS0 and CS1, + */ +void mem_init(void) +{ +	/* only init up first bank here */ +	do_sdrc_init(CS0, EARLY_INIT); +} diff --git a/arch/arm/cpu/arm_cortexa8/omap3/sys_info.c b/arch/arm/cpu/arm_cortexa8/omap3/sys_info.c index 08fb32eaa..1df4401d4 100644 --- a/arch/arm/cpu/arm_cortexa8/omap3/sys_info.c +++ b/arch/arm/cpu/arm_cortexa8/omap3/sys_info.c @@ -32,7 +32,6 @@  #include <i2c.h>  extern omap3_sysinfo sysinfo; -static struct sdrc *sdrc_base = (struct sdrc *)OMAP34XX_SDRC_BASE;  static struct ctrl *ctrl_base = (struct ctrl *)OMAP34XX_CTRL_BASE;  static char *rev_s[CPU_3XX_MAX_REV] = {  				"1.0", @@ -104,46 +103,6 @@ u32 get_cpu_rev(void)  	}  } -/**************************************************** - * is_mem_sdr() - return 1 if mem type in use is SDR - ****************************************************/ -u32 is_mem_sdr(void) -{ -	if (readl(&sdrc_base->cs[CS0].mr) == SDRC_MR_0_SDR) -		return 1; -	return 0; -} - -/*********************************************************************** - * get_cs0_size() - get size of chip select 0/1 - ************************************************************************/ -u32 get_sdr_cs_size(u32 cs) -{ -	u32 size; - -	/* get ram size field */ -	size = readl(&sdrc_base->cs[cs].mcfg) >> 8; -	size &= 0x3FF;		/* remove unwanted bits */ -	size <<= 21;		/* multiply by 2 MiB to find size in MB */ -	return size; -} - -/*********************************************************************** - * get_sdr_cs_offset() - get offset of cs from cs0 start - ************************************************************************/ -u32 get_sdr_cs_offset(u32 cs) -{ -	u32 offset; - -	if (!cs) -		return 0; - -	offset = readl(&sdrc_base->cs_cfg); -	offset = (offset & 15) << 27 | (offset & 0x30) >> 17; - -	return offset; -} -  /***************************************************************************   *  get_gpmc0_base() - Return current address hardware will be   *     fetching from. The below effectively gives what is correct, its a bit |