mv78xx0.c revision 1.1 1 1.1 kiyohara /* $NetBSD: mv78xx0.c,v 1.1 2013/09/30 13:07:30 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: mv78xx0.c,v 1.1 2013/09/30 13:07:30 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 #include <sys/cpu.h>
38 1.1 kiyohara
39 1.1 kiyohara #include <machine/intr.h>
40 1.1 kiyohara
41 1.1 kiyohara #include <arm/pic/picvar.h>
42 1.1 kiyohara #include <arm/pic/picvar.h>
43 1.1 kiyohara
44 1.1 kiyohara #include <arm/marvell/mvsocreg.h>
45 1.1 kiyohara #include <arm/marvell/mvsocvar.h>
46 1.1 kiyohara #include <arm/marvell/mv78xx0reg.h>
47 1.1 kiyohara
48 1.1 kiyohara #include <dev/marvell/marvellreg.h>
49 1.1 kiyohara
50 1.1 kiyohara #define MV78XX0_ICI_MICR(g) (MV78XX0_ICI_MICLR + ((g) << 2))
51 1.1 kiyohara #define MV78XX0_ICI_IRQIMR(g) (MV78XX0_ICI_IRQIMLR + ((g) << 2))
52 1.1 kiyohara
53 1.1 kiyohara static void mv78xx0_intr_init(void);
54 1.1 kiyohara
55 1.1 kiyohara static void mv78xx0_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
56 1.1 kiyohara static void mv78xx0_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
57 1.1 kiyohara static void mv78xx0_pic_establish_irq(struct pic_softc *, struct intrsource *);
58 1.1 kiyohara static void mv78xx0_pic_source_name(struct pic_softc *, int, char *, size_t);
59 1.1 kiyohara
60 1.1 kiyohara static int mv78xx0_find_pending_irqs(void);
61 1.1 kiyohara
62 1.1 kiyohara static const char * const sources[64] = {
63 1.1 kiyohara "ErrSum(0)", "SPI(1)", "TWSI0(2)", "TWSI1(3)",
64 1.1 kiyohara "IDMA0(4)", "IDMA1(5)", "IDMA2(6)", "IDMA3(7)",
65 1.1 kiyohara "Timer0(8)", "Timer1(9)", "Timer2(10)", "Timer3(11)",
66 1.1 kiyohara "UART0(12)", "UART1(13)", "UART2(14)", "UART3(15)",
67 1.1 kiyohara "USB0(16)", "USB1(17)", "USB2(18)", "Crypto(19)",
68 1.1 kiyohara "Reserved(20)", "Reserved(21)", "XOR0(22)", "XOR1(23)",
69 1.1 kiyohara "Reserved(24)", "Reserved(25)", "SATA(26)", "TDMI_INT(27)",
70 1.1 kiyohara "Reserved(28)", "Reserved(29)", "Reserved(30)", "Reserved(31)"
71 1.1 kiyohara
72 1.1 kiyohara "PEX00INTA(32)", "PEX01INTA(33)", "PEX02INTA(34)", "PEX03INTA(35)"
73 1.1 kiyohara "PEX10INTA(36)", "PEX11INTA(37)", "PEX12INTA(38)", "PEX13INTA(39)"
74 1.1 kiyohara "GE00Sum(40)", "GE00Rx(41)", "GE00Tx(42)", "GE00Misc(43)"
75 1.1 kiyohara "GE01Sum(44)", "GE01Rx(45)", "GE01Tx(46)", "GE01Misc(47)"
76 1.1 kiyohara "GE10Sum(48)", "GE10Rx(49)", "GE10Tx(50)", "GE10Misc(51)"
77 1.1 kiyohara "GE11Sum(52)", "GE11Rx(53)", "GE11Tx(54)", "GE11Misc(55)"
78 1.1 kiyohara "GPIO0_7(56)", "GPIO8_15(57)", "GPIO16_23(58)", "GPIO24_31(59)"
79 1.1 kiyohara "DB_INT(60)", "DB_OUT(61)", "Reserved(62)", "Reserved(63)"
80 1.1 kiyohara };
81 1.1 kiyohara
82 1.1 kiyohara static struct pic_ops mv78xx0_picops = {
83 1.1 kiyohara .pic_unblock_irqs = mv78xx0_pic_unblock_irqs,
84 1.1 kiyohara .pic_block_irqs = mv78xx0_pic_block_irqs,
85 1.1 kiyohara .pic_establish_irq = mv78xx0_pic_establish_irq,
86 1.1 kiyohara .pic_source_name = mv78xx0_pic_source_name,
87 1.1 kiyohara };
88 1.1 kiyohara static struct pic_softc mv78xx0_pic = {
89 1.1 kiyohara .pic_ops = &mv78xx0_picops,
90 1.1 kiyohara .pic_maxsources = 64,
91 1.1 kiyohara .pic_name = "mv78xx0_pic",
92 1.1 kiyohara };
93 1.1 kiyohara
94 1.1 kiyohara
95 1.1 kiyohara /*
96 1.1 kiyohara * mv78xx0_intr_bootstrap:
97 1.1 kiyohara *
98 1.1 kiyohara * Initialize the rest of the interrupt subsystem, making it
99 1.1 kiyohara * ready to handle interrupts from devices.
100 1.1 kiyohara */
101 1.1 kiyohara void
102 1.1 kiyohara mv78xx0_intr_bootstrap(void)
103 1.1 kiyohara {
104 1.1 kiyohara extern void (*mvsoc_intr_init)(void);
105 1.1 kiyohara
106 1.1 kiyohara /* disable all interrupts */
107 1.1 kiyohara write_mlmbreg(MV78XX0_ICI_IRQIMER, 0);
108 1.1 kiyohara write_mlmbreg(MV78XX0_ICI_IRQIMLR, 0);
109 1.1 kiyohara write_mlmbreg(MV78XX0_ICI_IRQIMHR, 0);
110 1.1 kiyohara
111 1.1 kiyohara /* disable all bridge interrupts */
112 1.1 kiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
113 1.1 kiyohara
114 1.1 kiyohara mvsoc_intr_init = mv78xx0_intr_init;
115 1.1 kiyohara
116 1.1 kiyohara gpp_npins = 32;
117 1.1 kiyohara gpp_irqbase = 64; /* Main Low(32) + High(32) */
118 1.1 kiyohara }
119 1.1 kiyohara
120 1.1 kiyohara static void
121 1.1 kiyohara mv78xx0_intr_init(void)
122 1.1 kiyohara {
123 1.1 kiyohara
124 1.1 kiyohara pic_add(&mv78xx0_pic, 0);
125 1.1 kiyohara
126 1.1 kiyohara find_pending_irqs = mv78xx0_find_pending_irqs;
127 1.1 kiyohara }
128 1.1 kiyohara
129 1.1 kiyohara /* ARGSUSED */
130 1.1 kiyohara static void
131 1.1 kiyohara mv78xx0_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
132 1.1 kiyohara uint32_t irq_mask)
133 1.1 kiyohara {
134 1.1 kiyohara const size_t group = irqbase / 32;
135 1.1 kiyohara
136 1.1 kiyohara write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
137 1.1 kiyohara read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) | irq_mask);
138 1.1 kiyohara }
139 1.1 kiyohara
140 1.1 kiyohara /* ARGSUSED */
141 1.1 kiyohara static void
142 1.1 kiyohara mv78xx0_pic_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask)
143 1.1 kiyohara {
144 1.1 kiyohara const size_t group = irqbase / 32;
145 1.1 kiyohara
146 1.1 kiyohara write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
147 1.1 kiyohara read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) & ~irq_mask);
148 1.1 kiyohara }
149 1.1 kiyohara
150 1.1 kiyohara /* ARGSUSED */
151 1.1 kiyohara static void
152 1.1 kiyohara mv78xx0_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
153 1.1 kiyohara {
154 1.1 kiyohara uint32_t mlmbim;
155 1.1 kiyohara
156 1.1 kiyohara /* Also enable MbusL-Mbus Bridge Interrupt Mask, if irq is TimerX. */
157 1.1 kiyohara if (is->is_irq == MV78XX0_IRQ_TIMER0 ||
158 1.1 kiyohara is->is_irq == MV78XX0_IRQ_TIMER1 ||
159 1.1 kiyohara is->is_irq == MV78XX0_IRQ_TIMER2 ||
160 1.1 kiyohara is->is_irq == MV78XX0_IRQ_TIMER3) {
161 1.1 kiyohara mlmbim = read_mlmbreg(MVSOC_MLMB_MLMBIMR);
162 1.1 kiyohara mlmbim |= TIMER_IRQ2MLMBIMR(is->is_irq);
163 1.1 kiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR, mlmbim);
164 1.1 kiyohara }
165 1.1 kiyohara }
166 1.1 kiyohara
167 1.1 kiyohara static void
168 1.1 kiyohara mv78xx0_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
169 1.1 kiyohara {
170 1.1 kiyohara
171 1.1 kiyohara strlcpy(buf, sources[pic->pic_irqbase + irq], len);
172 1.1 kiyohara }
173 1.1 kiyohara
174 1.1 kiyohara /*
175 1.1 kiyohara * Called with interrupts disabled
176 1.1 kiyohara */
177 1.1 kiyohara static int
178 1.1 kiyohara mv78xx0_find_pending_irqs(void)
179 1.1 kiyohara {
180 1.1 kiyohara uint32_t pending;
181 1.1 kiyohara int ipl = 0;
182 1.1 kiyohara
183 1.1 kiyohara pending = read_mlmbreg(MV78XX0_ICI_MICR(0)) &
184 1.1 kiyohara read_mlmbreg(MV78XX0_ICI_IRQIMR(0));
185 1.1 kiyohara if (pending != 0)
186 1.1 kiyohara ipl = pic_mark_pending_sources(&mv78xx0_pic, 0, pending);
187 1.1 kiyohara
188 1.1 kiyohara pending = read_mlmbreg(MV78XX0_ICI_MICR(1)) &
189 1.1 kiyohara read_mlmbreg(MV78XX0_ICI_IRQIMR(1));
190 1.1 kiyohara if (pending != 0)
191 1.1 kiyohara ipl |= pic_mark_pending_sources(&mv78xx0_pic, 32, pending);
192 1.1 kiyohara
193 1.1 kiyohara return ipl;
194 1.1 kiyohara }
195 1.1 kiyohara
196 1.1 kiyohara /*
197 1.1 kiyohara * Clock functions
198 1.1 kiyohara */
199 1.1 kiyohara
200 1.1 kiyohara void
201 1.1 kiyohara mv78xx0_getclks(bus_addr_t iobase)
202 1.1 kiyohara {
203 1.1 kiyohara const static int sys2cpu_clk_ratio_m[] = /* Mul constant */
204 1.1 kiyohara { 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 6 };
205 1.1 kiyohara const static int sys2cpu_clk_ratio_n[] = /* Div constant */
206 1.1 kiyohara { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 };
207 1.1 kiyohara uint32_t reg;
208 1.1 kiyohara int x;
209 1.1 kiyohara
210 1.1 kiyohara #define MHz * 1000 * 1000
211 1.1 kiyohara
212 1.1 kiyohara reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_HIGH);
213 1.1 kiyohara switch (reg & 0x180) {
214 1.1 kiyohara case 0x000: mvTclk = 166666667; break;
215 1.1 kiyohara case 0x080: mvTclk = 200 MHz; break;
216 1.1 kiyohara default: mvTclk = 200 MHz; break;
217 1.1 kiyohara }
218 1.1 kiyohara
219 1.1 kiyohara reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_LOW);
220 1.1 kiyohara
221 1.1 kiyohara switch (reg & 0x0e0) {
222 1.1 kiyohara case 0x020: mvSysclk = 200 MHz; break;
223 1.1 kiyohara case 0x040: mvSysclk = 266666667; break;
224 1.1 kiyohara case 0x060: mvSysclk = 333333334; break;
225 1.1 kiyohara case 0x080: mvSysclk = 400 MHz; break;
226 1.1 kiyohara case 0x0a0: mvSysclk = 250 MHz; break;
227 1.1 kiyohara case 0x0c0: mvSysclk = 300 MHz; break;
228 1.1 kiyohara default: mvSysclk = 266666667; break;
229 1.1 kiyohara }
230 1.1 kiyohara
231 1.1 kiyohara x = (reg & 0xf00) >> 8;
232 1.1 kiyohara mvPclk = sys2cpu_clk_ratio_m[x] * mvSysclk / sys2cpu_clk_ratio_n[x];
233 1.1 kiyohara
234 1.1 kiyohara #undef MHz
235 1.1 kiyohara
236 1.1 kiyohara }
237