diff options
Diffstat (limited to 'arch/powerpc/mach-mpc85xx')
24 files changed, 1968 insertions, 0 deletions
diff --git a/arch/powerpc/mach-mpc85xx/.gitignore b/arch/powerpc/mach-mpc85xx/.gitignore new file mode 100644 index 0000000000..03987a7009 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +barebox.lds diff --git a/arch/powerpc/mach-mpc85xx/Kconfig b/arch/powerpc/mach-mpc85xx/Kconfig new file mode 100644 index 0000000000..550c554286 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/Kconfig @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: GPL-2.0-only + +if ARCH_MPC85XX + +config MMU + default y + +config BTB + bool + default y + +config TEXT_BASE + hex + default 0xeff80000 if P1010RDB || P2020RDB || P1022DS + default 0xfff80000 if DA923RC + +config RESET_VECTOR_ADDRESS + hex + default 0xfffffffc if DA923RC + default 0xeffffffc if P1010RDB || P2020RDB || P1022DS + +config MPC85xx + bool + default y + +config BOOKE + bool + default y + +config E500 + bool + default y + +choice + prompt "Select your board" +config P1010RDB + bool "P1010RDB" + select P1010 + select DDR_SPD + select FSL_DDR3 + help + Say Y here if you are using the Freescale P1010RDB + +config P2020RDB + bool "P2020RDB" + select P2020 + select FSL_ELBC + help + Say Y here if you are using the Freescale P2020RDB + +config P1022DS + bool "P1022DS" + select P1022 + select DDR_SPD + select FSL_DDR3 + select FSL_ELBC + help + Say Y here if you are using the Freescale P1022DS + +config DA923RC + bool "DA923RC" + select MPC8544 + select DDR_SPD + select FSL_DDR2 + help + Say Y here if you are using the GE Intelligent Platforms DA923RC +endchoice +endif + +config P1010 + select FSL_IFC + select FSL_ERRATUM_IFC_A002769 + select FSL_ERRATUM_P1010_A003549 + select FSL_ERRATUM_IFC_A003399 + bool + +config P2020 + bool + +config P1022 + bool + +config MPC8544 + bool + +config FSL_DDR2 + bool + +config FSL_DDR3 + bool + +config FSL_IFC + bool + +config FSL_ELBC + bool + +config FSL_ERRATUM_IFC_A002769 + bool + +config FSL_ERRATUM_IFC_A003399 + bool + +config FSL_ERRATUM_P1010_A003549 + bool + diff --git a/arch/powerpc/mach-mpc85xx/Makefile b/arch/powerpc/mach-mpc85xx/Makefile new file mode 100644 index 0000000000..3e23c1b812 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-y += cpuid.o +obj-y += cpu.o +obj-y += cpu_init.o +obj-y += fsl_law.o +obj-y += speed.o +obj-y +=time.o +obj-y += fsl_gpio.o +obj-y += fsl_i2c.o +obj-$(CONFIG_MP) += mp.o +obj-$(CONFIG_OFTREE) += fdt.o +obj-$(CONFIG_DRIVER_NET_GIANFAR) += eth-devices.o +extra-y += barebox.lds diff --git a/arch/powerpc/mach-mpc85xx/barebox.lds.S b/arch/powerpc/mach-mpc85xx/barebox.lds.S new file mode 100644 index 0000000000..6e348d4db3 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/barebox.lds.S @@ -0,0 +1,154 @@ +/* + * Copyright 2013 GE Intelligent Platforms, Inc. + * Copyright 2007-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. + */ + +#include <asm/barebox.lds.h> + +#ifdef CONFIG_RESET_VECTOR_ADDRESS +#define RESET_VECTOR_ADDRESS CONFIG_RESET_VECTOR_ADDRESS +#else +#define RESET_VECTOR_ADDRESS 0xfffffffc +#endif + +OUTPUT_ARCH(BAREBOX_OUTPUT_ARCH) +ENTRY(_start_e500) + +PHDRS +{ + text PT_LOAD; + bss PT_LOAD; +} + +SECTIONS +{ + . = TEXT_BASE; + _stext = .; + PROVIDE (stext = .); + + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata)} + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + *(.text*) + *(.got1*) + + } :text + _etext = .; + PROVIDE (etext = .); + _sdata = .; + + .barebox_imd : { BAREBOX_IMD } + + .rodata : + { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + RO_DATA_SECTION + } :text + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + KEEP(*(.got)) + _GOT2_TABLE_ = .; + KEEP(*(.got2)) + PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); + _FIXUP_TABLE_ = .; + KEEP(*(.fixup)) + } + __got2_entries = ((_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2); + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data*) + *(.data1*) + *(.sdata*) + *(.sdata2*) + *(.dynamic*) + CONSTRUCTORS + } + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + _edata = .; + PROVIDE (edata = .); + + . = 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 = .; + arch/powerpc/cpu-85xx/start.o (.bootpg) + } :text = 0xffff + + .resetvec RESET_VECTOR_ADDRESS : + { + KEEP(*(.resetvec)) + arch/powerpc/cpu-85xx/resetvec.o (.resetvec) + } :text = 0xffff + + . = RESET_VECTOR_ADDRESS + 0x4; + +#if (RESET_VECTOR_ADDRESS == 0xfffffffc) + /* This avoids wrapping around to offset 0 */ + . |= 0x10; +#endif + + __bss_start = .; + .bss : + { + *(.sbss*) *(.scommon*) + *(.dynbss*) + *(.bss*) + *(COMMON) + } :bss + . = ALIGN(4); + __bss_stop = .; + _end = . ; + PROVIDE (end = .); +} diff --git a/arch/powerpc/mach-mpc85xx/cpu.c b/arch/powerpc/mach-mpc85xx/cpu.c new file mode 100644 index 0000000000..2119352f84 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/cpu.c @@ -0,0 +1,103 @@ +/* + * 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. + * + * 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. + * + */ + +#include <config.h> +#include <common.h> +#include <memory.h> +#include <init.h> +#include <restart.h> +#include <asm/fsl_ddr_sdram.h> +#include <asm-generic/memory_layout.h> +#include <mach/mmu.h> +#include <mach/immap_85xx.h> +#include <mach/mpc85xx.h> + +static void __noreturn mpc85xx_restart_soc(struct restart_handler *rst) +{ + 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); + + hang(); +} + +static int restart_register_feature(void) +{ + restart_handler_register_fn("soc", mpc85xx_restart_soc); + + return 0; +} +coredevice_initcall(restart_register_feature); + +/* Called from assembly */ +long int initdram(int board_type); + +long int initdram(int board_type) +{ + phys_size_t dram_size = 0; + + if (IS_ENABLED(CONFIG_DDR_SPD)) + dram_size = fsl_ddr_sdram(); + else + 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 * 4)) & + 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; +} + +static int fsl_reserve_region(void) +{ + request_sdram_region("stack", _text_base - STACK_SIZE, + STACK_SIZE); + return 0; +} +coredevice_initcall(fsl_reserve_region); diff --git a/arch/powerpc/mach-mpc85xx/cpu_init.c b/arch/powerpc/mach-mpc85xx/cpu_init.c new file mode 100644 index 0000000000..3259945fda --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/cpu_init.c @@ -0,0 +1,218 @@ +/* + * 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. + * + * 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. + * + */ + +#include <common.h> +#include <init.h> +#include <asm/processor.h> +#include <asm/cache.h> +#include <asm/fsl_law.h> +#include <asm/fsl_ifc.h> +#include <mach/mpc85xx.h> +#include <mach/mmu.h> +#include <mach/immap_85xx.h> + +/* NOR workaround for P1010 erratum A003399 */ +#if defined(CONFIG_FSL_ERRATUM_P1010_A003549) +#define SRAM_BASE_ADDR 0x100 +static void setup_ifc(void) +{ + u32 mas0, mas1, mas2, mas3, mas7; + phys_addr_t flash_phys = CFG_FLASH_BASE_PHYS; + + /* + * Adjust the TLB we were running out of to match the phys addr of the + * chip select we are adjusting and will return to. + */ + flash_phys += (~CFG_IFC_AMASK0) + 1 - 4*1024*1024; + mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(15); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_IPROT | + MAS1_TSIZE(BOOKE_PAGESZ_4M); + mas2 = FSL_BOOKE_MAS2(CONFIG_TEXT_BASE, MAS2_I|MAS2_G); + mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX); + mas7 = FSL_BOOKE_MAS7(flash_phys); + mtspr(MAS0, mas0); + mtspr(MAS1, mas1); + mtspr(MAS2, mas2); + mtspr(MAS3, mas3); + mtspr(MAS7, mas7); + asm volatile("isync;msync;tlbwe;isync"); + +#if defined(PPC_E500_DEBUG_TLB) + /* + * TLB entry for debuggging in AS1 + * Create temporary TLB entry in AS0 to handle debug exception + * As on debug exception MSR is cleared i.e. Address space is + * changed to 0. A TLB entry (in AS0) is required to handle + * debug exception generated * in AS1. + * + * TLB entry is created for IVPR + IVOR15 to map on valid OP + * code address because flash's physical address is going to + * change as CFG_FLASH_BASE_PHYS. + */ + mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(PPC_E500_DEBUG_TLB); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_IPROT | + MAS1_TSIZE(BOOKE_PAGESZ_4M); + mas2 = FSL_BOOKE_MAS2(CONFIG_TEXT_BASE, MAS2_I|MAS2_G); + mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX); + mas7 = FSL_BOOKE_MAS7(flash_phys); + + mtspr(MAS0, mas0); + mtspr(MAS1, mas1); + mtspr(MAS2, mas2); + mtspr(MAS3, mas3); + mtspr(MAS7, mas7); + + asm volatile("isync;msync;tlbwe;isync"); +#endif + set_ifc_cspr(0, CFG_IFC_CSPR0); + set_ifc_csor(0, CFG_IFC_CSOR0); + set_ifc_amask(0, CFG_IFC_AMASK0); +} + +static void fsl_erratum_ifc_a003399(void) +{ + u32 mas0, mas1, mas2, mas3, mas7; + void __iomem *l2cache = IOMEM(MPC85xx_L2_ADDR); + void (*setup_ifc_sram)(void) = (void *)SRAM_BASE_ADDR; + u32 *dst, *src, ix; + + /* TLB for SRAM */ + mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(9); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | + MAS1_TSIZE(BOOKE_PAGESZ_1M); + mas2 = FSL_BOOKE_MAS2(SRAM_BASE_ADDR, MAS2_I); + mas3 = FSL_BOOKE_MAS3(SRAM_BASE_ADDR, 0, + MAS3_SX | MAS3_SW | MAS3_SR); + mas7 = FSL_BOOKE_MAS7(0); + e500_write_tlb(mas0, mas1, mas2, mas3, mas7); + + out_be32(l2cache + MPC85xx_L2_L2SRBAR0_OFFSET, SRAM_BASE_ADDR); + out_be32(l2cache + MPC85xx_L2_L2ERRDIS_OFFSET, + (MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC)); + out_be32(l2cache + MPC85xx_L2_CTL_OFFSET, + (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE)); + /* + * Copy the code in setup_ifc to L2SRAM. Do a word copy + * because NOR Flash on P1010 does not support byte + * access (Erratum IFC-A002769) + */ + dst = (u32 *) SRAM_BASE_ADDR; + src = (u32 *) setup_ifc; + for (ix = 0; ix < 1024; ix++) + *dst++ = *src++; + setup_ifc_sram(); + + clrbits_be32(l2cache + MPC85xx_L2_CTL_OFFSET, + (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE)); + out_be32(l2cache + MPC85xx_L2_L2SRBAR0_OFFSET, 0x0); +} +#else +static void fsl_erratum_ifc_a003399(void) {} +#endif + +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; +} + +#if defined(CONFIG_FSL_ERRATUM_P1010_A003549) +static void fsl_erratum_p1010_a003549(void) +{ + void __iomem *guts = IOMEM(MPC85xx_GUTS_ADDR); + + setbits_be32(guts + MPC85xx_GUTS_PMUXCR_OFFSET, + MPC85xx_PMUXCR_LCLK_IFC_CS3); +} +#else +static void fsl_erratum_p1010_a003549(void) {} +#endif + +/* Called from assembly */ +void cpu_init_early_f(void); + +void cpu_init_early_f(void) +{ + u32 mas0, mas1, mas2, mas3, mas7; + + mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(13); + mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | + MAS1_TSIZE(BOOKE_PAGESZ_1M); + 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); + + fsl_erratum_p1010_a003549(); + fsl_init_laws(); + fsl_erratum_ifc_a003399(); + + e500_invalidate_tlb(1); + e500_init_tlbs(); +} + +static int cpu_init_r(void) +{ + e500_disable_tlb(14); + e500_disable_tlb(15); + + return 0; +} +core_initcall(cpu_init_r); diff --git a/arch/powerpc/mach-mpc85xx/cpuid.c b/arch/powerpc/mach-mpc85xx/cpuid.c new file mode 100644 index 0000000000..28f08ca292 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/cpuid.c @@ -0,0 +1,72 @@ +/* + * 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. + * + * 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. + * + */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <asm/cache.h> +#include <asm/io.h> +#include <mach/immap_85xx.h> +#include <mach/mpc85xx.h> + +struct cpu_type cpu_type_list[] = { + CPU_TYPE_ENTRY(8544, 8544, 1), + CPU_TYPE_ENTRY(8544, 8544_E, 1), + CPU_TYPE_ENTRY(P1010, P1010, 1), + CPU_TYPE_ENTRY(P1022, P1022, 2), + 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/powerpc/mach-mpc85xx/eth-devices.c b/arch/powerpc/mach-mpc85xx/eth-devices.c new file mode 100644 index 0000000000..b1e830a37b --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/eth-devices.c @@ -0,0 +1,54 @@ +/* + * 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 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. + * + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <mach/immap_85xx.h> +#include <mach/gianfar.h> + +static int fsl_phy_init(void) +{ + int i; + void __iomem *base = IOMEM(GFAR_BASE_ADDR + GFAR_TBIPA_OFFSET); + + /* + * The TBI address must be initialised to enable the PHY to + * link up after the MDIO reset. + */ + out_be32(base, GFAR_TBIPA_END); + /* All ports access external PHYs via the "gfar-mdio" device */ + add_generic_device("gfar-mdio", 0, NULL, MDIO_BASE_ADDR, + 0x1000, IORESOURCE_MEM, NULL); + + for (i = 1; i < FSL_NUM_TSEC; i++) { + out_be32(base + (i * 0x1000), GFAR_TBIPA_END - i); + /* Use "gfar-tbiphy" devices to access internal PHY. */ + add_generic_device("gfar-tbiphy", i, NULL, + MDIO_BASE_ADDR + (i * 0x1000), + 0x1000, IORESOURCE_MEM, NULL); + } + return 0; +} + +coredevice_initcall(fsl_phy_init); + +int fsl_eth_init(int num, struct gfar_info_struct *gf) +{ + add_generic_device("gfar", DEVICE_ID_DYNAMIC, NULL, + GFAR_BASE_ADDR + ((num - 1) * 0x1000), 0x1000, + IORESOURCE_MEM, gf); + return 0; +} diff --git a/arch/powerpc/mach-mpc85xx/fdt.c b/arch/powerpc/mach-mpc85xx/fdt.c new file mode 100644 index 0000000000..de0114ad64 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/fdt.c @@ -0,0 +1,154 @@ +/* + * Copyright 2013 GE Intelligent Platforms, Inc. + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * Based on U-Boot arch/powerpc/cpu/mpc85xx/fdt.c and + * common/fdt_support.c - version git-2b26201. + */ +#include <common.h> +#include <init.h> +#include <errno.h> +#include <environment.h> +#include <asm/processor.h> +#include <mach/clock.h> +#include <of.h> + +static void of_setup_crypto_node(void *blob) +{ + struct device_node *crypto_node; + + crypto_node = of_find_compatible_node(blob, NULL, "fsl,sec2.0"); + if (crypto_node == NULL) + return; + + of_delete_node(crypto_node); +} + +/* These properties specify whether the hardware supports the stashing + * of buffer descriptors in L2 cache. + */ +static void fdt_add_enet_stashing(void *fdt) +{ + struct device_node *node; + + node = of_find_compatible_node(fdt, NULL, "gianfar"); + while (node) { + of_set_property(node, "bd-stash", NULL, 0, 1); + of_property_write_u32(node, "rx-stash-len", 96); + of_property_write_u32(node, "rx-stash-idx", 0); + node = of_find_compatible_node(node, NULL, "gianfar"); + } + + node = of_find_compatible_node(fdt, NULL, "fsl,etsec2"); + while (node) { + of_set_property(node, "bd-stash", NULL, 0, 1); + of_property_write_u32(node, "rx-stash-len", 96); + of_property_write_u32(node, "rx-stash-idx", 0); + node = of_find_compatible_node(node, NULL, "fsl,etsec2"); + } +} + +static int fdt_stdout_setup(struct device_node *blob) +{ + struct device_node *node, *alias; + char sername[9] = { 0 }; + const char *prop; + struct console_device *cdev; + int len; + + node = of_create_node(blob, "/chosen"); + if (node == NULL) { + pr_err("%s: could not open /chosen node\n", __func__); + goto error; + } + + cdev = console_get_first_active(); + if (cdev) + sprintf(sername, "serial%d", cdev->dev->id); + else + sprintf(sername, "serial%d", 0); + + alias = of_find_node_by_path_from(blob, "/aliases"); + if (!alias) { + pr_err("%s: could not get aliases node.\n", __func__); + goto error; + } + prop = of_get_property(alias, sername, &len); + of_set_property(node, "linux,stdout-path", prop, len, 1); + + return 0; +error: + return -ENODEV; +} + +static int fdt_cpu_setup(struct device_node *blob, void *unused) +{ + struct device_node *node; + struct sys_info sysinfo; + + /* delete crypto node if not on an E-processor */ + if (!IS_E_PROCESSOR(get_svr())) + of_setup_crypto_node(blob); + + fdt_add_enet_stashing(blob); + fsl_get_sys_info(&sysinfo); + + node = of_find_node_by_type(blob, "cpu"); + while (node) { + const uint32_t *reg; + + of_property_write_u32(node, "timebase-frequency", + fsl_get_timebase_clock()); + of_property_write_u32(node, "bus-frequency", + sysinfo.freqSystemBus); + reg = of_get_property(node, "reg", NULL); + of_property_write_u32(node, "clock-frequency", + sysinfo.freqProcessor[*reg]); + node = of_find_node_by_type(node, "cpu"); + } + + node = of_find_node_by_type(blob, "soc"); + if (node) + of_property_write_u32(node, "bus-frequency", + sysinfo.freqSystemBus); + + node = of_find_compatible_node(blob, NULL, "fsl,elbc"); + if (node) + of_property_write_u32(node, "bus-frequency", + sysinfo.freqLocalBus); + + node = of_find_compatible_node(blob, NULL, "ns16550"); + while (node) { + of_property_write_u32(node, "clock-frequency", + sysinfo.freqSystemBus); + node = of_find_compatible_node(node, NULL, "ns16550"); + } + + node = of_find_compatible_node(blob, NULL, "fsl,mpic"); + if (node) + of_property_write_u32(node, "clock-frequency", + sysinfo.freqSystemBus); + + fdt_stdout_setup(blob); + + return 0; +} + +static int of_register_mpc85xx_fixup(void) +{ + return of_register_fixup(fdt_cpu_setup, NULL); +} +late_initcall(of_register_mpc85xx_fixup); diff --git a/arch/powerpc/mach-mpc85xx/fsl_gpio.c b/arch/powerpc/mach-mpc85xx/fsl_gpio.c new file mode 100644 index 0000000000..85994dcf1b --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/fsl_gpio.c @@ -0,0 +1,31 @@ +/* + * Copyright 2013 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 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. + * + * Minimal GPIO support. + */ + +#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <mach/gpio.h> +#include <mach/immap_85xx.h> + +#ifdef CONFIG_MPC8544 +/* Enable all GPIO output pins */ +void fsl_enable_gpiout(void) +{ + void __iomem *gpiocr = IOMEM(MPC85xx_GUTS_ADDR + MPC85xx_GPIOCR_OFFSET); + + out_be32(gpiocr, in_be32(gpiocr) | MPC85xx_GPIOCR_GPOUT); +} +#endif diff --git a/arch/powerpc/mach-mpc85xx/fsl_i2c.c b/arch/powerpc/mach-mpc85xx/fsl_i2c.c new file mode 100644 index 0000000000..8cf80713f6 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/fsl_i2c.c @@ -0,0 +1,254 @@ +/* + * Copyright 2013 GE Intelligent Platforms, Inc + * Copyright 2006,2009 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. + * + * Early I2C support functions to read SPD data or board + * information. + * Based on U-Boot drivers/i2c/fsl_i2c.c + */ +#include <common.h> +#include <i2c/i2c.h> +#include <mach/clock.h> +#include <mach/immap_85xx.h> +#include <mach/early_udelay.h> +#include <mach/fsl_i2c.h> + +/* FSL I2C registers */ +#define FSL_I2C_ADR 0x00 +#define FSL_I2C_FDR 0x04 +#define FSL_I2C_CR 0x08 +#define FSL_I2C_SR 0x0C +#define FSL_I2C_DR 0x10 +#define FSL_I2C_DFSRR 0x14 + +/* Bits of FSL I2C registers */ +#define I2C_SR_RXAK 0x01 +#define I2C_SR_MIF 0x02 +#define I2C_SR_MAL 0x10 +#define I2C_SR_MBB 0x20 +#define I2C_SR_MCF 0x80 +#define I2C_CR_RSTA 0x04 +#define I2C_CR_TXAK 0x08 +#define I2C_CR_MTX 0x10 +#define I2C_CR_MSTA 0x20 +#define I2C_CR_MEN 0x80 + +/* + * Set the I2C bus speed for a given I2C device + * + * parameters: + * - i2c: the I2C base address. + * - i2c_clk: I2C bus clock frequency. + * - speed: the desired speed of the bus. + * + * The I2C device must be stopped before calling this function. + * + * The return value is the actual bus speed that is set. + */ +static uint32_t fsl_set_i2c_bus_speed(const void __iomem *i2c, + uint32_t i2c_clk, uint32_t speed) +{ + uint8_t dfsr, fdr = 0x31; /* Default if no FDR found */ + uint16_t a, b, ga, gb, bin_gb, bin_ga, divider; + uint32_t c_div, est_div; + + divider = min((uint16_t)(i2c_clk / speed), (uint16_t) -1); + /* Condition 1: dfsr <= 50/T */ + dfsr = (5 * (i2c_clk / 1000)) / 100000; + if (!dfsr) + dfsr = 1; + est_div = ~0; + + /* + * Bus speed is calculated as per Freescale AN2919. + * a, b and dfsr matches identifiers A,B and C as in the + * application note. + */ + for (ga = 0x4, a = 10; a <= 30; ga++, a += 2) { + for (gb = 0; gb < 8; gb++) { + b = 16 << gb; + c_div = b * (a + (((3 * dfsr) / b) * 2)); + + if ((c_div > divider) && (c_div < est_div)) { + est_div = c_div; + bin_gb = gb << 2; + bin_ga = (ga & 0x3) | ((ga & 0x4) << 3); + fdr = bin_gb | bin_ga; + speed = i2c_clk / est_div; + } + } + if (a == 20) + a += 2; + if (a == 24) + a += 4; + } + writeb(dfsr, i2c + FSL_I2C_DFSRR); /* set default filter */ + writeb(fdr, i2c + FSL_I2C_FDR); /* set bus speed */ + + return speed; +} + +void fsl_i2c_init(void __iomem *i2c, int speed, int slaveadd) +{ + uint32_t i2c_clk; + + i2c_clk = fsl_get_i2c_freq(); + writeb(0, i2c + FSL_I2C_CR); + early_udelay(5); + + fsl_set_i2c_bus_speed(i2c, i2c_clk, speed); + writeb(slaveadd << 1, i2c + FSL_I2C_ADR); + writeb(0x0, i2c + FSL_I2C_SR); + writeb(I2C_CR_MEN, i2c + FSL_I2C_CR); +} + +static uint32_t fsl_usec2ticks(uint32_t usec) +{ + ulong ticks; + + if (usec < 1000) { + ticks = (usec * (fsl_get_timebase_clock() / 1000)); + ticks = (ticks + 500) / 1000; + } else { + ticks = (usec / 10); + ticks *= (fsl_get_timebase_clock() / 100000); + } + + return ticks; +} + +static int fsl_i2c_wait4bus(void __iomem *i2c) +{ + uint64_t timeval = get_ticks(); + const uint64_t timeout = fsl_usec2ticks(20000); + + while (readb(i2c + FSL_I2C_SR) & I2C_SR_MBB) + if ((get_ticks() - timeval) > timeout) + return -1; + + return 0; +} + +void fsl_i2c_stop(void __iomem *i2c) +{ + writeb(I2C_CR_MEN, i2c + FSL_I2C_CR); +} + +static int fsl_i2c_wait(void __iomem *i2c, int write) +{ + const uint64_t timeout = fsl_usec2ticks(100000); + uint64_t timeval = get_ticks(); + int csr; + + do { + csr = readb(i2c + FSL_I2C_SR); + if (csr & I2C_SR_MIF) + break; + } while ((get_ticks() - timeval) < timeout); + + if ((get_ticks() - timeval) > timeout) + goto error; + + csr = readb(i2c + FSL_I2C_SR); + writeb(0x0, i2c + FSL_I2C_SR); + + if (csr & I2C_SR_MAL) + goto error; + + if (!(csr & I2C_SR_MCF)) + goto error; + + if (write == 0 && (csr & I2C_SR_RXAK)) + goto error; + + return 0; +error: + return -1; +} + +static int __i2c_write(void __iomem *i2c, uint8_t *data, int length) +{ + int i; + + for (i = 0; i < length; i++) { + writeb(data[i], i2c + FSL_I2C_DR); + if (fsl_i2c_wait(i2c, 0) < 0) + break; + } + + return i; +} + +static int __i2c_read(void __iomem *i2c, uint8_t *data, int length) +{ + int i; + uint8_t val = I2C_CR_MEN | I2C_CR_MSTA; + + if (length == 1) + writeb(val | I2C_CR_TXAK, i2c + FSL_I2C_CR); + else + writeb(val, i2c + FSL_I2C_CR); + + readb(i2c + FSL_I2C_DR); + for (i = 0; i < length; i++) { + if (fsl_i2c_wait(i2c, 1) < 0) + break; + + /* Generate ack on last next to last byte */ + if (i == length - 2) + writeb(val | I2C_CR_TXAK, i2c + FSL_I2C_CR); + /* Do not generate stop on last byte */ + if (i == length - 1) + writeb(val | I2C_CR_MTX, i2c + FSL_I2C_CR); + + data[i] = readb(i2c + FSL_I2C_DR); + } + + return i; +} + +static int +fsl_i2c_write_addr(void __iomem *i2c, uint8_t dev, uint8_t dir, int rsta) +{ + uint8_t val = I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX; + + if (rsta) + val |= I2C_CR_RSTA; + writeb(val, i2c + FSL_I2C_CR); + writeb((dev << 1) | dir, i2c + FSL_I2C_DR); + + if (fsl_i2c_wait(i2c, 0) < 0) + return 0; + + return 1; +} + +int fsl_i2c_read(void __iomem *i2c, uint8_t dev, uint addr, int alen, + uint8_t *data, int length) +{ + int i = -1; + uint8_t *a = (uint8_t *)&addr; + + if (alen && (fsl_i2c_wait4bus(i2c) >= 0) && + (fsl_i2c_write_addr(i2c, dev, 0, 0) != 0) && + (__i2c_write(i2c, &a[4 - alen], alen) == alen)) + i = 0; + + if (length && fsl_i2c_write_addr(i2c, dev, 1, 1) != 0) + i = __i2c_read(i2c, data, length); + + if (i == length) + return 0; + + return -1; +} diff --git a/arch/powerpc/mach-mpc85xx/fsl_law.c b/arch/powerpc/mach-mpc85xx/fsl_law.c new file mode 100644 index 0000000000..e3c765f30f --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/fsl_law.c @@ -0,0 +1,154 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + */ + +#include <common.h> +#include <asm/config.h> +#include <asm/fsl_law.h> +#include <mach/ffs64.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) +{ + int 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/powerpc/mach-mpc85xx/include/mach/clock.h b/arch/powerpc/mach-mpc85xx/include/mach/clock.h new file mode 100644 index 0000000000..bfd9cf4d8e --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/clock.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#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; +}; + +unsigned long fsl_get_bus_freq(ulong dummy); +unsigned long fsl_get_ddr_freq(ulong dummy); +unsigned long fsl_get_timebase_clock(void); +unsigned long fsl_get_i2c_freq(void); +void fsl_get_sys_info(struct sys_info *sysInfo); +#endif /* __ASM_ARCH_CLOCKS_H */ diff --git a/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h new file mode 100644 index 0000000000..fad2c47d11 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h @@ -0,0 +1,64 @@ +/* + * 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. + * + */ + +#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 +#define FSL_NUM_TSEC 3 +#define FSL_ERRATUM_A005125 +#define PPC_E500_DEBUG_TLB 2 + +#elif defined(CONFIG_MPC8544) +#define MAX_CPUS 1 +#define FSL_NUM_LAWS 10 +#define FSL_NUM_TSEC 2 +#define FSL_ERRATUM_A005125 +#define PPC_E500_DEBUG_TLB 0 + +#elif defined(CONFIG_P1022) +#define MAX_CPUS 2 +#define FSL_NUM_LAWS 12 +#define FSL_NUM_TSEC 2 +#define FSL_SEC_COMPAT 2 +#define PPC_E500_DEBUG_TLB 2 +#define FSL_TSECV2 +#define FSL_ERRATUM_A005125 + +#elif defined(CONFIG_P1010) +#define MAX_CPUS 1 +#define FSL_NUM_LAWS 12 +#define FSL_NUM_TSEC 3 +#define FSL_SEC_COMPAT 4 +#define FSL_ERRATUM_A005125 +#define PPC_E500_DEBUG_TLB 2 +#define FSL_TSECV2 + +#else +#error Processor type not defined for this platform +#endif + +#endif /* _ASM_MPC85xx_CONFIG_H_ */ diff --git a/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h b/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h new file mode 100644 index 0000000000..12020dd96d --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * 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. + * + */ + +#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/powerpc/mach-mpc85xx/include/mach/ffs64.h b/arch/powerpc/mach-mpc85xx/include/mach/ffs64.h new file mode 100644 index 0000000000..045498c513 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/ffs64.h @@ -0,0 +1,20 @@ +/* + * Copyright 2013 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 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. + * + */ +#include <linux/log2.h> + +static inline int ffs64(u64 x) +{ + return __ilog2_u64(x & -x) + 1ull; +} diff --git a/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h b/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h new file mode 100644 index 0000000000..d187c6cf49 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h @@ -0,0 +1,17 @@ +/* + * Copyright 2013 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 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. + */ +void fsl_i2c_init(void __iomem *i2c, int speed, int slaveadd); +int fsl_i2c_read(void __iomem *i2c, uint8_t dev, uint addr, int alen, + uint8_t *data, int length); +void fsl_i2c_stop(void __iomem *i2c); diff --git a/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h b/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h new file mode 100644 index 0000000000..660cb1e98f --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h @@ -0,0 +1,30 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * based on tsec.h by Xianghua Xiao and Andy Fleming 2003-2009 + * + * 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. + * + * Platform data for the Motorola Triple Speed Ethernet Controller + */ + +#define GFAR_TBIPA_OFFSET 0x030 /* TBI PHY address */ +#define GFAR_TBIPA_END 0x1f /* Last valid PHY address */ + +struct gfar_info_struct { + unsigned int phyaddr; + unsigned int tbiana; + unsigned int tbicr; + unsigned int mdiobus_tbi; +}; + +int fsl_eth_init(int num, struct gfar_info_struct *gf); diff --git a/arch/powerpc/mach-mpc85xx/include/mach/gpio.h b/arch/powerpc/mach-mpc85xx/include/mach/gpio.h new file mode 100644 index 0000000000..b41ecc5214 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/gpio.h @@ -0,0 +1,15 @@ +/* + * Copyright 2013 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 as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#ifndef _MACH_PPC_GPIO_H +#define _MACH_PPC_GPIO_H + +extern void fsl_enable_gpiout(void); + +#endif /* _MACH_PPC_GPIO_H */ diff --git a/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h new file mode 100644 index 0000000000..d348f86dac --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h @@ -0,0 +1,199 @@ +/* + * MPC85xx Internal Memory Map + * + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * + * Copyright(c) 2002,2003 Motorola Inc. + * Xianghua Xiao (x.xiao@motorola.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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. + * + */ + +#ifndef __IMMAP_85xx__ +#define __IMMAP_85xx__ + +#include <asm/types.h> +#include <asm/fsl_lbc.h> +#include <asm/fsl_ifc.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_PCI1_OFFSET 0x8000 + +#define MPC85xx_GPIO_OFFSET 0xf000 +#define MPC85xx_IFC_OFFSET 0x1e000 +#define MPC85xx_L2_OFFSET 0x20000 +#ifdef FSL_TSECV2 +#define TSEC1_OFFSET 0xB0000 +#else +#define TSEC1_OFFSET 0x24000 +#endif + +#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 IFC_ADDR (CFG_IMMR + MPC85xx_IFC_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 */ +#define MPC85xx_ECM_EEDR_OFFSET 0xE00 /* ECM error detect register */ +#define MPC85xx_ECM_EEER_OFFSET 0xE08 /* ECM error enable register */ + +/* + * 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 +/* Chip Select 0, 1, 2, 3 Configuration 2 */ +#define MPC85xx_DDR_CS0_CONFIG_2_OFFSET 0x0c0 +#define MPC85xx_DDR_CS1_CONFIG_2_OFFSET 0x0c4 +#define MPC85xx_DDR_CS2_CONFIG_2_OFFSET 0x0c8 +#define MPC85xx_DDR_CS3_CONFIG_2_OFFSET 0x0cc +/* 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 +/* SDRAM Timing Configuration 4,5 */ +#define MPC85xx_DDR_TIMING_CFG_4_OFFSET 0x160 +#define MPC85xx_DDR_TIMING_CFG_5_OFFSET 0x164 +/* DDR ZQ calibration control */ +#define MPC85xx_DDR_ZQ_CNTL_OFFSET 0x170 +/* DDR write leveling control */ +#define MPC85xx_DDR_WRLVL_CNTL_OFFSET 0x174 +/* Self Refresh Counter */ +#define MPC85xx_DDR_SR_CNTL_OFFSET 0x17c +/* DDR SDRAM Register Control Word */ +#define MPC85xx_DDR_SDRAM_RCW_1_OFFSET 0x180 +#define MPC85xx_DDR_SDRAM_RCW_2_OFFSET 0x184 +/* DDR write leveling control */ +#define MPC85xx_DDR_WRLVL_CNTL_2_OFFSET 0x190 +#define MPC85xx_DDR_WRLVL_CNTL_3_OFFSET 0x194 +/* DDR Control Driver */ +#define MPC85xx_DDR_DDRCDR1_OFFSET 0xb28 +#define MPC85xx_DDR_DDRCDR2_OFFSET 0xb2c +/* DDR IP block revision */ +#define MPC85xx_DDR_IP_REV1_OFFSET 0xbf8 +#define MPC85xx_DDR_IP_REV2_OFFSET 0xbfc +/* Memory Error Disable */ +#define MPC85xx_DDR_ERR_DISABLE_OFFSET 0xe44 +#define MPC85xx_DDR_ERR_INT_EN_OFFSET 0xe48 + +#define DDR_OFF(REGNAME) (MPC85xx_DDR_##REGNAME##_OFFSET) + +/* + * GPIO Register Offsets + */ +#define MPC85xx_GPIO_GPDIR 0x00 +#define MPC85xx_GPIO_GPDAT 0x08 +#define MPC85xx_GPIO_GPDIR_OFFSET 0x00 +#define MPC85xx_GPIO_GPDAT_OFFSET 0x08 + +/* Global Utilities Registers */ +#define MPC85xx_GPIOCR_OFFSET 0x30 +#define MPC85xx_GPIOCR_GPOUT 0x00000200 +#define MPC85xx_GPOUTDR_OFFSET 0x40 +#define MPC85xx_GPIOBIT(i) (1 << (31 - i)) +#define MPC85xx_GPINDR_OFFSET 0x50 + +#define MPC85xx_DEVDISR_OFFSET 0x70 +#define MPC85xx_DEVDISR_TSEC1 0x00000080 +#define MPC85xx_DEVDISR_TSEC2 0x00000040 +#define MPC85xx_DEVDISR_TSEC3 0x00000020 + +/* + * L2 Cache Register Offsets + */ +#define MPC85xx_L2_CTL_OFFSET 0x0 /* L2 configuration 0 */ +#define MPC85xx_L2CTL_L2E 0x80000000 +#define MPC85xx_L2CTL_L2SRAM_ENTIRE 0x00010000 +#define MPC85xx_L2_L2SRBAR0_OFFSET 0x100 +#define MPC85xx_L2_L2ERRDIS_OFFSET 0xe44 +#define MPC85xx_L2ERRDIS_MBECC 0x00000008 +#define MPC85xx_L2ERRDIS_SBECC 0x00000004 + +/* 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_PORDEVSR2_OFFSET 0x14 +#define MPC85xx_PORDEVSR2_SEC_CFG 0x00000080 +#define MPC85xx_GUTS_PMUXCR_OFFSET 0x60 +#define MPC85xx_PMUXCR_LCLK_IFC_CS3 0x000000C0 +#define MPC85xx_GUTS_PMUXCR2_OFFSET 0x64 +#define MPC85xx_GUTS_DEVDISR_OFFSET 0x70 +#define MPC85xx_DEVDISR_TB0 0x00004000 +#define MPC85xx_DEVDISR_TB1 0x00001000 +#define MPC85xx_GUTS_RSTCR_OFFSET 0xb0 + +#define GFAR_BASE_ADDR (CFG_IMMR + TSEC1_OFFSET) +#define MDIO_BASE_ADDR (CFG_IMMR + 0x24000) + +#define I2C1_BASE_ADDR (CFG_IMMR + 0x3000) +#define I2C2_BASE_ADDR (CFG_IMMR + 0x3100) + +/* Global Timer Registers */ +#define MPC8xxx_PIC_TFRR_OFFSET 0x10F0 + +#define PCI1_BASE_ADDR (CFG_IMMR + MPC85xx_PCI1_OFFSET) +#endif /*__IMMAP_85xx__*/ diff --git a/arch/powerpc/mach-mpc85xx/include/mach/mmu.h b/arch/powerpc/mach-mpc85xx/include/mach/mmu.h new file mode 100644 index 0000000000..e2ecc62ef0 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/mmu.h @@ -0,0 +1,52 @@ +/* + * 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 int e500_find_free_tlbcam(void); +extern void e500_read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, + unsigned long *epn, phys_addr_t *rpn); +extern void e500_read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, + unsigned long *epn, phys_addr_t *rpn); +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/powerpc/mach-mpc85xx/include/mach/mpc85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h new file mode 100644 index 0000000000..5491f0b08d --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * 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/powerpc/mach-mpc85xx/speed.c b/arch/powerpc/mach-mpc85xx/speed.c new file mode 100644 index 0000000000..16ce72d846 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/speed.c @@ -0,0 +1,131 @@ +/* + * 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. + * + * 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. + * + */ + +#include <common.h> +#include <asm/processor.h> +#include <mach/clock.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, lcrr_div, ccr; + 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 + + if (IS_ENABLED(CONFIG_FSL_IFC)) { + void __iomem *ifc = IFC_BASE_ADDR; + + ccr = in_be32(ifc + FSL_IFC_CCR_OFFSET); + ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT); + sysInfo->freqLocalBus = sysInfo->freqSystemBus / (ccr + 1); + } else { + 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_ddr_freq(ulong dummy) +{ + struct sys_info sys_info; + + fsl_get_sys_info(&sys_info); + + return sys_info.freqDDRBus; +} + +unsigned long fsl_get_timebase_clock(void) +{ + struct sys_info sysinfo; + + fsl_get_sys_info(&sysinfo); + + return (sysinfo.freqSystemBus + 4UL)/8UL; +} + +unsigned long fsl_get_i2c_freq(void) +{ + uint svr; + struct sys_info sysinfo; + void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR); + + fsl_get_sys_info(&sysinfo); + + svr = get_svr(); + if ((svr == SVR_8544) || (svr == SVR_8544_E)) { + if (in_be32(gur + MPC85xx_GUTS_PORDEVSR2_OFFSET) & + MPC85xx_PORDEVSR2_SEC_CFG) + return sysinfo.freqSystemBus / 3; + } + + return sysinfo.freqSystemBus / 2; +} diff --git a/arch/powerpc/mach-mpc85xx/time.c b/arch/powerpc/mach-mpc85xx/time.c new file mode 100644 index 0000000000..5981995ac2 --- /dev/null +++ b/arch/powerpc/mach-mpc85xx/time.c @@ -0,0 +1,45 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + */ + +#include <common.h> +#include <clock.h> +#include <init.h> +#include <mach/clock.h> + +static uint64_t ppc_clocksource_read(void) +{ + return get_ticks(); +} + +static struct clocksource cs = { + .read = ppc_clocksource_read, + .mask = CLOCKSOURCE_MASK(64), + .priority = 80, +}; + +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); + + return init_clock(&cs); +} + +core_initcall(clocksource_init); |