summaryrefslogtreecommitdiff
path: root/src/arch/ppc/lib/setup.c
blob: 09fd4c06e2df89de989f59223abf4c815c378d84 (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
/* Copyright 2000  AG Electronics Ltd. */
/* This code is distributed without warranty under the GPL v2 (see COPYING) */

#include "ppc.h"
#include "ppcreg.h"

unsigned __getmsr(void)
{
    unsigned result;   
    __asm__ volatile ("mfmsr %0" : "=r" (result));
    return result;
}

unsigned __gethid0(void)
{
    unsigned result;
    __asm__ volatile ("mfspr %0,1008" : "=r" (result));
    return result;
}

unsigned __gethid1(void)
{
    unsigned result;
    __asm__ volatile ("mfspr %0,1009" : "=r" (result));
    return result;
}

void __sethid0(unsigned value)
{
    __asm__ volatile ("mtspr 1008,%0" : : "r" (value));
}

unsigned __getpvr(void)
{
    int result;
    __asm__("mfspr %0, 287" : "=r" (result));
    return result;
}

void __setmsr(unsigned value)
{
    __asm__ volatile ("mtmsr %0; sync" :: "r" (value));   
}

void __set1015(unsigned value)
{
    __asm__ volatile ("mtspr 1015,%0" : : "r" (value));
}

extern void _init_float_registers(const double *);
/*RODATA static const double dummy_float = 1.0;*/
static const double dummy_float = 1.0;

#define HID0_DCACHE HID0_DCE
#define MSR_DATA MSR_DR

void ppc_setup_cpu(int icache)
{
    int type = __getpvr() >> 16;
    int version = __getpvr() & 0xffff;
    
    if (type == 0xc) 
    {
        if (version == 0x0200)
            __set1015(0x19000004);
        else if (((version & 0xff00) == 0x0200) && 
            (version != 0x0209))
            __set1015(0x01000000);
    }
    if (icache)
    {
        __sethid0(HID0_NHR | HID0_BHT | HID0_ICE | HID0_ICFI | HID0_BTIC
                | HID0_DCACHE);
        __sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_ICE | HID0_BTIC
                | HID0_DCACHE);        
    }
    else
    {
        __sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_BTIC | HID0_DCACHE);
    }
#if 1
   /* if (type == 8 || type == 12) */
    {
        __setmsr(MSR_FP | MSR_DATA);
        _init_float_registers(&dummy_float);
    }
#endif
}

void ppc_enable_dcache(void)
{
	/*
	 * Already enabled in crt0.S
	 */
#if 0
    unsigned hid0 = __gethid0();
    __sethid0(hid0 | HID0_DCFI | HID0_DCE);
    __sethid0(hid0 | HID0_DCE);
#endif
}

void ppc_disable_dcache(void)
{
    unsigned hid0 = __gethid0();
    __sethid0(hid0 & ~HID0_DCE);
}

void ppc_enable_mmu(void)
{
    unsigned msr = __getmsr();
    __setmsr(msr | MSR_DR | MSR_IR); 
}

void make_coherent(void *base, unsigned length)
{
    unsigned hid0 = __gethid0();
    
    if (hid0 & HID0_DCE)
    {
        unsigned i;
        unsigned offset = 0x1f & (unsigned) base;
        unsigned adjusted_base = (unsigned) base & ~0x1f;
        for(i = 0; i < length + offset; i+= 32)
            __asm__ volatile ("dcbf %1,%0" : : "r" (adjusted_base), "r" (i));
        if (hid0 & HID0_ICE)
            for(i = 0; i < length + offset; i+= 32)
                __asm__ volatile ("icbi %1,%0" : : "r" (adjusted_base), "r" (i));
    }
}