diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-05-21 08:56:31 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-05-21 08:56:31 +0200 |
commit | 307a6209a5dcbac88e83feee8a17a221fe0f2bee (patch) | |
tree | 6686f64861b60bc716f2c2997eeefb387f61a5f7 /arch | |
parent | c48de4beee21c3a5573cec084123c33ae08f6f7a (diff) | |
parent | fdf48169087cfd3dd29d84f5e59efaef7255b8f3 (diff) | |
download | barebox-307a6209a5dcbac88e83feee8a17a221fe0f2bee.tar.gz barebox-307a6209a5dcbac88e83feee8a17a221fe0f2bee.tar.xz |
Merge branch 'ppc' into next
Diffstat (limited to 'arch')
36 files changed, 3404 insertions, 0 deletions
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 164598f5de..d12406522e 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -12,9 +12,12 @@ choice config ARCH_MPC5XXX bool "Freescale MPC5xxx" +config ARCH_MPC85XX + bool "Freescale MPC85xx" endchoice source arch/ppc/mach-mpc5xxx/Kconfig +source arch/ppc/mach-mpc85xx/Kconfig source common/Kconfig source commands/Kconfig source net/Kconfig diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 2d9e47fe56..f0322a26b4 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -7,9 +7,17 @@ ifdef CONFIG_RELOCATABLE CPPFLAGS += -fPIC -mrelocatable endif +ifdef CONFIG_MPC85xx +CPPFLAGS += -Wa,-me500x2 -msoft-float -mno-string +endif board-$(CONFIG_MACH_PHYCORE_MPC5200B_TINY) := pcm030 +board-$(CONFIG_P2020RDB) := freescale-p2020rdb + machine-$(CONFIG_ARCH_MPC5200) := mpc5xxx +machine-$(CONFIG_ARCH_MPC85XX) := mpc85xx + +cpu-$(CONFIG_ARCH_MPC85XX) := 85xx TEXT_BASE = $(CONFIG_TEXT_BASE) diff --git a/arch/ppc/boards/freescale-p2020rdb/Makefile b/arch/ppc/boards/freescale-p2020rdb/Makefile new file mode 100644 index 0000000000..141b6806e2 --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/Makefile @@ -0,0 +1,4 @@ +obj-y += p2020rdb.o +obj-y += law.o +obj-y += tlb.o +extra-y += barebox.lds diff --git a/arch/ppc/boards/freescale-p2020rdb/barebox.lds.S b/arch/ppc/boards/freescale-p2020rdb/barebox.lds.S new file mode 100644 index 0000000000..cfccea94df --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/barebox.lds.S @@ -0,0 +1,144 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2007-2009, 2011 Freescale Semiconductor, Inc. + * + * 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 <asm-generic/barebox.lds.h> + +#define RESET_VECTOR_ADDRESS 0xeffffffc + +OUTPUT_ARCH("powerpc") + +PHDRS +{ + text PT_LOAD; + bss PT_LOAD; +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = TEXT_BASE; + + .text : + { + *(.text*) + } :text + + _etext = .; + PROVIDE (etext = .); + + .rodata : + { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } :text + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + _GOT2_TABLE_ = .; + KEEP(*(.got2)) + KEEP(*(.got)) + PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); + _FIXUP_TABLE_ = .; + KEEP(*(.fixup)) + } + __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data*) + *(.data1*) + *(.sdata*) + *(.sdata2*) + *(.dynamic*) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __barebox_cmd_start = .; + .barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + __barebox_initcalls_start = .; + .barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + __initcall_entries = (__barebox_initcalls_end - __barebox_initcalls_start)>>2; + + __usymtab_start = .; + __usymtab : { BAREBOX_SYMS } + __usymtab_end = .; + + __early_init_data_begin = .; + .early_init_data : { *(.early_init_data) } + __early_init_data_end = .; + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __init_size = __init_end - _start; + + .bootpg RESET_VECTOR_ADDRESS - 0xffc : + { + _text = .; + _stext = .; + arch/ppc/cpu-85xx/start.o (.bootpg) + } :text = 0xffff + + .resetvec RESET_VECTOR_ADDRESS : + { + arch/ppc/cpu-85xx/resetvec.o (.resetvec) + } :text = 0xffff + + . = RESET_VECTOR_ADDRESS + 0x4; + + . = 0x10000; + __bss_start = .; + .bss : + { + *(.sbss*) *(.scommon*) + *(.dynbss*) + *(.bss*) + *(COMMON) + } :bss + + . = ALIGN(4); + __bss_stop = .; + _end = . ; + PROVIDE (end = .); +} diff --git a/arch/ppc/boards/freescale-p2020rdb/config.h b/arch/ppc/boards/freescale-p2020rdb/config.h new file mode 100644 index 0000000000..c780747d00 --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/config.h @@ -0,0 +1,98 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * 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 + */ + +/* + * P2020RDB board configuration file + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#ifndef __ASSEMBLY__ +extern unsigned long get_board_sys_clk(unsigned long dummy); +#endif +#define CFG_SYS_CLK_FREQ get_board_sys_clk(0) +#define CFG_DDR_CLK_FREQ 66666666 + +#define CFG_BTB /* toggle branch predition */ + +/* + * Base addresses -- Note these are effective addresses where the + * actual resources get mapped (not physical addresses) + */ +#define CFG_CCSRBAR_DEFAULT 0xff700000 + +#define CFG_CCSRBAR 0xffe00000 /* relocated CCSRBAR */ +#define CFG_CCSRBAR_PHYS CFG_CCSRBAR + +#define CFG_IMMR CFG_CCSRBAR + +/* DDR Setup */ + +#define CFG_CHIP_SELECTS_PER_CTRL 1 + +#define CFG_SDRAM_BASE 0x00000000 + +/* These timings are adjusted for a 667Mhz clock. */ +#define CFG_SYS_DDR_CS0_BNDS 0x0000003f /* 1GB */ +#define CFG_SYS_DDR_CS0_CONFIG 0x80014202 +#define CFG_SYS_DDR_TIMING_3 0x00030000 +#define CFG_SYS_DDR_TIMING_0 0x55770802 +#define CFG_SYS_DDR_TIMING_1 0x5f599543 +#define CFG_SYS_DDR_TIMING_2 0x0fa074d1 + +#define CFG_SYS_DDR_CONTROL 0xc3000000 +#define CFG_SYS_DDR_CONTROL2 0x24401000 +#define CFG_SYS_DDR_MODE_1 0x00040852 +#define CFG_SYS_DDR_MODE_2 0x00000000 +#define CFG_SYS_MD_CNTL 0x00000000 +#define CFG_SYS_DDR_INTERVAL 0x0a280100 + +#define CFG_SYS_DDR_DATA_INIT 0xdeadbeef +#define CFG_SYS_DDR_CLK_CTRL 0x03000000 + +/* + * Memory map + * + * 0x0000_0000 0x3fff_ffff DDR 1G cacheablen + * + * Localbus non-cacheable + * 0xef00_0000 0xefff_ffff FLASH 16M non-cacheable + * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0 + */ + +/* + * Local Bus Definitions + */ +#define CFG_FLASH_BASE 0xef000000 +#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE + +#define CFG_INIT_RAM_ADDR 0xffd00000 /* stack in RAM */ +/* Leave 256 bytes for global data */ +#define CFG_INIT_SP_OFFSET (0x00004000 - 256) + +#define CFG_BR0_PRELIM (BR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | \ + BR_PS_16 | BR_V) /* NOR Base Address */ +#define CFG_OR0_PRELIM 0xff000ff7 /* NOR Options */ + +#endif /* __CONFIG_H */ diff --git a/arch/ppc/boards/freescale-p2020rdb/law.c b/arch/ppc/boards/freescale-p2020rdb/law.c new file mode 100644 index 0000000000..394c512210 --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/law.c @@ -0,0 +1,31 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/fsl_law.h> +#include <asm/mmu.h> + +struct law_entry law_table[] = { + FSL_SET_LAW(CFG_FLASH_BASE_PHYS, LAW_SIZE_16M, LAW_TRGT_IF_LBC), +}; + +int num_law_entries = ARRAY_SIZE(law_table); diff --git a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c new file mode 100644 index 0000000000..20897cbaee --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c @@ -0,0 +1,230 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * 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 <init.h> +#include <driver.h> +#include <ns16550.h> +#include <types.h> +#include <partition.h> +#include <memory.h> +#include <asm/cache.h> +#include <asm/fsl_ddr_sdram.h> +#include <asm/fsl_law.h> +#include <mach/mpc85xx.h> +#include <mach/mmu.h> +#include <mach/immap_85xx.h> +#include <mach/clocks.h> +#include <mach/early_udelay.h> + +#define VSC7385_RST_SET 0x00080000 +#define SLIC_RST_SET 0x00040000 +#define SGMII_PHY_RST_SET 0x00020000 +#define PCIE_RST_SET 0x00010000 +#define RGMII_PHY_RST_SET 0x02000000 + +#define USB_RST_CLR 0x04000000 + +#define GPIO_DIR 0x060f0000 + +#define BOARD_PERI_RST_SET (VSC7385_RST_SET | SLIC_RST_SET | \ + SGMII_PHY_RST_SET | PCIE_RST_SET | \ + RGMII_PHY_RST_SET) + +#define SYSCLK_MASK 0x00200000 +#define BOARDREV_MASK 0x10100000 +#define BOARDREV_B 0x10100000 +#define BOARDREV_C 0x00100000 +#define BOARDREV_D 0x00000000 + +#define SYSCLK_66 66666666 +#define SYSCLK_50 50000000 +#define SYSCLK_100 100000000 + +static int devices_init(void) +{ + add_cfi_flash_device(-1, CFG_FLASH_BASE, 16 << 20, 0); + + devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED, + "self0"); + return 0; +} + +device_initcall(devices_init); + +static struct NS16550_plat serial_plat = { + .clock = 0, + .shift = 0, +}; + +static int p2020_console_init(void) +{ + serial_plat.clock = fsl_get_bus_freq(0); + + add_ns16550_device(-1, 0xffe04500, 16, IORESOURCE_MEM_8BIT, + &serial_plat); + return 0; +} + +console_initcall(p2020_console_init); + +static int mem_init(void) +{ + barebox_add_memory_bank("ram0", 0x0, 1024 << 20); + + return 0; +} +mem_initcall(mem_init); + +/* + * fixed_sdram: fixed sdram settings. + */ +phys_size_t fixed_sdram(void) +{ + void __iomem *regs = (void __iomem *)(MPC85xx_DDR_ADDR); + int sdram_cfg = (SDRAM_CFG_MEM_EN | SDRAM_CFG_SREN | + SDRAM_CFG_SDRAM_TYPE_DDR2); + phys_size_t dram_size; + + /* If already enabled (running from RAM), get out */ + if (in_be32(regs + DDR_OFF(SDRAM_CFG)) & SDRAM_CFG_MEM_EN) + return fsl_get_effective_memsize(); + + out_be32(regs + DDR_OFF(CS0_BNDS), CFG_SYS_DDR_CS0_BNDS); + out_be32(regs + DDR_OFF(CS0_CONFIG), CFG_SYS_DDR_CS0_CONFIG); + out_be32(regs + DDR_OFF(TIMING_CFG_3), CFG_SYS_DDR_TIMING_3); + out_be32(regs + DDR_OFF(TIMING_CFG_0), CFG_SYS_DDR_TIMING_0); + out_be32(regs + DDR_OFF(TIMING_CFG_1), CFG_SYS_DDR_TIMING_1); + out_be32(regs + DDR_OFF(TIMING_CFG_2), CFG_SYS_DDR_TIMING_2); + out_be32(regs + DDR_OFF(SDRAM_CFG_2), CFG_SYS_DDR_CONTROL2); + out_be32(regs + DDR_OFF(SDRAM_MODE), CFG_SYS_DDR_MODE_1); + out_be32(regs + DDR_OFF(SDRAM_MODE_2), CFG_SYS_DDR_MODE_2); + out_be32(regs + DDR_OFF(SDRAM_MD_CNTL), CFG_SYS_MD_CNTL); + /* Basic refresh rate (7.8us),high temp is 3.9us */ + out_be32(regs + DDR_OFF(SDRAM_INTERVAL), + CFG_SYS_DDR_INTERVAL); + out_be32(regs + DDR_OFF(SDRAM_DATA_INIT), + CFG_SYS_DDR_DATA_INIT); + out_be32(regs + DDR_OFF(SDRAM_CLK_CNTL), + CFG_SYS_DDR_CLK_CTRL); + + out_be32(regs + DDR_OFF(SDRAM_INIT_ADDR), 0); + out_be32(regs + DDR_OFF(SDRAM_INIT_ADDR_EXT), 0); + /* + * Wait 200us for the DDR clock to stabilize. + */ + early_udelay(200); + asm volatile ("sync;isync"); + + out_be32(regs + DDR_OFF(SDRAM_CFG), sdram_cfg); + + dram_size = fsl_get_effective_memsize(); + if (fsl_set_ddr_laws(0, dram_size, LAW_TRGT_IF_DDR) < 0) + return 0; + + return dram_size; +} + +unsigned long get_board_sys_clk(ulong dummy) +{ + u32 val_gpdat, sysclk_gpio, board_rev_gpio; + void __iomem *gpio_regs = (void __iomem *)MPC85xx_GPIO_ADDR; + + val_gpdat = in_be32(gpio_regs + MPC85xx_GPIO_GPDAT); + sysclk_gpio = val_gpdat & SYSCLK_MASK; + board_rev_gpio = val_gpdat & BOARDREV_MASK; + + if (board_rev_gpio == BOARDREV_C) { + if (sysclk_gpio == 0) + return SYSCLK_66; + else + return SYSCLK_100; + } else if (board_rev_gpio == BOARDREV_B) { + if (sysclk_gpio == 0) + return SYSCLK_66; + else + return SYSCLK_50; + } else if (board_rev_gpio == BOARDREV_D) { + if (sysclk_gpio == 0) + return SYSCLK_66; + else + return SYSCLK_100; + } + return 0; +} + +static void checkboard(void) +{ + u32 val_gpdat, board_rev_gpio; + void __iomem *gpio_regs = (void __iomem *)MPC85xx_GPIO_ADDR; + + val_gpdat = in_be32(gpio_regs + MPC85xx_GPIO_GPDAT); + board_rev_gpio = val_gpdat & BOARDREV_MASK; + + if ((board_rev_gpio != BOARDREV_C) && (board_rev_gpio != BOARDREV_B) && + (board_rev_gpio != BOARDREV_D)) + panic("Unexpected Board REV %x detected!!\n", board_rev_gpio); + + setbits_be32((gpio_regs + MPC85xx_GPIO_GPDIR), GPIO_DIR); + + /* + * Bringing the following peripherals out of reset via GPIOs + * 0 = reset and 1 = out of reset + * GPIO12 - Reset to Ethernet Switch + * GPIO13 - Reset to SLIC/SLAC devices + * GPIO14 - Reset to SGMII_PHY_N + * GPIO15 - Reset to PCIe slots + * GPIO6 - Reset to RGMII PHY + * GPIO5 - Reset to USB3300 devices 1 = reset and 0 = out of reset + */ + clrsetbits_be32((gpio_regs + MPC85xx_GPIO_GPDAT), USB_RST_CLR, + BOARD_PERI_RST_SET); +} + +static int board_init_r(void) +{ + const unsigned int flashbase = CFG_FLASH_BASE; + const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1); + + checkboard(); + + /* Flush d-cache and invalidate i-cache of any FLASH data */ + flush_dcache(); + invalidate_icache(); + + /* invalidate existing TLB entry for flash */ + e500_disable_tlb(flash_esel); + + /* + * Remap Boot flash region to caching-inhibited + * so that flash can be erased properly. + */ + e500_set_tlb(1, flashbase, CFG_FLASH_BASE_PHYS, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, flash_esel, BOOKE_PAGESZ_16M, 1); + + fsl_l2_cache_init(); + + return 0; +} +core_initcall(board_init_r); diff --git a/arch/ppc/boards/freescale-p2020rdb/tlb.c b/arch/ppc/boards/freescale-p2020rdb/tlb.c new file mode 100644 index 0000000000..5f3b4a7ec7 --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/tlb.c @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * + * 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 <mach/mmu.h> + +struct fsl_e_tlb_entry tlb_table[] = { + /* TLB 0 - for temp stack in cache */ + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR, + MAS3_SX|MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024), + CFG_INIT_RAM_ADDR + (4 * 1024), + MAS3_SX|MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024), + CFG_INIT_RAM_ADDR + (8 * 1024), + MAS3_SX|MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024), + CFG_INIT_RAM_ADDR + (12 * 1024), + MAS3_SX|MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + + /* TLB 1 */ + /* *I*** - Covers boot page */ + FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 0, BOOKE_PAGESZ_4K, 1), + + /* *I*G* - CCSRBAR */ + FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 1, BOOKE_PAGESZ_1M, 1), + + /* W**G* - Flash/promjet, localbus */ + /* This will be changed to *I*G* after relocation to RAM. */ + FSL_SET_TLB_ENTRY(1, CFG_FLASH_BASE, CFG_FLASH_BASE_PHYS, + MAS3_SX|MAS3_SR, MAS2_W|MAS2_G, + 0, 2, BOOKE_PAGESZ_16M, 1), +}; + +int num_tlb_entries = ARRAY_SIZE(tlb_table); diff --git a/arch/ppc/configs/p2020rdb_defconfig b/arch/ppc/configs/p2020rdb_defconfig new file mode 100644 index 0000000000..f8a0687251 --- /dev/null +++ b/arch/ppc/configs/p2020rdb_defconfig @@ -0,0 +1,23 @@ +CONFIG_ARCH_MPC85XX=y +CONFIG_P2020RDB=y +CONFIG_P2020=y +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_FSL_ELBC=y +CONFIG_DRIVER_CFI=y +CONFIG_DRIVER_CFI_AMD=y +CONFIG_DRIVER_CFI_INTEL=n +CONFIG_DRIVER_CFI_BANK_WIDTH_1=n +CONFIG_DRIVER_CFI_BANK_WIDTH_2=y +CONFIG_DRIVER_CFI_BANK_WIDTH_4=n +CONFIG_MTD=y +CONFIG_MALLOC_SIZE=0x200000 +CONFIG_BAUDRATE=115200 +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_RELOCATABLE=y diff --git a/arch/ppc/cpu-85xx/Makefile b/arch/ppc/cpu-85xx/Makefile new file mode 100644 index 0000000000..3ee039778c --- /dev/null +++ b/arch/ppc/cpu-85xx/Makefile @@ -0,0 +1,4 @@ +obj-y += traps.o +obj-y += tlb.o +extra-y += start.o +extra-y += resetvec.o diff --git a/arch/ppc/cpu-85xx/fixed_ivor.S b/arch/ppc/cpu-85xx/fixed_ivor.S new file mode 100644 index 0000000000..a00a4355d3 --- /dev/null +++ b/arch/ppc/cpu-85xx/fixed_ivor.S @@ -0,0 +1,61 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. + * + * Kumar Gala <kumar.gala@freescale.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This file is intended to be included by other asm code since + * we will want to execute this on both the primary core when + * it does a bootm and the secondary core's that get released + * out of the spin table. + */ + +#define SET_IVOR(vector_number, vector_offset) \ + li r3,vector_offset@l; \ + mtspr SPRN_IVOR##vector_number,r3; + +#define SET_GIVOR(vector_number, vector_offset) \ + li r3,vector_offset@l; \ + mtspr SPRN_GIVOR##vector_number,r3; + + SET_IVOR(0, 0x020) /* Critical Input */ + SET_IVOR(1, 0x000) /* Machine Check */ + SET_IVOR(2, 0x060) /* Data Storage */ + SET_IVOR(3, 0x080) /* Instruction Storage */ + SET_IVOR(4, 0x0a0) /* External Input */ + SET_IVOR(5, 0x0c0) /* Alignment */ + SET_IVOR(6, 0x0e0) /* Program */ + SET_IVOR(7, 0x100) /* FP Unavailable */ + SET_IVOR(8, 0x120) /* System Call */ + SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ + SET_IVOR(10, 0x160) /* Decrementer */ + SET_IVOR(11, 0x180) /* Fixed Interval Timer */ + SET_IVOR(12, 0x1a0) /* Watchdog Timer */ + SET_IVOR(13, 0x1c0) /* Data TLB Error */ + SET_IVOR(14, 0x1e0) /* Instruction TLB Error */ + SET_IVOR(15, 0x040) /* Debug */ + + /* e500v1 & e500v2 only */ + SET_IVOR(32, 0x200) /* SPE Unavailable */ + SET_IVOR(33, 0x220) /* Embedded FP Data */ + SET_IVOR(34, 0x240) /* Embedded FP Round */ + + SET_IVOR(35, 0x260) /* Performance monitor */ diff --git a/arch/ppc/cpu-85xx/resetvec.S b/arch/ppc/cpu-85xx/resetvec.S new file mode 100644 index 0000000000..29555d4a00 --- /dev/null +++ b/arch/ppc/cpu-85xx/resetvec.S @@ -0,0 +1,2 @@ + .section .resetvec,"ax" + b _start_e500 diff --git a/arch/ppc/cpu-85xx/start.S b/arch/ppc/cpu-85xx/start.S new file mode 100644 index 0000000000..fd9051b4fe --- /dev/null +++ b/arch/ppc/cpu-85xx/start.S @@ -0,0 +1,1085 @@ +/* + * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2003 Motorola,Inc. + * + * 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 + */ + +/* + * U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards + * + * The processor starts at 0xfffffffc and the code is first executed in the + * last 4K page(0xfffff000-0xffffffff) in flash/rom. + */ + +#include <config.h> +#include <asm/config.h> + +#include <asm/processor.h> +#include <asm/ppc_asm.tmpl> +#include <asm/ppc_defs.h> +#include <asm/cache.h> + +#include <mach/mpc85xx.h> +#include <mach/mmu.h> + +#undef MSR_KERNEL +#define MSR_KERNEL ( MSR_ME ) /* Machine Check */ + +/* + * Set up GOT: Global Offset Table + * + * Use r12 to access the GOT + */ + START_GOT + GOT_ENTRY(_GOT2_TABLE_) + GOT_ENTRY(_FIXUP_TABLE_) + + GOT_ENTRY(_start) + GOT_ENTRY(_start_of_vectors) + GOT_ENTRY(_end_of_vectors) + GOT_ENTRY(transfer_to_handler) + GOT_ENTRY(__init_end) + GOT_ENTRY(_end) + GOT_ENTRY(__bss_start) + END_GOT + +/* + * e500 Startup -- after reset only the last 4KB of the effective + * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg + * section is located at THIS LAST page and basically does three + * things: clear some registers, set up exception tables and + * add more TLB entries for 'larger spaces'(e.g. the boot rom) to + * continue the boot procedure. + * Once the boot rom is mapped by TLB entries we can proceed + * with normal startup. + */ + + .section .bootpg,"ax" + .globl _start_e500 + +_start_e500: + +/* clear registers/arrays not reset by hardware */ + + /* L1 */ + li r0,2 + mtspr L1CSR0,r0 /* invalidate d-cache */ + mtspr L1CSR1,r0 /* invalidate i-cache */ + + mfspr r1,DBSR + mtspr DBSR,r1 /* Clear all valid bits */ + + /* Enable/invalidate the I-Cache */ + lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h + ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l + mtspr SPRN_L1CSR1,r2 +1: + mfspr r3,SPRN_L1CSR1 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h + ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l + mtspr SPRN_L1CSR1,r3 + isync +2: + mfspr r3,SPRN_L1CSR1 + andi. r1,r3,L1CSR1_ICE@l + beq 2b + + /* Enable/invalidate the D-Cache */ + lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h + ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l + mtspr SPRN_L1CSR0,r2 +1: + mfspr r3,SPRN_L1CSR0 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h + ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l + mtspr SPRN_L1CSR0,r3 + isync +2: + mfspr r3,SPRN_L1CSR0 + andi. r1,r3,L1CSR0_DCE@l + beq 2b + + /* Setup interrupt vectors */ + lis r1,TEXT_BASE@h + mtspr IVPR,r1 + + li r1,0x0100 + mtspr IVOR0,r1 /* 0: Critical input */ + li r1,0x0200 + mtspr IVOR1,r1 /* 1: Machine check */ + li r1,0x0300 + mtspr IVOR2,r1 /* 2: Data storage */ + li r1,0x0400 + mtspr IVOR3,r1 /* 3: Instruction storage */ + li r1,0x0500 + mtspr IVOR4,r1 /* 4: External interrupt */ + li r1,0x0600 + mtspr IVOR5,r1 /* 5: Alignment */ + li r1,0x0700 + mtspr IVOR6,r1 /* 6: Program check */ + li r1,0x0800 + mtspr IVOR7,r1 /* 7: floating point unavailable */ + li r1,0x0900 + mtspr IVOR8,r1 /* 8: System call */ + /* 9: Auxiliary processor unavailable(unsupported) */ + li r1,0x0a00 + mtspr IVOR10,r1 /* 10: Decrementer */ + li r1,0x0b00 + mtspr IVOR11,r1 /* 11: Interval timer */ + li r1,0x0c00 + mtspr IVOR12,r1 /* 12: Watchdog timer */ + li r1,0x0d00 + mtspr IVOR13,r1 /* 13: Data TLB error */ + li r1,0x0e00 + mtspr IVOR14,r1 /* 14: Instruction TLB error */ + li r1,0x0f00 + mtspr IVOR15,r1 /* 15: Debug */ + + /* Clear and set up some registers. */ + li r0,0x0000 + lis r1,0xffff + mtspr DEC,r0 /* prevent dec exceptions */ + mttbl r0 /* prevent fit & wdt exceptions */ + mttbu r0 + mtspr TSR,r1 /* clear all timer exception status */ + mtspr TCR,r0 /* disable all */ + mtspr ESR,r0 /* clear exception syndrome register */ + mtspr MCSR,r0 /* machine check syndrome register */ + mtxer r0 /* clear integer exception register */ + + /* Enable Time Base and Select Time Base Clock */ + lis r0,HID0_EMCP@h /* Enable machine check */ + ori r0,r0,HID0_TBEN@l /* Enable Timebase */ + mtspr HID0,r0 + + li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */ + mfspr r3,PVR + andi. r3,r3, 0xff + cmpwi r3,0x50@l /* if we are rev 5.0 or greater set MBDD */ + blt 1f + /* Set MBDD bit also */ + ori r0, r0, HID1_MBDD@l +1: + mtspr HID1,r0 + + /* Enable Branch Prediction */ +#if defined(CFG_BTB) + lis r0,BUCSR_ENABLE@h + ori r0,r0,BUCSR_ENABLE@l + mtspr SPRN_BUCSR,r0 +#endif + + lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h + ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l + + /* create a temp mapping in AS=1 to the 4M boot window */ + lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h + ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l + + lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h + ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l + + lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h + ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l + + mtspr MAS0,r6 + mtspr MAS1,r7 + mtspr MAS2,r8 + mtspr MAS3,r9 + isync + msync + tlbwe + + /* create a temp mapping in AS=1 to the stack */ + lis r6,FSL_BOOKE_MAS0(1, 14, 0)@h + ori r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l + + lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h + ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l + + lis r8,FSL_BOOKE_MAS2(CFG_INIT_RAM_ADDR, 0)@h + ori r8,r8,FSL_BOOKE_MAS2(CFG_INIT_RAM_ADDR, 0)@l + + lis r9,FSL_BOOKE_MAS3(CFG_INIT_RAM_ADDR, 0, + (MAS3_SX|MAS3_SW|MAS3_SR))@h + ori r9,r9,FSL_BOOKE_MAS3(CFG_INIT_RAM_ADDR, 0, + (MAS3_SX|MAS3_SW|MAS3_SR))@l + + mtspr MAS0,r6 + mtspr MAS1,r7 + mtspr MAS2,r8 + mtspr MAS3,r9 + isync + msync + tlbwe + + lis r6,MSR_IS|MSR_DS@h + ori r6,r6,MSR_IS|MSR_DS@l + lis r7,switch_as@h + ori r7,r7,switch_as@l + + mtspr SPRN_SRR0,r7 + mtspr SPRN_SRR1,r6 + rfi + +switch_as: +/* L1 DCache is used for initial RAM */ + + /* Allocate initial RAM in data cache. */ + lis r3,CFG_INIT_RAM_ADDR@h + ori r3,r3,CFG_INIT_RAM_ADDR@l + mfspr r2, L1CFG0 + andi. r2, r2, 0x1ff + /* cache size * 1024 / (2 * L1 line size) */ + slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT) + mtctr r2 + li r0,0 +1: + dcbz r0,r3 + dcbtls 0,r0,r3 + addi r3,r3,CACHELINE_SIZE + bdnz 1b + + /* + * Jump out the last 4K page and continue to 'normal' start. + * Calculate absolute address in FLASH and jump there. + */ + lis r3,TEXT_BASE@h + ori r3,r3,TEXT_BASE@l + addi r3,r3,_start_cont - _start + _START_OFFSET + mtlr r3 + blr + + .text + .globl _start +_start: + .long 0x62626F78 /* Magic Number */ + + .align 4 + .globl _start_cont +_start_cont: + /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache */ + lis r1,CFG_INIT_RAM_ADDR@h + ori r1,r1,CFG_INIT_SP_OFFSET@l + + li r0,0 + stwu r0,-4(r1) + stwu r0,-4(r1) /* Terminate call chain */ + + stwu r1,-8(r1) /* Save back chain and move SP */ + lis r0,RESET_VECTOR@h /* Address of reset vector */ + ori r0,r0,RESET_VECTOR@l + stwu r1,-8(r1) /* Save back chain and move SP */ + stw r0,+12(r1) /* Save return addr (underflow vect) */ + + GET_GOT + bl cpu_init_early_f + + /* switch back to AS = 0 */ + lis r3,(MSR_CE|MSR_ME|MSR_DE)@h + ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l + mtmsr r3 + isync + + bl cpu_init_f + bl initdram + b relocate_code + isync + + /* NOTREACHED - board_init_f() does not return */ + + . = EXC_OFF_SYS_RESET + .globl _start_of_vectors +_start_of_vectors: + +/* Critical input. */ + CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException) + +/* Machine check */ + MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException) + +/* Data Storage exception. */ + STD_EXCEPTION(0x0300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ + STD_EXCEPTION(0x0400, InstStorage, UnknownException) + +/* Alignment exception. */ + . = 0x0600 +Alignment: + EXCEPTION_PROLOG(SRR0, SRR1) + mfspr r4,DAR + stw r4,_DAR(r21) + mfspr r5,DSISR + stw r5,_DSISR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) + +/* Program check exception */ + . = 0x0700 +ProgramCheck: + EXCEPTION_PROLOG(SRR0, SRR1) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, + MSR_KERNEL, COPY_EE) + + /* No FPU on MPC85xx. This exception is not supposed to happen. */ + STD_EXCEPTION(0x0800, FPUnavailable, UnknownException) + + . = 0x0900 +/* + * r0 - SYSCALL number + * r3-... arguments + */ +SystemCall: + addis r11,r0,0 /* get functions table addr */ + ori r11,r11,0 /* Note: this code is patched in trap_init */ + addis r12,r0,0 /* get number of functions */ + ori r12,r12,0 + + cmplw 0,r0,r12 + bge 1f + + rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */ + add r11,r11,r0 + lwz r11,0(r11) + + li r20,0xd00-4 /* Get stack pointer */ + lwz r12,0(r20) + subi r12,r12,12 /* Adjust stack pointer */ + li r0,0xc00+_end_back-SystemCall + cmplw 0,r0,r12 /* Check stack overflow */ + bgt 1f + stw r12,0(r20) + + mflr r0 + stw r0,0(r12) + mfspr r0,SRR0 + stw r0,4(r12) + mfspr r0,SRR1 + stw r0,8(r12) + + li r12,0xc00+_back-SystemCall + mtlr r12 + mtspr SRR0,r11 + +1: SYNC + rfi +_back: + + mfmsr r11 /* Disable interrupts */ + li r12,0 + ori r12,r12,MSR_EE + andc r11,r11,r12 + SYNC /* Some chip revs need this... */ + mtmsr r11 + SYNC + + li r12,0xd00-4 /* restore regs */ + lwz r12,0(r12) + + lwz r11,0(r12) + mtlr r11 + lwz r11,4(r12) + mtspr SRR0,r11 + lwz r11,8(r12) + mtspr SRR1,r11 + + addi r12,r12,12 /* Adjust stack pointer */ + li r20,0xd00-4 + stw r12,0(r20) + + SYNC + rfi +_end_back: + + STD_EXCEPTION(0x0a00, Decrementer, UnknownException) + STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException) + STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException) + + STD_EXCEPTION(0x0d00, DataTLBError, UnknownException) + STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException) + + CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException ) + + .globl _end_of_vectors +_end_of_vectors: + + . = . + (0x100 - ( . & 0xff )) /* align for debug */ + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ + .globl transfer_to_handler +transfer_to_handler: + stw r22,_NIP(r21) + lis r22,MSR_POW@h + andc r23,r23,r22 + stw r23,_MSR(r21) + SAVE_GPR(7, r21) + SAVE_4GPRS(8, r21) + SAVE_8GPRS(12, r21) + SAVE_8GPRS(24, r21) + + mflr r23 + andi. r24,r23,0x3f00 /* get vector offset */ + stw r24,TRAP(r21) + li r22,0 + stw r22,RESULT(r21) + mtspr SPRG2,r22 /* r1 is now kernel sp */ + + lwz r24,0(r23) /* virtual address of handler */ + lwz r23,4(r23) /* where to go when done */ + mtspr SRR0,r24 + mtspr SRR1,r20 + mtlr r23 + SYNC + rfi /* jump to handler, enable MMU */ + +int_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SRR0,r2 + mtspr SRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfi + +crit_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SPRN_CSRR0,r2 + mtspr SPRN_CSRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfci + +mck_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SPRN_MCSRR0,r2 + mtspr SPRN_MCSRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfmci + +/* + * Cache functions. + */ +.globl invalidate_icache +invalidate_icache: + mfspr r0,L1CSR1 + ori r0,r0,L1CSR1_ICFI + msync + isync + mtspr L1CSR1,r0 + isync + blr + +.globl invalidate_dcache +invalidate_dcache: + mfspr r0,L1CSR0 + ori r0,r0,L1CSR0_DCFI + msync + isync + mtspr L1CSR0,r0 + isync + blr + + .globl icache_enable +icache_enable: + mflr r8 + bl invalidate_icache + mtlr r8 + isync + mfspr r4,L1CSR1 + ori r4,r4,0x0001 + oris r4,r4,0x0001 + mtspr L1CSR1,r4 + isync + blr + + .globl icache_disable +icache_disable: + mfspr r0,L1CSR1 + lis r3,0 + ori r3,r3,L1CSR1_ICE + andc r0,r0,r3 + mtspr L1CSR1,r0 + isync + blr + + .globl icache_status +icache_status: + mfspr r3,L1CSR1 + andi. r3,r3,L1CSR1_ICE + blr + + .globl dcache_enable +dcache_enable: + mflr r8 + bl invalidate_dcache + mtlr r8 + isync + mfspr r0,L1CSR0 + ori r0,r0,0x0001 + oris r0,r0,0x0001 + msync + isync + mtspr L1CSR0,r0 + isync + blr + + .globl dcache_disable +dcache_disable: + mfspr r3,L1CSR0 + lis r4,0 + ori r4,r4,L1CSR0_DCE + andc r3,r3,r4 + mtspr L1CSR0,r3 + isync + blr + + .globl dcache_status +dcache_status: + mfspr r3,L1CSR0 + andi. r3,r3,L1CSR0_DCE + blr + + .globl get_pir +get_pir: + mfspr r3,PIR + blr + + .globl get_pvr +get_pvr: + mfspr r3,PVR + blr + + .globl get_svr +get_svr: + mfspr r3,SVR + blr + + .globl wr_tcr +wr_tcr: + mtspr TCR,r3 + blr + +/* + * Function: in8 + * Description: Input 8 bits + */ + .globl in8 +in8: + lbz r3,0x0000(r3) + blr + +/* + * Function: out8 + * Description: Output 8 bits + */ + .globl out8 +out8: + stb r4,0x0000(r3) + sync + blr + +/* + * Function: out16 + * Description: Output 16 bits + */ + .globl out16 +out16: + sth r4,0x0000(r3) + sync + blr + +/* + * Function: out16r + * Description: Byte reverse and output 16 bits + */ + .globl out16r +out16r: + sthbrx r4,r0,r3 + sync + blr + +/* + * Function: out32 + * Description: Output 32 bits + */ + .globl out32 +out32: + stw r4,0x0000(r3) + sync + blr + +/* + * Function: out32r + * Description: Byte reverse and output 32 bits + */ + .globl out32r +out32r: + stwbrx r4,r0,r3 + sync + blr + +/* + * Function: in16 + * Description: Input 16 bits + */ + .globl in16 +in16: + lhz r3,0x0000(r3) + blr + +/* + * Function: in16r + * Description: Input 16 bits and byte reverse + */ + .globl in16r +in16r: + lhbrx r3,r0,r3 + blr + +/* + * Function: in32 + * Description: Input 32 bits + */ + .globl in32 +in32: + lwz 3,0x0000(3) + blr + +/* + * Function: in32r + * Description: Input 32 bits and byte reverse + */ + .globl in32r +in32r: + lwbrx r3,r0,r3 + blr + +/* + * void e500_write_tlb(mas0, mas1, mas2, mas3, mas7) + */ + .globl e500_write_tlb +e500_write_tlb: + mtspr MAS0,r3 + mtspr MAS1,r4 + mtspr MAS2,r5 + mtspr MAS3,r6 + li r3,0 + isync + tlbwe + msync + isync + blr + +/* + * void relocate_code (end of ram) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ + .globl relocate_code +relocate_code: + mr r9, r3 /* Save end of RAM */ + + lis r10, (_end - _start)@h /* Size */ + ori r10, r10, (_end - _start)@l + sub r3, r3, r10 + + /* 64KB aligned */ + lis r10, 0xffff0000@h + ori r10, r10, 0xffff0000@l + and r3, r3, r10 + + mr r1, r3 /* Set new stack just below barebox code */ + mr r10, r3 /* Save copy of Destination Address */ + + bl calc_source +calc_source: + mfspr r4, LR /* r4 = address in memory (flash, RAM) */ + subi r4, r4, (calc_source - _start) + + GET_GOT + lis r5, __init_size@h + ori r5, r5, __init_size@l + + li r6,CACHELINE_SIZE + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - TEXT_BASE) + Destination Address + * + * Offset: + */ + sub r15,r10,r4 + + /* First our own GOT */ + add r14,r14,r15 + /* then the one used by the C code */ + add r30,r30,r15 + + /* + * Now relocate code + */ + + cmplw cr1,r3,r4 + addi r0,r5,3 + srwi. r0,r0,2 + beq cr1,4f /* In place copy is not necessary */ + beq 7f /* Protect against 0 count */ + mtctr r0 + bge cr1,2f + + la r8,-4(r4) + la r7,-4(r3) +1: lwzu r0,4(r8) + stwu r0,4(r7) + bdnz 1b + b 4f + +2: slwi r0,r0,2 + add r8,r4,r0 + add r7,r3,r0 +3: lwzu r0,-4(r8) + stwu r0,-4(r7) + bdnz 3b + + /* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4: cmpwi r6,0 + add r5,r3,r5 + beq 7f /* Always flush prefetch queue in any case */ + subi r0,r6,1 + andc r3,r3,r0 + mr r4,r3 +5: dcbst 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 5b + sync /* Wait for all dcbst to complete on bus */ + mr r4,r3 +6: icbi 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 6b +7: sync /* Wait for all icbi to complete on bus */ + isync + + /* + * Re-point the IVPR at RAM + */ + mtspr IVPR,r10 + + /* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + + addi r0,r10,in_ram - _start + _START_OFFSET + mtlr r0 + blr /* NEVER RETURNS! */ + + .globl in_ram +in_ram: + + /* + * Relocation Function, r14 point to got2+0x8000 + * + * Adjust got2 pointers, no need to check for 0, this code + * already puts a few entries in the table. + */ + li r0,__got2_entries@sectoff@l + la r3,GOT(_GOT2_TABLE_) + lwz r11,GOT(_GOT2_TABLE_) + mtctr r0 + sub r11,r3,r11 + addi r3,r3,-4 +1: lwzu r0,4(r3) + cmpwi r0,0 + beq- 2f + add r0,r0,r11 + stw r0,0(r3) +2: bdnz 1b + + /* + * Now adjust the fixups and the pointers to the fixups + * in case we need to move ourselves again. + */ + li r0,__fixup_entries@sectoff@l + lwz r3,GOT(_FIXUP_TABLE_) + cmpwi r0,0 + mtctr r0 + addi r3,r3,-4 + beq 4f +3: lwzu r4,4(r3) + lwzux r0,r4,r11 + cmpwi r0,0 + add r0,r0,r11 + stw r4,0(r3) + beq- 5f + stw r0,0(r4) +5: bdnz 3b +4: +clear_bss: + /* + * Now clear BSS segment + */ + lwz r3,GOT(__bss_start) + lwz r4,GOT(_end) + + cmplw 0,r3,r4 + beq 6f + + li r0,0 +5: + stw r0,0(r3) + addi r3,r3,4 + cmplw 0,r3,r4 + bne 5b +6: + mr r3, r10 /* Destination Address */ + bl board_init_r + + /* + * Copy exception vector code to low memory + * + * r3: dest_addr + * r7: source address, r8: end address, r9: target address + */ + .globl trap_init +trap_init: + mflr r4 /* save link register */ + GET_GOT + lwz r7,GOT(_start_of_vectors) + lwz r8,GOT(_end_of_vectors) + + li r9,0x100 /* reset vector always at 0x100 */ + + cmplw 0,r7,r8 + bgelr /* return if r7>=r8 - just in case */ +1: + lwz r0,0(r7) + stw r0,0(r9) + addi r7,r7,4 + addi r9,r9,4 + cmplw 0,r7,r8 + bne 1b + + /* + * relocate `hdlr' and `int_return' entries + */ + li r7,.L_CriticalInput - _start + _START_OFFSET + bl trap_reloc + li r7,.L_MachineCheck - _start + _START_OFFSET + bl trap_reloc + li r7,.L_DataStorage - _start + _START_OFFSET + bl trap_reloc + li r7,.L_InstStorage - _start + _START_OFFSET + bl trap_reloc + li r7,.L_Alignment - _start + _START_OFFSET + bl trap_reloc + li r7,.L_ProgramCheck - _start + _START_OFFSET + bl trap_reloc + li r7,.L_FPUnavailable - _start + _START_OFFSET + bl trap_reloc + li r7,.L_Decrementer - _start + _START_OFFSET + bl trap_reloc + li r7,.L_IntervalTimer - _start + _START_OFFSET + li r8,_end_of_vectors - _start + _START_OFFSET +2: + bl trap_reloc + addi r7,r7,0x100 /* next exception vector */ + cmplw 0,r7,r8 + blt 2b + + lis r7,0x0 + mtspr IVPR,r7 + + mtlr r4 /* restore link register */ + blr + + +.globl _text_base +_text_base: + .long TEXT_BASE + +.globl unlock_ram_in_cache +unlock_ram_in_cache: + /* invalidate the INIT_RAM section */ + lis r3,(CFG_INIT_RAM_ADDR & ~(CACHELINE_SIZE-1))@h + ori r3,r3,(CFG_INIT_RAM_ADDR & ~(CACHELINE_SIZE-1))@l + mfspr r4,L1CFG0 + andi. r4,r4,0x1ff + slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT) + mtctr r4 +1: dcbi r0,r3 + addi r3,r3,CACHELINE_SIZE + bdnz 1b + sync + + /* Invalidate the TLB entries for the cache */ + lis r3,CFG_INIT_RAM_ADDR@h + ori r3,r3,CFG_INIT_RAM_ADDR@l + tlbivax 0,r3 + addi r3,r3,0x1000 + tlbivax 0,r3 + addi r3,r3,0x1000 + tlbivax 0,r3 + addi r3,r3,0x1000 + tlbivax 0,r3 + isync + blr + +.globl flush_dcache +flush_dcache: + mfspr r3,SPRN_L1CFG0 + + rlwinm r5,r3,9,3 /* Extract cache block size */ + twlgti r5,1 /* Only 32 and 64 byte cache blocks + * are currently defined. + */ + li r4,32 + subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) - + * log2(number of ways) + */ + slw r5,r4,r5 /* r5 = cache block size */ + + rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */ + mulli r7,r7,13 /* An 8-way cache will require 13 + * loads per set. + */ + slw r7,r7,r6 + + /* save off HID0 and set DCFA */ + mfspr r8,SPRN_HID0 + ori r9,r8,HID0_DCFA@l + mtspr SPRN_HID0,r9 + isync + + lis r4,0 + mtctr r7 + +1: lwz r3,0(r4) /* Load... */ + add r4,r4,r5 + bdnz 1b + + msync + lis r4,0 + mtctr r7 + +1: dcbf 0,r4 /* ...and flush. */ + add r4,r4,r5 + bdnz 1b + + /* restore HID0 */ + mtspr SPRN_HID0,r8 + isync + + blr + +.globl setup_ivors +setup_ivors: + +#include "fixed_ivor.S" + blr diff --git a/arch/ppc/cpu-85xx/tlb.c b/arch/ppc/cpu-85xx/tlb.c new file mode 100644 index 0000000000..07ecdef5e8 --- /dev/null +++ b/arch/ppc/cpu-85xx/tlb.c @@ -0,0 +1,175 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright 2008-2009 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/config.h> +#include <asm/bitops.h> +#include <mach/mmu.h> + +void e500_invalidate_tlb(u8 tlb) +{ + if (tlb == 0) + mtspr(MMUCSR0, 0x4); + if (tlb == 1) + mtspr(MMUCSR0, 0x2); +} + +void e500_init_tlbs(void) +{ + int i; + + for (i = 0; i < num_tlb_entries; i++) { + e500_write_tlb(tlb_table[i].mas0, + tlb_table[i].mas1, + tlb_table[i].mas2, + tlb_table[i].mas3, + tlb_table[i].mas7); + } + + return ; +} + +static int e500_find_free_tlbcam(void) +{ + int ix; + u32 _mas1; + unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff; + + for (ix = 0; ix < num_cam; ix++) { + mtspr(MAS0, FSL_BOOKE_MAS0(1, ix, 0)); + asm volatile("tlbre;isync"); + _mas1 = mfspr(MAS1); + if (!(_mas1 & MAS1_VALID)) + return ix; + } + + if (ix >= NUM_TLBCAMS) + panic("No more free TLBs"); + + return ix; +} + +void e500_set_tlb(u8 tlb, u32 epn, u64 rpn, + u8 perms, u8 wimge, + u8 ts, u8 esel, u8 tsize, u8 iprot) +{ + u32 _mas0, _mas1, _mas2, _mas3, _mas7; + + _mas0 = FSL_BOOKE_MAS0(tlb, esel, 0); + _mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize); + _mas2 = FSL_BOOKE_MAS2(epn, wimge); + _mas3 = FSL_BOOKE_MAS3(rpn, 0, perms); + _mas7 = FSL_BOOKE_MAS7(rpn); + + e500_write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7); +} + +void e500_disable_tlb(u8 esel) +{ + mtspr(MAS0, FSL_BOOKE_MAS0(1, esel, 0)); + mtspr(MAS1, 0); + mtspr(MAS2, 0); + mtspr(MAS3, 0); + asm volatile("isync;msync;tlbwe;isync"); +} + +static inline void tlbsx(const unsigned *addr) +{ + __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr)); +} + +int e500_find_tlb_idx(void *addr, u8 tlbsel) +{ + u32 _mas0, _mas1; + + /* zero out Search PID, AS */ + mtspr(MAS6, 0); + tlbsx(addr); + + _mas0 = mfspr(MAS0); + _mas1 = mfspr(MAS1); + + /* we found something, and its in the TLB we expect */ + if ((MAS1_VALID & _mas1) && + (MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) { + return (_mas0 & MAS0_ESEL_MSK) >> 16; + } + + panic("Address 0x%p not found in TLB %d\n", addr, tlbsel); +} + +static unsigned int e500_setup_ddr_tlbs_phys(phys_addr_t p_addr, + unsigned int memsize_in_meg) +{ + int i; + unsigned int tlb_size; + unsigned int wimge = 0; + unsigned int ram_tlb_address = (unsigned int)CFG_SDRAM_BASE; + unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf; + u64 size, memsize = (u64)memsize_in_meg << 20; + + size = min((u64)memsize, (u64)MAX_MEM_MAPPED); + + /* Convert (4^max) kB to (2^max) bytes */ + max_cam = (max_cam * 2) + 10; + + for (i = 0; size && (i < 8); i++) { + int ram_tlb_index = e500_find_free_tlbcam(); + u32 camsize = __ilog2_u64(size) & ~1U; + u32 align = __ilog2(ram_tlb_address) & ~1U; + + if (align == -2) + align = max_cam; + if (camsize > align) + camsize = align; + + if (camsize > max_cam) + camsize = max_cam; + + tlb_size = (camsize - 10) / 2; + + e500_set_tlb(1, ram_tlb_address, p_addr, + MAS3_SX|MAS3_SW|MAS3_SR, wimge, + 0, ram_tlb_index, tlb_size, 1); + + size -= 1ULL << camsize; + memsize -= 1ULL << camsize; + ram_tlb_address += 1UL << camsize; + p_addr += 1UL << camsize; + } + + if (memsize) + printf("%lld left unmapped\n", memsize); + + return memsize_in_meg; +} + +inline unsigned int e500_setup_ddr_tlbs(unsigned int memsize_in_meg) +{ + return e500_setup_ddr_tlbs_phys(CFG_SDRAM_BASE, memsize_in_meg); +} diff --git a/arch/ppc/cpu-85xx/traps.c b/arch/ppc/cpu-85xx/traps.c new file mode 100644 index 0000000000..caead96dda --- /dev/null +++ b/arch/ppc/cpu-85xx/traps.c @@ -0,0 +1,272 @@ +/* + * linux/arch/powerpc/kernel/traps.c + * + * Copyright 2007 Freescale Semiconductor. + * Copyright (C) 2003 Motorola + * Modified by Xianghua Xiao(x.xiao@motorola.com) + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au) + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +/* + * This file handles the architecture-dependent parts of hardware exceptions + */ + +#include <common.h> +#include <command.h> +#include <init.h> +#include <asm/processor.h> +#include <mach/mpc85xx.h> + +int machinecheck_count; +int machinecheck_error; + +static inline void set_tsr(unsigned long val) +{ + asm volatile("mtspr 0x150, %0" : : "r" (val)); +} + +static inline unsigned long get_esr(void) +{ + unsigned long val; + asm volatile("mfspr %0, 0x03e" : "=r" (val) : ); + return val; +} + +#define ESR_MCI 0x80000000 +#define ESR_PIL 0x08000000 +#define ESR_PPR 0x04000000 +#define ESR_PTR 0x02000000 +#define ESR_DST 0x00800000 +#define ESR_DIZ 0x00400000 +#define ESR_U0F 0x00008000 + +/* + * Trap & Exception support + */ +void print_backtrace(unsigned long *sp) +{ + int cnt = 0; + unsigned long i; + + printf("Call backtrace: "); + while (sp) { + if ((uint)sp > END_OF_MEM) + break; + + i = sp[1]; + if ((cnt++ % 7) == 0) + printf("\n"); + printf("%08lX ", i); + if (cnt > 32) + break; + sp = (unsigned long *)*sp; + } + printf("\n"); +} + +void show_regs(struct pt_regs *regs) +{ + int i; + + printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx " + "DAR: %08lX\n", + regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); + printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x " + "IR/DR: %01x%01x\n", + regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, + regs->msr & MSR_FP ? 1 : 0, regs->msr&MSR_ME ? 1 : 0, + regs->msr&MSR_IR ? 1 : 0, + regs->msr&MSR_DR ? 1 : 0); + + printf("\n"); + for (i = 0; i < 32; i++) { + if ((i % 8) == 0) + printf("GPR%02d: ", i); + + printf("%08lX ", regs->gpr[i]); + if ((i % 8) == 7) + printf("\n"); + } +} + +void _exception(int signr, struct pt_regs *regs) +{ + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Exception in kernel pc %lx signal %d", regs->nip, signr); +} + +void CritcalInputException(struct pt_regs *regs) +{ + panic("Critical Input Exception"); +} + +static int exception_init(void) +{ + machinecheck_count = 0; + machinecheck_error = 0; + + return 0; +} +core_initcall(exception_init); + +void MachineCheckException(struct pt_regs *regs) +{ + unsigned long fixup; + unsigned int mcsr, mcsrr0, mcsrr1, mcar; + + /* + * Probing PCI using config cycles cause this exception + * when a device is not present. Catch it and return to + * the PCI exception handler. + */ + fixup = search_exception_table(regs->nip); + if (fixup != 0) { + regs->nip = fixup; + return; + } + + mcsrr0 = mfspr(SPRN_MCSRR0); + mcsrr1 = mfspr(SPRN_MCSRR1); + mcsr = mfspr(SPRN_MCSR); + mcar = mfspr(SPRN_MCAR); + + machinecheck_count++; + machinecheck_error = 1; + +#if defined(CONFIG_KGDB) + if (debugger_exception_handler && (*debugger_exception_handler)(regs)) + return; +#endif + + printf("Machine check in kernel mode.\n"); + printf("Caused by (from mcsr): "); + printf("mcsr = 0x%08x\n", mcsr); + if (mcsr & 0x80000000) + printf("Machine check input pin\n"); + if (mcsr & 0x40000000) + printf("Instruction cache parity error\n"); + if (mcsr & 0x20000000) + printf("Data cache push parity error\n"); + if (mcsr & 0x10000000) + printf("Data cache parity error\n"); + if (mcsr & 0x00000080) + printf("Bus instruction address error\n"); + if (mcsr & 0x00000040) + printf("Bus Read address error\n"); + if (mcsr & 0x00000020) + printf("Bus Write address error\n"); + if (mcsr & 0x00000010) + printf("Bus Instruction data bus error\n"); + if (mcsr & 0x00000008) + printf("Bus Read data bus error\n"); + if (mcsr & 0x00000004) + printf("Bus Write bus error\n"); + if (mcsr & 0x00000002) + printf("Bus Instruction parity error\n"); + if (mcsr & 0x00000001) + printf("Bus Read parity error\n"); + + show_regs(regs); + printf("MCSR=0x%08x\tMCSRR0=0x%08x\nMCSRR1=0x%08x\tMCAR=0x%08x\n", + mcsr, mcsrr0, mcsrr1, mcar); + print_backtrace((unsigned long *)regs->gpr[1]); + + if (machinecheck_count > 10) + panic("machine check count too high\n"); + + if (machinecheck_count > 1) { + regs->nip += 4; /* skip offending instruction */ + printf("Skipping current instr, Returning to 0x%08lx\n", + regs->nip); + } else { + printf("Returning back to 0x%08lx\n", regs->nip); + } +} + +void AlignmentException(struct pt_regs *regs) +{ +#if defined(CONFIG_KGDB) + if (debugger_exception_handler && (*debugger_exception_handler)(regs)) + return; +#endif + + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Alignment Exception"); +} + +void ProgramCheckException(struct pt_regs *regs) +{ + long esr_val; + +#if defined(CONFIG_KGDB) + if (debugger_exception_handler && (*debugger_exception_handler)(regs)) + return; +#endif + + show_regs(regs); + + esr_val = get_esr(); + if (esr_val & ESR_PIL) + printf("** Illegal Instruction **\n"); + else if (esr_val & ESR_PPR) + printf("** Privileged Instruction **\n"); + else if (esr_val & ESR_PTR) + printf("** Trap Instruction **\n"); + + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Program Check Exception"); +} + +void PITException(struct pt_regs *regs) +{ + /* Reset PIT interrupt */ + set_tsr(0x0c000000); +} + +void UnknownException(struct pt_regs *regs) +{ +#if defined(CONFIG_KGDB) + if (debugger_exception_handler && (*debugger_exception_handler)(regs)) + return; +#endif + + printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", + regs->nip, regs->msr, regs->trap); + _exception(0, regs); +} + +void DebugException(struct pt_regs *regs) +{ + printf("Debugger trap at @ %lx\n", regs->nip); + show_regs(regs); +#if defined(CONFIG_BEDBUG) + do_bedbug_breakpoint(regs); +#endif +} diff --git a/arch/ppc/include/asm/cache.h b/arch/ppc/include/asm/cache.h index 4f7ca86881..147ceb6714 100644 --- a/arch/ppc/include/asm/cache.h +++ b/arch/ppc/include/asm/cache.h @@ -31,6 +31,8 @@ extern void flush_dcache_range(unsigned long start, unsigned long stop); extern void clean_dcache_range(unsigned long start, unsigned long stop); extern void invalidate_dcache_range(unsigned long start, unsigned long stop); +extern void flush_dcache(void); +extern void invalidate_icache(void); #ifdef CFG_INIT_RAM_LOCK extern void unlock_ram_in_cache(void); #endif /* CFG_INIT_RAM_LOCK */ diff --git a/arch/ppc/include/asm/config.h b/arch/ppc/include/asm/config.h new file mode 100644 index 0000000000..4abded9aac --- /dev/null +++ b/arch/ppc/include/asm/config.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * 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 + */ + +#ifndef _ASM_CONFIG_H_ +#define _ASM_CONFIG_H_ + +#ifdef CONFIG_MPC85xx +#include <mach/config_mpc85xx.h> +#endif + +#ifndef MAX_MEM_MAPPED +#if defined(CONFIG_E500) +#define MAX_MEM_MAPPED ((phys_size_t)(2 << 30)) +#endif +#endif + +/* + * Provide a default boot page translation virtual address that lines up with + * Freescale's default e500 reset page. + */ +#if (defined(CONFIG_E500) && defined(CONFIG_MP)) +#ifndef BPTR_VIRT_ADDR +#define BPTR_VIRT_ADDR 0xfffff000 +#endif +#endif + +#endif /* _ASM_CONFIG_H_ */ diff --git a/arch/ppc/include/asm/fsl_ddr_sdram.h b/arch/ppc/include/asm/fsl_ddr_sdram.h new file mode 100644 index 0000000000..ef793c9d65 --- /dev/null +++ b/arch/ppc/include/asm/fsl_ddr_sdram.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef FSL_DDR_MEMCTL_H +#define FSL_DDR_MEMCTL_H + +/* + * DDR_SDRAM_CFG - DDR SDRAM Control Configuration + */ +#define SDRAM_CFG_MEM_EN 0x80000000 +#define SDRAM_CFG_SREN 0x40000000 +#define SDRAM_CFG_ECC_EN 0x20000000 +#define SDRAM_CFG_RD_EN 0x10000000 +#define SDRAM_CFG_SDRAM_TYPE_DDR1 0x02000000 +#define SDRAM_CFG_SDRAM_TYPE_DDR2 0x03000000 +#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000 +#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24 +#define SDRAM_CFG_DYN_PWR 0x00200000 +#define SDRAM_CFG_32_BE 0x00080000 +#define SDRAM_CFG_8_BE 0x00040000 +#define SDRAM_CFG_NCAP 0x00020000 +#define SDRAM_CFG_2T_EN 0x00008000 +#define SDRAM_CFG_BI 0x00000001 + +extern phys_size_t fixed_sdram(void); + +#endif diff --git a/arch/ppc/include/asm/fsl_law.h b/arch/ppc/include/asm/fsl_law.h new file mode 100644 index 0000000000..813a8ee0b3 --- /dev/null +++ b/arch/ppc/include/asm/fsl_law.h @@ -0,0 +1,91 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef _FSL_LAW_H_ +#define _FSL_LAW_H_ + +#include <asm/io.h> + +#define LAW_EN 0x80000000 + +#define FSL_SET_LAW_ENTRY(idx, a, sz, trgt) \ + { .index = idx, .addr = a, .size = sz, .trgt_id = trgt } + +#define FSL_SET_LAW(a, sz, trgt) \ + { .index = -1, .addr = a, .size = sz, .trgt_id = trgt } + +enum law_size { + LAW_SIZE_4K = 0xb, + LAW_SIZE_8K, + LAW_SIZE_16K, + LAW_SIZE_32K, + LAW_SIZE_64K, + LAW_SIZE_128K, + LAW_SIZE_256K, + LAW_SIZE_512K, + LAW_SIZE_1M, + LAW_SIZE_2M, + LAW_SIZE_4M, + LAW_SIZE_8M, + LAW_SIZE_16M, + LAW_SIZE_32M, + LAW_SIZE_64M, + LAW_SIZE_128M, + LAW_SIZE_256M, + LAW_SIZE_512M, + LAW_SIZE_1G, + LAW_SIZE_2G, + LAW_SIZE_4G, + LAW_SIZE_8G, + LAW_SIZE_16G, + LAW_SIZE_32G, +}; + +#define fsl_law_size_bits(sz) (__ilog2_u64(sz) - 1) +#define fsl_lawar_size(x) (1ULL << (((x) & 0x3f) + 1)) + +enum law_trgt_if { + LAW_TRGT_IF_PCI = 0x00, + LAW_TRGT_IF_PCI_2 = 0x01, + LAW_TRGT_IF_PCIE_1 = 0x02, +#if !defined(CONFIG_P2020) + LAW_TRGT_IF_PCIE_3 = 0x03, +#endif + LAW_TRGT_IF_LBC = 0x04, + LAW_TRGT_IF_CCSR = 0x08, + LAW_TRGT_IF_DDR_INTRLV = 0x0b, + LAW_TRGT_IF_RIO = 0x0c, + LAW_TRGT_IF_RIO_2 = 0x0d, + LAW_TRGT_IF_DDR = 0x0f, + LAW_TRGT_IF_DDR_2 = 0x16, /* 2nd controller */ +}; +#define LAW_TRGT_IF_DDR_1 LAW_TRGT_IF_DDR +#define LAW_TRGT_IF_PCI_1 LAW_TRGT_IF_PCI +#define LAW_TRGT_IF_PCIX LAW_TRGT_IF_PCI +#define LAW_TRGT_IF_PCIE_2 LAW_TRGT_IF_PCI_2 +#define LAW_TRGT_IF_RIO_1 LAW_TRGT_IF_RIO + + +#if defined(CONFIG_P2020) +#define LAW_TRGT_IF_PCIE_3 LAW_TRGT_IF_PCI +#endif + +struct law_entry { + int index; + phys_addr_t addr; + enum law_size size; + enum law_trgt_if trgt_id; +}; + +extern int fsl_set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id); +extern void fsl_init_laws(void); + +/* define in board code */ +extern struct law_entry law_table[]; +extern int num_law_entries; +#endif diff --git a/arch/ppc/include/asm/fsl_lbc.h b/arch/ppc/include/asm/fsl_lbc.h new file mode 100644 index 0000000000..47205e7ab9 --- /dev/null +++ b/arch/ppc/include/asm/fsl_lbc.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright (C) 2004-2008,2010-2011 Freescale Semiconductor, Inc. + * + * 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. + */ + +#ifndef __ASM_PPC_FSL_LBC_H +#define __ASM_PPC_FSL_LBC_H + +#include <config.h> +#include <common.h> + +/* + * BR - Base Registers + */ +#define BR_PS 0x00001800 +#define BR_PS_SHIFT 11 +#define BR_PS_8 0x00000800 /* Port Size 8 bit */ +#define BR_PS_16 0x00001000 /* Port Size 16 bit */ +#define BR_PS_32 0x00001800 /* Port Size 32 bit */ +#define BR_V 0x00000001 +#define BR_V_SHIFT 0 + +/* Convert an address into the right format for the BR registers */ +#define BR_PHYS_ADDR(x) ((x) & 0xffff8000) + +/* + * CLKDIV is five bits only on 8536, 8572, and 8610, so far, but the fifth bit + * should always be zero on older parts that have a four bit CLKDIV. + */ +#define LCRR_CLKDIV 0x0000001f +#define LCRR_CLKDIV_SHIFT 0 +#define LCRR_CLKDIV_4 0x00000002 +#define LCRR_CLKDIV_8 0x00000004 +#define LCRR_CLKDIV_16 0x00000008 + +#ifndef __ASSEMBLY__ +#include <asm/io.h> + +extern void fsl_init_early_memctl_regs(void); + +/* LBC register offsets. */ +#define FSL_LBC_BRX(x) ((x) * 8) /* bank register offsets. */ +#define FSL_LBC_ORX(x) (4 + ((x) * 8)) /* option register offset. */ +#define FSL_LBC_LCCR 0x0d4 /* Clock ration register. */ + +#define LBC_BASE_ADDR ((void __iomem *)LBC_ADDR) +#define fsl_get_lbc_br(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x)))) +#define fsl_get_lbc_or(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x)))) +#define fsl_set_lbc_br(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x)), v)) +#define fsl_set_lbc_or(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x)), v)) + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_PPC_FSL_LBC_H */ diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c index a840c75204..6b6268f679 100644 --- a/arch/ppc/lib/board.c +++ b/arch/ppc/lib/board.c @@ -46,6 +46,10 @@ void board_init_r (ulong end_of_ram) asm ("sync ; isync"); +#ifdef CONFIG_MPC85xx + _text_base = end_of_ram; +#endif + /* * FIXME: 128k stack size. Is this enough? should * it be configurable? diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig new file mode 100644 index 0000000000..b2af05ec59 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/Kconfig @@ -0,0 +1,41 @@ +if ARCH_MPC85XX + +config TEXT_BASE + hex + default 0xeff80000 if P2020RDB + +config BOARDINFO + default "P2020_RDB" if P2020RDB + +config MPC85xx + bool + default y if P2020RDB + +choice + prompt "Select your board" + +config P2020RDB + bool "P2020RDB" + help + Say Y here if you are using the Freescale P2020RDB + +endchoice +endif + +if P2020RDB +config P2020 + bool + default y + +config BOOKE + bool + default y + +config E500 + bool + default y + +config FSL_ELBC + bool + default y +endif diff --git a/arch/ppc/mach-mpc85xx/Makefile b/arch/ppc/mach-mpc85xx/Makefile new file mode 100644 index 0000000000..03addaf47b --- /dev/null +++ b/arch/ppc/mach-mpc85xx/Makefile @@ -0,0 +1,8 @@ +obj-y += cpuid.o +obj-y += cpu.o +obj-y += cpu_init.o +obj-y += fsl_lbc.o +obj-y += fsl_law.o +obj-y += speed.o +obj-y +=time.o +obj-$(CONFIG_MP) += mp.o diff --git a/arch/ppc/mach-mpc85xx/cpu.c b/arch/ppc/mach-mpc85xx/cpu.c new file mode 100644 index 0000000000..f7308383c7 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/cpu.c @@ -0,0 +1,85 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc + * Copyright 2004,2007-2011 Freescale Semiconductor, Inc. + * (C) Copyright 2002, 2003 Motorola Inc. + * Xianghua Xiao (X.Xiao@motorola.com) + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 <config.h> +#include <common.h> +#include <asm/fsl_ddr_sdram.h> +#include <mach/mmu.h> +#include <mach/immap_85xx.h> + +void __noreturn reset_cpu(unsigned long addr) +{ + void __iomem *regs = (void __iomem *)MPC85xx_GUTS_ADDR; + + /* Everything after the first generation of PQ3 parts has RSTCR */ + out_be32(regs + MPC85xx_GUTS_RSTCR_OFFSET, 0x2); /* HRESET_REQ */ + udelay(100); + + while (1) + ; +} + +long int initdram(int board_type) +{ + phys_size_t dram_size = 0; + + dram_size = fixed_sdram(); + + dram_size = e500_setup_ddr_tlbs(dram_size / 0x100000); + dram_size *= 0x100000; + + return dram_size; +} + +/* + * Return the memory size based on the configuration registers. + */ +phys_size_t fsl_get_effective_memsize(void) +{ + void __iomem *regs = (void __iomem *)(MPC85xx_DDR_ADDR); + phys_size_t sdram_size; + uint san , ean; + uint reg; + int ix; + + sdram_size = 0; + + for (ix = 0; ix < CFG_CHIP_SELECTS_PER_CTRL; ix++) { + if (in_be32(regs + DDR_OFF(CS0_CONFIG) + (ix * 8)) & + SDRAM_CFG_MEM_EN) { + reg = in_be32(regs + DDR_OFF(CS0_BNDS) + (ix * 8)); + /* start address */ + san = (reg & 0x0fff00000) >> 16; + /* end address */ + ean = (reg & 0x00000fff); + sdram_size = ((ean - san + 1) << 24); + } + } + + return sdram_size; +} diff --git a/arch/ppc/mach-mpc85xx/cpu_init.c b/arch/ppc/mach-mpc85xx/cpu_init.c new file mode 100644 index 0000000000..958250db54 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/cpu_init.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2003 Motorola Inc. + * Modified by Xianghua Xiao, X.Xiao@motorola.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 <init.h> +#include <asm/processor.h> +#include <asm/fsl_law.h> +#include <mach/mpc85xx.h> +#include <mach/mmu.h> +#include <mach/immap_85xx.h> + +static void fsl_setup_ccsrbar(void) +{ + u32 temp; + u32 mas0, mas1, mas2, mas3, mas7; + u32 *ccsr_virt = (u32 *)(CFG_CCSRBAR + 0x1000); + + mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(1); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K); + mas2 = FSL_BOOKE_MAS2(CFG_CCSRBAR + 0x1000, MAS2_I|MAS2_G); + mas3 = FSL_BOOKE_MAS3(CFG_CCSRBAR_DEFAULT, 0, MAS3_SW|MAS3_SR); + mas7 = FSL_BOOKE_MAS7(CFG_CCSRBAR_DEFAULT); + + e500_write_tlb(mas0, mas1, mas2, mas3, mas7); + + temp = in_be32(ccsr_virt); + out_be32(ccsr_virt, CFG_CCSRBAR_PHYS >> 12); + temp = in_be32((u32 *)CFG_CCSRBAR); +} + +int fsl_l2_cache_init(void) +{ + void __iomem *l2cache = (void __iomem *)MPC85xx_L2_ADDR; + uint cache_ctl; + uint svr, ver; + u32 l2siz_field; + + svr = get_svr(); + ver = SVR_SOC_VER(svr); + + asm("msync;isync"); + cache_ctl = in_be32(l2cache + MPC85xx_L2_CTL_OFFSET); + + l2siz_field = (cache_ctl >> 28) & 0x3; + + switch (l2siz_field) { + case 0x0: + return -1; + break; + case 0x1: + cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, L2SRAM=0 */ + break; + case 0x2: + /* set L2E=1, L2I=1, & L2SRAM=0 */ + cache_ctl = 0xc0000000; + break; + case 0x3: + /* set L2E=1, L2I=1, & L2SRAM=0 */ + cache_ctl = 0xc0000000; + break; + } + + if (!(in_be32(l2cache + MPC85xx_L2_CTL_OFFSET) & MPC85xx_L2CTL_L2E)) { + asm("msync;isync"); + /* invalidate & enable */ + out_be32(l2cache + MPC85xx_L2_CTL_OFFSET, cache_ctl); + asm("msync;isync"); + } + + return 0; +} + +void cpu_init_early_f(void) +{ + u32 mas0, mas1, mas2, mas3, mas7; + + mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(0); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K); + mas2 = FSL_BOOKE_MAS2(CFG_CCSRBAR, MAS2_I|MAS2_G); + mas3 = FSL_BOOKE_MAS3(CFG_CCSRBAR_PHYS, 0, MAS3_SW|MAS3_SR); + mas7 = FSL_BOOKE_MAS7(CFG_CCSRBAR_PHYS); + + e500_write_tlb(mas0, mas1, mas2, mas3, mas7); + + /* set up CCSR if we want it moved */ + if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR_PHYS) + fsl_setup_ccsrbar(); + + fsl_init_laws(); + e500_invalidate_tlb(0); + e500_init_tlbs(); +} + +void cpu_init_f(void) +{ + e500_disable_tlb(14); + e500_disable_tlb(15); + + fsl_init_early_memctl_regs(); +} diff --git a/arch/ppc/mach-mpc85xx/cpuid.c b/arch/ppc/mach-mpc85xx/cpuid.c new file mode 100644 index 0000000000..598201b5b5 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/cpuid.c @@ -0,0 +1,73 @@ +/* + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and + * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains + * cpu specific common code for 85xx/86xx processors. + * 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 <config.h> +#include <common.h> +#include <command.h> +#include <asm/cache.h> +#include <asm/io.h> +#include <mach/immap_85xx.h> + +struct cpu_type cpu_type_list[] = { + CPU_TYPE_ENTRY(P2020, P2020, 2), + CPU_TYPE_ENTRY(P2020, P2020_E, 2), +}; + +struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 1); + +struct cpu_type *identify_cpu(u32 ver) +{ + int i; + for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) { + if (cpu_type_list[i].soc_ver == ver) + return &cpu_type_list[i]; + } + return &cpu_type_unknown; +} + +int fsl_cpu_numcores(void) +{ + void __iomem *pic = (void __iomem *)MPC8xxx_PIC_ADDR; + struct cpu_type *cpu; + uint svr; + uint ver; + int tmp; + + svr = get_svr(); + ver = SVR_SOC_VER(svr); + cpu = identify_cpu(ver); + + /* better to query feature reporting register than just assume 1 */ + if (cpu == &cpu_type_unknown) { + tmp = in_be32(pic + MPC85xx_PIC_FRR_OFFSET); + tmp = (tmp & MPC8xxx_PICFRR_NCPU_MASK) >> + MPC8xxx_PICFRR_NCPU_SHIFT; + tmp += 1; + } else { + tmp = cpu->num_cores; + } + + return tmp; +} diff --git a/arch/ppc/mach-mpc85xx/fsl_law.c b/arch/ppc/mach-mpc85xx/fsl_law.c new file mode 100644 index 0000000000..422943dea2 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/fsl_law.c @@ -0,0 +1,160 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/config.h> +#include <asm/fsl_law.h> + +#define FSL_HW_NUM_LAWS FSL_NUM_LAWS + +#define LAW_BASE (CFG_IMMR + 0xc08) +#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * (x) + 2) +#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * (x)) +#define LAWBAR_SHIFT 12 + +static inline phys_addr_t fsl_get_law_base_addr(int idx) +{ + return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT; +} + +static inline void fsl_set_law_base_addr(int idx, phys_addr_t addr) +{ + out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT); +} + +static void fsl_set_law(u8 idx, phys_addr_t addr, enum law_size sz, + enum law_trgt_if id) +{ + out_be32(LAWAR_ADDR(idx), 0); + fsl_set_law_base_addr(idx, addr); + out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz); + + /* Read back so that we sync the writes */ + in_be32(LAWAR_ADDR(idx)); +} + +static int fsl_is_free_law(int idx) +{ + u32 lawar; + + lawar = in_be32(LAWAR_ADDR(idx)); + if (!(lawar & LAW_EN)) + return 1; + + return 0; +} + +static void fsl_set_next_law(phys_addr_t addr, enum law_size sz, + enum law_trgt_if id) +{ + u32 idx; + + for (idx = 0; idx < FSL_HW_NUM_LAWS; idx++) { + if (fsl_is_free_law(idx)) { + fsl_set_law(idx, addr, sz, id); + break; + } + } + + if (idx >= FSL_HW_NUM_LAWS) + panic("No more LAWS available\n"); +} + +static void fsl_set_last_law(phys_addr_t addr, enum law_size sz, + enum law_trgt_if id) +{ + u32 idx; + + for (idx = (FSL_HW_NUM_LAWS - 1); idx >= 0; idx--) { + if (fsl_is_free_law(idx)) { + fsl_set_law(idx, addr, sz, id); + break; + } + } + + if (idx < 0) + panic("No more LAWS available\n"); +} + +/* use up to 2 LAWs for DDR, use the last available LAWs */ +int fsl_set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) +{ + u64 start_align, law_sz; + int law_sz_enc; + + if (start == 0) + start_align = 1ull << (LAW_SIZE_32G + 1); + else + start_align = 1ull << (ffs64(start) - 1); + + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + fsl_set_last_law(start, law_sz_enc, id); + + /* recalculate size based on what was actually covered by the law */ + law_sz = 1ull << __ilog2_u64(law_sz); + + /* do we still have anything to map */ + sz = sz - law_sz; + if (sz) { + start += law_sz; + + start_align = 1ull << (ffs64(start) - 1); + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + fsl_set_last_law(start, law_sz_enc, id); + } else { + return 0; + } + + /* do we still have anything to map */ + sz = sz - law_sz; + if (sz) + return 1; + + return 0; +} + +void fsl_init_laws(void) +{ + int i; + + if (FSL_HW_NUM_LAWS > 32) + panic("FSL_HW_NUM_LAWS can not be > 32 w/o code changes"); + + for (i = 0; i < num_law_entries; i++) { + if (law_table[i].index == -1) + fsl_set_next_law(law_table[i].addr, + law_table[i].size, + law_table[i].trgt_id); + else + fsl_set_law(law_table[i].index, law_table[i].addr, + law_table[i].size, law_table[i].trgt_id); + } +} diff --git a/arch/ppc/mach-mpc85xx/fsl_lbc.c b/arch/ppc/mach-mpc85xx/fsl_lbc.c new file mode 100644 index 0000000000..ac9ca7402b --- /dev/null +++ b/arch/ppc/mach-mpc85xx/fsl_lbc.c @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include <common.h> +#include <asm/fsl_lbc.h> +#include <mach/immap_85xx.h> + +void fsl_init_early_memctl_regs(void) +{ + fsl_set_lbc_br(0, CFG_BR0_PRELIM); + fsl_set_lbc_or(0, CFG_OR0_PRELIM); +} diff --git a/arch/ppc/mach-mpc85xx/include/mach/clocks.h b/arch/ppc/mach-mpc85xx/include/mach/clocks.h new file mode 100644 index 0000000000..94771682e8 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/clocks.h @@ -0,0 +1,18 @@ +#ifndef __ASM_ARCH_CLOCKS_H +#define __ASM_ARCH_CLOCKS_H + +#include <mach/config_mpc85xx.h> + +struct sys_info { + unsigned long freqProcessor[MAX_CPUS]; + unsigned long freqSystemBus; + unsigned long freqDDRBus; + unsigned long freqLocalBus; +}; + +#define NSEC_PER_SEC 1000000000L + +unsigned long fsl_get_bus_freq(ulong dummy); +unsigned long fsl_get_timebase_clock(void); +void fsl_get_sys_info(struct sys_info *sysInfo); +#endif /* __ASM_ARCH_CLOCKS_H */ diff --git a/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h b/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h new file mode 100644 index 0000000000..9b095c71a4 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2011 Freescale Semiconductor, Inc. + * + * 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 + */ + +#ifndef _ASM_MPC85xx_CONFIG_H_ +#define _ASM_MPC85xx_CONFIG_H_ + +#define RESET_VECTOR 0xfffffffc + +/* Number of TLB CAM entries we have on FSL Book-E chips */ +#if defined(CONFIG_E500) +#define NUM_TLBCAMS 16 +#endif + +#if defined(CONFIG_P2020) +#define MAX_CPUS 2 +#define FSL_NUM_LAWS 12 +#define FSL_SEC_COMPAT 2 +#else +#error Processor type not defined for this platform +#endif + +#endif /* _ASM_MPC85xx_CONFIG_H_ */ diff --git a/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h b/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h new file mode 100644 index 0000000000..dc2d8bcdd0 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h @@ -0,0 +1,40 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * 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> + +/* early_udelay: delay execution before timers are initialized + * + * "usecs * 100" gives a time of around 1 second on a 1Ghz CPU. + */ +static inline void early_udelay(unsigned long usecs) +{ + uint64_t start; + uint32_t loops = usecs * 100; + + start = get_ticks(); + + while ((get_ticks() - start) < loops) + ; +} diff --git a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h new file mode 100644 index 0000000000..b80224952d --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h @@ -0,0 +1,132 @@ +/* + * MPC85xx Internal Memory Map + * + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * + * Copyright(c) 2002,2003 Motorola Inc. + * Xianghua Xiao (x.xiao@motorola.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __IMMAP_85xx__ +#define __IMMAP_85xx__ + +#include <asm/types.h> +#include <asm/fsl_lbc.h> +#include <asm/config.h> + +#define MPC85xx_LOCAL_OFFSET 0x0000 +#define MPC85xx_ECM_OFFSET 0x1000 +#define MPC85xx_DDR_OFFSET 0x2000 +#define MPC85xx_LBC_OFFSET 0x5000 + +#define MPC85xx_GPIO_OFFSET 0xf000 +#define MPC85xx_L2_OFFSET 0x20000 + +#define MPC85xx_PIC_OFFSET 0x40000 +#define MPC85xx_GUTS_OFFSET 0xe0000 + +#define MPC85xx_LOCAL_ADDR (CFG_IMMR + MPC85xx_LOCAL_OFFSET) +#define MPC85xx_ECM_ADDR (CFG_IMMR + MPC85xx_ECM_OFFSET) +#define MPC85xx_GUTS_ADDR (CFG_IMMR + MPC85xx_GUTS_OFFSET) +#define MPC85xx_DDR_ADDR (CFG_IMMR + MPC85xx_DDR_OFFSET) +#define LBC_ADDR (CFG_IMMR + MPC85xx_LBC_OFFSET) +#define MPC85xx_GPIO_ADDR (CFG_IMMR + MPC85xx_GPIO_OFFSET) +#define MPC85xx_L2_ADDR (CFG_IMMR + MPC85xx_L2_OFFSET) +#define MPC8xxx_PIC_ADDR (CFG_IMMR + MPC85xx_PIC_OFFSET) + +/* Local-Access Registers */ +#define MPC85xx_LOCAL_BPTR_OFFSET 0x20 /* Boot Page Translation */ + +/* ECM Registers */ +#define MPC85xx_ECM_EEBPCR_OFFSET 0x00 /* ECM CCB Port Configuration */ + +/* + * DDR Memory Controller Register Offsets + */ +/* Chip Select 0, 1,2, 3 Memory Bounds */ +#define MPC85xx_DDR_CS0_BNDS_OFFSET 0x000 +#define MPC85xx_DDR_CS1_BNDS_OFFSET 0x008 +#define MPC85xx_DDR_CS2_BNDS_OFFSET 0x010 +#define MPC85xx_DDR_CS3_BNDS_OFFSET 0x018 +/* Chip Select 0, 1, 2, 3 Configuration */ +#define MPC85xx_DDR_CS0_CONFIG_OFFSET 0x080 +#define MPC85xx_DDR_CS1_CONFIG_OFFSET 0x084 +#define MPC85xx_DDR_CS2_CONFIG_OFFSET 0x088 +#define MPC85xx_DDR_CS3_CONFIG_OFFSET 0x08c +/* SDRAM Timing Configuration 0, 1, 2, 3 */ +#define MPC85xx_DDR_TIMING_CFG_3_OFFSET 0x100 +#define MPC85xx_DDR_TIMING_CFG_0_OFFSET 0x104 +#define MPC85xx_DDR_TIMING_CFG_1_OFFSET 0x108 +#define MPC85xx_DDR_TIMING_CFG_2_OFFSET 0x10c +/* SDRAM Control Configuration */ +#define MPC85xx_DDR_SDRAM_CFG_OFFSET 0x110 +#define MPC85xx_DDR_SDRAM_CFG_2_OFFSET 0x114 +/* SDRAM Mode Configuration */ +#define MPC85xx_DDR_SDRAM_MODE_OFFSET 0x118 +#define MPC85xx_DDR_SDRAM_MODE_2_OFFSET 0x11c +/* SDRAM Mode Control */ +#define MPC85xx_DDR_SDRAM_MD_CNTL_OFFSET 0x120 +/* SDRAM Interval Configuration */ +#define MPC85xx_DDR_SDRAM_INTERVAL_OFFSET 0x124 +/* SDRAM Data initialization */ +#define MPC85xx_DDR_SDRAM_DATA_INIT_OFFSET 0x128 +/* SDRAM Clock Control */ +#define MPC85xx_DDR_SDRAM_CLK_CNTL_OFFSET 0x130 +/* training init and extended addr */ +#define MPC85xx_DDR_SDRAM_INIT_ADDR_OFFSET 0x148 +#define MPC85xx_DDR_SDRAM_INIT_ADDR_EXT_OFFSET 0x14c + +#define DDR_OFF(REGNAME) (MPC85xx_DDR_##REGNAME##_OFFSET) + +/* + * GPIO Register Offsets + */ +#define MPC85xx_GPIO_GPDIR 0x00 +#define MPC85xx_GPIO_GPDAT 0x08 + +/* + * L2 Cache Register Offsets + */ +#define MPC85xx_L2_CTL_OFFSET 0x0 /* L2 configuration 0 */ +#define MPC85xx_L2CTL_L2E 0x80000000 + +/* PIC registers offsets */ +#define MPC85xx_PIC_WHOAMI_OFFSET 0x090 +#define MPC85xx_PIC_FRR_OFFSET 0x1000 /* Feature Reporting */ +/* PIC registers fields values and masks. */ +#define MPC8xxx_PICFRR_NCPU_MASK 0x00001f00 +#define MPC8xxx_PICFRR_NCPU_SHIFT 8 +#define MPC85xx_PICGCR_RST 0x80000000 +#define MPC85xx_PICGCR_M 0x20000000 + +#define MPC85xx_PIC_IACK0_OFFSET 0x600a0 /* IRQ Acknowledge for + Processor 0 */ + +/* Global Utilities Register Offsets and field values */ +#define MPC85xx_GUTS_PORPLLSR_OFFSET 0x0 +#define MPC85xx_PORPLLSR_DDR_RATIO 0x00003e00 +#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT 9 +#define MPC85xx_GUTS_DEVDISR_OFFSET 0x70 +#define MPC85xx_DEVDISR_TB0 0x00004000 +#define MPC85xx_DEVDISR_TB1 0x00001000 +#define MPC85xx_GUTS_RSTCR_OFFSET 0xb0 + +#endif /*__IMMAP_85xx__*/ diff --git a/arch/ppc/mach-mpc85xx/include/mach/mmu.h b/arch/ppc/mach-mpc85xx/include/mach/mmu.h new file mode 100644 index 0000000000..00459e2d29 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/mmu.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef _MPC85XX_MMU_H_ +#define _MPC85XX_MMU_H_ + +#ifdef CONFIG_E500 +#include <asm/mmu.h> + +#ifndef __ASSEMBLY__ +extern void e500_set_tlb(u8 tlb, u32 epn, u64 rpn, u8 perms, u8 wimge, + u8 ts, u8 esel, u8 tsize, u8 iprot); +extern void e500_disable_tlb(u8 esel); +extern void e500_invalidate_tlb(u8 tlb); +extern void e500_init_tlbs(void); +extern int e500_find_tlb_idx(void *addr, u8 tlbsel); +extern void e500_init_used_tlb_cams(void); + +extern unsigned int e500_setup_ddr_tlbs(unsigned int memsize_in_meg); +extern void e500_write_tlb(u32 _mas0, u32 _mas1, u32 _mas2, u32 _mas3, + u32 _mas7); + +#define FSL_SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz,\ + _iprot) \ + { .mas0 = FSL_BOOKE_MAS0(_tlb, _esel, 0), \ + .mas1 = FSL_BOOKE_MAS1(1, _iprot, 0, _ts, _sz), \ + .mas2 = FSL_BOOKE_MAS2(_epn, _wimge), \ + .mas3 = FSL_BOOKE_MAS3(_rpn, 0, _perms), \ + .mas7 = FSL_BOOKE_MAS7(_rpn), } + +struct fsl_e_tlb_entry { + u32 mas0; + u32 mas1; + u32 mas2; + u32 mas3; + u32 mas7; +}; +extern struct fsl_e_tlb_entry tlb_table[]; +extern int num_tlb_entries; +#endif +#endif +#endif /* _MPC85XX_MMU_H_ */ diff --git a/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h b/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h new file mode 100644 index 0000000000..1d9993ace9 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h @@ -0,0 +1,23 @@ +/* + * Copyright 2004, 2007 Freescale Semiconductor. + * Copyright(c) 2003 Motorola Inc. + */ + +#ifndef __MPC85xx_H__ +#define __MPC85xx_H__ + +/* define for common ppc_asm.tmpl */ +#define EXC_OFF_SYS_RESET 0x100 /* System reset */ +#define _START_OFFSET 0 + +#ifndef __ASSEMBLY__ +int fsl_l2_cache_init(void); +int fsl_cpu_numcores(void); + +phys_size_t fsl_get_effective_memsize(void); + +#endif /* __ASSEMBLY__ */ + +#define END_OF_MEM (fsl_get_effective_memsize()) + +#endif /* __MPC85xx_H__ */ diff --git a/arch/ppc/mach-mpc85xx/speed.c b/arch/ppc/mach-mpc85xx/speed.c new file mode 100644 index 0000000000..40d3664188 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/speed.c @@ -0,0 +1,104 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2003 Motorola Inc. + * Xianghua Xiao, (X.Xiao@motorola.com) + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <mach/clocks.h> +#include <mach/immap_85xx.h> +#include <mach/mpc85xx.h> + +void fsl_get_sys_info(struct sys_info *sysInfo) +{ + void __iomem *gur = (void __iomem *)(MPC85xx_GUTS_ADDR); + uint plat_ratio, e500_ratio, half_freqSystemBus; + uint lcrr_div; + int i; + + plat_ratio = in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) & 0x0000003e; + plat_ratio >>= 1; + sysInfo->freqSystemBus = plat_ratio * CFG_SYS_CLK_FREQ; + + /* + * Divide before multiply to avoid integer + * overflow for processor speeds above 2GHz. + */ + half_freqSystemBus = sysInfo->freqSystemBus/2; + for (i = 0; i < fsl_cpu_numcores(); i++) { + e500_ratio = (in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) >> + (i * 8 + 16)) & 0x3f; + sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus; + } + + /* Note: freqDDRBus is the MCLK frequency, not the data rate. */ + sysInfo->freqDDRBus = sysInfo->freqSystemBus; + +#ifdef CFG_DDR_CLK_FREQ + { + u32 ddr_ratio = (in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) & + MPC85xx_PORPLLSR_DDR_RATIO) >> + MPC85xx_PORPLLSR_DDR_RATIO_SHIFT; + if (ddr_ratio != 0x7) + sysInfo->freqDDRBus = ddr_ratio * CFG_DDR_CLK_FREQ; + } +#endif + + lcrr_div = in_be32(LBC_BASE_ADDR + FSL_LBC_LCCR) & LCRR_CLKDIV; + + if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) { + /* + * The entire PQ38 family use the same bit-representation + * for twice the clock divider values. + */ + lcrr_div *= 2; + + sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div; + } else { + /* In case anyone cares what the unknown value is */ + sysInfo->freqLocalBus = lcrr_div; + } +} + +unsigned long fsl_get_bus_freq(ulong dummy) +{ + struct sys_info sys_info; + + fsl_get_sys_info(&sys_info); + + return sys_info.freqSystemBus; +} + +unsigned long fsl_get_timebase_clock(void) +{ + struct sys_info sysinfo; + + fsl_get_sys_info(&sysinfo); + + return (sysinfo.freqSystemBus + 4UL)/8UL; +} diff --git a/arch/ppc/mach-mpc85xx/time.c b/arch/ppc/mach-mpc85xx/time.c new file mode 100644 index 0000000000..408a28a2eb --- /dev/null +++ b/arch/ppc/mach-mpc85xx/time.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 <clock.h> +#include <init.h> +#include <mach/clocks.h> + +uint64_t ppc_clocksource_read(void) +{ + return get_ticks(); +} + +static struct clocksource cs = { + .read = ppc_clocksource_read, + .mask = CLOCKSOURCE_MASK(64), +}; + +static int clocksource_init(void) +{ + /* reset time base */ + asm ("li 3,0 ; mttbu 3 ; mttbl 3 ;"); + + clocks_calc_mult_shift(&cs.mult, &cs.shift, + fsl_get_timebase_clock(), NSEC_PER_SEC, 10); + + init_clock(&cs); + + return 0; +} + +core_initcall(clocksource_init); |