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

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

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

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

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

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

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

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

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

extern void ppc_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 = ppc_getpvr() >> 16;
	int version = ppc_getpvr() & 0xffff;

	if (type == 0xc) 
	{
		if (version == 0x0200)
			ppc_set1015(0x19000004);
		else if (((version & 0xff00) == 0x0200) && 
			(version != 0x0209))
			ppc_set1015(0x01000000);
	}
	if (icache)
	{
		ppc_sethid0(HID0_NHR | HID0_BHT | HID0_ICE | HID0_ICFI 
			| HID0_BTIC | HID0_DCACHE);
		ppc_sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_ICE 
			| HID0_BTIC | HID0_DCACHE);        
	}
	else
	{
		ppc_sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_BTIC 
			| HID0_DCACHE);
	}
#if 1
	/* if (type == 8 || type == 12) */
	{
		ppc_setmsr(MSR_FP | MSR_DATA);
		ppc_init_float_registers(&dummy_float);
	}
#endif
}

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

void ppc_disable_dcache(void)
{
	unsigned hid0 = ppc_gethid0();
	ppc_sethid0(hid0 & ~HID0_DCE);
}

void ppc_enable_mmu(void)
{
	unsigned msr = ppc_getmsr();
	ppc_setmsr(msr | MSR_DR | MSR_IR); 
}

void make_coherent(void *base, unsigned length)
{
	unsigned hid0 = ppc_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));
	}
}