diff options
Diffstat (limited to 'arch/m68k/cpu')
-rw-r--r-- | arch/m68k/cpu/mcf530x/Makefile | 9 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/config.mk | 12 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/cpu.c | 36 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/cpu_init.c | 160 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/interrupts.c | 29 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/speed.c | 23 | ||||
-rw-r--r-- | arch/m68k/cpu/mcf530x/start.S | 257 |
7 files changed, 526 insertions, 0 deletions
diff --git a/arch/m68k/cpu/mcf530x/Makefile b/arch/m68k/cpu/mcf530x/Makefile new file mode 100644 index 0000000000..9492bde816 --- /dev/null +++ b/arch/m68k/cpu/mcf530x/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-y = start.o +obj-y = interrupts.o cpu.o speed.o cpu_init.o + diff --git a/arch/m68k/cpu/mcf530x/config.mk b/arch/m68k/cpu/mcf530x/config.mk new file mode 100644 index 0000000000..aef72d70c5 --- /dev/null +++ b/arch/m68k/cpu/mcf530x/config.mk @@ -0,0 +1,12 @@ +# +# (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h +is5307:=$(shell grep CONFIG_M5307 $(cfg)) + +ifneq (,$(findstring CONFIG_M5307,$(is5307))) +PLATFORM_CPPFLAGS += -mcpu=5307 +endif diff --git a/arch/m68k/cpu/mcf530x/cpu.c b/arch/m68k/cpu/mcf530x/cpu.c new file mode 100644 index 0000000000..78f438548b --- /dev/null +++ b/arch/m68k/cpu/mcf530x/cpu.c @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <common.h> +#include <asm/immap.h> +#include <asm/io.h> + +#ifdef CONFIG_M5307 +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + sim_t *sim = (sim_t *)(MMAP_SIM); + + /* enable watchdog/reset, set timeout to 0 and wait */ + out_8(&sim->sypcr, SYPCR_SWE | SYPCR_SWRI); + + /* wait for watchdog reset */ + for (;;) + ; + + /* we don't return! */ + return 0; +} + +int checkcpu(void) +{ + char buf[32]; + + printf("CPU: Freescale Coldfire MCF5307 at %s MHz\n", + strmhz(buf, CONFIG_SYS_CPU_CLK)); + return 0; +} +#endif diff --git a/arch/m68k/cpu/mcf530x/cpu_init.c b/arch/m68k/cpu/mcf530x/cpu_init.c new file mode 100644 index 0000000000..80dc23910e --- /dev/null +++ b/arch/m68k/cpu/mcf530x/cpu_init.c @@ -0,0 +1,160 @@ +/* + * (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/immap.h> +#include <asm/io.h> + +#if defined(CONFIG_M5307) +/* + * Simple mcf5307 chip select module init. + * + * Note: this chip has an issue reported in the device "errata": + * MCF5307ER Rev 4.2 reports @ section 35: + * Corrupted Return PC in Exception Stack Frame + * When processing an autovectored interrupt an error can occur that + * causes 0xFFFFFFFF to be written as the return PC value in the + * exception stack frame. The problem is caused by a conflict between + * an internal autovector access and a chip select mapped to the IACK + * address space (0xFFFFXXXX). + * Workaround: + * Set the C/I bit in the chip select mask register (CSMR) for the + * chip select that is mapped to 0xFFFFXXXX. + * This will prevent the chip select from asserting for IACK accesses. + */ + +#define MCF5307_SP_ERR_FIX(cs_base, mask) \ + do { \ + if (((cs_base<<16)+(in_be32(&mask)&0xffff0000)) >= \ + 0xffff0000) \ + setbits_be32(&mask, CSMR_CI); \ + } while (0) + +void init_csm(void) +{ + csm_t *csm = (csm_t *)(MMAP_CSM); + +#if (defined(CONFIG_SYS_CS0_BASE) && defined(CONFIG_SYS_CS0_MASK) && \ + defined(CONFIG_SYS_CS0_CTRL)) + out_be16(&csm->csar0, CONFIG_SYS_CS0_BASE); + out_be32(&csm->csmr0, CONFIG_SYS_CS0_MASK); + out_be16(&csm->cscr0, CONFIG_SYS_CS0_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS0_BASE, csm->csmr0); +#else +#warning "Chip Select 0 are not initialized/used" +#endif +#if (defined(CONFIG_SYS_CS1_BASE) && defined(CONFIG_SYS_CS1_MASK) && \ + defined(CONFIG_SYS_CS1_CTRL)) + out_be16(&csm->csar1, CONFIG_SYS_CS1_BASE); + out_be32(&csm->csmr1, CONFIG_SYS_CS1_MASK); + out_be16(&csm->cscr1, CONFIG_SYS_CS1_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS1_BASE, csm->csmr1); +#endif +#if (defined(CONFIG_SYS_CS2_BASE) && defined(CONFIG_SYS_CS2_MASK) && \ + defined(CONFIG_SYS_CS2_CTRL)) + out_be16(&csm->csar2, CONFIG_SYS_CS2_BASE); + out_be32(&csm->csmr2, CONFIG_SYS_CS2_MASK); + out_be16(&csm->cscr2, CONFIG_SYS_CS2_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS2_BASE, csm->csmr2); +#endif +#if (defined(CONFIG_SYS_CS3_BASE) && defined(CONFIG_SYS_CS3_MASK) && \ + defined(CONFIG_SYS_CS3_CTRL)) + out_be16(&csm->csar3, CONFIG_SYS_CS3_BASE); + out_be32(&csm->csmr3, CONFIG_SYS_CS3_MASK); + out_be16(&csm->cscr3, CONFIG_SYS_CS3_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS3_BASE, csm->csmr3); +#endif +#if (defined(CONFIG_SYS_CS4_BASE) && defined(CONFIG_SYS_CS4_MASK) && \ + defined(CONFIG_SYS_CS4_CTRL)) + out_be16(&csm->csar4, CONFIG_SYS_CS4_BASE); + out_be32(&csm->csmr4, CONFIG_SYS_CS4_MASK); + out_be16(&csm->cscr4, CONFIG_SYS_CS4_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS4_BASE, csm->csmr4); +#endif +#if (defined(CONFIG_SYS_CS5_BASE) && defined(CONFIG_SYS_CS5_MASK) && \ + defined(CONFIG_SYS_CS5_CTRL)) + out_be16(&csm->csar5, CONFIG_SYS_CS5_BASE); + out_be32(&csm->csmr5, CONFIG_SYS_CS5_MASK); + out_be16(&csm->cscr5, CONFIG_SYS_CS5_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS5_BASE, csm->csmr5); +#endif +#if (defined(CONFIG_SYS_CS6_BASE) && defined(CONFIG_SYS_CS6_MASK) && \ + defined(CONFIG_SYS_CS6_CTRL)) + out_be16(&csm->csar6, CONFIG_SYS_CS6_BASE); + out_be32(&csm->csmr6, CONFIG_SYS_CS6_MASK); + out_be16(&csm->cscr6, CONFIG_SYS_CS6_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS6_BASE, csm->csmr6); +#endif +#if (defined(CONFIG_SYS_CS7_BASE) && defined(CONFIG_SYS_CS7_MASK) && \ + defined(CONFIG_SYS_CS7_CTRL)) + out_be16(&csm->csar7, CONFIG_SYS_CS7_BASE); + out_be32(&csm->csmr7, CONFIG_SYS_CS7_MASK); + out_be16(&csm->cscr7, CONFIG_SYS_CS7_CTRL); + MCF5307_SP_ERR_FIX(CONFIG_SYS_CS7_BASE, csm->csmr7); +#endif +} + +/* + * Set up the memory map and initialize registers + */ +void cpu_init_f(void) +{ + sim_t *sim = (sim_t *)(MMAP_SIM); + + out_8(&sim->sypcr, 0x00); + out_8(&sim->swivr, 0x0f); + out_8(&sim->swsr, 0x00); + out_8(&sim->mpark, 0x00); + + intctrl_t *icr = (intctrl_t *)(MMAP_INTC); + + /* timer 2 not masked */ + out_be32(&icr->imr, 0xfffffbff); + + out_8(&icr->icr0, 0x00); /* sw watchdog */ + out_8(&icr->icr1, 0x00); /* timer 1 */ + out_8(&icr->icr2, 0x88); /* timer 2 */ + out_8(&icr->icr3, 0x00); /* i2c */ + out_8(&icr->icr4, 0x00); /* uart 0 */ + out_8(&icr->icr5, 0x00); /* uart 1 */ + out_8(&icr->icr6, 0x00); /* dma 0 */ + out_8(&icr->icr7, 0x00); /* dma 1 */ + out_8(&icr->icr8, 0x00); /* dma 2 */ + out_8(&icr->icr9, 0x00); /* dma 3 */ + + /* Chipselect Init */ + init_csm(); + + /* enable data/instruction cache now */ + icache_enable(); +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r(void) +{ + return 0; +} + +void uart_port_conf(void) +{ +} + +void arch_preboot_os(void) +{ + /* + * OS can change interrupt offsets and are about to boot the OS so + * we need to make sure we disable all async interrupts. + */ + intctrl_t *icr = (intctrl_t *)(MMAP_INTC); + + out_8(&icr->icr1, 0x00); /* timer 1 */ + out_8(&icr->icr2, 0x00); /* timer 2 */ +} +#endif diff --git a/arch/m68k/cpu/mcf530x/interrupts.c b/arch/m68k/cpu/mcf530x/interrupts.c new file mode 100644 index 0000000000..bf4038dff8 --- /dev/null +++ b/arch/m68k/cpu/mcf530x/interrupts.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <common.h> +#include <asm/immap.h> +#include <asm/io.h> + +#ifdef CONFIG_M5307 +int interrupt_init(void) +{ + enable_interrupts(); + + return 0; +} + +void dtimer_intr_setup(void) +{ + intctrl_t *icr = (intctrl_t *)(MMAP_INTC); + + /* clearing TIMER2 mask, so enabling the related interrupt */ + out_be32(&icr->imr, in_be32(&icr->imr) & ~0x00000400); + /* set TIMER2 interrupt priority */ + out_8(&icr->icr2, CONFIG_SYS_TMRINTR_PRI); +} +#endif diff --git a/arch/m68k/cpu/mcf530x/speed.c b/arch/m68k/cpu/mcf530x/speed.c new file mode 100644 index 0000000000..3cf1986fc9 --- /dev/null +++ b/arch/m68k/cpu/mcf530x/speed.c @@ -0,0 +1,23 @@ +/* + * (C) Copyright 2014 Angelo Dureghello <angelo@sysam.it> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/immap.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* get_clocks() fills in gd->cpu_clock and gd->bus_clk */ +int get_clocks(void) +{ +#if defined(CONFIG_M5307) + gd->bus_clk = CONFIG_SYS_CLK; + gd->cpu_clk = CONFIG_SYS_CPU_CLK; +#endif + + return 0; +} diff --git a/arch/m68k/cpu/mcf530x/start.S b/arch/m68k/cpu/mcf530x/start.S new file mode 100644 index 0000000000..097958afda --- /dev/null +++ b/arch/m68k/cpu/mcf530x/start.S @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2015 Angelo Dureghello <angelo@sysam.it> + * Based on code from Bernhard Kuhn <bkuhn@metrowerks.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include "version.h" +#include <asm/cache.h> + +#ifndef CONFIG_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + +#define _START _start +#define _FAULT _fault + + +.macro SAVE_ALL + move.w #0x2700,%sr; /* disable intrs */ + subl #60,%sp; /* space for 15 regs */ + moveml %d0-%d7/%a0-%a6,%sp@ +.endm + +.macro RESTORE_ALL + moveml %sp@,%d0-%d7/%a0-%a6; + addl #60,%sp; /* space for 15 regs */ + rte +.endm + +/* If we come from a pre-loader we don't need an initial exception + * table. + */ +#if !defined(CONFIG_MONITOR_IS_IN_RAM) + +.text +/* + * Vector table. This is used for initial platform startup. + * These vectors are to catch any un-intended traps. + */ +_vectors: + +/* Flash offset is 0 until we setup CS0 */ +.long 0x00000000 +#if defined(CONFIG_M5307) && \ + (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE) +.long _start - CONFIG_SYS_TEXT_BASE +#else +.long _START +#endif + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT +.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT + +#endif + + .text + .globl _start +_start: + nop + nop + move.w #0x2700,%sr + + /* set MBAR address + valid flag */ + move.l #(CONFIG_SYS_MBAR + 1), %d0 + move.c %d0, %MBAR + + move.l #(CONFIG_SYS_INIT_RAM_ADDR + 1), %d0 + move.c %d0, %RAMBAR + + /* DS 4.8.2 (Cache Organization) invalidate and disable cache */ + move.l #CF_CACR_CINVA, %d0 + movec %d0, %CACR + move.l #0, %d0 + movec %d0, %ACR0 + movec %d0, %ACR1 + + /* + * if we come from a pre-loader we have no exception table and + * therefore no VBR to set + */ +#if !defined(CONFIG_MONITOR_IS_IN_RAM) + move.l #CONFIG_SYS_FLASH_BASE, %d0 + movec %d0, %VBR +#endif + + /* initialize general use internal ram */ + move.l #0, %d0 + move.l #(ICACHE_STATUS), %a1 /* icache */ + move.l #(DCACHE_STATUS), %a2 /* dcache */ + move.l %d0, (%a1) + move.l %d0, (%a2) + + /* + * set stackpointer to internal sram end - 80 + * (global data struct size + some bytes) + * get some stackspace for the first c-code, + */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp + clr.l %sp@- + + /* put relocation table address to a5 */ + move.l #__got_start, %a5 + + /* run low-level CPU init code (from flash) */ + bsr cpu_init_f + + /* run low-level board init code (from flash) */ + bsr board_init_f + + /* board_init_f() does not return */ + +/*--------------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + */ + .globl relocate_code +relocate_code: + link.w %a6,#0 + move.l 8(%a6), %sp /* set new stack pointer */ + move.l 12(%a6), %d0 /* Save copy of Global Data pointer */ + move.l 16(%a6), %a0 /* Save copy of Destination Address */ + + move.l #CONFIG_SYS_MONITOR_BASE, %a1 + move.l #__init_end, %a2 + move.l %a0, %a3 + /* copy the code to RAM */ +1: + move.l (%a1)+, (%a3)+ + cmp.l %a1,%a2 + bgt.s 1b + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + move.l %a0, %a1 + add.l #(in_ram - CONFIG_SYS_MONITOR_BASE), %a1 + jmp (%a1) + +in_ram: + +clear_bss: + /* + * Now clear BSS segment + */ + move.l %a0, %a1 + add.l #(_sbss - CONFIG_SYS_MONITOR_BASE), %a1 + move.l %a0, %d1 + add.l #(_ebss - CONFIG_SYS_MONITOR_BASE), %d1 +6: + clr.l (%a1)+ + cmp.l %a1,%d1 + bgt.s 6b + + /* + * fix got table in RAM + */ + move.l %a0, %a1 + add.l #(__got_start - CONFIG_SYS_MONITOR_BASE), %a1 + /* * fix got pointer register a5 */ + move.l %a1,%a5 + + move.l %a0, %a2 + add.l #(__got_end - CONFIG_SYS_MONITOR_BASE), %a2 + +7: + move.l (%a1),%d1 + sub.l #_start, %d1 + add.l %a0,%d1 + move.l %d1,(%a1)+ + cmp.l %a2, %a1 + bne 7b + + /* calculate relative jump to board_init_r in ram */ + move.l %a0, %a1 + add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1 + + /* set parameters for board_init_r */ + move.l %a0,-(%sp) /* dest_addr */ + move.l %d0,-(%sp) /* gd */ +#if defined(DEBUG) && (CONFIG_SYS_TEXT_BASE!=CONFIG_SYS_INT_FLASH_BASE) && \ + defined(CONFIG_SYS_HALT_BEFOR_RAM_JUMP) + halt +#endif + jsr (%a1) + +/*--------------------------------------------------------------------------*/ +/* exception code */ + .globl _fault +_fault: + bra _fault + + .globl _exc_handler +_exc_handler: + SAVE_ALL + movel %sp,%sp@- + bsr exc_handler + addql #4,%sp + RESTORE_ALL + + .globl _int_handler +_int_handler: + SAVE_ALL + movel %sp,%sp@- + bsr int_handler + addql #4,%sp + RESTORE_ALL + +/*--------------------------------------------------------------------------*/ + + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" + .ascii CONFIG_IDENT_STRING, "\0" + .align 4 |