summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/system-target.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/system-target.h')
-rw-r--r--firmware/target/mips/ingenic_x1000/system-target.h148
1 files changed, 148 insertions, 0 deletions
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __SYSTEM_TARGET_H__
23#define __SYSTEM_TARGET_H__
24
25/* For the sake of system.h CACHEALIGN macros.
26 * We need this to align DMA buffers, etc.
27 */
28#define CACHEALIGN_BITS 5
29#define CACHE_SIZE (16*1024)
30
31#include "mmu-mips.h"
32#include "mipsregs.h"
33#include "mipsr2-endian.h"
34#include <stdint.h>
35
36/* Get physical address for DMA */
37#define PHYSADDR(addr) (((unsigned long)(addr)) & 0x1fffffff)
38
39#define HIGHEST_IRQ_LEVEL 0
40
41/* Rockbox API */
42#define enable_irq() set_c0_status(ST0_IE)
43#define disable_irq() clear_c0_status(ST0_IE)
44#define disable_irq_save() set_irq_level(0)
45#define restore_irq(arg) write_c0_status(arg)
46
47static inline int set_irq_level(int lev)
48{
49 unsigned reg, oldreg;
50 reg = oldreg = read_c0_status();
51 if(lev)
52 reg |= ST0_IE;
53 else
54 reg &= ~ST0_IE;
55
56 write_c0_status(reg);
57 return oldreg;
58}
59
60/* CPU idle stats, updated each kernel tick in kernel-x1000.c */
61extern int __cpu_idle_avg;
62extern int __cpu_idle_cur;
63extern uint32_t __cpu_idle_ticks;
64extern uint32_t __cpu_idle_reftick;
65
66static inline uint32_t __ost_read32(void);
67static inline void core_sleep(void)
68{
69 uint32_t t1 = __ost_read32();
70
71 __asm__ __volatile__(
72 ".set push\n\t"
73 ".set mips32r2\n\t"
74 "mfc0 $8, $12\n\t"
75 "move $9, $8\n\t"
76 "la $10, 0x8000000\n\t"
77 "or $8, $10\n\t"
78 "mtc0 $8, $12\n\t"
79 "wait\n\t"
80 "mtc0 $9, $12\n\t"
81 ".set pop\n\t"
82 ::: "t0", "t1", "t2");
83
84 uint32_t t2 = __ost_read32();
85 __cpu_idle_ticks += t2 - t1;
86
87 enable_irq();
88}
89
90/* IRQ control */
91extern void system_enable_irq(int irq);
92extern void system_disable_irq(int irq);
93
94/* Simple delay API */
95#define OST_FREQUENCY (X1000_EXCLK_FREQ / 4)
96#define OST_TICKS_PER_US (OST_FREQUENCY / 1000000)
97#define MAX_OST_DELAY_ARG 0x7fffffff
98#define MAX_UDELAY_ARG (MAX_OST_DELAY_ARG / OST_TICKS_PER_US)
99#define MAX_MDELAY_ARG (MAX_UDELAY_ARG / 1000)
100
101/* Macros adapted from include/linux/delay.h,
102 * Copyright (C) 1993 Linus Torvalds
103 *
104 * These optimize away all calculations to compile time for the common case
105 * of small constant arguments, reducing to a single __ost_delay() call.
106 */
107
108#define udelay(n) \
109 ((__builtin_constant_p(n) && (n) <= MAX_UDELAY_ARG) ? \
110 __ost_delay((n) * OST_TICKS_PER_US) : __udelay((n)))
111
112#define mdelay(n) \
113 ((__builtin_constant_p(n) && (n) <= MAX_MDELAY_ARG) ? \
114 __ost_delay((n) * 1000 * OST_TICKS_PER_US) : __mdelay((n)))
115
116/* Slow path implementations which handle their full argument range by
117 * looping and calling __ost_delay() repeatedly.
118 */
119extern void __udelay(uint32_t us);
120extern void __mdelay(uint32_t ms);
121
122/* Read full 64-bit OST counter value; this requires disabling IRQs
123 * to safely read the counter.
124 */
125extern uint64_t __ost_read64(void);
126
127static inline uint32_t __ost_read32(void)
128{
129 /* Read OST_2CNTL using raw address to avoid exposing internal headers.
130 * The 64-bit counter is read with IRQs disabled and since threads are
131 * not pre-emptive in Rockbox we won't trash anybody's 64-bit read by
132 * reading the low count without locking.
133 */
134 return *(const volatile uint32_t*)0xb2000020;
135}
136
137/* NOTE: it is required that count < MAX_OST_DELAY_ARG, this is to provide
138 * some slack in the 32-bit counter so we can reliably detect the timeout.
139 */
140static inline void __ost_delay(uint32_t count)
141{
142 /* Add one to ensure we delay for at least the time given */
143 count += 1;
144 uint32_t start = __ost_read32();
145 while(__ost_read32() - start < count);
146}
147
148#endif /* __SYSTEM_TARGET_H__ */