summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/mips/cache.S209
-rw-r--r--cpu/mips/cpu.c35
-rw-r--r--cpu/mips/start.S48
-rw-r--r--cpu/mpc5xxx/cpu.c4
-rw-r--r--cpu/mpc83xx/Makefile15
-rw-r--r--cpu/mpc83xx/cpu_init.c6
-rw-r--r--cpu/mpc83xx/fdt.c12
-rw-r--r--cpu/mpc83xx/pci.c2
-rw-r--r--cpu/mpc83xx/qe_io.c3
-rw-r--r--cpu/mpc83xx/serdes.c145
-rw-r--r--cpu/mpc8xx/Makefile2
-rw-r--r--cpu/mpc8xx/cpu.c13
-rw-r--r--cpu/mpc8xx/fdt.c46
-rw-r--r--cpu/mpc8xx/speed.c25
-rw-r--r--cpu/ppc4xx/44x_spd_ddr2.c41
-rw-r--r--cpu/ppc4xx/4xx_enet.c369
-rw-r--r--cpu/ppc4xx/4xx_pci.c9
-rw-r--r--cpu/ppc4xx/4xx_pcie.c203
-rw-r--r--cpu/ppc4xx/4xx_uart.c24
-rw-r--r--cpu/ppc4xx/cpu.c45
-rw-r--r--cpu/ppc4xx/cpu_init.c1
-rw-r--r--cpu/ppc4xx/interrupts.c589
-rw-r--r--cpu/ppc4xx/miiphy.c196
-rw-r--r--cpu/ppc4xx/ndfc.c3
-rw-r--r--cpu/ppc4xx/speed.c125
-rw-r--r--cpu/ppc4xx/start.S19
-rw-r--r--cpu/ppc4xx/tlb.c27
-rw-r--r--cpu/s3c44b0/cpu.c4
28 files changed, 1410 insertions, 810 deletions
diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S
index 443240e..89ada71 100644
--- a/cpu/mips/cache.S
+++ b/cpu/mips/cache.S
@@ -1,5 +1,5 @@
/*
- * Cache-handling routined for MIPS 4K CPUs
+ * Cache-handling routined for MIPS CPUs
*
* Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
*
@@ -24,15 +24,32 @@
#include <config.h>
#include <version.h>
+#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
- /* 16KB is the maximum size of instruction and data caches on
- * MIPS 4K.
- */
-#define MIPS_MAX_CACHE_SIZE 0x4000
+#define RA t8
+
+/*
+ * 16kB is the maximum size of instruction and data caches on MIPS 4K,
+ * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
+ *
+ * Note that the above size is the maximum size of primary cache. U-Boot
+ * doesn't have L2 cache support for now.
+ */
+#define MIPS_MAX_CACHE_SIZE 0x10000
+
+#define INDEX_BASE KSEG0
+
+ .macro cache_op op addr
+ .set push
+ .set noreorder
+ .set mips3
+ cache \op, 0(\addr)
+ .set pop
+ .endm
/*
* cacheop macro to automate cache operations
@@ -103,6 +120,77 @@
#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+ .macro f_fill64 dst, offset, val
+ LONG_S \val, (\offset + 0 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 1 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 2 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 3 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 4 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 5 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 6 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 7 * LONGSIZE)(\dst)
+#if LONGSIZE == 4
+ LONG_S \val, (\offset + 8 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 9 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 10 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 11 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 12 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 13 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 14 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 15 * LONGSIZE)(\dst)
+#endif
+ .endm
+
+/*
+ * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
+ */
+LEAF(mips_init_icache)
+ blez a1, 9f
+ mtc0 zero, CP0_TAGLO
+ /* clear tag to invalidate */
+ PTR_LI t0, INDEX_BASE
+ PTR_ADDU t1, t0, a1
+1: cache_op Index_Store_Tag_I t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+ /* fill once, so data field parity is correct */
+ PTR_LI t0, INDEX_BASE
+2: cache_op Fill t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 2b
+ /* invalidate again - prudent but not strictly neccessary */
+ PTR_LI t0, INDEX_BASE
+1: cache_op Index_Store_Tag_I t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+9: jr ra
+ END(mips_init_icache)
+
+/*
+ * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
+ */
+LEAF(mips_init_dcache)
+ blez a1, 9f
+ mtc0 zero, CP0_TAGLO
+ /* clear all tags */
+ PTR_LI t0, INDEX_BASE
+ PTR_ADDU t1, t0, a1
+1: cache_op Index_Store_Tag_D t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+ /* load from each line (in cached space) */
+ PTR_LI t0, INDEX_BASE
+2: LONG_L zero, 0(t0)
+ PTR_ADDU t0, a2
+ bne t0, t1, 2b
+ /* clear all tags */
+ PTR_LI t0, INDEX_BASE
+1: cache_op Index_Store_Tag_D t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+9: jr ra
+ END(mips_init_dcache)
+
/*******************************************************************************
*
* mips_cache_reset - low level initialisation of the primary caches
@@ -119,10 +207,8 @@
* RETURNS: N/A
*
*/
- .globl mips_cache_reset
- .ent mips_cache_reset
-mips_cache_reset:
-
+NESTED(mips_cache_reset, 0, ra)
+ move RA, ra
li t2, CFG_ICACHE_SIZE
li t3, CFG_DCACHE_SIZE
li t4, CFG_CACHELINE_SIZE
@@ -130,27 +216,14 @@ mips_cache_reset:
li v0, MIPS_MAX_CACHE_SIZE
- /* Now clear that much memory starting from zero.
- */
-
- li a0, KSEG1
- addu a1, a0, v0
-2:
- sw zero, 0(a0)
- sw zero, 4(a0)
- sw zero, 8(a0)
- sw zero, 12(a0)
- sw zero, 16(a0)
- sw zero, 20(a0)
- sw zero, 24(a0)
- sw zero, 28(a0)
- addu a0, 32
- bltu a0, a1, 2b
-
- /* Set invalid tag.
+ /*
+ * Now clear that much memory starting from zero.
*/
-
- mtc0 zero, CP0_TAGLO
+ PTR_LI a0, KSEG1
+ PTR_ADDU a1, a0, v0
+2: PTR_ADDIU a0, 64
+ f_fill64 a0, -64, zero
+ bne a0, a1, 2b
/*
* The caches are probably in an indeterminate state,
@@ -158,48 +231,26 @@ mips_cache_reset:
* invalidate, load/fill, invalidate for each line.
*/
- /* Assume bottom of RAM will generate good parity for the cache.
- */
-
- li a0, K0BASE
- move a2, t2 # icacheSize
- move a3, t4 # icacheLineSize
- move a1, a2
- icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
-
- /* To support Orion/R4600, we initialise the data cache in 3 passes.
- */
-
- /* 1: initialise dcache tags.
+ /*
+ * Assume bottom of RAM will generate good parity for the cache.
*/
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
-
- /* 2: fill dcache.
+ /*
+ * Initialize the I-cache first,
*/
+ move a1, t2
+ move a2, t4
+ bal mips_init_icache
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheopn(a0,a1,a2,a3,1lw,(dummy))
-
- /* 3: clear dcache tags.
+ /*
+ * then initialize D-cache.
*/
+ move a1, t3
+ move a2, t5
+ bal mips_init_dcache
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
-
- j ra
-
- .end mips_cache_reset
+ jr RA
+ END(mips_cache_reset)
/*******************************************************************************
*
@@ -208,15 +259,15 @@ mips_cache_reset:
* RETURNS: 0 - cache disabled; 1 - cache enabled
*
*/
- .globl dcache_status
- .ent dcache_status
-dcache_status:
-
- mfc0 v0, CP0_CONFIG
- andi v0, v0, 1
- j ra
-
- .end dcache_status
+LEAF(dcache_status)
+ mfc0 t0, CP0_CONFIG
+ li t1, CONF_CM_UNCACHED
+ andi t0, t0, CONF_CM_CMASK
+ move v0, zero
+ beq t0, t1, 2f
+ li v0, 1
+2: jr ra
+ END(dcache_status)
/*******************************************************************************
*
@@ -225,19 +276,16 @@ dcache_status:
* RETURNS: N/A
*
*/
- .globl dcache_disable
- .ent dcache_disable
-dcache_disable:
-
+LEAF(dcache_disable)
mfc0 t0, CP0_CONFIG
li t1, -8
and t0, t0, t1
ori t0, t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
j ra
+ END(dcache_disable)
- .end dcache_disable
-
+#ifdef CFG_INIT_RAM_LOCK_MIPS
/*******************************************************************************
*
* mips_cache_lock - lock RAM area pointed to by a0 in cache.
@@ -263,3 +311,4 @@ mips_cache_lock:
j ra
.end mips_cache_lock
+#endif /* CFG_INIT_RAM_LOCK_MIPS */
diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c
index 7559ac6..8b43d8e 100644
--- a/cpu/mips/cpu.c
+++ b/cpu/mips/cpu.c
@@ -23,24 +23,45 @@
#include <common.h>
#include <command.h>
-#include <asm/inca-ip.h>
#include <asm/mipsregs.h>
+#include <asm/cacheops.h>
+#include <asm/reboot.h>
+
+#define cache_op(op,addr) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips3\n\t \n" \
+ " cache %0, %1 \n" \
+ " .set pop \n" \
+ : \
+ : "i" (op), "R" (*(unsigned char *)(addr)))
+
+void __attribute__((weak)) _machine_restart(void)
+{
+}
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
-#if defined(CONFIG_INCA_IP)
- *INCA_IP_WDT_RST_REQ = 0x3f;
-#elif defined(CONFIG_PURPLE) || defined(CONFIG_TB0229)
- void (*f)(void) = (void *) 0xbfc00000;
+ _machine_restart();
- f();
-#endif
fprintf(stderr, "*** reset failed ***\n");
return 0;
}
void flush_cache(ulong start_addr, ulong size)
{
+ unsigned long lsize = CFG_CACHELINE_SIZE;
+ unsigned long addr = start_addr & ~(lsize - 1);
+ unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
+
+ while (1) {
+ cache_op(Hit_Writeback_Inv_D, start_addr);
+ cache_op(Hit_Invalidate_I, start_addr);
+ if (addr == aend)
+ break;
+ addr += lsize;
+ }
}
void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
diff --git a/cpu/mips/start.S b/cpu/mips/start.S
index c92b162..baac2ce 100644
--- a/cpu/mips/start.S
+++ b/cpu/mips/start.S
@@ -27,6 +27,30 @@
#include <asm/regdef.h>
#include <asm/mipsregs.h>
+ /*
+ * For the moment disable interrupts, mark the kernel mode and
+ * set ST0_KX so that the CPU does not spit fire when using
+ * 64-bit addresses.
+ */
+ .macro setup_c0_status set clr
+ .set push
+ mfc0 t0, CP0_STATUS
+ or t0, ST0_CU0 | \set | 0x1f | \clr
+ xor t0, 0x1f | \clr
+ mtc0 t0, CP0_STATUS
+ .set noreorder
+ sll zero, 3 # ehb
+ .set pop
+ .endm
+
+ .macro setup_c0_status_reset
+#ifdef CONFIG_64BIT
+ setup_c0_status ST0_KX 0
+#else
+ setup_c0_status 0 0
+#endif
+ .endm
+
#define RVECENT(f,n) \
b f; nop
#define XVECENT(f,bev) \
@@ -211,19 +235,11 @@ reset:
mtc0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
- /* STATUS register */
-#ifdef CONFIG_TB0229
- li k0, ST0_CU0
-#else
- mfc0 k0, CP0_STATUS
-#endif
- li k1, ~ST0_IE
- and k0, k1
- mtc0 k0, CP0_STATUS
-
- /* CAUSE register */
+ /* WP(Watch Pending), SW0/1 should be cleared. */
mtc0 zero, CP0_CAUSE
+ setup_c0_status_reset
+
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
@@ -240,14 +256,6 @@ reset:
1:
lw gp, 0(ra)
-#ifdef CONFIG_INCA_IP
- /* Disable INCA-IP Watchdog.
- */
- la t9, disable_incaip_wdt
- jalr t9
- nop
-#endif
-
/* Initialize any external memory.
*/
la t9, lowlevel_init
@@ -267,10 +275,12 @@ reset:
/* Set up temporary stack.
*/
+#ifdef CFG_INIT_RAM_LOCK_MIPS
li a0, CFG_INIT_SP_OFFSET
la t9, mips_cache_lock
jalr t9
nop
+#endif
li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
la sp, 0(t0)
diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c
index 7522afe..ace1653 100644
--- a/cpu/mpc5xxx/cpu.c
+++ b/cpu/mpc5xxx/cpu.c
@@ -119,7 +119,9 @@ void ft_cpu_setup(void *blob, bd_t *bd)
{
int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4;
char * cpu_path = "/cpus/" OF_CPU;
+#ifdef CONFIG_MPC5xxx_FEC
char * eth_path = "/" OF_SOC "/ethernet@3000";
+#endif
do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
@@ -127,7 +129,9 @@ void ft_cpu_setup(void *blob, bd_t *bd)
do_fixup_by_path_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipbfreq, 1);
do_fixup_by_path_u32(blob, "/" OF_SOC, "system-frequency",
bd->bi_busfreq*div, 1);
+#ifdef CONFIG_MPC5xxx_FEC
do_fixup_by_path(blob, eth_path, "mac-address", bd->bi_enetaddr, 6, 0);
do_fixup_by_path(blob, eth_path, "local-mac-address", bd->bi_enetaddr, 6, 0);
+#endif
}
#endif
diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile
index 94a3cb8..fcb6a52 100644
--- a/cpu/mpc83xx/Makefile
+++ b/cpu/mpc83xx/Makefile
@@ -28,9 +28,20 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).a
START = start.o
-COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
- spd_sdram.o ecc.o qe_io.o pci.o fdt.o
+COBJS-y += traps.o
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += speed.o
+COBJS-y += interrupts.o
+COBJS-y += spd_sdram.o
+COBJS-y += ecc.o
+COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_FSL_SERDES) += serdes.o
+COBJS-$(CONFIG_83XX_GENERIC_PCI) += pci.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+
+COBJS := $(COBJS-y)
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
START := $(addprefix $(obj),$(START))
diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c
index e643037..fba5b02 100644
--- a/cpu/mpc83xx/cpu_init.c
+++ b/cpu/mpc83xx/cpu_init.c
@@ -79,6 +79,12 @@ void cpu_init_f (volatile immap_t * im)
(CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT);
#endif
+#ifdef CFG_SPCR_OPT
+ /* Optimize transactions between CSB and other devices */
+ im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) |
+ (CFG_SPCR_OPT << SPCR_OPT_SHIFT);
+#endif
+
#ifdef CFG_SPCR_TSECEP
/* all eTSEC's Emergency priority */
im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSECEP) |
diff --git a/cpu/mpc83xx/fdt.c b/cpu/mpc83xx/fdt.c
index 6f55932..b39f678 100644
--- a/cpu/mpc83xx/fdt.c
+++ b/cpu/mpc83xx/fdt.c
@@ -24,9 +24,6 @@
*/
#include <common.h>
-
-#if defined(CONFIG_OF_LIBFDT)
-
#include <libfdt.h>
#include <fdt_support.h>
@@ -49,6 +46,14 @@ void ft_cpu_setup(void *blob, bd_t *bd)
"clock-frequency", gd->core_clk, 1);
do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
"bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,soc",
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,soc",
+ "clock-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,immr",
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,immr",
+ "clock-frequency", bd->bi_busfreq, 1);
#ifdef CONFIG_QE
ft_qe_setup(blob);
#endif
@@ -68,4 +73,3 @@ void ft_cpu_setup(void *blob, bd_t *bd)
fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
}
-#endif /* CONFIG_OF_LIBFDT */
diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c
index 18558db..adabf7a 100644
--- a/cpu/mpc83xx/pci.c
+++ b/cpu/mpc83xx/pci.c
@@ -33,7 +33,6 @@
#include <asm/mpc8349_pci.h>
-#ifdef CONFIG_83XX_GENERIC_PCI
#define MAX_BUSES 2
DECLARE_GLOBAL_DATA_PTR;
@@ -209,4 +208,3 @@ void ft_pci_setup(void *blob, bd_t *bd)
}
}
#endif /* CONFIG_OF_LIBFDT */
-#endif /* CONFIG_83XX_GENERIC_PCI */
diff --git a/cpu/mpc83xx/qe_io.c b/cpu/mpc83xx/qe_io.c
index 8b3937a..ce91a07 100644
--- a/cpu/mpc83xx/qe_io.c
+++ b/cpu/mpc83xx/qe_io.c
@@ -25,7 +25,6 @@
#include "asm/io.h"
#include "asm/immap_83xx.h"
-#if defined(CONFIG_QE)
#define NUM_OF_PINS 32
void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
{
@@ -81,5 +80,3 @@ void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
out_be32(&par_io->ioport[port].ppar1, pin_2bit_assign | tmp_val);
}
}
-
-#endif /* CONFIG_QE */
diff --git a/cpu/mpc83xx/serdes.c b/cpu/mpc83xx/serdes.c
new file mode 100644
index 0000000..020c4c8
--- /dev/null
+++ b/cpu/mpc83xx/serdes.c
@@ -0,0 +1,145 @@
+/*
+ * Freescale SerDes initialization routine
+ *
+ * Copyright (C) 2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc. All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.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 <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_serdes.h>
+
+/* SerDes registers */
+#define FSL_SRDSCR0_OFFS 0x0
+#define FSL_SRDSCR0_DPP_1V2 0x00008800
+#define FSL_SRDSCR1_OFFS 0x4
+#define FSL_SRDSCR1_PLLBW 0x00000040
+#define FSL_SRDSCR2_OFFS 0x8
+#define FSL_SRDSCR2_VDD_1V2 0x00800000
+#define FSL_SRDSCR2_SEIC_MASK 0x00001c1c
+#define FSL_SRDSCR2_SEIC_SATA 0x00001414
+#define FSL_SRDSCR2_SEIC_PEX 0x00001010
+#define FSL_SRDSCR2_SEIC_SGMII 0x00000101
+#define FSL_SRDSCR3_OFFS 0xc
+#define FSL_SRDSCR3_KFR_SATA 0x10100000
+#define FSL_SRDSCR3_KPH_SATA 0x04040000
+#define FSL_SRDSCR3_SDFM_SATA_PEX 0x01010000
+#define FSL_SRDSCR3_SDTXL_SATA 0x00000505
+#define FSL_SRDSCR4_OFFS 0x10
+#define FSL_SRDSCR4_PROT_SATA 0x00000808
+#define FSL_SRDSCR4_PROT_PEX 0x00000101
+#define FSL_SRDSCR4_PROT_SGMII 0x00000505
+#define FSL_SRDSCR4_PLANE_X2 0x01000000
+#define FSL_SRDSRSTCTL_OFFS 0x20
+#define FSL_SRDSRSTCTL_RST 0x80000000
+#define FSL_SRDSRSTCTL_SATA_RESET 0xf
+
+void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd)
+{
+ void *regs = (void *)CFG_IMMR + offset;
+ u32 tmp;
+
+ /* 1.0V corevdd */
+ if (vdd) {
+ /* DPPE/DPPA = 0 */
+ tmp = in_be32(regs + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_DPP_1V2;
+ out_be32(regs + FSL_SRDSCR0_OFFS, tmp);
+
+ /* VDD = 0 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_VDD_1V2;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+ }
+
+ /* protocol specific configuration */
+ switch (proto) {
+ case FSL_SERDES_PROTO_SATA:
+ /* Set and clear reset bits */
+ tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+ tmp |= FSL_SRDSRSTCTL_SATA_RESET;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+ udelay(1000);
+ tmp &= ~FSL_SRDSRSTCTL_SATA_RESET;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_SATA;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ tmp = FSL_SRDSCR3_KFR_SATA | FSL_SRDSCR3_KPH_SATA |
+ FSL_SRDSCR3_SDFM_SATA_PEX |
+ FSL_SRDSCR3_SDTXL_SATA;
+ out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_SATA;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ case FSL_SERDES_PROTO_PEX:
+ case FSL_SERDES_PROTO_PEX_X2:
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp |= FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_PEX;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ tmp = FSL_SRDSCR3_SDFM_SATA_PEX;
+ out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_PEX;
+ if (proto == FSL_SERDES_PROTO_PEX_X2)
+ tmp |= FSL_SRDSCR4_PLANE_X2;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ case FSL_SERDES_PROTO_SGMII:
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_SGMII;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ out_be32(regs + FSL_SRDSCR3_OFFS, 0);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_SGMII;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ default:
+ return;
+ }
+
+ /* Do a software reset */
+ tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+ tmp |= FSL_SRDSRSTCTL_RST;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+}
diff --git a/cpu/mpc8xx/Makefile b/cpu/mpc8xx/Makefile
index 223b30c..dbdc2e0 100644
--- a/cpu/mpc8xx/Makefile
+++ b/cpu/mpc8xx/Makefile
@@ -29,7 +29,7 @@ LIB = $(obj)lib$(CPU).a
START = start.o kgdb.o
COBJS = bedbug_860.o commproc.o cpu.o cpu_init.o \
- fec.o i2c.o interrupts.o lcd.o scc.o \
+ fec.o fdt.o i2c.o interrupts.o lcd.o scc.o \
serial.o speed.o spi.o \
traps.o upatch.o video.o
SOBJS = plprcr_write.o
diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c
index 5d4ab82..ec6a3fd 100644
--- a/cpu/mpc8xx/cpu.c
+++ b/cpu/mpc8xx/cpu.c
@@ -634,17 +634,4 @@ void reset_8xx_watchdog (volatile immap_t * immr)
immr->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */
# endif /* CONFIG_LWMON */
}
-
#endif /* CONFIG_WATCHDOG */
-
-/* ------------------------------------------------------------------------- */
-#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
-void ft_cpu_setup (void *blob, bd_t *bd)
-{
- char * cpu_path = "/cpus/" OF_CPU;
-
- do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
- do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
- do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1);
-}
-#endif /* CONFIG_OF_LIBFDT */
diff --git a/cpu/mpc8xx/fdt.c b/cpu/mpc8xx/fdt.c
new file mode 100644
index 0000000..567094a
--- /dev/null
+++ b/cpu/mpc8xx/fdt.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 (C) Bryan O'Donoghue
+ *
+ * Code copied & edited from Freescale mpc85xx stuff.
+ *
+ * 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 <libfdt.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", get_tbclk(), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,cpm-brg", "clock-frequency",
+ gd->brg_clk, 1);
+
+ /* Fixup ethernet MAC addresses */
+ fdt_fixup_ethernet(blob, bd);
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
diff --git a/cpu/mpc8xx/speed.c b/cpu/mpc8xx/speed.c
index 11b0893..070babc 100644
--- a/cpu/mpc8xx/speed.c
+++ b/cpu/mpc8xx/speed.c
@@ -174,6 +174,27 @@ unsigned long measure_gclk(void)
#endif
+void get_brgclk(uint sccr)
+{
+ uint divider = 0;
+
+ switch((sccr&SCCR_DFBRG11)>>11){
+ case 0:
+ divider = 1;
+ break;
+ case 1:
+ divider = 4;
+ break;
+ case 2:
+ divider = 16;
+ break;
+ case 3:
+ divider = 64;
+ break;
+ }
+ gd->brg_clk = gd->cpu_clk/divider;
+}
+
#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
/*
@@ -223,6 +244,8 @@ int get_clocks (void)
gd->bus_clk = gd->cpu_clk / 2;
}
+ get_brgclk(sccr);
+
return (0);
}
@@ -254,6 +277,8 @@ int get_clocks_866 (void)
gd->cpu_clk = measure_gclk ();
#endif
+ get_brgclk(immr->im_clkrst.car_sccr);
+
/* if cpu clock <= 66 MHz then set bus division factor to 1,
* otherwise set it to 2
*/
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 3bafea3..9e722b9 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -42,7 +42,8 @@
#include <asm/mmu.h>
#if defined(CONFIG_SPD_EEPROM) && \
- (defined(CONFIG_440SP) || defined(CONFIG_440SPE))
+ (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
/*-----------------------------------------------------------------------------+
* Defines
@@ -579,6 +580,13 @@ long int initdram(int board_type)
ppc440sp_sdram_register_dump();
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+
return dram_size;
}
@@ -2125,6 +2133,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
unsigned long baseadd_size;
unsigned long i;
unsigned long bank_0_populated = 0;
+ unsigned long total_size = 0;
/*------------------------------------------------------------------
* Reset the rank_base_address.
@@ -2147,28 +2156,38 @@ static void program_memory_queue(unsigned long *dimm_populated,
* Set the sizes
*-----------------------------------------------------------------*/
baseadd_size = 0;
- rank_size_bytes = 4 * 1024 * 1024 * rank_size_id;
switch (rank_size_id) {
+ case 0x01:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+ total_size = 1024;
+ break;
case 0x02:
- baseadd_size |= SDRAM_RXBAS_SDSZ_8;
+ baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+ total_size = 2048;
break;
case 0x04:
- baseadd_size |= SDRAM_RXBAS_SDSZ_16;
+ baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+ total_size = 4096;
break;
case 0x08:
baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+ total_size = 32;
break;
case 0x10:
baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+ total_size = 64;
break;
case 0x20:
baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+ total_size = 128;
break;
case 0x40:
baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+ total_size = 256;
break;
case 0x80:
baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+ total_size = 512;
break;
default:
printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
@@ -2178,6 +2197,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
printf("Replace the DIMM module with a supported DIMM.\n\n");
spd_ddr_init_hang ();
}
+ rank_size_bytes = total_size << 20;
if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
bank_0_populated = 1;
@@ -2190,6 +2210,19 @@ static void program_memory_queue(unsigned long *dimm_populated,
}
}
}
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ /*
+ * Enable high bandwidth access on 460EX/GT.
+ * This should/could probably be done on other
+ * PPC's too, like 440SPe.
+ * This is currently not used, but with this setup
+ * it is possible to use it later on in e.g. the Linux
+ * EMAC driver for performance gain.
+ */
+ mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+ mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+#endif
}
/*-----------------------------------------------------------------------------+
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 599f5ce..d990250 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -137,17 +137,32 @@
#define BI_PHYMODE_RTBI 4
#define BI_PHYMODE_TBI 5
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#define BI_PHYMODE_SMII 6
#define BI_PHYMODE_MII 7
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define BI_PHYMODE_RMII 8
+#endif
#endif
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1))
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_ETH_CFG_CLK_SEL_V(n) (0x01 << (8 + n))
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define MAL_RX_CHAN_MUL 8 /* 460EX/GT uses MAL channel 8 for EMAC1 */
+#else
+#define MAL_RX_CHAN_MUL 1
+#endif
+
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
@@ -214,6 +229,44 @@ extern int emac4xx_miiphy_write (char *devname, unsigned char addr,
int board_emac_count(void);
+static void emac_loopback_enable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+ u32 val;
+
+ mfsdr(sdr_mfr, val);
+ val |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+ mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 val;
+
+ mfsdr(SDR0_ETH_CFG, val);
+ val |= SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+ mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
+static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+ u32 val;
+
+ mfsdr(sdr_mfr, val);
+ val &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+ mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 val;
+
+ mfsdr(SDR0_ETH_CFG, val);
+ val &= ~SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+ mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
/*-----------------------------------------------------------------------------+
| ppc_4xx_eth_halt
| Disable MAL channel, and EMACn
@@ -222,11 +275,6 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
{
EMAC_4XX_HW_PST hw_p = dev->priv;
uint32_t failsafe = 10000;
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
- unsigned long mfr;
-#endif
out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
@@ -247,27 +295,14 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
break;
}
- /* EMAC RESET */
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* provide clocks for EMAC internal loopback */
- mfsdr (sdr_mfr, mfr);
- mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
- mtsdr(sdr_mfr, mfr);
-#endif
+ emac_loopback_enable(hw_p);
+ /* EMAC RESET */
out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* remove clocks for EMAC internal loopback */
- mfsdr (sdr_mfr, mfr);
- mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
- mtsdr(sdr_mfr, mfr);
-#endif
-
+ emac_loopback_disable(hw_p);
#ifndef CONFIG_NETCONSOLE
hw_p->print_speed = 1; /* print speed message again next time */
@@ -452,6 +487,187 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
}
#endif /* CONFIG_405EX */
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
+{
+ u32 eth_cfg;
+ u32 zmiifer; /* ZMII0_FER reg. */
+ u32 rmiifer; /* RGMII0_FER reg. Bridge 0 */
+ u32 rmiifer1; /* RGMII0_FER reg. Bridge 1 */
+
+ zmiifer = 0;
+ rmiifer = 0;
+ rmiifer1 = 0;
+
+ /* TODO:
+ * NOTE: 460GT has 2 RGMII bridge cores:
+ * emac0 ------ RGMII0_BASE
+ * |
+ * emac1 -----+
+ *
+ * emac2 ------ RGMII1_BASE
+ * |
+ * emac3 -----+
+ *
+ * 460EX has 1 RGMII bridge core:
+ * and RGMII1_BASE is disabled
+ * emac0 ------ RGMII0_BASE
+ * |
+ * emac1 -----+
+ */
+
+ /*
+ * Right now only 2*RGMII is supported. Please extend when needed.
+ * sr - 2008-02-19
+ */
+ switch (9) {
+ case 1:
+ /* 1 MII - 460EX */
+ /* GMC0 EMAC4_0, ZMII Bridge */
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 2:
+ /* 2 MII - 460GT */
+ /* GMC0 EMAC4_0, GMC1 EMAC4_2, ZMII Bridge */
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(2);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_MII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 3:
+ /* 2 RMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+ bis->bi_phymode[0] = BI_PHYMODE_RMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 4:
+ /* 4 RMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC1 EMAC4_2, GMC1, EMAC4_3 */
+ /* ZMII Bridge */
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2);
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3);
+ bis->bi_phymode[0] = BI_PHYMODE_RMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RMII;
+ bis->bi_phymode[2] = BI_PHYMODE_RMII;
+ bis->bi_phymode[3] = BI_PHYMODE_RMII;
+ break;
+ case 5:
+ /* 2 SMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+ bis->bi_phymode[0] = BI_PHYMODE_SMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 6:
+ /* 4 SMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC0 EMAC4_3, GMC0 EMAC4_3 */
+ /* ZMII Bridge */
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(2);
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(3);
+ bis->bi_phymode[0] = BI_PHYMODE_SMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SMII;
+ bis->bi_phymode[2] = BI_PHYMODE_SMII;
+ bis->bi_phymode[3] = BI_PHYMODE_SMII;
+ break;
+ case 7:
+ /* This is the default mode that we want for board bringup - Maple */
+ /* 1 GMII - 460EX */
+ /* GMC0 EMAC4_0, RGMII Bridge 0 */
+ rmiifer |= RGMII_FER_MDIO(0);
+
+ if (devnum == 0) {
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ } else {
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(3); /* CH1CFG - EMAC1 */
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_GMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ }
+ break;
+ case 8:
+ /* 2 GMII - 460GT */
+ /* GMC0 EMAC4_0, RGMII Bridge 0 */
+ /* GMC1 EMAC4_2, RGMII Bridge 1 */
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+ rmiifer1 |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC2 */
+ rmiifer |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC0 */
+ rmiifer1 |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC2 */
+
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_GMII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 9:
+ /* 2 RGMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ rmiifer |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC0 */
+
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 10:
+ /* 4 RGMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+ /* GMC1 EMAC4_2, GMC1 EMAC4_3, RGMII Bridge 1 */
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[3] = BI_PHYMODE_RGMII;
+ break;
+ default:
+ break;
+ }
+
+ /* Set EMAC for MDIO */
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ eth_cfg |= SDR0_ETH_CFG_MDIO_SEL_EMAC0;
+ mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+ out_be32((void *)RGMII_FER, rmiifer);
+#if defined(CONFIG_460GT)
+ out_be32((void *)RGMII_FER + RGMII1_BASE_OFFSET, rmiifer1);
+#endif
+
+ /* bypass the TAHOE0/TAHOE1 cores for U-Boot */
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ eth_cfg |= (SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+ mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+ return 0;
+}
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
static inline void *malloc_aligned(u32 size, u32 align)
{
return (void *)(((u32)malloc(size + align) + align - 1) &
@@ -472,19 +688,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
sys_info_t sysinfo;
#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
int ethgroup = -1;
#endif
#endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_405EX)
- unsigned long mfr;
-#endif
u32 bd_cached;
u32 bd_uncached = 0;
#ifdef CONFIG_4xx_DCACHE
@@ -503,6 +716,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
/* Need to get the OPB frequency so we can access the PHY */
get_sys_info (&sysinfo);
@@ -556,21 +770,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
out_be32((void *)ZMII_FER, 0);
udelay (100);
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#if defined(CONFIG_440GP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#elif defined(CONFIG_440GX) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
-#elif defined(CONFIG_440GP)
- /* set RMII mode */
- out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0);
-#else
- if ((devnum == 0) || (devnum == 1)) {
- out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
- } else { /* ((devnum == 2) || (devnum == 3)) */
- out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
- out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
- (RGMII_FER_RGMII << RGMII_FER_V (3))));
- }
#endif
out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
@@ -579,20 +784,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
#endif
- __asm__ volatile ("eieio");
+ sync();
- /* reset emac so we have access to the phy */
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* provide clocks for EMAC internal loopback */
- mfsdr (sdr_mfr, mfr);
- mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
- mtsdr(sdr_mfr, mfr);
-#endif
+ emac_loopback_enable(hw_p);
+ /* EMAC RESET */
out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+ /* remove clocks for EMAC internal loopback */
+ emac_loopback_disable(hw_p);
+
failsafe = 1000;
while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
udelay (1000);
@@ -601,18 +803,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
if (failsafe <= 0)
printf("\nProblem resetting EMAC!\n");
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
- /* remove clocks for EMAC internal loopback */
- mfsdr (sdr_mfr, mfr);
- mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
- mtsdr(sdr_mfr, mfr);
-#endif
-
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
/* Whack the M1 register */
mode_reg = 0x0;
@@ -674,6 +868,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#if defined(CONFIG_CIS8201_PHY)
@@ -772,8 +967,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->devnum);
}
-#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
- !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+#if defined(CONFIG_440) && \
+ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+ !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
+ !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
mfsdr(sdr_mfr, reg);
if (speed == 100) {
@@ -807,6 +1004,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
if (speed == 1000)
reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
@@ -819,12 +1017,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
return -1;
}
out_be32((void *)RGMII_SSR, reg);
+#if defined(CONFIG_460GT)
+ if ((devnum == 2) || (devnum == 3))
+ out_be32((void *)RGMII_SSR + RGMII1_BASE_OFFSET, reg);
+#endif
#endif
/* set the Mal configuration reg */
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
@@ -926,9 +1129,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ mtdcr (malrxctp8r, hw_p->rx);
+ /* set RX buffer size */
+ mtdcr (malrcbs8, ENET_MAX_MTU_ALIGNED / 16);
+#else
mtdcr (malrxctp1r, hw_p->rx_phys);
/* set RX buffer size */
mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
+#endif
break;
#if defined (CONFIG_440GX)
case 2:
@@ -1087,7 +1297,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
hw_p->tx[hw_p->tx_slot].data_len = (short) len;
hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;
- __asm__ volatile ("eieio");
+ sync();
out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
@@ -1127,15 +1337,31 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
*/
#define UIC0MSR uic1msr
#define UIC0SR uic1sr
+#define UIC1MSR uic1msr
+#define UIC1SR uic1sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/*
+ * Hack: On 460EX/GT all enet irq sources are located on UIC2
+ * Needs some cleanup. --ag
+ */
+#define UIC0MSR uic2msr
+#define UIC0SR uic2sr
+#define UIC1MSR uic2msr
+#define UIC1SR uic2sr
#else
#define UIC0MSR uic0msr
#define UIC0SR uic0sr
+#define UIC1MSR uic1msr
+#define UIC1SR uic1sr
#endif
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_405EX)
#define UICMSR_ETHX uic0msr
#define UICSR_ETHX uic0sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UICMSR_ETHX uic2msr
+#define UICSR_ETHX uic2sr
#else
#define UICMSR_ETHX uic1msr
#define UICSR_ETHX uic1sr
@@ -1173,7 +1399,7 @@ int enetInt (struct eth_device *dev)
serviced = 0;
my_uic0msr = mfdcr (UIC0MSR);
- my_uic1msr = mfdcr (uic1msr);
+ my_uic1msr = mfdcr (UIC1MSR);
#if defined(CONFIG_440GX)
my_uic2msr = mfdcr (uic2msr);
#endif
@@ -1219,7 +1445,7 @@ int enetInt (struct eth_device *dev)
if ((hw_p->emac_ier & emac_isr)
|| (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */
return (rc); /* we had errors so get out */
}
@@ -1238,7 +1464,7 @@ int enetInt (struct eth_device *dev)
if ((hw_p->emac_ier & emac_isr)
|| (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */
return (rc); /* we had errors so get out */
}
@@ -1256,7 +1482,7 @@ int enetInt (struct eth_device *dev)
if ((hw_p->emac_ier & emac_isr)
|| (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
mtdcr (uic2sr, UIC_ETH2);
return (rc); /* we had errors so get out */
}
@@ -1274,7 +1500,7 @@ int enetInt (struct eth_device *dev)
if ((hw_p->emac_ier & emac_isr)
|| (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
mtdcr (uic2sr, UIC_ETH3);
return (rc); /* we had errors so get out */
}
@@ -1292,7 +1518,9 @@ int enetInt (struct eth_device *dev)
/* check for EOB on valid channels */
if (my_uic0msr & UIC_MRE) {
mal_rx_eob = mfdcr (malrxeobisr);
- if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
+ if ((mal_rx_eob &
+ (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)))
+ != 0) { /* call emac routine for channel x */
/* clear EOB
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (dev, emac_isr);
@@ -1303,7 +1531,7 @@ int enetInt (struct eth_device *dev)
}
mtdcr (UIC0SR, UIC_MRE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
switch (hw_p->devnum) {
case 0:
mtdcr (UICSR_ETHX, UIC_ETH0);
@@ -1468,7 +1696,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
int loop_count = 0;
rx_eob_isr = mfdcr (malrxeobisr);
- if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
+ if ((0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)) & rx_eob_isr) {
/* clear EOB */
mtdcr (malrxeobisr, rx_eob_isr);
@@ -1482,7 +1710,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
loop_count++;
handled++;
- data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */
+ data_len = (unsigned long) hw_p->rx[i].data_len & 0x0fff; /* Get len */
if (data_len) {
if (data_len > ENET_MAX_MTU) /* Check len */
data_len = 0;
@@ -1568,7 +1796,7 @@ static int ppc_4xx_eth_rx (struct eth_device *dev)
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE));
- length = hw_p->rx[user_index].data_len;
+ length = hw_p->rx[user_index].data_len & 0x0fff;
/* Pass the packet up to the protocol layers. */
/* NetReceive(NetRxPackets[rxIdx], length - 4); */
@@ -1718,6 +1946,7 @@ int ppc_4xx_eth_initialize (bd_t * bis)
/* set the MAL IER ??? names may change with new spec ??? */
#if defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
mal_ier =
MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
index a5b9690..941d4dc 100644
--- a/cpu/ppc4xx/4xx_pci.c
+++ b/cpu/ppc4xx/4xx_pci.c
@@ -531,7 +531,8 @@ int pci_440_init (struct pci_controller *hose)
out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
out32r( PCIX0_BRDGOPT1, 0x04000060 ); /* PLB Rq pri highest */
out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1 */
#elif defined(PCIX0_BRDGOPT1)
@@ -549,7 +550,8 @@ int pci_440_init (struct pci_controller *hose)
out32r( PCIX0_POM0SA, 0 ); /* disable */
out32r( PCIX0_POM1SA, 0 ); /* disable */
out32r( PCIX0_POM2SA, 0 ); /* disable */
-#if defined(CONFIG_440SPE)
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
out32r( PCIX0_POM0LAL, 0x10000000 );
out32r( PCIX0_POM0LAH, 0x0000000c );
#else
@@ -586,7 +588,8 @@ void pci_init_board(void)
int busno;
busno = pci_440_init (&ppc440_hose);
-#if defined(CONFIG_440SPE)
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
pcie_setup_hoses(busno + 1);
#endif
}
diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c
index 3af9862..f9a1988 100644
--- a/cpu/ppc4xx/4xx_pcie.c
+++ b/cpu/ppc4xx/4xx_pcie.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2006 - 2007
+ * (C) Copyright 2006 - 2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (c) 2005 Cisco Systems. All rights reserved.
@@ -31,7 +31,8 @@
#include <common.h>
#include <pci.h>
-#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX)) && \
+#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
defined(CONFIG_PCI)
#include <asm/4xx_pcie.h>
@@ -306,9 +307,8 @@ static int check_error(void)
int err = 0;
/* SDR0_PEGPLLLCT1 reset */
- if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
+ if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000))
printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0);
- }
valPE0 = SDR_READ(PESDR0_RCSSET);
valPE1 = SDR_READ(PESDR1_RCSSET);
@@ -400,7 +400,108 @@ int ppc4xx_init_pcie(void)
}
return 0;
}
-#else
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static void ppc4xx_setup_utl(u32 port)
+{
+ volatile void *utl_base = NULL;
+
+ /*
+ * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* BAM 11100000=4KB */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE)
+ + 0x1000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* BAM 11100000=4KB */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+ break;
+ }
+ utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port);
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32(utl_base + PEUTL_PBCTL, 0x0800000c); /* PLBME, CRRE */
+ out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+ out_be32(utl_base + PEUTL_INTR, 0x02000000);
+ out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000); /* OPD = 512 Bytes */
+ out_be32(utl_base + PEUTL_PBBSZ, 0x00000000); /* Max 512 Bytes */
+ out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000);
+ out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000); /* IPD = 512 Bytes */
+ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+ out_be32(utl_base + PEUTL_PCTL, 0x80800066); /* VRB,TXE,timeout=default */
+}
+
+/*
+ * TODO: double check PCI express SDR based on the latest user manual
+ * Some registers specified here no longer exist.. has to be
+ * updated based on the final EAS spec.
+ */
+static int check_error(void)
+{
+ u32 valPE0, valPE1;
+ int err = 0;
+
+ valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0));
+ valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1));
+
+ /* SDR0_PExRCSSET rstgu */
+ if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) {
+ printf("PCIE: SDR0_PExRCSSET rstgu error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstdl */
+ if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) {
+ printf("PCIE: SDR0_PExRCSSET rstdl error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstpyn */
+ if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) {
+ printf("PCIE: SDR0_PExRCSSET rstpyn error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET hldplb */
+ if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) {
+ printf("PCIE: SDR0_PExRCSSET hldplb error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rdy */
+ if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) {
+ printf("PCIE: SDR0_PExRCSSET rdy error\n");
+ err = -1;
+ }
+
+ return err;
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual
+ * TODO: double check PE SDR PLL Register with the updated user manual.
+ */
+int ppc4xx_init_pcie(void)
+{
+ if (check_error())
+ return -1;
+
+ return 0;
+}
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX)
static void ppc4xx_setup_utl(u32 port)
{
u32 utl_base;
@@ -450,7 +551,7 @@ int ppc4xx_init_pcie(void)
*/
return 0;
}
-#endif
+#endif /* CONFIG_405EX */
/*
* Board-specific pcie initialization
@@ -511,6 +612,82 @@ int __ppc4xx_init_pcie_port_hw(int port, int rootport)
}
#endif /* CONFIG_440SPE */
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+ u32 val = 1 << 24;
+ u32 utlset1;
+
+ if (rootport) {
+ val = PTYPE_ROOT_PORT << 20;
+ utlset1 = 0x21222222;
+ } else {
+ val = PTYPE_LEGACY_ENDPOINT << 20;
+ utlset1 = 0x20222222;
+ }
+
+ if (port == 0) {
+ val |= LNKW_X1 << 12;
+ } else {
+ val |= LNKW_X4 << 12;
+ utlset1 |= 0x00101101;
+ }
+
+ SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+ SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+ SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000);
+
+ switch (port) {
+ case 0:
+ SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR0_L0DRV, 0x00000136);
+ SDR_WRITE(PESDR0_L0CLK, 0x00000006);
+
+ SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000);
+ break;
+
+ case 1:
+ SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L0DRV, 0x00000136);
+ SDR_WRITE(PESDR1_L1DRV, 0x00000136);
+ SDR_WRITE(PESDR1_L2DRV, 0x00000136);
+ SDR_WRITE(PESDR1_L3DRV, 0x00000136);
+ SDR_WRITE(PESDR1_L0CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L1CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L2CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L3CLK, 0x00000006);
+
+ SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000);
+ break;
+ }
+
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) |
+ (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
+
+ /* Poll for PHY reset */
+ switch (port) {
+ case 0:
+ while (!(SDR_READ(PESDR0_RSTSTA) & 0x1))
+ udelay(10);
+ break;
+ case 1:
+ while (!(SDR_READ(PESDR1_RSTSTA) & 0x1))
+ udelay(10);
+ break;
+ }
+
+ SDR_WRITE(SDRN_PESDR_RCSSET(port),
+ (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+ ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
+ PESDRx_RCSSET_RSTPYN);
+
+ return 0;
+}
+#endif /* CONFIG_440SPE */
+
#if defined(CONFIG_405EX)
int __ppc4xx_init_pcie_port_hw(int port, int rootport)
{
@@ -564,12 +741,12 @@ __attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
* range (hangs the core upon config transaction attempts when set
* otherwise) while revA uses c_nnnn_nnnn.
*
- * For revA:
+ * For 440SPe revA:
* PCIE0: 0xc_4000_0000
* PCIE1: 0xc_8000_0000
* PCIE2: 0xc_c000_0000
*
- * For revB:
+ * For 440SPe revB:
* PCIE0: 0xd_0000_0000
* PCIE1: 0xd_2000_0000
* PCIE2: 0xd_4000_0000
@@ -577,6 +754,10 @@ __attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
* For 405EX:
* PCIE0: 0xa000_0000
* PCIE1: 0xc000_0000
+ *
+ * For 460EX/GT:
+ * PCIE0: 0xd_0000_0000
+ * PCIE1: 0xd_2000_0000
*/
static inline u64 ppc4xx_get_cfgaddr(int port)
{
@@ -609,6 +790,12 @@ static inline u64 ppc4xx_get_cfgaddr(int port)
}
}
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ if (port == 0)
+ return 0x0000000d00000000ULL;
+ else
+ return 0x0000000d20000000ULL;
+#endif
}
/*
diff --git a/cpu/ppc4xx/4xx_uart.c b/cpu/ppc4xx/4xx_uart.c
index 3d1124e..ffbc222 100644
--- a/cpu/ppc4xx/4xx_uart.c
+++ b/cpu/ppc4xx/4xx_uart.c
@@ -64,16 +64,22 @@ DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_440)
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000300
-#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000400
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART0_BASE (CFG_PERIPHERAL_BASE + 0x00000300)
+#define UART1_BASE (CFG_PERIPHERAL_BASE + 0x00000400)
#else
-#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000200
-#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300
+#define UART0_BASE (CFG_PERIPHERAL_BASE + 0x00000200)
+#define UART1_BASE (CFG_PERIPHERAL_BASE + 0x00000300)
#endif
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
-#define UART2_BASE CFG_PERIPHERAL_BASE + 0x00000600
+#define UART2_BASE (CFG_PERIPHERAL_BASE + 0x00000600)
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART2_BASE (CFG_PERIPHERAL_BASE + 0x00000500)
+#define UART3_BASE (CFG_PERIPHERAL_BASE + 0x00000600)
#endif
#if defined(CONFIG_440GP)
@@ -94,11 +100,13 @@ DECLARE_GLOBAL_DATA_PTR;
#define UART1_SDR sdr_uart1
#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPe)
+ defined(CONFIG_440SP) || defined(CONFIG_440SPe) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
#define UART2_SDR sdr_uart2
#endif
#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
- defined(CONFIG_440GR) || defined(CONFIG_440GRx)
+ defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
#define UART3_SDR sdr_uart3
#endif
#define MFREG(a, d) mfsdr(a, d)
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index 9e9c685..54cc256 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -54,7 +54,8 @@ static int pci_async_enabled(void)
#endif
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
unsigned long val;
mfsdr(sdr_sdstp1, val);
@@ -86,7 +87,8 @@ static int pci_arbiter_enabled(void)
return (val & 0x80000000);
#endif
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
unsigned long val;
mfsdr(sdr_pci0, val);
@@ -167,6 +169,21 @@ static char *bootstrap_str[] = {
static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "PCI",
+ "PCI",
+ "EBC (16 bits)",
+ "NAND (8 bits)",
+ "I2C (Addr 0x54)", /* A8 */
+ "I2C (Addr 0x52)", /* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
#if defined(CONFIG_405EZ)
#define SDR0_PINSTP_SHIFT 28
static char *bootstrap_str[] = {
@@ -257,8 +274,12 @@ int checkcpu (void)
puts("05");
#endif
#if defined(CONFIG_440)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ puts("60");
+#else
puts("40");
#endif
+#endif
switch (pvr) {
case PVR_405GP_RB:
@@ -448,6 +469,26 @@ int checkcpu (void)
strcpy(addstr, "No RAID 6 support");
break;
+ case PVR_460EX_RA:
+ puts("EX Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+
+ case PVR_460EX_SE_RA:
+ puts("EX Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_460GT_RA:
+ puts("GT Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+
+ case PVR_460GT_SE_RA:
+ puts("GT Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
default:
printf (" UNKNOWN (PVR=%08x)", pvr);
break;
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c
index 2e0dd6f..5d15e2f 100644
--- a/cpu/ppc4xx/cpu_init.c
+++ b/cpu/ppc4xx/cpu_init.c
@@ -302,5 +302,6 @@ int cpu_init_r (void)
}
#endif /* defined(CONFIG_405GP) */
#endif /* defined(CONFIG_405GP) || defined(CONFIG_405EP) */
+
return (0);
}
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index 2f3dc32..698bcb5 100644
--- a/cpu/ppc4xx/interrupts.c
+++ b/cpu/ppc4xx/interrupts.c
@@ -38,7 +38,22 @@
DECLARE_GLOBAL_DATA_PTR;
-/****************************************************************************/
+/*
+ * Define the number of UIC's
+ */
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UIC_MAX 4
+#elif defined(CONFIG_440GX) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+#define UIC_MAX 3
+#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define UIC_MAX 2
+#else
+#define UIC_MAX 1
+#endif
/*
* CPM interrupt vector functions.
@@ -49,28 +64,15 @@ struct irq_action {
int count;
};
-static struct irq_action irq_vecs[32];
-void uic0_interrupt( void * parms); /* UIC0 handler */
+static struct irq_action irq_vecs[UIC_MAX * 32];
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-static struct irq_action irq_vecs1[32]; /* For UIC1 */
+u32 get_dcr(u16);
+void set_dcr(u16, u32);
-void uic1_interrupt( void * parms); /* UIC1 handler */
-
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-static struct irq_action irq_vecs2[32]; /* For UIC2 */
-void uic2_interrupt( void * parms); /* UIC2 handler */
-#endif /* CONFIG_440GX CONFIG_440SPE */
-
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-static struct irq_action irq_vecs3[32]; /* For UIC3 */
-void uic3_interrupt( void * parms); /* UIC3 handler */
-#endif /* CONFIG_440SPE */
-
-#endif /* CONFIG_440 */
+#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
+static void uic_cascade_interrupt(void *para);
+#endif
-/****************************************************************************/
#if defined(CONFIG_440)
/* SPRN changed in 440 */
@@ -99,8 +101,6 @@ static __inline__ void set_evpr(unsigned long val)
}
#endif /* defined(CONFIG_440 */
-/****************************************************************************/
-
int interrupt_init_cpu (unsigned *decrementer_count)
{
int vec;
@@ -112,26 +112,10 @@ int interrupt_init_cpu (unsigned *decrementer_count)
/*
* Mark all irqs as free
*/
- for (vec=0; vec<32; vec++) {
+ for (vec = 0; vec < (UIC_MAX * 32); vec++) {
irq_vecs[vec].handler = NULL;
irq_vecs[vec].arg = NULL;
irq_vecs[vec].count = 0;
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
- irq_vecs1[vec].handler = NULL;
- irq_vecs1[vec].arg = NULL;
- irq_vecs1[vec].count = 0;
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- irq_vecs2[vec].handler = NULL;
- irq_vecs2[vec].arg = NULL;
- irq_vecs2[vec].count = 0;
-#endif /* CONFIG_440GX */
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- irq_vecs3[vec].handler = NULL;
- irq_vecs3[vec].arg = NULL;
- irq_vecs3[vec].count = 0;
-#endif /* CONFIG_440SPE */
-#endif
}
#ifdef CONFIG_4xx
@@ -172,15 +156,21 @@ int interrupt_init_cpu (unsigned *decrementer_count)
*/
set_evpr(0x00000000);
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
#if !defined(CONFIG_440GX)
+#if (UIC_MAX > 1)
/* Install the UIC1 handlers */
- irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0);
- irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0);
+ irq_install_handler(VECNUM_UIC1NC, uic_cascade_interrupt, 0);
+ irq_install_handler(VECNUM_UIC1C, uic_cascade_interrupt, 0);
#endif
+#if (UIC_MAX > 2)
+ irq_install_handler(VECNUM_UIC2NC, uic_cascade_interrupt, 0);
+ irq_install_handler(VECNUM_UIC2C, uic_cascade_interrupt, 0);
#endif
-
-#if defined(CONFIG_440GX)
+#if (UIC_MAX > 3)
+ irq_install_handler(VECNUM_UIC3NC, uic_cascade_interrupt, 0);
+ irq_install_handler(VECNUM_UIC3C, uic_cascade_interrupt, 0);
+#endif
+#else /* !defined(CONFIG_440GX) */
/* Take the GX out of compatibility mode
* Travis Sawyer, 9 Mar 2004
* NOTE: 440gx user manual inconsistency here
@@ -196,110 +186,24 @@ int interrupt_init_cpu (unsigned *decrementer_count)
mtdcr(uicb0er, 0x54000000);
/* None are critical */
mtdcr(uicb0cr, 0);
-#endif
+#endif /* !defined(CONFIG_440GX) */
return (0);
}
-/****************************************************************************/
-
-/*
- * Handle external interrupts
- */
-#if defined(CONFIG_440GX)
-void external_interrupt(struct pt_regs *regs)
+/* Handler for UIC interrupt */
+static void uic_interrupt(u32 uic_base, int vec_base)
{
- ulong uic_msr;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- /* 440 GX uses base uic register */
- uic_msr = mfdcr(uicb0msr);
-
- if ( (UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr) )
- uic0_interrupt(0);
-
- if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) )
- uic1_interrupt(0);
-
- if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) )
- uic2_interrupt(0);
-
- mtdcr(uicb0sr, uic_msr);
-
- return;
-
-} /* external_interrupt CONFIG_440GX */
-
-#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-void external_interrupt(struct pt_regs *regs)
-{
- ulong uic_msr;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- /* 440 SPe uses base uic register */
- uic_msr = mfdcr(uic0msr);
-
- if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) )
- uic1_interrupt(0);
-
- if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) )
- uic2_interrupt(0);
-
- if (uic_msr & ~(UICB0_ALL))
- uic0_interrupt(0);
-
- mtdcr(uic0sr, uic_msr);
-
- return;
-
-} /* external_interrupt CONFIG_440EPX & CONFIG_440GRX */
-
-#elif defined(CONFIG_440SPE)
-void external_interrupt(struct pt_regs *regs)
-{
- ulong uic_msr;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- /* 440 SPe uses base uic register */
- uic_msr = mfdcr(uic0msr);
-
- if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) )
- uic1_interrupt(0);
-
- if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) )
- uic2_interrupt(0);
-
- if ( (UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr) )
- uic3_interrupt(0);
-
- if (uic_msr & ~(UICB0_ALL))
- uic0_interrupt(0);
-
- mtdcr(uic0sr, uic_msr);
-
- return;
-} /* external_interrupt CONFIG_440SPE */
-
-#else
-
-void external_interrupt(struct pt_regs *regs)
-{
- ulong uic_msr;
- ulong msr_shift;
+ u32 uic_msr;
+ u32 msr_shift;
int vec;
/*
* Read masked interrupt status register to determine interrupt source
*/
- uic_msr = mfdcr(uicmsr);
+ uic_msr = get_dcr(uic_base + UIC_MSR);
msr_shift = uic_msr;
- vec = 0;
+ vec = vec_base;
while (msr_shift != 0) {
if (msr_shift & 0x80000000) {
@@ -312,14 +216,17 @@ void external_interrupt(struct pt_regs *regs)
/* call isr */
(*irq_vecs[vec].handler)(irq_vecs[vec].arg);
} else {
- mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector 0x%x\n", vec);
+ set_dcr(uic_base + UIC_ER,
+ get_dcr(uic_base + UIC_ER) &
+ ~(0x80000000 >> vec));
+ printf("Masking bogus interrupt vector %d"
+ " (UIC_BASE=0x%x)\n", vec, uic_base);
}
/*
* After servicing the interrupt, we have to remove the status indicator.
*/
- mtdcr(uicsr, (0x80000000 >> vec));
+ set_dcr(uic_base + UIC_SR, (0x80000000 >> vec));
}
/*
@@ -329,324 +236,150 @@ void external_interrupt(struct pt_regs *regs)
vec++;
}
}
-#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-/* Handler for UIC0 interrupt */
-void uic0_interrupt( void * parms)
+#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
+static void uic_cascade_interrupt(void *para)
{
- ulong uic_msr;
- ulong msr_shift;
- int vec;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic_msr = mfdcr(uicmsr);
- msr_shift = uic_msr;
- vec = 0;
-
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs[vec].count++;
-
- if (irq_vecs[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs[vec].handler)(irq_vecs[vec].arg);
- } else {
- mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic0) 0x%x\n", vec);
- }
-
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uicsr, (0x80000000 >> vec));
- }
-
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
+ external_interrupt(para);
}
+#endif
-#endif /* CONFIG_440GX */
-
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-/* Handler for UIC1 interrupt */
-void uic1_interrupt( void * parms)
-{
- ulong uic1_msr;
- ulong msr_shift;
- int vec;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic1_msr = mfdcr(uic1msr);
- msr_shift = uic1_msr;
- vec = 0;
-
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs1[vec].count++;
-
- if (irq_vecs1[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg);
- } else {
- mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec);
- }
-
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uic1sr, (0x80000000 >> vec));
- }
-
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
-}
-#endif /* defined(CONFIG_440) */
+#if defined(CONFIG_440)
+#if defined(CONFIG_440GX)
+/* 440GX uses base uic register */
+#define UIC_BMSR uicb0msr
+#define UIC_BSR uicb0sr
+#else
+#define UIC_BMSR uic0msr
+#define UIC_BSR uic0sr
+#endif
+#else /* CONFIG_440 */
+#define UIC_BMSR uicmsr
+#define UIC_BSR uicsr
+#endif /* CONFIG_440 */
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-/* Handler for UIC2 interrupt */
-void uic2_interrupt( void * parms)
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
{
- ulong uic2_msr;
- ulong msr_shift;
- int vec;
+ u32 uic_msr;
/*
* Read masked interrupt status register to determine interrupt source
*/
- uic2_msr = mfdcr(uic2msr);
- msr_shift = uic2_msr;
- vec = 0;
+ uic_msr = mfdcr(UIC_BMSR);
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs2[vec].count++;
-
- if (irq_vecs2[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs2[vec].handler)(irq_vecs2[vec].arg);
- } else {
- mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec);
- }
-
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uic2sr, (0x80000000 >> vec));
- }
-
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
-}
-#endif /* defined(CONFIG_440GX) */
-
-#if defined(CONFIG_440SPE)
-/* Handler for UIC3 interrupt */
-void uic3_interrupt( void * parms)
-{
- ulong uic3_msr;
- ulong msr_shift;
- int vec;
+#if (UIC_MAX > 1)
+ if ((UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr))
+ uic_interrupt(UIC1_DCR_BASE, 32);
+#endif
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic3_msr = mfdcr(uic3msr);
- msr_shift = uic3_msr;
- vec = 0;
+#if (UIC_MAX > 2)
+ if ((UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr))
+ uic_interrupt(UIC2_DCR_BASE, 64);
+#endif
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs3[vec].count++;
+#if (UIC_MAX > 3)
+ if ((UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr))
+ uic_interrupt(UIC3_DCR_BASE, 96);
+#endif
- if (irq_vecs3[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs3[vec].handler)(irq_vecs3[vec].arg);
- } else {
- mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic3) 0x%x\n", vec);
- }
+#if defined(CONFIG_440)
+#if !defined(CONFIG_440GX)
+ if (uic_msr & ~(UICB0_ALL))
+ uic_interrupt(UIC0_DCR_BASE, 0);
+#else
+ if ((UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr))
+ uic_interrupt(UIC0_DCR_BASE, 0);
+#endif
+#else /* CONFIG_440 */
+ uic_interrupt(UIC0_DCR_BASE, 0);
+#endif /* CONFIG_440 */
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uic3sr, (0x80000000 >> vec));
- }
+ mtdcr(UIC_BSR, uic_msr);
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
+ return;
}
-#endif /* defined(CONFIG_440SPE) */
-
-/****************************************************************************/
/*
* Install and free a interrupt handler.
*/
-
-void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
+void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
{
- struct irq_action *irqa = irq_vecs;
- int i = vec;
-
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- if ((vec > 31) && (vec < 64)) {
- i = vec - 32;
- irqa = irq_vecs1;
- } else if (vec > 63) {
- i = vec - 64;
- irqa = irq_vecs2;
- }
-#else /* CONFIG_440GX */
- if (vec > 31) {
- i = vec - 32;
- irqa = irq_vecs1;
- }
-#endif /* CONFIG_440GX */
-#endif /* CONFIG_440 */
+ int i;
/*
- * print warning when replacing with a different irq vector
+ * Print warning when replacing with a different irq vector
*/
- if ((irqa[i].handler != NULL) && (irqa[i].handler != handler)) {
- printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
- vec, (uint) handler, (uint) irqa[i].handler);
+ if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
+ printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+ vec, (uint) handler, (uint) irq_vecs[vec].handler);
}
- irqa[i].handler = handler;
- irqa[i].arg = arg;
-
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- if ((vec > 31) && (vec < 64))
- mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
- else if (vec > 63)
- mtdcr (uic2er, mfdcr (uic2er) | (0x80000000 >> i));
- else
-#endif /* CONFIG_440GX */
- if (vec > 31)
- mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
- else
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
+
+ i = vec & 0x1f;
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(uicer, mfdcr(uicer) | (0x80000000 >> i));
+#if (UIC_MAX > 1)
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i));
+#endif
+#if (UIC_MAX > 2)
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(uic2er, mfdcr(uic2er) | (0x80000000 >> i));
#endif
- mtdcr (uicer, mfdcr (uicer) | (0x80000000 >> i));
-#if 0
- printf ("Install interrupt for vector %d ==> %p\n", vec, handler);
+#if (UIC_MAX > 3)
+ else if (vec >= 96)
+ mtdcr(uic3er, mfdcr(uic3er) | (0x80000000 >> i));
#endif
+
+ debug("Install interrupt for vector %d ==> %p\n", vec, handler);
}
void irq_free_handler (int vec)
{
- struct irq_action *irqa = irq_vecs;
- int i = vec;
-
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- if ((vec > 31) && (vec < 64)) {
- irqa = irq_vecs1;
- i = vec - 32;
- } else if (vec > 63) {
- irqa = irq_vecs2;
- i = vec - 64;
- }
-#endif /* CONFIG_440GX */
- if (vec > 31) {
- irqa = irq_vecs1;
- i = vec - 32;
- }
-#endif
+ int i;
-#if 0
- printf ("Free interrupt for vector %d ==> %p\n",
- vec, irq_vecs[vec].handler);
-#endif
+ debug("Free interrupt for vector %d ==> %p\n",
+ vec, irq_vecs[vec].handler);
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- if ((vec > 31) && (vec < 64))
- mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
- else if (vec > 63)
- mtdcr (uic2er, mfdcr (uic2er) & ~(0x80000000 >> i));
- else
-#endif /* CONFIG_440GX */
- if (vec > 31)
- mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
- else
+ i = vec & 0x1f;
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i));
+#if (UIC_MAX > 1)
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i));
+#endif
+#if (UIC_MAX > 2)
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> i));
+#endif
+#if (UIC_MAX > 3)
+ else if (vec >= 96)
+ mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> i));
#endif
- mtdcr (uicer, mfdcr (uicer) & ~(0x80000000 >> i));
- irqa[i].handler = NULL;
- irqa[i].arg = NULL;
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
}
-/****************************************************************************/
-
void timer_interrupt_cpu (struct pt_regs *regs)
{
/* nothing to do here */
return;
}
-/****************************************************************************/
-
#if defined(CONFIG_CMD_IRQ)
-
-/*******************************************************************************
- *
- * irqinfo - print information about PCI devices
- *
- */
-int
-do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int vec;
- printf ("\nInterrupt-Information:\n");
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
- printf ("\nUIC 0\n");
-#endif
+ printf ("Interrupt-Information:\n");
printf ("Nr Routine Arg Count\n");
- for (vec=0; vec<32; vec++) {
+ for (vec = 0; vec < (UIC_MAX * 32); vec++) {
if (irq_vecs[vec].handler != NULL) {
printf ("%02d %08lx %08lx %d\n",
vec,
@@ -656,46 +389,6 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
}
-#if defined(CONFIG_440) || defined(CONFIG_405EX)
- printf ("\nUIC 1\n");
- printf ("Nr Routine Arg Count\n");
-
- for (vec=0; vec<32; vec++) {
- if (irq_vecs1[vec].handler != NULL)
- printf ("%02d %08lx %08lx %d\n",
- vec+31, (ulong)irq_vecs1[vec].handler,
- (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count);
- }
- printf("\n");
-#endif
-
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
- printf ("\nUIC 2\n");
- printf ("Nr Routine Arg Count\n");
-
- for (vec=0; vec<32; vec++) {
- if (irq_vecs2[vec].handler != NULL)
- printf ("%02d %08lx %08lx %d\n",
- vec+63, (ulong)irq_vecs2[vec].handler,
- (ulong)irq_vecs2[vec].arg, irq_vecs2[vec].count);
- }
- printf("\n");
-#endif
-
-#if defined(CONFIG_440SPE)
- printf ("\nUIC 3\n");
- printf ("Nr Routine Arg Count\n");
-
- for (vec=0; vec<32; vec++) {
- if (irq_vecs3[vec].handler != NULL)
- printf ("%02d %08lx %08lx %d\n",
- vec+63, (ulong)irq_vecs3[vec].handler,
- (ulong)irq_vecs3[vec].arg, irq_vecs3[vec].count);
- }
- printf("\n");
-#endif
-
return 0;
}
#endif
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index 3978773..c882720 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -29,6 +29,11 @@
|
+-----------------------------------------------------------------------------*/
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
#include <common.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -38,7 +43,10 @@
#include <405_mal.h>
#include <miiphy.h>
-#undef ET_DEBUG
+#if !defined(CONFIG_PHY_CLK_FREQ)
+#define CONFIG_PHY_CLK_FREQ 0
+#endif
+
/***********************************************************/
/* Dump out to the screen PHY regs */
/***********************************************************/
@@ -164,9 +172,21 @@ int phy_setup_aneg (char *devname, unsigned char addr)
/***********************************************************/
/* read a phy reg and return the value with a rc */
/***********************************************************/
+/* AMCC_TODO:
+ * Find out of the choice for the emac for MDIO is from the bridges,
+ * i.e. ZMII or RGMII as approporiate. If the bridges are not used
+ * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL]
+ * used? If so, then this routine below does not apply to the 460EX/GT.
+ *
+ * sr: Currently on 460EX only EMAC0 works with MDIO, so we always
+ * return EMAC0 offset here
+ */
unsigned int miiphy_getemac_offset (void)
{
-#if (defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)) && defined(CONFIG_NET_MULTI)
+#if (defined(CONFIG_440) && \
+ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+ !defined(CONFIG_460EX) && !defined(CONFIG_460GT)) && \
+ defined(CONFIG_NET_MULTI)
unsigned long zmii;
unsigned long eoffset;
@@ -217,153 +237,97 @@ unsigned int miiphy_getemac_offset (void)
#endif
}
-int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
- unsigned short *value)
+static int emac_miiphy_wait(u32 emac_reg)
{
- unsigned long sta_reg; /* STA scratch area */
- unsigned long i;
- unsigned long emac_reg;
+ u32 sta_reg;
+ int i;
- emac_reg = miiphy_getemac_offset ();
- /* see if it is ready for 1000 nsec */
+ /* wait for completion */
i = 0;
-
- /* see if it is ready for sec */
- while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
- EMAC_STACR_OC_MASK) {
- udelay (7);
- if (i > 5) {
-#ifdef ET_DEBUG
- sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
- printf ("read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
- printf ("read err 1\n");
-#endif
+ do {
+ sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
+ if (i++ > 5) {
+ debug("%s [%d]: Timeout! EMAC_STACR=0x%0x\n", __func__,
+ __LINE__, sta_reg);
return -1;
}
- i++;
- }
+ udelay(10);
+ } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK);
+
+ return 0;
+}
+
+static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
+{
+ u32 emac_reg;
+ u32 sta_reg;
+
+ emac_reg = miiphy_getemac_offset();
+
+ /* wait for completion */
+ if (emac_miiphy_wait(emac_reg) != 0)
+ return -1;
+
sta_reg = reg; /* reg address */
+
/* set clock (50Mhz) and read flags */
#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
- sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ;
+ sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd;
#else
- sta_reg |= EMAC_STACR_READ;
+ sta_reg |= cmd;
#endif
#else
- sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
+ sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ;
#endif
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \
- !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
- !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
- !defined(CONFIG_405EX)
+ /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */
sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
-#endif
- sta_reg = sta_reg | (addr << 5); /* Phy address */
+ sta_reg = sta_reg | ((u32)addr << 5); /* Phy address */
sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
+ if (cmd == EMAC_STACR_WRITE)
+ memcpy(&sta_reg, &value, 2); /* put in data */
+
out_be32((void *)EMAC_STACR + emac_reg, sta_reg);
-#ifdef ET_DEBUG
- printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
-#endif
+ debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
- sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
-#ifdef ET_DEBUG
- printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
-#endif
- i = 0;
- while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
- udelay (7);
- if (i > 5)
- return -1;
+ /* wait for completion */
+ if (emac_miiphy_wait(emac_reg) != 0)
+ return -1;
- i++;
- sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
-#ifdef ET_DEBUG
- printf ("a22: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
-#endif
- }
+ debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
if ((sta_reg & EMAC_STACR_PHYE) != 0)
return -1;
- *value = *(short *)(&sta_reg);
return 0;
+}
-} /* phy_read */
-
-/***********************************************************/
-/* write a phy reg and return the value with a rc */
-/***********************************************************/
-
-int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
- unsigned short value)
+int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
+ unsigned short *value)
{
- unsigned long sta_reg; /* STA scratch area */
- unsigned long i;
+ unsigned long sta_reg;
unsigned long emac_reg;
emac_reg = miiphy_getemac_offset ();
- /* see if it is ready for 1000 nsec */
- i = 0;
-
- while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
- EMAC_STACR_OC_MASK) {
- if (i > 5)
- return -1;
-
- udelay (7);
- i++;
- }
- sta_reg = 0;
- sta_reg = reg; /* reg address */
- /* set clock (50Mhz) and read flags */
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
-#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
- sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE;
-#else
- sta_reg |= EMAC_STACR_WRITE;
-#endif
-#else
- sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
-#endif
-
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \
- !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
- !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
- !defined(CONFIG_405EX)
- sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */
-#endif
- sta_reg = sta_reg | ((unsigned long)addr << 5); /* Phy address */
- sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
- memcpy (&sta_reg, &value, 2); /* put in data */
- out_be32((void *)EMAC_STACR + emac_reg, sta_reg);
+ if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
+ return -1;
- /* wait for completion */
- i = 0;
sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
-#ifdef ET_DEBUG
- printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
-#endif
- while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
- udelay (7);
- if (i > 5)
- return -1;
-
- i++;
- sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
-#ifdef ET_DEBUG
- printf ("a32: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
-#endif
- }
-
- if ((sta_reg & EMAC_STACR_PHYE) != 0)
- return -1;
+ *value = *(u16 *)(&sta_reg);
return 0;
+}
-} /* phy_write */
+/***********************************************************/
+/* write a phy reg and return the value with a rc */
+/***********************************************************/
+
+int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
+ unsigned short value)
+{
+ return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
+}
diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c
index 9e2229d..5b2ae88 100644
--- a/cpu/ppc4xx/ndfc.c
+++ b/cpu/ppc4xx/ndfc.c
@@ -34,7 +34,8 @@
#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \
(defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EZ) || defined(CONFIG_405EX))
+ defined(CONFIG_405EZ) || defined(CONFIG_405EX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
#include <nand.h>
#include <linux/mtd/ndfc.h>
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 9006614..fa79952 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2000-2007
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
@@ -35,6 +35,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define DEBUGF(fmt,args...)
#endif
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
@@ -201,7 +203,126 @@ ulong get_PCI_freq (void)
#elif defined(CONFIG_440)
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static u8 pll_fwdv_multi_bits[] = {
+ /* values for: 1 - 16 */
+ 0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
+ 0x05, 0x08, 0x07, 0x02, 0x0b, 0x06
+};
+
+u32 get_cpr0_fwdv(unsigned long cpr_reg_fwdv)
+{
+ u32 index;
+
+ for (index = 0; index < ARRAY_SIZE(pll_fwdv_multi_bits); index++)
+ if (cpr_reg_fwdv == (u32)pll_fwdv_multi_bits[index])
+ return index + 1;
+
+ return 0;
+}
+
+static u8 pll_fbdv_multi_bits[] = {
+ /* values for: 1 - 100 */
+ 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
+ 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
+ 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
+ 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
+ 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
+ 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
+ 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
+ 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
+ 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
+ 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
+ /* values for: 101 - 200 */
+ 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
+ 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
+ 0x20, 0xc0, 0x01, 0x83, 0x77, 0xff, 0x1f, 0xbf, 0x7f, 0xfe,
+ 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
+ 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
+ 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
+ 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
+ 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
+ 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
+ 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
+ /* values for: 201 - 255 */
+ 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
+ 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
+ 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
+ 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
+ 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
+ 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */
+};
+
+u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv)
+{
+ u32 index;
+
+ for (index = 0; index < ARRAY_SIZE(pll_fbdv_multi_bits); index++)
+ if (cpr_reg_fbdv == (u32)pll_fbdv_multi_bits[index])
+ return index + 1;
+
+ return 0;
+}
+
+/*
+ * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
+ * with latest EAS
+ */
+void get_sys_info (sys_info_t * sysInfo)
+{
+ unsigned long strp0;
+ unsigned long strp1;
+ unsigned long temp;
+ unsigned long m;
+ unsigned long plbedv0;
+
+ /* Extract configured divisors */
+ mfsdr(sdr_sdstp0, strp0);
+ mfsdr(sdr_sdstp1, strp1);
+
+ temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4);
+ sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
+
+ temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK);
+ sysInfo->pllFwdDivB = get_cpr0_fwdv(temp);
+
+ temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8;
+ sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
+
+ temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26;
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+
+ /* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */
+ temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24;
+ sysInfo->pllExtBusDiv = temp ? temp : 4;
+
+ temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29;
+ plbedv0 = temp ? temp: 8;
+
+ /* Calculate 'M' based on feedback source */
+ temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+ if (temp == 0) {
+ /* PLL internal feedback */
+ m = sysInfo->pllFbkDiv;
+ } else {
+ /* PLL PerClk feedback */
+ m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv *
+ sysInfo->pllExtBusDiv;
+ }
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0;
+ sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+ sysInfo->freqDDR = sysInfo->freqPLB;
+ sysInfo->freqUART = sysInfo->freqPLB;
+
+ return;
+}
+
+#elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
void get_sys_info (sys_info_t *sysInfo)
{
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index d8df67b..8d2777d 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -403,7 +403,8 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
2:
#if defined(CONFIG_NAND_SPL)
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
/*
* Enable internal SRAM (only on 440EPx/GRx, 440EP/GR have no OCM)
*/
@@ -415,6 +416,11 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
mfdcr r1,isram0_pmeg
and r1,r1,r2 /* Disable pwr mgmt */
mtdcr isram0_pmeg,r1
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ lis r1,0x4000 /* BAS = 8000_0000 */
+ ori r1,r1,0x4580 /* 16k */
+ mtdcr isram0_sb0cr,r1
+#endif
#endif
#if defined(CONFIG_440EP)
/*
@@ -672,7 +678,9 @@ _start:
/* 440EP & 440GR are only 440er PPC's without internal SRAM */
#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR)
/* not all PPC's have internal SRAM usable as L2-cache */
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */
#endif
@@ -711,6 +719,10 @@ _start:
lis r1, 0x0003
ori r1,r1, 0x0984 /* fourth 64k */
mtdcr isram0_sb3cr,r1
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ lis r1,0x4000 /* BAS = 8000_0000 */
+ ori r1,r1,0x4580 /* 16k */
+ mtdcr isram0_sb0cr,r1
#elif defined(CONFIG_440GP)
ori r1,r1,0x0380 /* 8k rw */
mtdcr isram0_sb0cr,r1
@@ -1370,7 +1382,8 @@ relocate_code:
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
/*
* On some 440er platforms the cache is enabled in the first TLB (Boot-CS)
* to speed up the boot process. Now this cache needs to be disabled.
diff --git a/cpu/ppc4xx/tlb.c b/cpu/ppc4xx/tlb.c
index ed493f1..2bfcba1 100644
--- a/cpu/ppc4xx/tlb.c
+++ b/cpu/ppc4xx/tlb.c
@@ -31,9 +31,9 @@
#include <asm/mmu.h>
typedef struct region {
- unsigned long base;
- unsigned long size;
- unsigned long tlb_word2_i_value;
+ u64 base;
+ u32 size;
+ u32 tlb_word2_i_value;
} region_t;
void remove_tlb(u32 vaddr, u32 size)
@@ -182,10 +182,10 @@ void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value)
asm("isync");
}
-static int add_tlb_entry(unsigned long phys_addr,
- unsigned long virt_addr,
- unsigned long tlb_word0_size_value,
- unsigned long tlb_word2_i_value)
+static int add_tlb_entry(u64 phys_addr,
+ u32 virt_addr,
+ u32 tlb_word0_size_value,
+ u32 tlb_word2_i_value)
{
int i;
unsigned long tlb_word0_value;
@@ -204,7 +204,8 @@ static int add_tlb_entry(unsigned long phys_addr,
/* Second, create the TLB entry */
tlb_word0_value = TLB_WORD0_EPN_ENCODE(virt_addr) | TLB_WORD0_V_ENABLE |
TLB_WORD0_TS_0 | tlb_word0_size_value;
- tlb_word1_value = TLB_WORD1_RPN_ENCODE(phys_addr) | TLB_WORD1_ERPN_ENCODE(0);
+ tlb_word1_value = TLB_WORD1_RPN_ENCODE((u32)phys_addr) |
+ TLB_WORD1_ERPN_ENCODE(phys_addr >> 32);
tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE |
TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE |
TLB_WORD2_W_DISABLE | tlb_word2_i_value |
@@ -228,10 +229,10 @@ static int add_tlb_entry(unsigned long phys_addr,
return 0;
}
-static void program_tlb_addr(unsigned long phys_addr,
- unsigned long virt_addr,
- unsigned long mem_size,
- unsigned long tlb_word2_i_value)
+static void program_tlb_addr(u64 phys_addr,
+ u32 virt_addr,
+ u32 mem_size,
+ u32 tlb_word2_i_value)
{
int rc;
int tlb_i;
@@ -331,7 +332,7 @@ static void program_tlb_addr(unsigned long phys_addr,
* Common usage for boards with SDRAM DIMM modules to dynamically
* configure the TLB's for the SDRAM
*/
-void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value)
+void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value)
{
region_t region_array;
diff --git a/cpu/s3c44b0/cpu.c b/cpu/s3c44b0/cpu.c
index 5d50b3c..eae6adb 100644
--- a/cpu/s3c44b0/cpu.c
+++ b/cpu/s3c44b0/cpu.c
@@ -155,7 +155,7 @@ int dcache_status (void)
#define HEX2BCD(x) ((((x) / 10) << 4) + (x) % 10)
#endif
-void rtc_get (struct rtc_time* tm)
+int rtc_get (struct rtc_time* tm)
{
RTCCON |= 1;
tm->tm_year = BCD2HEX(BCDYEAR);
@@ -184,6 +184,8 @@ void rtc_get (struct rtc_time* tm)
tm->tm_year += 1900;
else
tm->tm_year += 2000;
+
+ return 0;
}
void rtc_set (struct rtc_time* tm)