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