avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
13
u-boot/arch/arm/mach-at91/arm920t/Makefile
Normal file
13
u-boot/arch/arm/mach-at91/arm920t/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += lowlevel_init.o
|
||||
obj-y += reset.o
|
||||
obj-y += timer.o
|
||||
obj-y += clock.o
|
||||
obj-y += cpu.o
|
||||
obj-y += at91rm9200_devices.o
|
||||
61
u-boot/arch/arm/mach-at91/arm920t/at91rm9200_devices.c
Normal file
61
u-boot/arch/arm/mach-at91/arm920t/at91rm9200_devices.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* [partely copied from arch/arm/cpu/arm926ejs/at91/arm9260_devices.c]
|
||||
*
|
||||
* (C) Copyright 2011
|
||||
* Andreas Bießmann <andreas@biessmann.org>
|
||||
*
|
||||
* (C) Copyright 2007-2008
|
||||
* Stelian Pop <stelian@popies.net>
|
||||
* Lead Tech Design <www.leadtechdesign.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/at91_common.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
|
||||
/*
|
||||
* if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
|
||||
* peripheral pins. Good to have if hardware is soldered optionally
|
||||
* or in case of SPI no slave is selected. Avoid lines to float
|
||||
* needlessly. Use a short local PUP define.
|
||||
*
|
||||
* Due to errata "TXD floats when CTS is inactive" pullups are always
|
||||
* on for TXD pins.
|
||||
*/
|
||||
#ifdef CONFIG_AT91_GPIO_PULLUP
|
||||
# define PUP CONFIG_AT91_GPIO_PULLUP
|
||||
#else
|
||||
# define PUP 0
|
||||
#endif
|
||||
|
||||
void at91_serial0_hw_init(void)
|
||||
{
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 17, 1); /* TXD0 */
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 18, PUP); /* RXD0 */
|
||||
at91_periph_clk_enable(ATMEL_ID_USART0);
|
||||
}
|
||||
|
||||
void at91_serial1_hw_init(void)
|
||||
{
|
||||
at91_set_a_periph(AT91_PIO_PORTB, 20, PUP); /* RXD1 */
|
||||
at91_set_a_periph(AT91_PIO_PORTB, 21, 1); /* TXD1 */
|
||||
at91_periph_clk_enable(ATMEL_ID_USART1);
|
||||
}
|
||||
|
||||
void at91_serial2_hw_init(void)
|
||||
{
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 22, PUP); /* RXD2 */
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 23, 1); /* TXD2 */
|
||||
at91_periph_clk_enable(ATMEL_ID_USART2);
|
||||
}
|
||||
|
||||
void at91_seriald_hw_init(void)
|
||||
{
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 30, PUP); /* DRXD */
|
||||
at91_set_a_periph(AT91_PIO_PORTA, 31, 1); /* DTXD */
|
||||
/* writing SYS to PCER has no effect on AT91RM9200 */
|
||||
}
|
||||
195
u-boot/arch/arm/mach-at91/arm920t/clock.c
Normal file
195
u-boot/arch/arm/mach-at91/arm920t/clock.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
|
||||
*
|
||||
* Copyright (C) 2011 Andreas Bießmann
|
||||
* Copyright (C) 2005 David Brownell
|
||||
* Copyright (C) 2005 Ivan Kokshaysky
|
||||
* Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#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
|
||||
|
||||
#define EN_PLLB_TIMEOUT 500
|
||||
|
||||
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;
|
||||
case AT91_PMC_MCKR_CSS_PLLB:
|
||||
return gd->arch.pllb_rate_hz;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_ATMEL
|
||||
static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
|
||||
{
|
||||
unsigned i, div = 0, mul = 0, diff = 1 << 30;
|
||||
unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
|
||||
|
||||
/* PLL output max 240 MHz (or 180 MHz per errata) */
|
||||
if (out_freq > 240000000)
|
||||
goto fail;
|
||||
|
||||
for (i = 1; i < 256; i++) {
|
||||
int diff1;
|
||||
unsigned input, mul1;
|
||||
|
||||
/*
|
||||
* PLL input between 1MHz and 32MHz per spec, but lower
|
||||
* frequences seem necessary in some cases so allow 100K.
|
||||
* Warning: some newer products need 2MHz min.
|
||||
*/
|
||||
input = main_freq / i;
|
||||
if (input < 100000)
|
||||
continue;
|
||||
if (input > 32000000)
|
||||
continue;
|
||||
|
||||
mul1 = out_freq / input;
|
||||
if (mul1 > 2048)
|
||||
continue;
|
||||
if (mul1 < 2)
|
||||
goto fail;
|
||||
|
||||
diff1 = out_freq - input * mul1;
|
||||
if (diff1 < 0)
|
||||
diff1 = -diff1;
|
||||
if (diff > diff1) {
|
||||
diff = diff1;
|
||||
div = i;
|
||||
mul = mul1;
|
||||
if (diff == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 256 && diff > (out_freq >> 5))
|
||||
goto fail;
|
||||
return ret | ((mul - 1) << 16) | div;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 at91_pll_rate(u32 freq, u32 reg)
|
||||
{
|
||||
unsigned mul, div;
|
||||
|
||||
div = reg & 0xff;
|
||||
mul = (reg >> 16) & 0x7ff;
|
||||
if (div && mul) {
|
||||
freq /= div;
|
||||
freq *= mul + 1;
|
||||
} else
|
||||
freq = 0;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
int at91_clock_init(unsigned long main_clock)
|
||||
{
|
||||
unsigned freq, mckr;
|
||||
at91_pmc_t *pmc = (at91_pmc_t *) 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));
|
||||
|
||||
#ifdef CONFIG_USB_ATMEL
|
||||
/*
|
||||
* USB clock init: choose 48 MHz PLLB value,
|
||||
* disable 48MHz clock during usb peripheral suspend.
|
||||
*
|
||||
* REVISIT: assumes MCK doesn't derive from PLLB!
|
||||
*/
|
||||
gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
|
||||
AT91_PMC_PLLBR_USBDIV_2;
|
||||
gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
|
||||
gd->arch.at91_pllb_usb_init);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MCK and CPU derive from one of those primary clocks.
|
||||
* For now, assume this parentage won't change.
|
||||
*/
|
||||
mckr = readl(&pmc->mckr);
|
||||
gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
|
||||
freq = gd->arch.mck_rate_hz;
|
||||
|
||||
freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
|
||||
/* mdiv */
|
||||
gd->arch.mck_rate_hz = freq /
|
||||
(1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
gd->arch.cpu_clk_rate_hz = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int at91_pllb_clk_enable(u32 pllbr)
|
||||
{
|
||||
struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
|
||||
ulong start_time, tmp_time;
|
||||
|
||||
start_time = get_timer(0);
|
||||
writel(pllbr, &pmc->pllbr);
|
||||
while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) {
|
||||
tmp_time = get_timer(0);
|
||||
if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
|
||||
printf("ERROR: failed to enable PLLB\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int at91_pllb_clk_disable(void)
|
||||
{
|
||||
struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
|
||||
ulong start_time, tmp_time;
|
||||
|
||||
start_time = get_timer(0);
|
||||
writel(0, &pmc->pllbr);
|
||||
while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) {
|
||||
tmp_time = get_timer(0);
|
||||
if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
|
||||
printf("ERROR: failed to disable PLLB\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
u-boot/arch/arm/mach-at91/arm920t/cpu.c
Normal file
26
u-boot/arch/arm/mach-at91/arm920t/cpu.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* [origin: arch/arm/cpu/arm926ejs/at91/cpu.c]
|
||||
*
|
||||
* (C) Copyright 2011
|
||||
* Andreas Bießmann, andreas@biessmann.org
|
||||
* (C) Copyright 2010
|
||||
* Reinhard Meyer, reinhard.meyer@emk-elektronik.de
|
||||
* (C) Copyright 2009
|
||||
* Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.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);
|
||||
}
|
||||
152
u-boot/arch/arm/mach-at91/arm920t/lowlevel_init.S
Normal file
152
u-boot/arch/arm/mach-at91/arm920t/lowlevel_init.S
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
|
||||
* Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
|
||||
*
|
||||
* Modified for the at91rm9200dk board by
|
||||
* (C) Copyright 2004
|
||||
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/at91_mc.h>
|
||||
#include <asm/arch/at91_pmc.h>
|
||||
#include <asm/arch/at91_pio.h>
|
||||
|
||||
#define ARM920T_CONTROL 0xC0000000 /* @ set bit 31 (iA) and 30 (nF) */
|
||||
|
||||
_MTEXT_BASE:
|
||||
#undef START_FROM_MEM
|
||||
#ifdef START_FROM_MEM
|
||||
.word CONFIG_SYS_TEXT_BASE-PHYS_FLASH_1
|
||||
#else
|
||||
.word CONFIG_SYS_TEXT_BASE
|
||||
#endif
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
ldr r1, =AT91_ASM_PMC_MOR
|
||||
/* Main oscillator Enable register */
|
||||
#ifdef CONFIG_SYS_USE_MAIN_OSCILLATOR
|
||||
ldr r0, =0x0000FF01 /* Enable main oscillator */
|
||||
#else
|
||||
ldr r0, =0x0000FF00 /* Disable main oscillator */
|
||||
#endif
|
||||
str r0, [r1] /*AT91C_CKGR_MOR] */
|
||||
/* Add loop to compensate Main Oscillator startup time */
|
||||
ldr r0, =0x00000010
|
||||
LoopOsc:
|
||||
subs r0, r0, #1
|
||||
bhi LoopOsc
|
||||
|
||||
/* memory control configuration */
|
||||
/* this isn't very elegant, but what the heck */
|
||||
ldr r0, =SMRDATA
|
||||
ldr r1, _MTEXT_BASE
|
||||
sub r0, r0, r1
|
||||
ldr r2, =SMRDATAE
|
||||
sub r2, r2, r1
|
||||
pllloop:
|
||||
/* the address */
|
||||
ldr r1, [r0], #4
|
||||
/* the value */
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1]
|
||||
cmp r2, r0
|
||||
bne pllloop
|
||||
/* delay - this is all done by guess */
|
||||
ldr r0, =0x00010000
|
||||
/* (vs reading PMC_SR for LOCKA, LOCKB ... or MOSCS earlier) */
|
||||
lock:
|
||||
subs r0, r0, #1
|
||||
bhi lock
|
||||
ldr r0, =SMRDATA1
|
||||
ldr r1, _MTEXT_BASE
|
||||
sub r0, r0, r1
|
||||
ldr r2, =SMRDATA1E
|
||||
sub r2, r2, r1
|
||||
sdinit:
|
||||
/* the address */
|
||||
ldr r1, [r0], #4
|
||||
/* the value */
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1]
|
||||
cmp r2, r0
|
||||
bne sdinit
|
||||
|
||||
/* switch from FastBus to Asynchronous clock mode */
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
orr r0, r0, #ARM920T_CONTROL
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/* everything is fine now */
|
||||
mov pc, lr
|
||||
|
||||
.ltorg
|
||||
|
||||
SMRDATA:
|
||||
.word AT91_ASM_MC_EBI_CFG
|
||||
.word CONFIG_SYS_EBI_CFGR_VAL
|
||||
.word AT91_ASM_MC_SMC_CSR0
|
||||
.word CONFIG_SYS_SMC_CSR0_VAL
|
||||
.word AT91_ASM_PMC_PLLAR
|
||||
.word CONFIG_SYS_PLLAR_VAL
|
||||
.word AT91_ASM_PMC_PLLBR
|
||||
.word CONFIG_SYS_PLLBR_VAL
|
||||
.word AT91_ASM_PMC_MCKR
|
||||
.word CONFIG_SYS_MCKR_VAL
|
||||
SMRDATAE:
|
||||
/* here there's a delay */
|
||||
SMRDATA1:
|
||||
.word AT91_ASM_PIOC_ASR
|
||||
.word CONFIG_SYS_PIOC_ASR_VAL
|
||||
.word AT91_ASM_PIOC_BSR
|
||||
.word CONFIG_SYS_PIOC_BSR_VAL
|
||||
.word AT91_ASM_PIOC_PDR
|
||||
.word CONFIG_SYS_PIOC_PDR_VAL
|
||||
.word AT91_ASM_MC_EBI_CSA
|
||||
.word CONFIG_SYS_EBI_CSA_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_CR
|
||||
.word CONFIG_SYS_SDRC_CR_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_MR
|
||||
.word CONFIG_SYS_SDRC_MR_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_MR
|
||||
.word CONFIG_SYS_SDRC_MR_VAL1
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_MR
|
||||
.word CONFIG_SYS_SDRC_MR_VAL2
|
||||
.word CONFIG_SYS_SDRAM1
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_TR
|
||||
.word CONFIG_SYS_SDRC_TR_VAL
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
.word AT91_ASM_MC_SDRAMC_MR
|
||||
.word CONFIG_SYS_SDRC_MR_VAL3
|
||||
.word CONFIG_SYS_SDRAM
|
||||
.word CONFIG_SYS_SDRAM_VAL
|
||||
SMRDATA1E:
|
||||
/* SMRDATA1 is 176 bytes long */
|
||||
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
|
||||
41
u-boot/arch/arm/mach-at91/arm920t/reset.c
Normal file
41
u-boot/arch/arm/mach-at91/arm920t/reset.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Lineo, Inc. <www.lineo.com>
|
||||
* Bernhard Kuhn <bkuhn@lineo.com>
|
||||
*
|
||||
* (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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/at91_st.h>
|
||||
|
||||
void __attribute__((weak)) board_reset(void)
|
||||
{
|
||||
/* true empty function for defining weak symbol */
|
||||
}
|
||||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST;
|
||||
|
||||
board_reset();
|
||||
|
||||
/* Reset the cpu by setting up the watchdog timer */
|
||||
writel(AT91_ST_WDMR_RSTEN | AT91_ST_WDMR_EXTEN | AT91_ST_WDMR_WDV(2),
|
||||
&st->wdmr);
|
||||
writel(AT91_ST_CR_WDRST, &st->cr);
|
||||
/* and let it timeout */
|
||||
while (1)
|
||||
;
|
||||
/* Never reached */
|
||||
}
|
||||
125
u-boot/arch/arm/mach-at91/arm920t/timer.c
Normal file
125
u-boot/arch/arm/mach-at91/arm920t/timer.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Lineo, Inc. <www.lineo.com>
|
||||
* Bernhard Kuhn <bkuhn@lineo.com>
|
||||
*
|
||||
* (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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/at91_tc.h>
|
||||
#include <asm/arch/clk.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* the number of clocks per CONFIG_SYS_HZ */
|
||||
#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK/CONFIG_SYS_HZ)
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC;
|
||||
|
||||
at91_periph_clk_enable(ATMEL_ID_TC0);
|
||||
|
||||
writel(0, &tc->bcr);
|
||||
writel(AT91_TC_BMR_TC0XC0S_NONE | AT91_TC_BMR_TC1XC1S_NONE |
|
||||
AT91_TC_BMR_TC2XC2S_NONE , &tc->bmr);
|
||||
|
||||
writel(AT91_TC_CCR_CLKDIS, &tc->tc[0].ccr);
|
||||
/* set to MCLK/2 and restart the timer
|
||||
when the value in TC_RC is reached */
|
||||
writel(AT91_TC_CMR_TCCLKS_CLOCK1 | AT91_TC_CMR_CPCTRG, &tc->tc[0].cmr);
|
||||
|
||||
writel(0xFFFFFFFF, &tc->tc[0].idr); /* disable interrupts */
|
||||
writel(TIMER_LOAD_VAL, &tc->tc[0].rc);
|
||||
|
||||
writel(AT91_TC_CCR_SWTRG | AT91_TC_CCR_CLKEN, &tc->tc[0].ccr);
|
||||
gd->arch.lastinc = 0;
|
||||
gd->arch.tbl = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer without interrupts
|
||||
*/
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return get_timer_masked() - base;
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
udelay_masked(usec);
|
||||
}
|
||||
|
||||
ulong get_timer_raw(void)
|
||||
{
|
||||
at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC;
|
||||
u32 now;
|
||||
|
||||
now = readl(&tc->tc[0].cv) & 0x0000ffff;
|
||||
|
||||
if (now >= gd->arch.lastinc) {
|
||||
/* normal mode */
|
||||
gd->arch.tbl += now - gd->arch.lastinc;
|
||||
} else {
|
||||
/* we have an overflow ... */
|
||||
gd->arch.tbl += now + TIMER_LOAD_VAL - gd->arch.lastinc;
|
||||
}
|
||||
gd->arch.lastinc = now;
|
||||
|
||||
return gd->arch.tbl;
|
||||
}
|
||||
|
||||
ulong get_timer_masked(void)
|
||||
{
|
||||
return get_timer_raw()/TIMER_LOAD_VAL;
|
||||
}
|
||||
|
||||
void udelay_masked(unsigned long usec)
|
||||
{
|
||||
u32 tmo;
|
||||
u32 endtime;
|
||||
signed long diff;
|
||||
|
||||
tmo = CONFIG_SYS_HZ_CLOCK / 1000;
|
||||
tmo *= usec;
|
||||
tmo /= 1000;
|
||||
|
||||
endtime = get_timer_raw() + tmo;
|
||||
|
||||
do {
|
||||
u32 now = get_timer_raw();
|
||||
diff = endtime - now;
|
||||
} while (diff >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (read timebase as long long).
|
||||
* On ARM it just returns the timer value.
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
return get_timer(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (timebase clock frequency).
|
||||
* On ARM it returns the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return CONFIG_SYS_HZ;
|
||||
}
|
||||
Reference in New Issue
Block a user