diff options
Diffstat (limited to 'arch/arm/cpu/armv7/at91')
| -rw-r--r-- | arch/arm/cpu/armv7/at91/Makefile | 52 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/at91/clock.c | 125 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/at91/cpu.c | 90 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/at91/reset.c | 47 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/at91/sama5d3_devices.c | 196 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/at91/timer.c | 139 | 
6 files changed, 649 insertions, 0 deletions
| diff --git a/arch/arm/cpu/armv7/at91/Makefile b/arch/arm/cpu/armv7/at91/Makefile new file mode 100644 index 000000000..040c67d51 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2013 +# Bo Shen <voice.shen@atmel.com> +# +# 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-$(CONFIG_SAMA5D3)	+= sama5d3_devices.o +COBJS-y += clock.o +COBJS-y += cpu.o +COBJS-y += reset.o +COBJS-y += timer.o + +SRCS    := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS    := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) + +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/at91/clock.c b/arch/arm/cpu/armv7/at91/clock.c new file mode 100644 index 000000000..624b52cc3 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/clock.c @@ -0,0 +1,125 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright (C) 2013 Bo Shen <voice.shen@atmel.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. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long at91_css_to_rate(unsigned long css) +{ +	switch (css) { +	case AT91_PMC_MCKR_CSS_SLOW: +		return CONFIG_SYS_AT91_SLOW_CLOCK; +	case AT91_PMC_MCKR_CSS_MAIN: +		return gd->arch.main_clk_rate_hz; +	case AT91_PMC_MCKR_CSS_PLLA: +		return gd->arch.plla_rate_hz; +	} + +	return 0; +} + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ +	unsigned mul, div; + +	div = reg & 0xff; +	mul = (reg >> 18) & 0x7f; +	if (div && mul) { +		freq /= div; +		freq *= mul + 1; +	} else { +		freq = 0; +	} + +	return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ +	unsigned freq, mckr; +	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK +	unsigned tmp; +	/* +	 * When the bootloader initialized the main oscillator correctly, +	 * there's no problem using the cycle counter.  But if it didn't, +	 * or when using oscillator bypass mode, we must be told the speed +	 * of the main clock. +	 */ +	if (!main_clock) { +		do { +			tmp = readl(&pmc->mcfr); +		} while (!(tmp & AT91_PMC_MCFR_MAINRDY)); +		tmp &= AT91_PMC_MCFR_MAINF_MASK; +		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); +	} +#endif +	gd->arch.main_clk_rate_hz = main_clock; + +	/* report if PLLA is more than mildly overclocked */ +	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + +	/* +	 * MCK and CPU derive from one of those primary clocks. +	 * For now, assume this parentage won't change. +	 */ +	mckr = readl(&pmc->mckr); + +	/* plla divisor by 2 */ +	if (mckr & (1 << 12)) +		gd->arch.plla_rate_hz >>= 1; + +	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); +	freq = gd->arch.mck_rate_hz; + +	/* prescale */ +	freq >>= mckr & AT91_PMC_MCKR_PRES_MASK; + +	switch (mckr & AT91_PMC_MCKR_MDIV_MASK) { +	case AT91_PMC_MCKR_MDIV_2: +		gd->arch.mck_rate_hz = freq / 2; +		break; +	case AT91_PMC_MCKR_MDIV_3: +		gd->arch.mck_rate_hz = freq / 3; +		break; +	case AT91_PMC_MCKR_MDIV_4: +		gd->arch.mck_rate_hz = freq / 4; +		break; +	default: +		break; +	} + +	gd->arch.cpu_clk_rate_hz = freq; + +	return 0; +} + +void at91_periph_clk_enable(int id) +{ +	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + +	if (id > 31) +		writel(1 << (id - 32), &pmc->pcer1); +	else +		writel(1 << id, &pmc->pcer); +} diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c new file mode 100644 index 000000000..3df6143d7 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/cpu.c @@ -0,0 +1,90 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, reinhard.meyer@emk-elektronik.de + * (C) Copyright 2009 + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_dbu.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_gpbr.h> +#include <asm/arch/clk.h> + +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK +#define CONFIG_SYS_AT91_MAIN_CLOCK 0 +#endif + +int arch_cpu_init(void) +{ +	return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); +} + +void arch_preboot_os(void) +{ +	ulong cpiv; +	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + +	cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir)); + +	/* +	 * Disable PITC +	 * Add 0x1000 to current counter to stop it faster +	 * without waiting for wrapping back to 0 +	 */ +	writel(cpiv + 0x1000, &pit->mr); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ +	char buf[32]; + +	printf("CPU: %s\n", get_cpu_name()); +	printf("Crystal frequency: %8s MHz\n", +	       strmhz(buf, get_main_clk_rate())); +	printf("CPU clock        : %8s MHz\n", +	       strmhz(buf, get_cpu_clk_rate())); +	printf("Master clock     : %8s MHz\n", +	       strmhz(buf, get_mck_clk_rate())); + +	return 0; +} +#endif + +void enable_caches(void) +{ +} + +unsigned int get_chip_id(void) +{ +	return readl(ATMEL_BASE_DBGU + AT91_DBU_CIDR) & ~AT91_DBU_CIDR_MASK; +} + +unsigned int get_extension_chip_id(void) +{ +	return readl(ATMEL_BASE_DBGU + AT91_DBU_EXID); +} diff --git a/arch/arm/cpu/armv7/at91/reset.c b/arch/arm/cpu/armv7/at91/reset.c new file mode 100644 index 000000000..b9f83d91b --- /dev/null +++ b/arch/arm/cpu/armv7/at91/reset.c @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_rstc.h> + +/* Reset the cpu by telling the reset controller to do so */ +void reset_cpu(ulong ignored) +{ +	at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC; + +	writel(AT91_RSTC_KEY +		| AT91_RSTC_CR_PROCRST	/* Processor Reset */ +		| AT91_RSTC_CR_PERRST	/* Peripheral Reset */ +#ifdef CONFIG_AT91RESET_EXTRST +		| AT91_RSTC_CR_EXTRST	/* External Reset (assert nRST pin) */ +#endif +		, &rstc->cr); +	/* never reached */ +	do { } while (1); +} diff --git a/arch/arm/cpu/armv7/at91/sama5d3_devices.c b/arch/arm/cpu/armv7/at91/sama5d3_devices.c new file mode 100644 index 000000000..acf8b43ee --- /dev/null +++ b/arch/arm/cpu/armv7/at91/sama5d3_devices.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2012-2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/sama5d3.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> +#include <asm/arch/gpio.h> +#include <asm/io.h> + +unsigned int has_emac() +{ +	return cpu_is_sama5d31() || cpu_is_sama5d35(); +} + +unsigned int has_gmac() +{ +	return !cpu_is_sama5d31(); +} + +unsigned int has_lcdc() +{ +	return !cpu_is_sama5d35(); +} + +char *get_cpu_name() +{ +	unsigned int extension_id = get_extension_chip_id(); + +	if (cpu_is_sama5d3()) +		switch (extension_id) { +		case ARCH_EXID_SAMA5D31: +			return "SAMA5D31"; +		case ARCH_EXID_SAMA5D33: +			return "SAMA5D33"; +		case ARCH_EXID_SAMA5D34: +			return "SAMA5D34"; +		case ARCH_EXID_SAMA5D35: +			return "SAMA5D35"; +		default: +			return "Unknown CPU type"; +		} +	else +		return "Unknown CPU type"; +} + +void at91_serial0_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTD, 18, 1);	/* TXD0 */ +	at91_set_a_periph(AT91_PIO_PORTD, 17, 0);	/* RXD0 */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_USART0); +} + +void at91_serial1_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTB, 29, 1);	/* TXD1 */ +	at91_set_a_periph(AT91_PIO_PORTB, 28, 0);	/* RXD1 */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_USART1); +} + +void at91_serial2_hw_init(void) +{ +	at91_set_b_periph(AT91_PIO_PORTE, 26, 1);	/* TXD2 */ +	at91_set_b_periph(AT91_PIO_PORTE, 25, 0);	/* RXD2 */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_USART2); +} + +void at91_seriald_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTB, 31, 1);	/* DTXD */ +	at91_set_a_periph(AT91_PIO_PORTB, 30, 0);	/* DRXD */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_SYS); +} + +#if defined(CONFIG_ATMEL_SPI) +void at91_spi0_hw_init(unsigned long cs_mask) +{ +	at91_set_a_periph(AT91_PIO_PORTD, 10, 0);       /* SPI0_MISO */ +	at91_set_a_periph(AT91_PIO_PORTD, 11, 0);       /* SPI0_MOSI */ +	at91_set_a_periph(AT91_PIO_PORTD, 12, 0);       /* SPI0_SPCK */ + +	if (cs_mask & (1 << 0)) +		at91_set_pio_output(AT91_PIO_PORTD, 13, 1); +	if (cs_mask & (1 << 1)) +		at91_set_pio_output(AT91_PIO_PORTD, 14, 1); +	if (cs_mask & (1 << 2)) +		at91_set_pio_output(AT91_PIO_PORTD, 15, 1); +	if (cs_mask & (1 << 3)) +		at91_set_pio_output(AT91_PIO_PORTD, 16, 1); + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_SPI0); +} +#endif + +#ifdef CONFIG_GENERIC_ATMEL_MCI +void at91_mci_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTD, 0, 0);	/* MCI0 CMD */ +	at91_set_a_periph(AT91_PIO_PORTD, 1, 0);	/* MCI0 DA0 */ +	at91_set_a_periph(AT91_PIO_PORTD, 2, 0);	/* MCI0 DA1 */ +	at91_set_a_periph(AT91_PIO_PORTD, 3, 0);        /* MCI0 DA2 */ +	at91_set_a_periph(AT91_PIO_PORTD, 4, 0);        /* MCI0 DA3 */ +#ifdef CONFIG_ATMEL_MCI_8BIT +	at91_set_a_periph(AT91_PIO_PORTD, 5, 0);        /* MCI0 DA4 */ +	at91_set_a_periph(AT91_PIO_PORTD, 6, 0);        /* MCI0 DA5 */ +	at91_set_a_periph(AT91_PIO_PORTD, 7, 0);        /* MCI0 DA6 */ +	at91_set_a_periph(AT91_PIO_PORTD, 8, 0);        /* MCI0 DA7 */ +#endif +	at91_set_a_periph(AT91_PIO_PORTD, 9, 0);        /* MCI0 CLK */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_MCI0); +} +#endif + +#ifdef CONFIG_MACB +void at91_macb_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTC, 7, 0);	/* ETXCK_EREFCK */ +	at91_set_a_periph(AT91_PIO_PORTC, 5, 0);	/* ERXDV */ +	at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* ERX0 */ +	at91_set_a_periph(AT91_PIO_PORTC, 3, 0);	/* ERX1 */ +	at91_set_a_periph(AT91_PIO_PORTC, 6, 0);	/* ERXER */ +	at91_set_a_periph(AT91_PIO_PORTC, 4, 0);	/* ETXEN */ +	at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* ETX0 */ +	at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* ETX1 */ +	at91_set_a_periph(AT91_PIO_PORTC, 9, 0);	/* EMDIO */ +	at91_set_a_periph(AT91_PIO_PORTC, 8, 0);	/* EMDC */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_EMAC); +} +#endif + +#ifdef CONFIG_LCD +void at91_lcd_hw_init(void) +{ +	at91_set_a_periph(AT91_PIO_PORTA, 24, 0);	/* LCDPWM */ +	at91_set_a_periph(AT91_PIO_PORTA, 25, 0);	/* LCDDISP */ +	at91_set_a_periph(AT91_PIO_PORTA, 26, 0);	/* LCDVSYNC */ +	at91_set_a_periph(AT91_PIO_PORTA, 27, 0);	/* LCDHSYNC */ +	at91_set_a_periph(AT91_PIO_PORTA, 28, 0);	/* LCDDOTCK */ +	at91_set_a_periph(AT91_PIO_PORTA, 29, 0);	/* LCDDEN */ + +	/* The lower 16-bit of LCD only available on Port A */ +	at91_set_a_periph(AT91_PIO_PORTA,  0, 0);	/* LCDD0 */ +	at91_set_a_periph(AT91_PIO_PORTA,  1, 0);	/* LCDD1 */ +	at91_set_a_periph(AT91_PIO_PORTA,  2, 0);	/* LCDD2 */ +	at91_set_a_periph(AT91_PIO_PORTA,  3, 0);	/* LCDD3 */ +	at91_set_a_periph(AT91_PIO_PORTA,  4, 0);	/* LCDD4 */ +	at91_set_a_periph(AT91_PIO_PORTA,  5, 0);	/* LCDD5 */ +	at91_set_a_periph(AT91_PIO_PORTA,  6, 0);	/* LCDD6 */ +	at91_set_a_periph(AT91_PIO_PORTA,  7, 0);	/* LCDD7 */ +	at91_set_a_periph(AT91_PIO_PORTA,  8, 0);	/* LCDD8 */ +	at91_set_a_periph(AT91_PIO_PORTA,  9, 0);	/* LCDD9 */ +	at91_set_a_periph(AT91_PIO_PORTA, 10, 0);	/* LCDD10 */ +	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* LCDD11 */ +	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* LCDD12 */ +	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* LCDD13 */ +	at91_set_a_periph(AT91_PIO_PORTA, 14, 0);	/* LCDD14 */ +	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* LCDD15 */ + +	/* Enable clock */ +	at91_periph_clk_enable(ATMEL_ID_LCDC); +} +#endif diff --git a/arch/arm/cpu/armv7/at91/timer.c b/arch/arm/cpu/armv7/at91/timer.c new file mode 100644 index 000000000..b3a450fb3 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/timer.c @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * (C) Copyright 2013 + * Bo Shen <voice.shen@atmel.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> +#include <div64.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* + * We're using the SAMA5D3x PITC in 32 bit mode, by + * setting the 20 bit counter period to its maximum (0xfffff). + * (See the relevant data sheets to understand that this really works) + * + * We do also mimic the typical powerpc way of incrementing + * two 32 bit registers called tbl and tbu. + * + * Those registers increment at 1/16 the main clock rate. + */ + +#define TIMER_LOAD_VAL	0xfffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ +	tick *= CONFIG_SYS_HZ; +	do_div(tick, gd->arch.timer_rate_hz); + +	return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ +	usec *= gd->arch.timer_rate_hz; +	do_div(usec, 1000000); + +	return usec; +} + +/* + * Use the PITC in full 32 bit incrementing mode + */ +int timer_init(void) +{ +	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + +	/* Enable PITC Clock */ +	at91_periph_clk_enable(ATMEL_ID_SYS); + +	/* Enable PITC */ +	writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr); + +	gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16; +	gd->arch.tbu = 0; +	gd->arch.tbl = 0; + +	return 0; +} + +/* + * Get the current 64 bit timer tick count + */ +unsigned long long get_ticks(void) +{ +	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT; + +	ulong now = readl(&pit->piir); + +	/* increment tbu if tbl has rolled over */ +	if (now < gd->arch.tbl) +		gd->arch.tbu++; +	gd->arch.tbl = now; +	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; +} + +void __udelay(unsigned long usec) +{ +	unsigned long long start; +	ulong tmo; + +	start = get_ticks();		/* get current timestamp */ +	tmo = usec_to_tick(usec);	/* convert usecs to ticks */ +	while ((get_ticks() - start) < tmo) +		;			/* loop till time has passed */ +} + +/* + * get_timer(base) can be used to check for timeouts or + * to measure elasped time relative to an event: + * + * ulong start_time = get_timer(0) sets start_time to the current + * time value. + * get_timer(start_time) returns the time elapsed since then. + * + * The time is used in CONFIG_SYS_HZ units! + */ +ulong get_timer(ulong base) +{ +	return tick_to_time(get_ticks()) - base; +} + +/* + * Return the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ +	return gd->arch.timer_rate_hz; +} |