diff options
Diffstat (limited to 'arch/arm/cpu/ixp')
-rw-r--r-- | arch/arm/cpu/ixp/config.mk | 5 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/cpu.c | 5 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/npe/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/npe/npe.c | 74 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/start.S | 59 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/timer.c | 124 | ||||
-rw-r--r-- | arch/arm/cpu/ixp/u-boot.lds | 8 |
7 files changed, 120 insertions, 156 deletions
diff --git a/arch/arm/cpu/ixp/config.mk b/arch/arm/cpu/ixp/config.mk index deca3f4d55..5868cba38b 100644 --- a/arch/arm/cpu/ixp/config.mk +++ b/arch/arm/cpu/ixp/config.mk @@ -27,6 +27,11 @@ BIG_ENDIAN = y PLATFORM_RELFLAGS += -fno-common -ffixed-r8 -msoft-float -mbig-endian PLATFORM_CPPFLAGS += -mbig-endian -march=armv5te -mtune=strongarm1100 + +# -fdata-sections triggers "section .bss overlaps section .rel.dyn" linker error +PLATFORM_RELFLAGS += -ffunction-sections +LDFLAGS_u-boot += --gc-sections + # ========================================================================= # # Supply options according to compiler version diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c index ce275e5f3c..942845d544 100644 --- a/arch/arm/cpu/ixp/cpu.c +++ b/arch/arm/cpu/ixp/cpu.c @@ -36,8 +36,6 @@ #include <asm/arch/ixp425.h> #include <asm/system.h> -ulong loops_per_jiffy; - static void cache_flush(void); #if defined(CONFIG_DISPLAY_CPUINFO) @@ -51,17 +49,14 @@ int print_cpuinfo (void) puts("CPU: Intel IXP425 at "); switch ((id & 0x000003f0) >> 4) { case 0x1c: - loops_per_jiffy = 887467; speed = 533; break; case 0x1d: - loops_per_jiffy = 666016; speed = 400; break; case 0x1f: - loops_per_jiffy = 442901; speed = 266; break; } diff --git a/arch/arm/cpu/ixp/npe/Makefile b/arch/arm/cpu/ixp/npe/Makefile index c756a1da41..14ab3c7a71 100644 --- a/arch/arm/cpu/ixp/npe/Makefile +++ b/arch/arm/cpu/ixp/npe/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libnpe.o LOCAL_CFLAGS += -I$(TOPDIR)/arch/arm/cpu/ixp/npe/include -DCONFIG_IXP425_COMPONENT_ETHDB -D__linux CFLAGS += $(LOCAL_CFLAGS) +CPPFLAGS += $(LOCAL_CFLAGS) # needed for depend HOSTCFLAGS += $(LOCAL_CFLAGS) COBJS-$(CONFIG_IXP4XX_NPE) := npe.o \ diff --git a/arch/arm/cpu/ixp/npe/npe.c b/arch/arm/cpu/ixp/npe/npe.c index 857bcadc0b..f0e02bf7d9 100644 --- a/arch/arm/cpu/ixp/npe/npe.c +++ b/arch/arm/cpu/ixp/npe/npe.c @@ -359,36 +359,53 @@ static int npe_init(struct eth_device *dev, bd_t * bis) debug("%s: 1\n", __FUNCTION__); - miiphy_read (dev->name, p_npe->phy_no, MII_BMSR, ®_short); - - /* - * Wait if PHY is capable of autonegotiation and autonegotiation is not complete - */ - if ((reg_short & BMSR_ANEGCAPABLE) && !(reg_short & BMSR_ANEGCOMPLETE)) { - puts ("Waiting for PHY auto negotiation to complete"); - i = 0; - while (!(reg_short & BMSR_ANEGCOMPLETE)) { - /* - * Timeout reached ? - */ - if (i > PHY_AUTONEGOTIATE_TIMEOUT) { - puts (" TIMEOUT !\n"); - break; - } +#ifdef CONFIG_MII_NPE0_FIXEDLINK + if (0 == p_npe->eth_id) { + speed = CONFIG_MII_NPE0_SPEED; + duplex = CONFIG_MII_NPE0_FULLDUPLEX ? FULL : HALF; + } else +#endif +#ifdef CONFIG_MII_NPE1_FIXEDLINK + if (1 == p_npe->eth_id) { + speed = CONFIG_MII_NPE1_SPEED; + duplex = CONFIG_MII_NPE1_FULLDUPLEX ? FULL : HALF; + } else +#endif + { + miiphy_read(dev->name, p_npe->phy_no, MII_BMSR, ®_short); + + /* + * Wait if PHY is capable of autonegotiation and + * autonegotiation is not complete + */ + if ((reg_short & BMSR_ANEGCAPABLE) && + !(reg_short & BMSR_ANEGCOMPLETE)) { + puts("Waiting for PHY auto negotiation to complete"); + i = 0; + while (!(reg_short & BMSR_ANEGCOMPLETE)) { + /* + * Timeout reached ? + */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + break; + } - if ((i++ % 1000) == 0) { - putc ('.'); - miiphy_read (dev->name, p_npe->phy_no, MII_BMSR, ®_short); + if ((i++ % 1000) == 0) { + putc('.'); + miiphy_read(dev->name, p_npe->phy_no, + MII_BMSR, ®_short); + } + udelay(1000); /* 1 ms */ } - udelay (1000); /* 1 ms */ + puts(" done\n"); + /* another 500 ms (results in faster booting) */ + udelay(500000); } - puts (" done\n"); - udelay (500000); /* another 500 ms (results in faster booting) */ + speed = miiphy_speed(dev->name, p_npe->phy_no); + duplex = miiphy_duplex(dev->name, p_npe->phy_no); } - speed = miiphy_speed (dev->name, p_npe->phy_no); - duplex = miiphy_duplex (dev->name, p_npe->phy_no); - if (p_npe->print_speed) { p_npe->print_speed = 0; printf ("ENET Speed is %d Mbps - %s duplex connection\n", @@ -621,9 +638,12 @@ int npe_initialize(bd_t * bis) if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X) { switch (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) { case IX_FEATURE_CTRL_SILICON_TYPE_B0: + default: /* newer than B0 */ /* - * If it is B0 Silicon, we only enable port when its corresponding - * Eth Coprocessor is available. + * If it is B0 or newer Silicon, we + * only enable port when its + * corresponding Eth Coprocessor is + * available. */ if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_ENABLED) diff --git a/arch/arm/cpu/ixp/start.S b/arch/arm/cpu/ixp/start.S index 561c1f4795..faa9a8ff99 100644 --- a/arch/arm/cpu/ixp/start.S +++ b/arch/arm/cpu/ixp/start.S @@ -65,7 +65,8 @@ .endm .globl _start -_start: b reset +_start: + ldr pc, _reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort @@ -74,6 +75,7 @@ _start: b reset ldr pc, _irq ldr pc, _fiq +_reset: .word reset _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort @@ -167,12 +169,6 @@ reset: str r1, [r2] /* make sure flash is visible at 0 */ -#if 0 - ldr r2, =IXP425_EXP_CFG0 - ldr r1, [r2] - orr r1, r1, #0x80000000 - str r1, [r2] -#endif mov r1, #CONFIG_SYS_SDR_CONFIG ldr r2, =IXP425_SDR_CONFIG str r1, [r2] @@ -216,19 +212,6 @@ reset: str r1, [r4] DELAY_FOR 0x4000, r0 - /* copy */ - mov r0, #0 - mov r4, r0 - add r2, r0, #CONFIG_SYS_MONITOR_LEN - mov r1, #0x10000000 - mov r5, r1 - - 30: - ldr r3, [r0], #4 - str r3, [r1], #4 - cmp r0, r2 - bne 30b - /* invalidate I & D caches & BTB */ mcr p15, 0, r0, c7, c7, 0 CPWAIT r0 @@ -241,19 +224,12 @@ reset: mcr p15, 0, r0, c7, c10, 4 CPWAIT r0 - /* move flash to 0x50000000 */ + /* remove flash mirror at 0x00000000 */ ldr r2, =IXP425_EXP_CFG0 ldr r1, [r2] bic r1, r1, #0x80000000 str r1, [r2] - nop - nop - nop - nop - nop - nop - /* invalidate I & Data TLB */ mcr p15, 0, r0, c8, c7, 0 CPWAIT r0 @@ -269,7 +245,7 @@ reset: orr r0,r0,#0x13 msr cpsr,r0 -/* Set stackpointer in internal RAM to call board_init_f */ +/* Set initial stackpointer in SDRAM to call board_init_f */ call_board_init_f: ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ @@ -580,28 +556,3 @@ reset_endless: b reset_endless -#ifdef CONFIG_USE_IRQ - -.LC0: .word loops_per_jiffy - -/* - * 0 <= r0 <= 2000 - */ -.globl __udelay -__udelay: - mov r2, #0x6800 - orr r2, r2, #0x00db - mul r0, r2, r0 - ldr r2, .LC0 - ldr r2, [r2] @ max = 0x0fffffff - mov r0, r0, lsr #11 @ max = 0x00003fff - mov r2, r2, lsr #11 @ max = 0x0003ffff - mul r0, r2, r0 @ max = 2^32-1 - movs r0, r0, lsr #6 - -delay_loop: - subs r0, r0, #1 - bne delay_loop - mov pc, lr - -#endif /* CONFIG_USE_IRQ */ diff --git a/arch/arm/cpu/ixp/timer.c b/arch/arm/cpu/ixp/timer.c index edf341ff9f..9f3ea42ece 100644 --- a/arch/arm/cpu/ixp/timer.c +++ b/arch/arm/cpu/ixp/timer.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2010 + * Michael Schwingen, michael@schwingen.org + * * (C) Copyright 2006 * Stefan Roese, DENX Software Engineering, sr@denx.de. * @@ -31,105 +34,94 @@ #include <common.h> #include <asm/arch/ixp425.h> +#include <asm/io.h> +#include <div64.h> -#ifdef CONFIG_TIMER_IRQ - -#define FREQ 66666666 -#define CLOCK_TICK_RATE (((FREQ / CONFIG_SYS_HZ & ~IXP425_OST_RELOAD_MASK) + 1) * CONFIG_SYS_HZ) -#define LATCH ((CLOCK_TICK_RATE + CONFIG_SYS_HZ/2) / CONFIG_SYS_HZ) /* For divider */ +DECLARE_GLOBAL_DATA_PTR; /* - * When interrupts are enabled, use timer 2 for time/delay generation... + * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a + * 33.333MHz crystal). */ - -static volatile ulong timestamp; - -static void timer_isr(void *data) +static inline unsigned long long tick_to_time(unsigned long long tick) { - unsigned int *pTime = (unsigned int *)data; - - (*pTime)++; - - /* - * Reset IRQ source - */ - *IXP425_OSST = IXP425_OSST_TIMER_2_PEND; + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_IXP425_TIMER_CLK); + return tick; } -ulong get_timer (ulong base) +static inline unsigned long long time_to_tick(unsigned long long time) { - return timestamp - base; + time *= CONFIG_IXP425_TIMER_CLK; + do_div(time, CONFIG_SYS_HZ); + return time; } -void reset_timer (void) +static inline unsigned long long us_to_tick(unsigned long long us) { - timestamp = 0; + us = us * CONFIG_IXP425_TIMER_CLK + 999999; + do_div(us, 1000000); + return us; } -int timer_init (void) +unsigned long long get_ticks(void) { - /* install interrupt handler for timer */ - irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void *)×tamp); - - /* setup the Timer counter value */ - *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; + ulong now = readl(IXP425_OSTS_B); + + if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) { + /* rollover of timestamp timer register */ + gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1; + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); + } else { + /* move stamp forward with absolut diff ticks */ + gd->timestamp += (now - gd->lastinc); + } + gd->lastinc = now; + return gd->timestamp; +} - /* enable timer irq */ - *IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ); - return 0; -} -#else -ulong get_timer (ulong base) +void reset_timer_masked(void) { - return get_timer_masked () - base; + /* capture current timestamp counter */ + gd->lastinc = readl(IXP425_OSTS_B); + /* start "advancing" time stamp from 0 */ + gd->timestamp = 0; } -void ixp425_udelay(unsigned long usec) +void reset_timer(void) { - /* - * This function has a max usec, but since it is called from udelay - * we should not have to worry... be happy - */ - unsigned long usecs = CONFIG_SYS_HZ/1000000L & ~IXP425_OST_RELOAD_MASK; - - *IXP425_OSST = IXP425_OSST_TIMER_1_PEND; - usecs |= IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE; - *IXP425_OSRT1 = usecs; - while (!(*IXP425_OSST & IXP425_OSST_TIMER_1_PEND)); + reset_timer_masked(); } -void __udelay (unsigned long usec) +ulong get_timer_masked(void) { - while (usec--) ixp425_udelay(1); + return tick_to_time(get_ticks()); } -static ulong reload_constant = 0xfffffff0; - -void reset_timer_masked (void) +ulong get_timer(ulong base) { - ulong reload = reload_constant | IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE; + return get_timer_masked() - base; +} - *IXP425_OSST = IXP425_OSST_TIMER_1_PEND; - *IXP425_OSRT1 = reload; +void set_timer(ulong t) +{ + gd->timestamp = time_to_tick(t); } -ulong get_timer_masked (void) +/* delay x useconds AND preserve advance timestamp value */ +void __udelay(unsigned long usec) { - /* - * Note that it is possible for this to wrap! - * In this case we return max. - */ - ulong current = *IXP425_OST1; - if (*IXP425_OSST & IXP425_OSST_TIMER_1_PEND) - { - return reload_constant; - } - return (reload_constant - current); + unsigned long long tmp; + + tmp = get_ticks() + us_to_tick(usec); + + while (get_ticks() < tmp) + ; } int timer_init(void) { + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); return 0; } -#endif diff --git a/arch/arm/cpu/ixp/u-boot.lds b/arch/arm/cpu/ixp/u-boot.lds index 3587f8aa6b..7199de4af1 100644 --- a/arch/arm/cpu/ixp/u-boot.lds +++ b/arch/arm/cpu/ixp/u-boot.lds @@ -31,8 +31,8 @@ SECTIONS . = ALIGN(4); .text : { - arch/arm/cpu/ixp/start.o(.text) - *(.text) + arch/arm/cpu/ixp/start.o(.text*) + *(.text*) } . = ALIGN(4); @@ -40,7 +40,7 @@ SECTIONS . = ALIGN(4); .data : { - *(.data) + *(.data*) } . = ALIGN(4); @@ -67,7 +67,7 @@ SECTIONS .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; - *(.bss) + *(.bss*) . = ALIGN(4); __bss_end__ = .; } |