treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156
[sfrench/cifs-2.6.git] / arch / mips / vr41xx / common / cmu.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
4  *
5  *  Copyright (C) 2001-2002  MontaVista Software Inc.
6  *    Author: Yoichi Yuasa <source@mvista.com>
7  *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
8  */
9 /*
10  * Changes:
11  *  MontaVista Software Inc. <source@mvista.com>
12  *  - New creation, NEC VR4122 and VR4131 are supported.
13  *  - Added support for NEC VR4111 and VR4121.
14  *
15  *  Yoichi Yuasa <yuasa@linux-mips.org>
16  *  - Added support for NEC VR4133.
17  */
18 #include <linux/export.h>
19 #include <linux/init.h>
20 #include <linux/ioport.h>
21 #include <linux/smp.h>
22 #include <linux/spinlock.h>
23 #include <linux/types.h>
24
25 #include <asm/cpu.h>
26 #include <asm/io.h>
27 #include <asm/vr41xx/vr41xx.h>
28
29 #define CMU_TYPE1_BASE  0x0b000060UL
30 #define CMU_TYPE1_SIZE  0x4
31
32 #define CMU_TYPE2_BASE  0x0f000060UL
33 #define CMU_TYPE2_SIZE  0x4
34
35 #define CMU_TYPE3_BASE  0x0f000060UL
36 #define CMU_TYPE3_SIZE  0x8
37
38 #define CMUCLKMSK       0x0
39  #define MSKPIU         0x0001
40  #define MSKSIU         0x0002
41  #define MSKAIU         0x0004
42  #define MSKKIU         0x0008
43  #define MSKFIR         0x0010
44  #define MSKDSIU        0x0820
45  #define MSKCSI         0x0040
46  #define MSKPCIU        0x0080
47  #define MSKSSIU        0x0100
48  #define MSKSHSP        0x0200
49  #define MSKFFIR        0x0400
50  #define MSKSCSI        0x1000
51  #define MSKPPCIU       0x2000
52 #define CMUCLKMSK2      0x4
53  #define MSKCEU         0x0001
54  #define MSKMAC0        0x0002
55  #define MSKMAC1        0x0004
56
57 static void __iomem *cmu_base;
58 static uint16_t cmuclkmsk, cmuclkmsk2;
59 static DEFINE_SPINLOCK(cmu_lock);
60
61 #define cmu_read(offset)                readw(cmu_base + (offset))
62 #define cmu_write(offset, value)        writew((value), cmu_base + (offset))
63
64 void vr41xx_supply_clock(vr41xx_clock_t clock)
65 {
66         spin_lock_irq(&cmu_lock);
67
68         switch (clock) {
69         case PIU_CLOCK:
70                 cmuclkmsk |= MSKPIU;
71                 break;
72         case SIU_CLOCK:
73                 cmuclkmsk |= MSKSIU | MSKSSIU;
74                 break;
75         case AIU_CLOCK:
76                 cmuclkmsk |= MSKAIU;
77                 break;
78         case KIU_CLOCK:
79                 cmuclkmsk |= MSKKIU;
80                 break;
81         case FIR_CLOCK:
82                 cmuclkmsk |= MSKFIR | MSKFFIR;
83                 break;
84         case DSIU_CLOCK:
85                 if (current_cpu_type() == CPU_VR4111 ||
86                     current_cpu_type() == CPU_VR4121)
87                         cmuclkmsk |= MSKDSIU;
88                 else
89                         cmuclkmsk |= MSKSIU | MSKDSIU;
90                 break;
91         case CSI_CLOCK:
92                 cmuclkmsk |= MSKCSI | MSKSCSI;
93                 break;
94         case PCIU_CLOCK:
95                 cmuclkmsk |= MSKPCIU;
96                 break;
97         case HSP_CLOCK:
98                 cmuclkmsk |= MSKSHSP;
99                 break;
100         case PCI_CLOCK:
101                 cmuclkmsk |= MSKPPCIU;
102                 break;
103         case CEU_CLOCK:
104                 cmuclkmsk2 |= MSKCEU;
105                 break;
106         case ETHER0_CLOCK:
107                 cmuclkmsk2 |= MSKMAC0;
108                 break;
109         case ETHER1_CLOCK:
110                 cmuclkmsk2 |= MSKMAC1;
111                 break;
112         default:
113                 break;
114         }
115
116         if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
117             clock == ETHER1_CLOCK)
118                 cmu_write(CMUCLKMSK2, cmuclkmsk2);
119         else
120                 cmu_write(CMUCLKMSK, cmuclkmsk);
121
122         spin_unlock_irq(&cmu_lock);
123 }
124
125 EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
126
127 void vr41xx_mask_clock(vr41xx_clock_t clock)
128 {
129         spin_lock_irq(&cmu_lock);
130
131         switch (clock) {
132         case PIU_CLOCK:
133                 cmuclkmsk &= ~MSKPIU;
134                 break;
135         case SIU_CLOCK:
136                 if (current_cpu_type() == CPU_VR4111 ||
137                     current_cpu_type() == CPU_VR4121) {
138                         cmuclkmsk &= ~(MSKSIU | MSKSSIU);
139                 } else {
140                         if (cmuclkmsk & MSKDSIU)
141                                 cmuclkmsk &= ~MSKSSIU;
142                         else
143                                 cmuclkmsk &= ~(MSKSIU | MSKSSIU);
144                 }
145                 break;
146         case AIU_CLOCK:
147                 cmuclkmsk &= ~MSKAIU;
148                 break;
149         case KIU_CLOCK:
150                 cmuclkmsk &= ~MSKKIU;
151                 break;
152         case FIR_CLOCK:
153                 cmuclkmsk &= ~(MSKFIR | MSKFFIR);
154                 break;
155         case DSIU_CLOCK:
156                 if (current_cpu_type() == CPU_VR4111 ||
157                     current_cpu_type() == CPU_VR4121) {
158                         cmuclkmsk &= ~MSKDSIU;
159                 } else {
160                         if (cmuclkmsk & MSKSSIU)
161                                 cmuclkmsk &= ~MSKDSIU;
162                         else
163                                 cmuclkmsk &= ~(MSKSIU | MSKDSIU);
164                 }
165                 break;
166         case CSI_CLOCK:
167                 cmuclkmsk &= ~(MSKCSI | MSKSCSI);
168                 break;
169         case PCIU_CLOCK:
170                 cmuclkmsk &= ~MSKPCIU;
171                 break;
172         case HSP_CLOCK:
173                 cmuclkmsk &= ~MSKSHSP;
174                 break;
175         case PCI_CLOCK:
176                 cmuclkmsk &= ~MSKPPCIU;
177                 break;
178         case CEU_CLOCK:
179                 cmuclkmsk2 &= ~MSKCEU;
180                 break;
181         case ETHER0_CLOCK:
182                 cmuclkmsk2 &= ~MSKMAC0;
183                 break;
184         case ETHER1_CLOCK:
185                 cmuclkmsk2 &= ~MSKMAC1;
186                 break;
187         default:
188                 break;
189         }
190
191         if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
192             clock == ETHER1_CLOCK)
193                 cmu_write(CMUCLKMSK2, cmuclkmsk2);
194         else
195                 cmu_write(CMUCLKMSK, cmuclkmsk);
196
197         spin_unlock_irq(&cmu_lock);
198 }
199
200 EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
201
202 static int __init vr41xx_cmu_init(void)
203 {
204         unsigned long start, size;
205
206         switch (current_cpu_type()) {
207         case CPU_VR4111:
208         case CPU_VR4121:
209                 start = CMU_TYPE1_BASE;
210                 size = CMU_TYPE1_SIZE;
211                 break;
212         case CPU_VR4122:
213         case CPU_VR4131:
214                 start = CMU_TYPE2_BASE;
215                 size = CMU_TYPE2_SIZE;
216                 break;
217         case CPU_VR4133:
218                 start = CMU_TYPE3_BASE;
219                 size = CMU_TYPE3_SIZE;
220                 break;
221         default:
222                 panic("Unexpected CPU of NEC VR4100 series");
223                 break;
224         }
225
226         if (request_mem_region(start, size, "CMU") == NULL)
227                 return -EBUSY;
228
229         cmu_base = ioremap(start, size);
230         if (cmu_base == NULL) {
231                 release_mem_region(start, size);
232                 return -EBUSY;
233         }
234
235         cmuclkmsk = cmu_read(CMUCLKMSK);
236         if (current_cpu_type() == CPU_VR4133)
237                 cmuclkmsk2 = cmu_read(CMUCLKMSK2);
238
239         spin_lock_init(&cmu_lock);
240
241         return 0;
242 }
243
244 core_initcall(vr41xx_cmu_init);