From 3ec66893e377b088c1284d2d23adb2aeea6d7965 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 27 Feb 2021 22:08:58 +0000 Subject: New port: FiiO M3K on bare metal Change-Id: I7517e7d5459e129dcfc9465c6fbd708619888fbe --- firmware/target/mips/ingenic_x1000/system-target.h | 148 +++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 firmware/target/mips/ingenic_x1000/system-target.h (limited to 'firmware/target/mips/ingenic_x1000/system-target.h') diff --git a/firmware/target/mips/ingenic_x1000/system-target.h b/firmware/target/mips/ingenic_x1000/system-target.h new file mode 100644 index 0000000000..a2f0a6ff70 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/system-target.h @@ -0,0 +1,148 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __SYSTEM_TARGET_H__ +#define __SYSTEM_TARGET_H__ + +/* For the sake of system.h CACHEALIGN macros. + * We need this to align DMA buffers, etc. + */ +#define CACHEALIGN_BITS 5 +#define CACHE_SIZE (16*1024) + +#include "mmu-mips.h" +#include "mipsregs.h" +#include "mipsr2-endian.h" +#include + +/* Get physical address for DMA */ +#define PHYSADDR(addr) (((unsigned long)(addr)) & 0x1fffffff) + +#define HIGHEST_IRQ_LEVEL 0 + +/* Rockbox API */ +#define enable_irq() set_c0_status(ST0_IE) +#define disable_irq() clear_c0_status(ST0_IE) +#define disable_irq_save() set_irq_level(0) +#define restore_irq(arg) write_c0_status(arg) + +static inline int set_irq_level(int lev) +{ + unsigned reg, oldreg; + reg = oldreg = read_c0_status(); + if(lev) + reg |= ST0_IE; + else + reg &= ~ST0_IE; + + write_c0_status(reg); + return oldreg; +} + +/* CPU idle stats, updated each kernel tick in kernel-x1000.c */ +extern int __cpu_idle_avg; +extern int __cpu_idle_cur; +extern uint32_t __cpu_idle_ticks; +extern uint32_t __cpu_idle_reftick; + +static inline uint32_t __ost_read32(void); +static inline void core_sleep(void) +{ + uint32_t t1 = __ost_read32(); + + __asm__ __volatile__( + ".set push\n\t" + ".set mips32r2\n\t" + "mfc0 $8, $12\n\t" + "move $9, $8\n\t" + "la $10, 0x8000000\n\t" + "or $8, $10\n\t" + "mtc0 $8, $12\n\t" + "wait\n\t" + "mtc0 $9, $12\n\t" + ".set pop\n\t" + ::: "t0", "t1", "t2"); + + uint32_t t2 = __ost_read32(); + __cpu_idle_ticks += t2 - t1; + + enable_irq(); +} + +/* IRQ control */ +extern void system_enable_irq(int irq); +extern void system_disable_irq(int irq); + +/* Simple delay API */ +#define OST_FREQUENCY (X1000_EXCLK_FREQ / 4) +#define OST_TICKS_PER_US (OST_FREQUENCY / 1000000) +#define MAX_OST_DELAY_ARG 0x7fffffff +#define MAX_UDELAY_ARG (MAX_OST_DELAY_ARG / OST_TICKS_PER_US) +#define MAX_MDELAY_ARG (MAX_UDELAY_ARG / 1000) + +/* Macros adapted from include/linux/delay.h, + * Copyright (C) 1993 Linus Torvalds + * + * These optimize away all calculations to compile time for the common case + * of small constant arguments, reducing to a single __ost_delay() call. + */ + +#define udelay(n) \ + ((__builtin_constant_p(n) && (n) <= MAX_UDELAY_ARG) ? \ + __ost_delay((n) * OST_TICKS_PER_US) : __udelay((n))) + +#define mdelay(n) \ + ((__builtin_constant_p(n) && (n) <= MAX_MDELAY_ARG) ? \ + __ost_delay((n) * 1000 * OST_TICKS_PER_US) : __mdelay((n))) + +/* Slow path implementations which handle their full argument range by + * looping and calling __ost_delay() repeatedly. + */ +extern void __udelay(uint32_t us); +extern void __mdelay(uint32_t ms); + +/* Read full 64-bit OST counter value; this requires disabling IRQs + * to safely read the counter. + */ +extern uint64_t __ost_read64(void); + +static inline uint32_t __ost_read32(void) +{ + /* Read OST_2CNTL using raw address to avoid exposing internal headers. + * The 64-bit counter is read with IRQs disabled and since threads are + * not pre-emptive in Rockbox we won't trash anybody's 64-bit read by + * reading the low count without locking. + */ + return *(const volatile uint32_t*)0xb2000020; +} + +/* NOTE: it is required that count < MAX_OST_DELAY_ARG, this is to provide + * some slack in the 32-bit counter so we can reliably detect the timeout. + */ +static inline void __ost_delay(uint32_t count) +{ + /* Add one to ensure we delay for at least the time given */ + count += 1; + uint32_t start = __ost_read32(); + while(__ost_read32() - start < count); +} + +#endif /* __SYSTEM_TARGET_H__ */ -- cgit v1.2.3