diff options
Diffstat (limited to 'roms/u-boot/arch/arm/cpu/arm926ejs/mx27')
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile | 7 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c | 379 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c | 41 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c | 162 | 
4 files changed, 589 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile new file mode 100644 index 00000000..4976bbb8 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ + +obj-y	= generic.o reset.o timer.o diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c new file mode 100644 index 00000000..5ee9f07d --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c @@ -0,0 +1,379 @@ +/* + *  Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> + *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio.h> +#ifdef CONFIG_MXC_MMC +#include <asm/arch/mxcmmc.h> +#endif + +/* + *  get the system pll clock in Hz + * + *                  mfi + mfn / (mfd +1) + *  f = 2 * f_ref * -------------------- + *                        pd + 1 + */ +static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) +{ +	unsigned int mfi = (pll >> 10) & 0xf; +	unsigned int mfn = pll & 0x3ff; +	unsigned int mfd = (pll >> 16) & 0x3ff; +	unsigned int pd =  (pll >> 26) & 0xf; + +	mfi = mfi <= 5 ? 5 : mfi; + +	return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn), +			(mfd + 1) * (pd + 1)); +} + +static ulong clk_in_32k(void) +{ +	return 1024 * CONFIG_MX27_CLK32; +} + +static ulong clk_in_26m(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) { +		/* divide by 1.5 */ +		return 26000000 * 2 / 3; +	} else { +		return 26000000; +	} +} + +static ulong imx_get_mpllclk(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; +	ulong cscr = readl(&pll->cscr); +	ulong fref; + +	if (cscr & CSCR_MCU_SEL) +		fref = clk_in_26m(); +	else +		fref = clk_in_32k(); + +	return imx_decode_pll(readl(&pll->mpctl0), fref); +} + +static ulong imx_get_armclk(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; +	ulong cscr = readl(&pll->cscr); +	ulong fref = imx_get_mpllclk(); +	ulong div; + +	if (!(cscr & CSCR_ARM_SRC_MPLL)) +		fref = lldiv((fref * 2), 3); + +	div = ((cscr >> 12) & 0x3) + 1; + +	return lldiv(fref, div); +} + +static ulong imx_get_ahbclk(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; +	ulong cscr = readl(&pll->cscr); +	ulong fref = imx_get_mpllclk(); +	ulong div; + +	div = ((cscr >> 8) & 0x3) + 1; + +	return lldiv(fref * 2, 3 * div); +} + +static __attribute__((unused)) ulong imx_get_spllclk(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; +	ulong cscr = readl(&pll->cscr); +	ulong fref; + +	if (cscr & CSCR_SP_SEL) +		fref = clk_in_26m(); +	else +		fref = clk_in_32k(); + +	return imx_decode_pll(readl(&pll->spctl0), fref); +} + +static ulong imx_decode_perclk(ulong div) +{ +	return lldiv((imx_get_mpllclk() * 2), (div * 3)); +} + +static ulong imx_get_perclk1(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1); +} + +static ulong imx_get_perclk2(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk3(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk4(void) +{ +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ +	switch (clk) { +	case MXC_ARM_CLK: +		return imx_get_armclk(); +	case MXC_I2C_CLK: +		return imx_get_ahbclk()/2; +	case MXC_UART_CLK: +		return imx_get_perclk1(); +	case MXC_FEC_CLK: +		return imx_get_ahbclk(); +	case MXC_ESDHC_CLK: +		return imx_get_perclk2(); +	} +	return -1; +} + + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo (void) +{ +	char buf[32]; + +	printf("CPU:   Freescale i.MX27 at %s MHz\n\n", +			strmhz(buf, imx_get_mpllclk())); +	return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ +#if defined(CONFIG_FEC_MXC) +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	/* enable FEC clock */ +	writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); +	writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); +	return fecmxc_initialize(bis); +#else +	return 0; +#endif +} + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_MXC_MMC +	return mxc_mmc_init(bis); +#else +	return 0; +#endif +} + +void imx_gpio_mode(int gpio_mode) +{ +	struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; +	unsigned int pin = gpio_mode & GPIO_PIN_MASK; +	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; +	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; +	unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; +	unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; +	unsigned int tmp; + +	/* Pullup enable */ +	if (gpio_mode & GPIO_PUEN) { +		writel(readl(®s->port[port].puen) | (1 << pin), +				®s->port[port].puen); +	} else { +		writel(readl(®s->port[port].puen) & ~(1 << pin), +				®s->port[port].puen); +	} + +	/* Data direction */ +	if (gpio_mode & GPIO_OUT) { +		writel(readl(®s->port[port].gpio_dir) | 1 << pin, +				®s->port[port].gpio_dir); +	} else { +		writel(readl(®s->port[port].gpio_dir) & ~(1 << pin), +				®s->port[port].gpio_dir); +	} + +	/* Primary / alternate function */ +	if (gpio_mode & GPIO_AF) { +		writel(readl(®s->port[port].gpr) | (1 << pin), +				®s->port[port].gpr); +	} else { +		writel(readl(®s->port[port].gpr) & ~(1 << pin), +				®s->port[port].gpr); +	} + +	/* use as gpio? */ +	if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { +		writel(readl(®s->port[port].gius) | (1 << pin), +				®s->port[port].gius); +	} else { +		writel(readl(®s->port[port].gius) & ~(1 << pin), +				®s->port[port].gius); +	} + +	/* Output / input configuration */ +	if (pin < 16) { +		tmp = readl(®s->port[port].ocr1); +		tmp &= ~(3 << (pin * 2)); +		tmp |= (ocr << (pin * 2)); +		writel(tmp, ®s->port[port].ocr1); + +		writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), +				®s->port[port].iconfa1); +		writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), +				®s->port[port].iconfa1); +		writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), +				®s->port[port].iconfb1); +		writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), +				®s->port[port].iconfb1); +	} else { +		pin -= 16; + +		tmp = readl(®s->port[port].ocr2); +		tmp &= ~(3 << (pin * 2)); +		tmp |= (ocr << (pin * 2)); +		writel(tmp, ®s->port[port].ocr2); + +		writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), +				®s->port[port].iconfa2); +		writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), +				®s->port[port].iconfa2); +		writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), +				®s->port[port].iconfb2); +		writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), +				®s->port[port].iconfb2); +	} +} + +#ifdef CONFIG_MXC_UART +void mx27_uart1_init_pins(void) +{ +	int i; +	unsigned int mode[] = { +		PE12_PF_UART1_TXD, +		PE13_PF_UART1_RXD, +	}; + +	for (i = 0; i < ARRAY_SIZE(mode); i++) +		imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MXC_UART */ + +#ifdef CONFIG_FEC_MXC +void mx27_fec_init_pins(void) +{ +	int i; +	unsigned int mode[] = { +		PD0_AIN_FEC_TXD0, +		PD1_AIN_FEC_TXD1, +		PD2_AIN_FEC_TXD2, +		PD3_AIN_FEC_TXD3, +		PD4_AOUT_FEC_RX_ER, +		PD5_AOUT_FEC_RXD1, +		PD6_AOUT_FEC_RXD2, +		PD7_AOUT_FEC_RXD3, +		PD8_AF_FEC_MDIO, +		PD9_AIN_FEC_MDC | GPIO_PUEN, +		PD10_AOUT_FEC_CRS, +		PD11_AOUT_FEC_TX_CLK, +		PD12_AOUT_FEC_RXD0, +		PD13_AOUT_FEC_RX_DV, +		PD14_AOUT_FEC_CLR, +		PD15_AOUT_FEC_COL, +		PD16_AIN_FEC_TX_ER, +		PF23_AIN_FEC_TX_EN, +	}; + +	for (i = 0; i < ARRAY_SIZE(mode); i++) +		imx_gpio_mode(mode[i]); +} + +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ +	int i; +	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; +	struct fuse_bank *bank = &iim->bank[0]; +	struct fuse_bank0_regs *fuse = +			(struct fuse_bank0_regs *)bank->fuse_regs; + +	for (i = 0; i < 6; i++) +		mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif /* CONFIG_FEC_MXC */ + +#ifdef CONFIG_MXC_MMC +void mx27_sd1_init_pins(void) +{ +	int i; +	unsigned int mode[] = { +		PE18_PF_SD1_D0, +		PE19_PF_SD1_D1, +		PE20_PF_SD1_D2, +		PE21_PF_SD1_D3, +		PE22_PF_SD1_CMD, +		PE23_PF_SD1_CLK, +	}; + +	for (i = 0; i < ARRAY_SIZE(mode); i++) +		imx_gpio_mode(mode[i]); + +} + +void mx27_sd2_init_pins(void) +{ +	int i; +	unsigned int mode[] = { +		PB4_PF_SD2_D0, +		PB5_PF_SD2_D1, +		PB6_PF_SD2_D2, +		PB7_PF_SD2_D3, +		PB8_PF_SD2_CMD, +		PB9_PF_SD2_CLK, +	}; + +	for (i = 0; i < ARRAY_SIZE(mode); i++) +		imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MXC_MMC */ + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ +	/* Enable D-cache. I-cache is already enabled in start.S */ +	dcache_enable(); +} +#endif /* CONFIG_SYS_DCACHE_OFF */ diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c new file mode 100644 index 00000000..f7b4a1c8 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu(ulong ignored) +{ +	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; +	/* Disable watchdog and set Time-Out field to 0 */ +	writel(0x00000000, ®s->wcr); + +	/* Write Service Sequence */ +	writel(0x00005555, ®s->wsr); +	writel(0x0000AAAA, ®s->wsr); + +	/* Enable watchdog */ +	writel(WCR_WDE, ®s->wcr); + +	while (1); +	/*NOTREACHED*/ +} diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c new file mode 100644 index 00000000..40fe2aaf --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* General purpose timers bitfields */ +#define GPTCR_SWR		(1 << 15)	/* Software reset	*/ +#define GPTCR_FRR		(1 << 8)	/* Freerun / restart	*/ +#define GPTCR_CLKSOURCE_32	(4 << 1)	/* Clock source		*/ +#define GPTCR_TEN		1		/* Timer enable		*/ + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp	(gd->arch.tbl) +#define lastinc		(gd->arch.lastinc) + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ +	tick *= CONFIG_SYS_HZ; +	do_div(tick, CONFIG_MX27_CLK32); +	return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ +	time *= CONFIG_MX27_CLK32; +	do_div(time, CONFIG_SYS_HZ); +	return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ +	us = us * CONFIG_MX27_CLK32 + 999999; +	do_div(us, 1000000); +	return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME	((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \ +		CONFIG_SYS_HZ) +#define US_PER_TICK	(1000000 / CONFIG_MX27_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ +	do_div(tick, TICK_PER_TIME); +	return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ +	return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ +	us += US_PER_TICK - 1; +	do_div(us, US_PER_TICK); +	return us; +} +#endif + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ +int timer_init(void) +{ +	int i; +	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; +	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + +	/* setup GP Timer 1 */ +	writel(GPTCR_SWR, ®s->gpt_tctl); + +	writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0); +	writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1); + +	for (i = 0; i < 100; i++) +		writel(0, ®s->gpt_tctl); /* We have no udelay by now */ +	writel(0, ®s->gpt_tprer); /* 32Khz */ +	/* Freerun Mode, PERCLK1 input */ +	writel(readl(®s->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, +			®s->gpt_tctl); +	writel(readl(®s->gpt_tctl) | GPTCR_TEN, ®s->gpt_tctl); + +	return 0; +} + +unsigned long long get_ticks(void) +{ +	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; +	ulong now = readl(®s->gpt_tcn); /* current tick value */ + +	if (now >= lastinc) { +		/* +		 * normal mode (non roll) +		 * move stamp forward with absolut diff ticks +		 */ +		timestamp += (now - lastinc); +	} else { +		/* we have rollover of incrementer */ +		timestamp += (0xFFFFFFFF - lastinc) + now; +	} +	lastinc = now; +	return timestamp; +} + +ulong get_timer_masked(void) +{ +	/* +	 * get_ticks() returns a long long (64 bit), it wraps in +	 * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ +	 * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in +	 * 5 * 10^6 days - long enough. +	 */ +	return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ +	return get_timer_masked() - base; +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ +	unsigned long long tmp; +	ulong tmo; + +	tmo = us_to_tick(usec); +	tmp = get_ticks() + tmo;	/* get current timestamp */ + +	while (get_ticks() < tmp)	/* loop till event */ +		 /*NOP*/; +} + +ulong get_tbclk(void) +{ +	return CONFIG_MX27_CLK32; +}  | 
