summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/system-target.h
blob: 764cd18d153b9ac8ba128ea2e49e65685b3e40ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2002 by Alan Korr
 * Copyright (C) 2007 by Michael Sevakis
 *
 * 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

#include "system-arm.h"

#ifdef CPU_PP
/* TODO: This header is actually portalplayer specific, and should be
 * moved into an appropriate subdir (or even split in 2). */

#if CONFIG_CPU == PP5002
#define CPUFREQ_SLEEP      32768
#define CPUFREQ_DEFAULT 24000000
#define CPUFREQ_NORMAL  30000000
#define CPUFREQ_MAX     80000000

#else /* PP5022, PP5024 */
#define CPUFREQ_SLEEP      32768
#define CPUFREQ_DEFAULT 24000000
#define CPUFREQ_NORMAL  30000000
#define CPUFREQ_MAX     80000000
#endif

#define inl(a) (*(volatile unsigned long *) (a))
#define outl(a,b) (*(volatile unsigned long *) (b) = (a))
#define inb(a) (*(volatile unsigned char *) (a))
#define outb(a,b) (*(volatile unsigned char *) (b) = (a))
#define inw(a) (*(volatile unsigned short *) (a))
#define outw(a,b) (*(volatile unsigned short *) (b) = (a))

static inline void udelay(unsigned usecs)
{
    unsigned stop = USEC_TIMER + usecs;
    while (TIME_BEFORE(USEC_TIMER, stop));
}

static inline unsigned int current_core(void)
{
    /*
     * PROCESSOR_ID seems to be 32-bits:
     * CPU = 0x55555555 = |01010101|01010101|01010101|01010101|
     * COP = 0xaaaaaaaa = |10101010|10101010|10101010|10101010|
     *                                                ^
     */
    unsigned int core;
    asm volatile (
        "ldrb   %0, [%1]       \n" /* Just load the LSB */
        "mov    %0, %0, lsr #7 \n" /* Bit 7 => index    */
        : "=r"(core)              /* CPU=0, COP=1      */
        : "r"(&PROCESSOR_ID)
    );
    return core;
}

/* Return the actual ID instead of core index */
static inline unsigned int processor_id(void)
{
    unsigned int id;

    asm volatile (
        "ldrb   %0, [%1] \n"
        : "=r"(id)
        : "r"(&PROCESSOR_ID)
    );

    return id;
}

#if CONFIG_CPU == PP5002
static inline void sleep_core(int core)
{
    asm volatile (
        /* Sleep: PP5002 crashes if the instruction that puts it to sleep is
         * located at 0xNNNNNNN0. 4/8/C works. This sequence makes sure
         * that the correct alternative is executed. Don't change the order
         * of the next 4 instructions! */
        "tst    pc, #0x0c       \n"
        "mov    r0, #0xca       \n"
        "strne  r0, [%[ctl]]    \n"
        "streq  r0, [%[ctl]]    \n"
        "nop                    \n" /* nop's needed because of pipeline */
        "nop                    \n"
        "nop                    \n"
        :
        : [ctl]"r"(&PROC_CTL(core))
        : "r0"
    );
}
static inline void wake_core(int core)
{
    asm volatile (
        "mov    r0, #0xce       \n"
        "str    r0, [%[ctl]]    \n"
        :
        : [ctl]"r"(&PROC_CTL(core))
        : "r0"
    );
}
#else /* PP502x */
static inline void sleep_core(int core)
{
    asm volatile (
        "mov    r0, #0x80000000  \n"
        "str    r0, [%[ctl]]     \n"
        "nop                     \n"
        :
        : [ctl]"r"(&PROC_CTL(core))
        : "r0"
    );
}
static inline void wake_core(int core)
{
    asm volatile (
        "mov    r0, #0           \n"
        "str    r0, [%[ctl]]     \n"
        :
        : [ctl]"r"(&PROC_CTL(core))
        : "r0"
    );
}
#endif

#ifdef BOOTLOADER
/* All addresses within rockbox are in IRAM in the bootloader so
   are therefore uncached */
#define UNCACHED_ADDR(a) (a)

#else /* !BOOTLOADER */

#if CONFIG_CPU == PP5002
#define UNCACHED_BASE_ADDR 0x28000000
#else /* PP502x */
#define UNCACHED_BASE_ADDR 0x10000000
#endif

#define UNCACHED_ADDR(a) \
    ((typeof (a))((uintptr_t)(a) | UNCACHED_BASE_ADDR))
#endif /* BOOTLOADER */

/* Certain data needs to be out of the way of cache line interference
 * such as data for COP use or for use with UNCACHED_ADDR */
#define PROC_NEEDS_CACHEALIGN
#define CACHEALIGN_BITS (4) /* 2^4 = 16 bytes */

/** cache functions **/
#ifndef BOOTLOADER
#define HAVE_CPUCACHE_INVALIDATE
#define HAVE_CPUCACHE_FLUSH
#endif

#endif /* CPU_PP */

#endif /* SYSTEM_TARGET_H */