Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/vr41xx/common/cmu.c
10820 views
1
/*
2
* cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
3
*
4
* Copyright (C) 2001-2002 MontaVista Software Inc.
5
* Author: Yoichi Yuasa <[email protected]>
6
* Copuright (C) 2003-2005 Yoichi Yuasa <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
/*
23
* Changes:
24
* MontaVista Software Inc. <[email protected]>
25
* - New creation, NEC VR4122 and VR4131 are supported.
26
* - Added support for NEC VR4111 and VR4121.
27
*
28
* Yoichi Yuasa <[email protected]>
29
* - Added support for NEC VR4133.
30
*/
31
#include <linux/init.h>
32
#include <linux/ioport.h>
33
#include <linux/module.h>
34
#include <linux/smp.h>
35
#include <linux/spinlock.h>
36
#include <linux/types.h>
37
38
#include <asm/cpu.h>
39
#include <asm/io.h>
40
#include <asm/vr41xx/vr41xx.h>
41
42
#define CMU_TYPE1_BASE 0x0b000060UL
43
#define CMU_TYPE1_SIZE 0x4
44
45
#define CMU_TYPE2_BASE 0x0f000060UL
46
#define CMU_TYPE2_SIZE 0x4
47
48
#define CMU_TYPE3_BASE 0x0f000060UL
49
#define CMU_TYPE3_SIZE 0x8
50
51
#define CMUCLKMSK 0x0
52
#define MSKPIU 0x0001
53
#define MSKSIU 0x0002
54
#define MSKAIU 0x0004
55
#define MSKKIU 0x0008
56
#define MSKFIR 0x0010
57
#define MSKDSIU 0x0820
58
#define MSKCSI 0x0040
59
#define MSKPCIU 0x0080
60
#define MSKSSIU 0x0100
61
#define MSKSHSP 0x0200
62
#define MSKFFIR 0x0400
63
#define MSKSCSI 0x1000
64
#define MSKPPCIU 0x2000
65
#define CMUCLKMSK2 0x4
66
#define MSKCEU 0x0001
67
#define MSKMAC0 0x0002
68
#define MSKMAC1 0x0004
69
70
static void __iomem *cmu_base;
71
static uint16_t cmuclkmsk, cmuclkmsk2;
72
static DEFINE_SPINLOCK(cmu_lock);
73
74
#define cmu_read(offset) readw(cmu_base + (offset))
75
#define cmu_write(offset, value) writew((value), cmu_base + (offset))
76
77
void vr41xx_supply_clock(vr41xx_clock_t clock)
78
{
79
spin_lock_irq(&cmu_lock);
80
81
switch (clock) {
82
case PIU_CLOCK:
83
cmuclkmsk |= MSKPIU;
84
break;
85
case SIU_CLOCK:
86
cmuclkmsk |= MSKSIU | MSKSSIU;
87
break;
88
case AIU_CLOCK:
89
cmuclkmsk |= MSKAIU;
90
break;
91
case KIU_CLOCK:
92
cmuclkmsk |= MSKKIU;
93
break;
94
case FIR_CLOCK:
95
cmuclkmsk |= MSKFIR | MSKFFIR;
96
break;
97
case DSIU_CLOCK:
98
if (current_cpu_type() == CPU_VR4111 ||
99
current_cpu_type() == CPU_VR4121)
100
cmuclkmsk |= MSKDSIU;
101
else
102
cmuclkmsk |= MSKSIU | MSKDSIU;
103
break;
104
case CSI_CLOCK:
105
cmuclkmsk |= MSKCSI | MSKSCSI;
106
break;
107
case PCIU_CLOCK:
108
cmuclkmsk |= MSKPCIU;
109
break;
110
case HSP_CLOCK:
111
cmuclkmsk |= MSKSHSP;
112
break;
113
case PCI_CLOCK:
114
cmuclkmsk |= MSKPPCIU;
115
break;
116
case CEU_CLOCK:
117
cmuclkmsk2 |= MSKCEU;
118
break;
119
case ETHER0_CLOCK:
120
cmuclkmsk2 |= MSKMAC0;
121
break;
122
case ETHER1_CLOCK:
123
cmuclkmsk2 |= MSKMAC1;
124
break;
125
default:
126
break;
127
}
128
129
if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
130
clock == ETHER1_CLOCK)
131
cmu_write(CMUCLKMSK2, cmuclkmsk2);
132
else
133
cmu_write(CMUCLKMSK, cmuclkmsk);
134
135
spin_unlock_irq(&cmu_lock);
136
}
137
138
EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
139
140
void vr41xx_mask_clock(vr41xx_clock_t clock)
141
{
142
spin_lock_irq(&cmu_lock);
143
144
switch (clock) {
145
case PIU_CLOCK:
146
cmuclkmsk &= ~MSKPIU;
147
break;
148
case SIU_CLOCK:
149
if (current_cpu_type() == CPU_VR4111 ||
150
current_cpu_type() == CPU_VR4121) {
151
cmuclkmsk &= ~(MSKSIU | MSKSSIU);
152
} else {
153
if (cmuclkmsk & MSKDSIU)
154
cmuclkmsk &= ~MSKSSIU;
155
else
156
cmuclkmsk &= ~(MSKSIU | MSKSSIU);
157
}
158
break;
159
case AIU_CLOCK:
160
cmuclkmsk &= ~MSKAIU;
161
break;
162
case KIU_CLOCK:
163
cmuclkmsk &= ~MSKKIU;
164
break;
165
case FIR_CLOCK:
166
cmuclkmsk &= ~(MSKFIR | MSKFFIR);
167
break;
168
case DSIU_CLOCK:
169
if (current_cpu_type() == CPU_VR4111 ||
170
current_cpu_type() == CPU_VR4121) {
171
cmuclkmsk &= ~MSKDSIU;
172
} else {
173
if (cmuclkmsk & MSKSSIU)
174
cmuclkmsk &= ~MSKDSIU;
175
else
176
cmuclkmsk &= ~(MSKSIU | MSKDSIU);
177
}
178
break;
179
case CSI_CLOCK:
180
cmuclkmsk &= ~(MSKCSI | MSKSCSI);
181
break;
182
case PCIU_CLOCK:
183
cmuclkmsk &= ~MSKPCIU;
184
break;
185
case HSP_CLOCK:
186
cmuclkmsk &= ~MSKSHSP;
187
break;
188
case PCI_CLOCK:
189
cmuclkmsk &= ~MSKPPCIU;
190
break;
191
case CEU_CLOCK:
192
cmuclkmsk2 &= ~MSKCEU;
193
break;
194
case ETHER0_CLOCK:
195
cmuclkmsk2 &= ~MSKMAC0;
196
break;
197
case ETHER1_CLOCK:
198
cmuclkmsk2 &= ~MSKMAC1;
199
break;
200
default:
201
break;
202
}
203
204
if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
205
clock == ETHER1_CLOCK)
206
cmu_write(CMUCLKMSK2, cmuclkmsk2);
207
else
208
cmu_write(CMUCLKMSK, cmuclkmsk);
209
210
spin_unlock_irq(&cmu_lock);
211
}
212
213
EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
214
215
static int __init vr41xx_cmu_init(void)
216
{
217
unsigned long start, size;
218
219
switch (current_cpu_type()) {
220
case CPU_VR4111:
221
case CPU_VR4121:
222
start = CMU_TYPE1_BASE;
223
size = CMU_TYPE1_SIZE;
224
break;
225
case CPU_VR4122:
226
case CPU_VR4131:
227
start = CMU_TYPE2_BASE;
228
size = CMU_TYPE2_SIZE;
229
break;
230
case CPU_VR4133:
231
start = CMU_TYPE3_BASE;
232
size = CMU_TYPE3_SIZE;
233
break;
234
default:
235
panic("Unexpected CPU of NEC VR4100 series");
236
break;
237
}
238
239
if (request_mem_region(start, size, "CMU") == NULL)
240
return -EBUSY;
241
242
cmu_base = ioremap(start, size);
243
if (cmu_base == NULL) {
244
release_mem_region(start, size);
245
return -EBUSY;
246
}
247
248
cmuclkmsk = cmu_read(CMUCLKMSK);
249
if (current_cpu_type() == CPU_VR4133)
250
cmuclkmsk2 = cmu_read(CMUCLKMSK2);
251
252
spin_lock_init(&cmu_lock);
253
254
return 0;
255
}
256
257
core_initcall(vr41xx_cmu_init);
258
259