kirkwood.c revision 1.9 1 1.9 martin /* $NetBSD: kirkwood.c,v 1.9 2014/03/11 07:52:37 martin 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.9 martin __KERNEL_RCSID(0, "$NetBSD: kirkwood.c,v 1.9 2014/03/11 07:52:37 martin 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.1 kiyohara static const char * const sources[64] = {
60 1.1 kiyohara "MainHighSum(0)", "Bridge(1)", "Host2CPU DB(2)", "CPU2Host DB(3)",
61 1.1 kiyohara "Reserved_4(4)", "Xor0Chan0(5)", "Xor0Chan1(6)", "Xor1Chan0(7)",
62 1.1 kiyohara "Xor1Chan1(8)", "PEX0INT(9)", "Reserved(10)", "GbE0Sum(11)",
63 1.1 kiyohara "GbE0Rx(12)", "GbE0Tx(13)", "GbE0Misc(14)", "GbE1Sum(15)",
64 1.1 kiyohara "GbE1Rx(16)", "GbE1Tx(17)", "GbE1Misc(18)", "USB0Cnt(19)",
65 1.1 kiyohara "Reserved(20)", "Sata(21)", "SecurityInt(22)", "SPIInt(23)",
66 1.1 kiyohara "AudioINT(24)", "Reserved(25)", "TS0Int(26)", "Reserved(27)",
67 1.7 msaitoh "SDIOInt(28)", "TWSI(29)", "AVBInt(30)", "TDMInt(31)",
68 1.1 kiyohara
69 1.7 msaitoh "Reserved(32)", "Uart0Int(33)", "Uart1Int(34)", "GPIOLo7_0(35)",
70 1.7 msaitoh "GPIOLo8_15(36)", "GPIOLo16_23(37)", "GPIOLo24_31(38)", "GPIOHi7_0(39)",
71 1.7 msaitoh "GPIOHi8_15(40)", "GPIOHi16_23(41)", "XOR0Err(42)", "XOR1Err(43)",
72 1.7 msaitoh "PEX0Err(44)", "Reserved(45)", "GbE0Err(46)", "GbE1Err(47)",
73 1.7 msaitoh "USBErr(48)", "SecurityErr(49)", "AudioErr(50)", "Reserved(51)",
74 1.7 msaitoh "Reserved(52)", "RTCInt(53)", "Reserved(54)", "Reserved(55)",
75 1.7 msaitoh "Reserved(56)", "Reserved(57)", "Reserved(58)", "Reserved(59)",
76 1.1 kiyohara "Reserved(60)", "Reserved(61)", "Reserved(62)", "Reserved(63)"
77 1.1 kiyohara };
78 1.1 kiyohara
79 1.4 matt static struct pic_ops kirkwood_picops = {
80 1.4 matt .pic_unblock_irqs = kirkwood_pic_unblock_irqs,
81 1.4 matt .pic_block_irqs = kirkwood_pic_block_irqs,
82 1.1 kiyohara .pic_establish_irq = kirkwood_pic_establish_irq,
83 1.1 kiyohara .pic_source_name = kirkwood_pic_source_name,
84 1.1 kiyohara };
85 1.4 matt static struct pic_softc kirkwood_pic = {
86 1.4 matt .pic_ops = &kirkwood_picops,
87 1.4 matt .pic_maxsources = 64,
88 1.4 matt .pic_name = "kirkwood",
89 1.1 kiyohara };
90 1.1 kiyohara
91 1.8 kiyohara static struct {
92 1.8 kiyohara bus_size_t offset;
93 1.8 kiyohara uint32_t bits;
94 1.8 kiyohara } clkgatings[]= {
95 1.8 kiyohara { KIRKWOOD_GBE0_BASE, (1 << 0) },
96 1.8 kiyohara { MVSOC_PEX_BASE, (1 << 2) },
97 1.8 kiyohara { KIRKWOOD_USB_BASE, (1 << 3) },
98 1.8 kiyohara { KIRKWOOD_SDIO_BASE, (1 << 4) },
99 1.8 kiyohara { KIRKWOOD_MTS_BASE, (1 << 5) },
100 1.8 kiyohara #if 0
101 1.8 kiyohara { Dunit, (1 << 6) }, /* SDRAM Unit Clock */
102 1.8 kiyohara { Runit, (1 << 7) }, /* Runit Clock */
103 1.8 kiyohara #endif
104 1.8 kiyohara { KIRKWOOD_IDMAC_BASE, (1 << 8) | (1 << 16) },
105 1.8 kiyohara { KIRKWOOD_AUDIO_BASE, (1 << 9) },
106 1.8 kiyohara { KIRKWOOD_SATAHC_BASE, (1 << 14) | (1 << 15) },
107 1.8 kiyohara { KIRKWOOD_CESA_BASE, (1 << 17) },
108 1.8 kiyohara { KIRKWOOD_GBE1_BASE, (1 << 19) },
109 1.8 kiyohara { KIRKWOOD_TDM_BASE, (1 << 20) },
110 1.8 kiyohara };
111 1.8 kiyohara
112 1.1 kiyohara
113 1.1 kiyohara /*
114 1.1 kiyohara * kirkwood_intr_bootstrap:
115 1.1 kiyohara *
116 1.1 kiyohara * Initialize the rest of the interrupt subsystem, making it
117 1.1 kiyohara * ready to handle interrupts from devices.
118 1.1 kiyohara */
119 1.1 kiyohara void
120 1.1 kiyohara kirkwood_intr_bootstrap(void)
121 1.1 kiyohara {
122 1.1 kiyohara extern void (*mvsoc_intr_init)(void);
123 1.1 kiyohara
124 1.1 kiyohara /* disable all interrupts */
125 1.1 kiyohara write_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR, 0);
126 1.1 kiyohara write_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR, 0);
127 1.1 kiyohara
128 1.1 kiyohara /* disable all bridge interrupts */
129 1.1 kiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
130 1.1 kiyohara
131 1.1 kiyohara mvsoc_intr_init = kirkwood_intr_init;
132 1.1 kiyohara
133 1.1 kiyohara #if NMVSOCGPP > 0
134 1.1 kiyohara switch (mvsoc_model()) {
135 1.1 kiyohara case MARVELL_KIRKWOOD_88F6180: gpp_npins = 30; break;
136 1.1 kiyohara case MARVELL_KIRKWOOD_88F6192: gpp_npins = 36; break;
137 1.1 kiyohara case MARVELL_KIRKWOOD_88F6281: gpp_npins = 50; break;
138 1.6 kiyohara case MARVELL_KIRKWOOD_88F6282: gpp_npins = 50; break;
139 1.1 kiyohara }
140 1.1 kiyohara gpp_irqbase = 96; /* Main Low(32) + High(32) + Bridge(32) */
141 1.1 kiyohara #endif
142 1.1 kiyohara }
143 1.1 kiyohara
144 1.1 kiyohara static void
145 1.1 kiyohara kirkwood_intr_init(void)
146 1.1 kiyohara {
147 1.1 kiyohara extern struct pic_softc mvsoc_bridge_pic;
148 1.9 martin void *ih __diagused;
149 1.1 kiyohara
150 1.4 matt pic_add(&kirkwood_pic, 0);
151 1.1 kiyohara
152 1.1 kiyohara pic_add(&mvsoc_bridge_pic, 64);
153 1.1 kiyohara ih = intr_establish(KIRKWOOD_IRQ_BRIDGE, IPL_HIGH, IST_LEVEL_HIGH,
154 1.1 kiyohara pic_handle_intr, &mvsoc_bridge_pic);
155 1.1 kiyohara KASSERT(ih != NULL);
156 1.1 kiyohara
157 1.1 kiyohara find_pending_irqs = kirkwood_find_pending_irqs;
158 1.1 kiyohara }
159 1.1 kiyohara
160 1.1 kiyohara /* ARGSUSED */
161 1.1 kiyohara static void
162 1.4 matt kirkwood_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
163 1.4 matt uint32_t irq_mask)
164 1.1 kiyohara {
165 1.4 matt const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
166 1.4 matt + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
167 1.1 kiyohara
168 1.4 matt KASSERT(irqbase < 64);
169 1.4 matt write_mlmbreg(reg, read_mlmbreg(reg) | irq_mask);
170 1.1 kiyohara }
171 1.1 kiyohara
172 1.1 kiyohara /* ARGSUSED */
173 1.1 kiyohara static void
174 1.4 matt kirkwood_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
175 1.4 matt uint32_t irq_mask)
176 1.1 kiyohara {
177 1.4 matt const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
178 1.4 matt + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
179 1.1 kiyohara
180 1.4 matt KASSERT(irqbase < 64);
181 1.4 matt write_mlmbreg(reg, read_mlmbreg(reg) & ~irq_mask);
182 1.1 kiyohara }
183 1.1 kiyohara
184 1.1 kiyohara /* ARGSUSED */
185 1.1 kiyohara static void
186 1.1 kiyohara kirkwood_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
187 1.1 kiyohara {
188 1.1 kiyohara /* Nothing */
189 1.1 kiyohara }
190 1.1 kiyohara
191 1.1 kiyohara static void
192 1.1 kiyohara kirkwood_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
193 1.1 kiyohara {
194 1.1 kiyohara
195 1.1 kiyohara strlcpy(buf, sources[pic->pic_irqbase + irq], len);
196 1.1 kiyohara }
197 1.1 kiyohara
198 1.1 kiyohara /*
199 1.1 kiyohara * Called with interrupts disabled
200 1.1 kiyohara */
201 1.1 kiyohara static int
202 1.1 kiyohara kirkwood_find_pending_irqs(void)
203 1.1 kiyohara {
204 1.4 matt int ipl = 0;
205 1.4 matt
206 1.4 matt uint32_t causelow = read_mlmbreg(KIRKWOOD_MLMB_MICLR);
207 1.4 matt uint32_t pendinglow = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR);
208 1.1 kiyohara
209 1.4 matt pendinglow &= causelow;
210 1.4 matt if (pendinglow != 0)
211 1.4 matt ipl |= pic_mark_pending_sources(&kirkwood_pic, 0, pendinglow);
212 1.4 matt
213 1.5 kiyohara if ((causelow & (1 << KIRKWOOD_IRQ_HIGH)) == (1 << KIRKWOOD_IRQ_HIGH)) {
214 1.4 matt uint32_t causehigh = read_mlmbreg(KIRKWOOD_MLMB_MICHR);
215 1.4 matt uint32_t pendinghigh = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR);
216 1.4 matt pendinghigh &= causehigh;
217 1.4 matt ipl |= pic_mark_pending_sources(&kirkwood_pic, 32, pendinghigh);
218 1.4 matt }
219 1.1 kiyohara
220 1.4 matt return ipl;
221 1.1 kiyohara }
222 1.1 kiyohara
223 1.1 kiyohara /*
224 1.1 kiyohara * Clock functions
225 1.1 kiyohara */
226 1.1 kiyohara
227 1.1 kiyohara void
228 1.1 kiyohara kirkwood_getclks(bus_addr_t iobase)
229 1.1 kiyohara {
230 1.1 kiyohara uint32_t reg;
231 1.1 kiyohara uint16_t model;
232 1.1 kiyohara
233 1.1 kiyohara #define MHz * 1000 * 1000
234 1.1 kiyohara
235 1.1 kiyohara model = mvsoc_model();
236 1.6 kiyohara if (model == MARVELL_KIRKWOOD_88F6281 ||
237 1.6 kiyohara model == MARVELL_KIRKWOOD_88F6282)
238 1.1 kiyohara mvTclk = 200 MHz;
239 1.1 kiyohara else /* 166MHz */
240 1.1 kiyohara mvTclk = 166666667;
241 1.1 kiyohara
242 1.1 kiyohara reg = *(volatile uint32_t *)(iobase + KIRKWOOD_MPP_BASE +
243 1.1 kiyohara KIRKWOOD_MPP_SAMPLE_AT_RESET);
244 1.1 kiyohara if (model == MARVELL_KIRKWOOD_88F6180) {
245 1.1 kiyohara switch (reg & 0x0000001c) {
246 1.2 kiyohara case 0x00000014: mvPclk = 600 MHz; break;
247 1.2 kiyohara case 0x00000018: mvPclk = 800 MHz; break;
248 1.1 kiyohara default:
249 1.1 kiyohara panic("unknown mvPclk\n");
250 1.1 kiyohara }
251 1.1 kiyohara mvSysclk = 200 MHz;
252 1.1 kiyohara } else {
253 1.1 kiyohara switch (reg & 0x0040001a) {
254 1.6 kiyohara case 0x00000002: mvPclk = 400 MHz; break;
255 1.1 kiyohara case 0x00000008: mvPclk = 600 MHz; break;
256 1.1 kiyohara case 0x00400008: mvPclk = 800 MHz; break;
257 1.1 kiyohara case 0x0040000a: mvPclk = 1000 MHz; break;
258 1.1 kiyohara case 0x00000012: mvPclk = 1200 MHz; break;
259 1.6 kiyohara case 0x00000018: mvPclk = 1500 MHz; break;
260 1.6 kiyohara case 0x0000001a: mvPclk = 1600 MHz; break;
261 1.6 kiyohara case 0x00400018: mvPclk = 1800 MHz; break;
262 1.6 kiyohara case 0x0040001a: mvPclk = 2000 MHz; break;
263 1.1 kiyohara default:
264 1.1 kiyohara panic("unknown mvPclk\n");
265 1.1 kiyohara }
266 1.1 kiyohara
267 1.1 kiyohara switch (reg & 0x000001e0) {
268 1.6 kiyohara case 0x00000000: mvSysclk = mvPclk * 1 / 1; break;
269 1.6 kiyohara case 0x00000040: mvSysclk = mvPclk * 1 / 2; break;
270 1.1 kiyohara case 0x00000060: mvSysclk = mvPclk * 2 / 5; break;
271 1.1 kiyohara case 0x00000080: mvSysclk = mvPclk * 1 / 3; break;
272 1.1 kiyohara case 0x000000c0: mvSysclk = mvPclk * 1 / 4; break;
273 1.6 kiyohara case 0x000000e0: mvSysclk = mvPclk * 2 / 9; break;
274 1.6 kiyohara case 0x00000100: mvSysclk = mvPclk * 1 / 5; break;
275 1.6 kiyohara case 0x00000120: mvSysclk = mvPclk * 1 / 6; break;
276 1.1 kiyohara default:
277 1.1 kiyohara panic("unknown mvSysclk\n");
278 1.1 kiyohara }
279 1.1 kiyohara }
280 1.1 kiyohara
281 1.1 kiyohara #undef MHz
282 1.1 kiyohara
283 1.1 kiyohara }
284 1.8 kiyohara
285 1.8 kiyohara int
286 1.8 kiyohara kirkwood_clkgating(struct marvell_attach_args *mva)
287 1.8 kiyohara {
288 1.8 kiyohara uint32_t val;
289 1.8 kiyohara int i;
290 1.8 kiyohara
291 1.8 kiyohara for (i = 0; i < __arraycount(clkgatings); i++) {
292 1.8 kiyohara if (clkgatings[i].offset == mva->mva_offset) {
293 1.8 kiyohara val = read_mlmbreg(MVSOC_MLMB_CLKGATING);
294 1.8 kiyohara if ((val & clkgatings[i].bits) == clkgatings[i].bits)
295 1.8 kiyohara /* Clock enabled */
296 1.8 kiyohara return 0;
297 1.8 kiyohara return 1;
298 1.8 kiyohara }
299 1.8 kiyohara }
300 1.8 kiyohara /* Clock Gating not support */
301 1.8 kiyohara return 0;
302 1.8 kiyohara }
303