-
Notifications
You must be signed in to change notification settings - Fork 1
/
pxa255_PwrClk.c
154 lines (110 loc) · 3.49 KB
/
pxa255_PwrClk.c
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
#include "pxa255_PwrClk.h"
static Boolean pxa255pwrClkPrvCoprocRegXferFunc(struct ArmCpu* cpu, void* userData, Boolean two, Boolean read, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2){
Pxa255pwrClk* pc = userData;
UInt32 val = 0;
if(!read) val = cpuGetRegExternal(cpu, Rx);
if(CRm == 0 && op2 == 0 && op1 == 0 && !two){
switch(CRn){
case 6:
if(read) val = 0;
else{
pc->turbo = (val & 1) != 0;
if(val & 2){
err_str("Set speed mode");
// err_str("(CCCR + cp14 reg6) to 0x");
// err_hex(pc->CCCR);
// err_str(", 0x");
// err_hex(val);
// err_str("\r\n");
}
}
case 7:
if(read) val = pc->turbo ? 1 : 0;
else if(val != 0){
// fprintf(stderr, "Someone tried to set processor power mode (cp14 reg7) to 0x%08lX\n", val);
}
goto success;
}
}
return false;
success:
if(read) cpuSetReg(cpu, Rx, val);
return true;
}
static Boolean pxa255pwrClkPrvClockMgrMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
Pxa255pwrClk* pc = userData;
UInt32 val = 0;
if(size != 4) {
err_str(__FILE__ ": Unexpected ");
// err_str(write ? "write" : "read");
// err_str(" of ");
// err_dec(size);
// err_str(" bytes to 0x");
// err_hex(pa);
// err_str("\r\n");
return true; //we do not support non-word accesses
}
pa = (pa - PXA255_CLOCK_MANAGER_BASE) >> 2;
if(write) val = *(UInt32*)buf;
switch(pa){
case 0: //CCCR
if(write) pc->CCCR = val;
else val = pc->CCCR;
break;
case 1: //CKEN
if(write) pc->CKEN = val;
else val = pc->CKEN;
break;
case 2: //OSCR
if(!write) val = pc->OSCR;
//no writing to this register
break;
}
if(!write) *(UInt32*)buf = val;
return true;
}
static Boolean pxa255pwrClkPrvPowerMgrMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
Pxa255pwrClk* pc = userData;
UInt32 val = 0;
if(size != 4) {
err_str(__FILE__ ": Unexpected ");
// err_str(write ? "write" : "read");
// err_str(" of ");
// err_dec(size);
// err_str(" bytes to 0x");
// err_hex(pa);
// err_str("\r\n");
return true; //we do not support non-word accesses
}
pa = (pa - PXA255_POWER_MANAGER_BASE) >> 2;
if(write) val = *(UInt32*)buf;
if(pa < 13){
if(write) pc->pwrRegs[pa] = val;
else val = pc->pwrRegs[pa];
}
if(!write) *(UInt32*)buf = val;
return true;
}
Boolean pxa255pwrClkInit(Pxa255pwrClk* pc, ArmCpu* cpu, ArmMem* physMem){
ArmCoprocessor cp;
Boolean ok = true;
__mem_zero(pc, sizeof(Pxa255pwrClk));
pc->cpu = cpu;
pc->CCCR = 0x00000122UL; //set CCCR to almost default value (we use mult 32 not 27)
pc->CKEN = 0x000179EFUL; //set CKEN to default value
pc->OSCR = 0x00000003UL; //32KHz oscillator on and stable
pc->pwrRegs[1] = 0x20; //set PSSR
pc->pwrRegs[3] = 3; //set PWER
pc->pwrRegs[4] = 3; //set PRER
pc->pwrRegs[5] = 3; //set PFER
pc->pwrRegs[12] = 1; //set RCSR
cp.regXfer = pxa255pwrClkPrvCoprocRegXferFunc;
cp.dataProcessing = NULL;
cp.memAccess = NULL;
cp.twoRegF = NULL;
cp.userData = pc;
cpuCoprocessorRegister(cpu, 14, &cp);
ok = ok && memRegionAdd(physMem, PXA255_CLOCK_MANAGER_BASE, PXA255_CLOCK_MANAGER_SIZE, pxa255pwrClkPrvClockMgrMemAccessF, pc);
ok = ok && memRegionAdd(physMem, PXA255_POWER_MANAGER_BASE, PXA255_POWER_MANAGER_SIZE, pxa255pwrClkPrvPowerMgrMemAccessF, pc);
return ok;
}