kirkwood.c revision 1.11 1 1.11 rin /* $NetBSD: kirkwood.c,v 1.11 2021/08/30 00:04:30 rin Exp $ */
2 1.1 kiyohara /*
3 1.1 kiyohara * Copyright (c) 2010 KIYOHARA Takashi
4 1.1 kiyohara * All rights reserved.
5 1.1 kiyohara *
6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without
7 1.1 kiyohara * modification, are permitted provided that the following conditions
8 1.1 kiyohara * are met:
9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright
10 1.1 kiyohara * notice, this list of conditions and the following disclaimer.
11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the
13 1.1 kiyohara * documentation and/or other materials provided with the distribution.
14 1.1 kiyohara *
15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE.
26 1.1 kiyohara */
27 1.1 kiyohara
28 1.1 kiyohara #include <sys/cdefs.h>
29 1.11 rin __KERNEL_RCSID(0, "$NetBSD: kirkwood.c,v 1.11 2021/08/30 00:04:30 rin Exp $");
30 1.1 kiyohara
31 1.1 kiyohara #define _INTR_PRIVATE
32 1.1 kiyohara
33 1.1 kiyohara #include "mvsocgpp.h"
34 1.1 kiyohara
35 1.1 kiyohara #include <sys/param.h>
36 1.1 kiyohara #include <sys/bus.h>
37 1.1 kiyohara
38 1.1 kiyohara #include <machine/intr.h>
39 1.1 kiyohara
40 1.1 kiyohara #include <arm/pic/picvar.h>
41 1.1 kiyohara #include <arm/pic/picvar.h>
42 1.1 kiyohara
43 1.1 kiyohara #include <arm/marvell/mvsocreg.h>
44 1.1 kiyohara #include <arm/marvell/mvsocvar.h>
45 1.1 kiyohara #include <arm/marvell/kirkwoodreg.h>
46 1.1 kiyohara
47 1.1 kiyohara #include <dev/marvell/marvellreg.h>
48 1.1 kiyohara
49 1.1 kiyohara
50 1.1 kiyohara static void kirkwood_intr_init(void);
51 1.1 kiyohara
52 1.4 matt static void kirkwood_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
53 1.4 matt static void kirkwood_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
54 1.1 kiyohara static void kirkwood_pic_establish_irq(struct pic_softc *, struct intrsource *);
55 1.1 kiyohara static void kirkwood_pic_source_name(struct pic_softc *, int, char *, size_t);
56 1.1 kiyohara
57 1.1 kiyohara static int kirkwood_find_pending_irqs(void);
58 1.1 kiyohara
59 1.10 kiyohara static void kirkwood_getclks(vaddr_t);
60 1.10 kiyohara static int kirkwood_clkgating(struct marvell_attach_args *);
61 1.10 kiyohara
62 1.1 kiyohara static const char * const sources[64] = {
63 1.1 kiyohara "MainHighSum(0)", "Bridge(1)", "Host2CPU DB(2)", "CPU2Host DB(3)",
64 1.1 kiyohara "Reserved_4(4)", "Xor0Chan0(5)", "Xor0Chan1(6)", "Xor1Chan0(7)",
65 1.1 kiyohara "Xor1Chan1(8)", "PEX0INT(9)", "Reserved(10)", "GbE0Sum(11)",
66 1.1 kiyohara "GbE0Rx(12)", "GbE0Tx(13)", "GbE0Misc(14)", "GbE1Sum(15)",
67 1.1 kiyohara "GbE1Rx(16)", "GbE1Tx(17)", "GbE1Misc(18)", "USB0Cnt(19)",
68 1.1 kiyohara "Reserved(20)", "Sata(21)", "SecurityInt(22)", "SPIInt(23)",
69 1.1 kiyohara "AudioINT(24)", "Reserved(25)", "TS0Int(26)", "Reserved(27)",
70 1.7 msaitoh "SDIOInt(28)", "TWSI(29)", "AVBInt(30)", "TDMInt(31)",
71 1.1 kiyohara
72 1.7 msaitoh "Reserved(32)", "Uart0Int(33)", "Uart1Int(34)", "GPIOLo7_0(35)",
73 1.7 msaitoh "GPIOLo8_15(36)", "GPIOLo16_23(37)", "GPIOLo24_31(38)", "GPIOHi7_0(39)",
74 1.7 msaitoh "GPIOHi8_15(40)", "GPIOHi16_23(41)", "XOR0Err(42)", "XOR1Err(43)",
75 1.7 msaitoh "PEX0Err(44)", "Reserved(45)", "GbE0Err(46)", "GbE1Err(47)",
76 1.7 msaitoh "USBErr(48)", "SecurityErr(49)", "AudioErr(50)", "Reserved(51)",
77 1.7 msaitoh "Reserved(52)", "RTCInt(53)", "Reserved(54)", "Reserved(55)",
78 1.7 msaitoh "Reserved(56)", "Reserved(57)", "Reserved(58)", "Reserved(59)",
79 1.1 kiyohara "Reserved(60)", "Reserved(61)", "Reserved(62)", "Reserved(63)"
80 1.1 kiyohara };
81 1.1 kiyohara
82 1.4 matt static struct pic_ops kirkwood_picops = {
83 1.4 matt .pic_unblock_irqs = kirkwood_pic_unblock_irqs,
84 1.4 matt .pic_block_irqs = kirkwood_pic_block_irqs,
85 1.1 kiyohara .pic_establish_irq = kirkwood_pic_establish_irq,
86 1.1 kiyohara .pic_source_name = kirkwood_pic_source_name,
87 1.1 kiyohara };
88 1.4 matt static struct pic_softc kirkwood_pic = {
89 1.4 matt .pic_ops = &kirkwood_picops,
90 1.4 matt .pic_maxsources = 64,
91 1.4 matt .pic_name = "kirkwood",
92 1.1 kiyohara };
93 1.1 kiyohara
94 1.8 kiyohara static struct {
95 1.8 kiyohara bus_size_t offset;
96 1.8 kiyohara uint32_t bits;
97 1.8 kiyohara } clkgatings[]= {
98 1.8 kiyohara { KIRKWOOD_GBE0_BASE, (1 << 0) },
99 1.8 kiyohara { MVSOC_PEX_BASE, (1 << 2) },
100 1.8 kiyohara { KIRKWOOD_USB_BASE, (1 << 3) },
101 1.8 kiyohara { KIRKWOOD_SDIO_BASE, (1 << 4) },
102 1.8 kiyohara { KIRKWOOD_MTS_BASE, (1 << 5) },
103 1.8 kiyohara #if 0
104 1.8 kiyohara { Dunit, (1 << 6) }, /* SDRAM Unit Clock */
105 1.8 kiyohara { Runit, (1 << 7) }, /* Runit Clock */
106 1.8 kiyohara #endif
107 1.8 kiyohara { KIRKWOOD_IDMAC_BASE, (1 << 8) | (1 << 16) },
108 1.8 kiyohara { KIRKWOOD_AUDIO_BASE, (1 << 9) },
109 1.8 kiyohara { KIRKWOOD_SATAHC_BASE, (1 << 14) | (1 << 15) },
110 1.8 kiyohara { KIRKWOOD_CESA_BASE, (1 << 17) },
111 1.8 kiyohara { KIRKWOOD_GBE1_BASE, (1 << 19) },
112 1.8 kiyohara { KIRKWOOD_TDM_BASE, (1 << 20) },
113 1.8 kiyohara };
114 1.8 kiyohara
115 1.1 kiyohara
116 1.1 kiyohara /*
117 1.10 kiyohara * kirkwood_bootstrap:
118 1.1 kiyohara *
119 1.10 kiyohara * Initialize the rest of the Kirkwood dependencies, making it
120 1.1 kiyohara * ready to handle interrupts from devices.
121 1.1 kiyohara */
122 1.1 kiyohara void
123 1.10 kiyohara kirkwood_bootstrap(vaddr_t iobase)
124 1.1 kiyohara {
125 1.1 kiyohara
126 1.1 kiyohara /* disable all interrupts */
127 1.1 kiyohara write_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR, 0);
128 1.1 kiyohara write_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR, 0);
129 1.1 kiyohara
130 1.1 kiyohara /* disable all bridge interrupts */
131 1.1 kiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
132 1.1 kiyohara
133 1.1 kiyohara mvsoc_intr_init = kirkwood_intr_init;
134 1.1 kiyohara
135 1.1 kiyohara #if NMVSOCGPP > 0
136 1.1 kiyohara switch (mvsoc_model()) {
137 1.1 kiyohara case MARVELL_KIRKWOOD_88F6180: gpp_npins = 30; break;
138 1.1 kiyohara case MARVELL_KIRKWOOD_88F6192: gpp_npins = 36; break;
139 1.1 kiyohara case MARVELL_KIRKWOOD_88F6281: gpp_npins = 50; break;
140 1.6 kiyohara case MARVELL_KIRKWOOD_88F6282: gpp_npins = 50; break;
141 1.1 kiyohara }
142 1.1 kiyohara gpp_irqbase = 96; /* Main Low(32) + High(32) + Bridge(32) */
143 1.1 kiyohara #endif
144 1.10 kiyohara
145 1.10 kiyohara kirkwood_getclks(iobase);
146 1.10 kiyohara mvsoc_clkgating = kirkwood_clkgating;
147 1.1 kiyohara }
148 1.1 kiyohara
149 1.1 kiyohara static void
150 1.1 kiyohara kirkwood_intr_init(void)
151 1.1 kiyohara {
152 1.1 kiyohara extern struct pic_softc mvsoc_bridge_pic;
153 1.9 martin void *ih __diagused;
154 1.1 kiyohara
155 1.4 matt pic_add(&kirkwood_pic, 0);
156 1.1 kiyohara
157 1.1 kiyohara pic_add(&mvsoc_bridge_pic, 64);
158 1.1 kiyohara ih = intr_establish(KIRKWOOD_IRQ_BRIDGE, IPL_HIGH, IST_LEVEL_HIGH,
159 1.1 kiyohara pic_handle_intr, &mvsoc_bridge_pic);
160 1.1 kiyohara KASSERT(ih != NULL);
161 1.1 kiyohara
162 1.1 kiyohara find_pending_irqs = kirkwood_find_pending_irqs;
163 1.1 kiyohara }
164 1.1 kiyohara
165 1.1 kiyohara /* ARGSUSED */
166 1.1 kiyohara static void
167 1.4 matt kirkwood_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
168 1.4 matt uint32_t irq_mask)
169 1.1 kiyohara {
170 1.4 matt const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
171 1.4 matt + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
172 1.1 kiyohara
173 1.4 matt KASSERT(irqbase < 64);
174 1.4 matt write_mlmbreg(reg, read_mlmbreg(reg) | irq_mask);
175 1.1 kiyohara }
176 1.1 kiyohara
177 1.1 kiyohara /* ARGSUSED */
178 1.1 kiyohara static void
179 1.4 matt kirkwood_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
180 1.4 matt uint32_t irq_mask)
181 1.1 kiyohara {
182 1.4 matt const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
183 1.4 matt + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
184 1.1 kiyohara
185 1.4 matt KASSERT(irqbase < 64);
186 1.4 matt write_mlmbreg(reg, read_mlmbreg(reg) & ~irq_mask);
187 1.1 kiyohara }
188 1.1 kiyohara
189 1.1 kiyohara /* ARGSUSED */
190 1.1 kiyohara static void
191 1.1 kiyohara kirkwood_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
192 1.1 kiyohara {
193 1.1 kiyohara /* Nothing */
194 1.1 kiyohara }
195 1.1 kiyohara
196 1.1 kiyohara static void
197 1.1 kiyohara kirkwood_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
198 1.1 kiyohara {
199 1.1 kiyohara
200 1.1 kiyohara strlcpy(buf, sources[pic->pic_irqbase + irq], len);
201 1.1 kiyohara }
202 1.1 kiyohara
203 1.1 kiyohara /*
204 1.1 kiyohara * Called with interrupts disabled
205 1.1 kiyohara */
206 1.1 kiyohara static int
207 1.1 kiyohara kirkwood_find_pending_irqs(void)
208 1.1 kiyohara {
209 1.4 matt int ipl = 0;
210 1.4 matt
211 1.4 matt uint32_t causelow = read_mlmbreg(KIRKWOOD_MLMB_MICLR);
212 1.4 matt uint32_t pendinglow = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR);
213 1.1 kiyohara
214 1.4 matt pendinglow &= causelow;
215 1.4 matt if (pendinglow != 0)
216 1.4 matt ipl |= pic_mark_pending_sources(&kirkwood_pic, 0, pendinglow);
217 1.4 matt
218 1.5 kiyohara if ((causelow & (1 << KIRKWOOD_IRQ_HIGH)) == (1 << KIRKWOOD_IRQ_HIGH)) {
219 1.4 matt uint32_t causehigh = read_mlmbreg(KIRKWOOD_MLMB_MICHR);
220 1.4 matt uint32_t pendinghigh = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR);
221 1.4 matt pendinghigh &= causehigh;
222 1.4 matt ipl |= pic_mark_pending_sources(&kirkwood_pic, 32, pendinghigh);
223 1.4 matt }
224 1.1 kiyohara
225 1.4 matt return ipl;
226 1.1 kiyohara }
227 1.1 kiyohara
228 1.1 kiyohara /*
229 1.1 kiyohara * Clock functions
230 1.1 kiyohara */
231 1.1 kiyohara
232 1.10 kiyohara static void
233 1.10 kiyohara kirkwood_getclks(vaddr_t iobase)
234 1.1 kiyohara {
235 1.1 kiyohara uint32_t reg;
236 1.1 kiyohara uint16_t model;
237 1.1 kiyohara
238 1.1 kiyohara #define MHz * 1000 * 1000
239 1.1 kiyohara
240 1.1 kiyohara model = mvsoc_model();
241 1.6 kiyohara if (model == MARVELL_KIRKWOOD_88F6281 ||
242 1.6 kiyohara model == MARVELL_KIRKWOOD_88F6282)
243 1.1 kiyohara mvTclk = 200 MHz;
244 1.1 kiyohara else /* 166MHz */
245 1.1 kiyohara mvTclk = 166666667;
246 1.1 kiyohara
247 1.11 rin reg = le32toh(*(volatile uint32_t *)(iobase + KIRKWOOD_MPP_BASE +
248 1.11 rin KIRKWOOD_MPP_SAMPLE_AT_RESET));
249 1.1 kiyohara if (model == MARVELL_KIRKWOOD_88F6180) {
250 1.1 kiyohara switch (reg & 0x0000001c) {
251 1.2 kiyohara case 0x00000014: mvPclk = 600 MHz; break;
252 1.2 kiyohara case 0x00000018: mvPclk = 800 MHz; break;
253 1.1 kiyohara default:
254 1.1 kiyohara panic("unknown mvPclk\n");
255 1.1 kiyohara }
256 1.1 kiyohara mvSysclk = 200 MHz;
257 1.1 kiyohara } else {
258 1.1 kiyohara switch (reg & 0x0040001a) {
259 1.6 kiyohara case 0x00000002: mvPclk = 400 MHz; break;
260 1.1 kiyohara case 0x00000008: mvPclk = 600 MHz; break;
261 1.1 kiyohara case 0x00400008: mvPclk = 800 MHz; break;
262 1.1 kiyohara case 0x0040000a: mvPclk = 1000 MHz; break;
263 1.1 kiyohara case 0x00000012: mvPclk = 1200 MHz; break;
264 1.6 kiyohara case 0x00000018: mvPclk = 1500 MHz; break;
265 1.6 kiyohara case 0x0000001a: mvPclk = 1600 MHz; break;
266 1.6 kiyohara case 0x00400018: mvPclk = 1800 MHz; break;
267 1.6 kiyohara case 0x0040001a: mvPclk = 2000 MHz; break;
268 1.1 kiyohara default:
269 1.1 kiyohara panic("unknown mvPclk\n");
270 1.1 kiyohara }
271 1.1 kiyohara
272 1.1 kiyohara switch (reg & 0x000001e0) {
273 1.6 kiyohara case 0x00000000: mvSysclk = mvPclk * 1 / 1; break;
274 1.6 kiyohara case 0x00000040: mvSysclk = mvPclk * 1 / 2; break;
275 1.1 kiyohara case 0x00000060: mvSysclk = mvPclk * 2 / 5; break;
276 1.1 kiyohara case 0x00000080: mvSysclk = mvPclk * 1 / 3; break;
277 1.1 kiyohara case 0x000000c0: mvSysclk = mvPclk * 1 / 4; break;
278 1.6 kiyohara case 0x000000e0: mvSysclk = mvPclk * 2 / 9; break;
279 1.6 kiyohara case 0x00000100: mvSysclk = mvPclk * 1 / 5; break;
280 1.6 kiyohara case 0x00000120: mvSysclk = mvPclk * 1 / 6; break;
281 1.1 kiyohara default:
282 1.1 kiyohara panic("unknown mvSysclk\n");
283 1.1 kiyohara }
284 1.1 kiyohara }
285 1.1 kiyohara
286 1.1 kiyohara #undef MHz
287 1.1 kiyohara
288 1.1 kiyohara }
289 1.8 kiyohara
290 1.10 kiyohara static int
291 1.8 kiyohara kirkwood_clkgating(struct marvell_attach_args *mva)
292 1.8 kiyohara {
293 1.8 kiyohara uint32_t val;
294 1.8 kiyohara int i;
295 1.8 kiyohara
296 1.8 kiyohara for (i = 0; i < __arraycount(clkgatings); i++) {
297 1.8 kiyohara if (clkgatings[i].offset == mva->mva_offset) {
298 1.8 kiyohara val = read_mlmbreg(MVSOC_MLMB_CLKGATING);
299 1.8 kiyohara if ((val & clkgatings[i].bits) == clkgatings[i].bits)
300 1.8 kiyohara /* Clock enabled */
301 1.8 kiyohara return 0;
302 1.8 kiyohara return 1;
303 1.8 kiyohara }
304 1.8 kiyohara }
305 1.8 kiyohara /* Clock Gating not support */
306 1.8 kiyohara return 0;
307 1.8 kiyohara }
308