mv78xx0.c revision 1.1.6.2 1 1.1.6.2 yamt /* $NetBSD: mv78xx0.c,v 1.1.6.2 2014/05/22 11:39:33 yamt Exp $ */
2 1.1.6.2 yamt /*
3 1.1.6.2 yamt * Copyright (c) 2010 KIYOHARA Takashi
4 1.1.6.2 yamt * All rights reserved.
5 1.1.6.2 yamt *
6 1.1.6.2 yamt * Redistribution and use in source and binary forms, with or without
7 1.1.6.2 yamt * modification, are permitted provided that the following conditions
8 1.1.6.2 yamt * are met:
9 1.1.6.2 yamt * 1. Redistributions of source code must retain the above copyright
10 1.1.6.2 yamt * notice, this list of conditions and the following disclaimer.
11 1.1.6.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
12 1.1.6.2 yamt * notice, this list of conditions and the following disclaimer in the
13 1.1.6.2 yamt * documentation and/or other materials provided with the distribution.
14 1.1.6.2 yamt *
15 1.1.6.2 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1.6.2 yamt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1.6.2 yamt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1.6.2 yamt * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1.6.2 yamt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1.6.2 yamt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1.6.2 yamt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1.6.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1.6.2 yamt * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1.6.2 yamt * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1.6.2 yamt * POSSIBILITY OF SUCH DAMAGE.
26 1.1.6.2 yamt */
27 1.1.6.2 yamt
28 1.1.6.2 yamt #include <sys/cdefs.h>
29 1.1.6.2 yamt __KERNEL_RCSID(0, "$NetBSD: mv78xx0.c,v 1.1.6.2 2014/05/22 11:39:33 yamt Exp $");
30 1.1.6.2 yamt
31 1.1.6.2 yamt #define _INTR_PRIVATE
32 1.1.6.2 yamt
33 1.1.6.2 yamt #include "mvsocgpp.h"
34 1.1.6.2 yamt
35 1.1.6.2 yamt #include <sys/param.h>
36 1.1.6.2 yamt #include <sys/bus.h>
37 1.1.6.2 yamt #include <sys/cpu.h>
38 1.1.6.2 yamt
39 1.1.6.2 yamt #include <machine/intr.h>
40 1.1.6.2 yamt
41 1.1.6.2 yamt #include <arm/pic/picvar.h>
42 1.1.6.2 yamt #include <arm/pic/picvar.h>
43 1.1.6.2 yamt
44 1.1.6.2 yamt #include <arm/marvell/mvsocreg.h>
45 1.1.6.2 yamt #include <arm/marvell/mvsocvar.h>
46 1.1.6.2 yamt #include <arm/marvell/mv78xx0reg.h>
47 1.1.6.2 yamt
48 1.1.6.2 yamt #include <dev/marvell/marvellreg.h>
49 1.1.6.2 yamt
50 1.1.6.2 yamt #define MV78XX0_ICI_MICR(g) (MV78XX0_ICI_MICLR + ((g) << 2))
51 1.1.6.2 yamt #define MV78XX0_ICI_IRQIMR(g) (MV78XX0_ICI_IRQIMLR + ((g) << 2))
52 1.1.6.2 yamt
53 1.1.6.2 yamt static void mv78xx0_intr_init(void);
54 1.1.6.2 yamt
55 1.1.6.2 yamt static void mv78xx0_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
56 1.1.6.2 yamt static void mv78xx0_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
57 1.1.6.2 yamt static void mv78xx0_pic_establish_irq(struct pic_softc *, struct intrsource *);
58 1.1.6.2 yamt static void mv78xx0_pic_source_name(struct pic_softc *, int, char *, size_t);
59 1.1.6.2 yamt
60 1.1.6.2 yamt static int mv78xx0_find_pending_irqs(void);
61 1.1.6.2 yamt
62 1.1.6.2 yamt static const char * const sources[64] = {
63 1.1.6.2 yamt "ErrSum(0)", "SPI(1)", "TWSI0(2)", "TWSI1(3)",
64 1.1.6.2 yamt "IDMA0(4)", "IDMA1(5)", "IDMA2(6)", "IDMA3(7)",
65 1.1.6.2 yamt "Timer0(8)", "Timer1(9)", "Timer2(10)", "Timer3(11)",
66 1.1.6.2 yamt "UART0(12)", "UART1(13)", "UART2(14)", "UART3(15)",
67 1.1.6.2 yamt "USB0(16)", "USB1(17)", "USB2(18)", "Crypto(19)",
68 1.1.6.2 yamt "Reserved(20)", "Reserved(21)", "XOR0(22)", "XOR1(23)",
69 1.1.6.2 yamt "Reserved(24)", "Reserved(25)", "SATA(26)", "TDMI_INT(27)",
70 1.1.6.2 yamt "Reserved(28)", "Reserved(29)", "Reserved(30)", "Reserved(31)"
71 1.1.6.2 yamt
72 1.1.6.2 yamt "PEX00INTA(32)", "PEX01INTA(33)", "PEX02INTA(34)", "PEX03INTA(35)"
73 1.1.6.2 yamt "PEX10INTA(36)", "PEX11INTA(37)", "PEX12INTA(38)", "PEX13INTA(39)"
74 1.1.6.2 yamt "GE00Sum(40)", "GE00Rx(41)", "GE00Tx(42)", "GE00Misc(43)"
75 1.1.6.2 yamt "GE01Sum(44)", "GE01Rx(45)", "GE01Tx(46)", "GE01Misc(47)"
76 1.1.6.2 yamt "GE10Sum(48)", "GE10Rx(49)", "GE10Tx(50)", "GE10Misc(51)"
77 1.1.6.2 yamt "GE11Sum(52)", "GE11Rx(53)", "GE11Tx(54)", "GE11Misc(55)"
78 1.1.6.2 yamt "GPIO0_7(56)", "GPIO8_15(57)", "GPIO16_23(58)", "GPIO24_31(59)"
79 1.1.6.2 yamt "DB_INT(60)", "DB_OUT(61)", "Reserved(62)", "Reserved(63)"
80 1.1.6.2 yamt };
81 1.1.6.2 yamt
82 1.1.6.2 yamt static struct pic_ops mv78xx0_picops = {
83 1.1.6.2 yamt .pic_unblock_irqs = mv78xx0_pic_unblock_irqs,
84 1.1.6.2 yamt .pic_block_irqs = mv78xx0_pic_block_irqs,
85 1.1.6.2 yamt .pic_establish_irq = mv78xx0_pic_establish_irq,
86 1.1.6.2 yamt .pic_source_name = mv78xx0_pic_source_name,
87 1.1.6.2 yamt };
88 1.1.6.2 yamt static struct pic_softc mv78xx0_pic = {
89 1.1.6.2 yamt .pic_ops = &mv78xx0_picops,
90 1.1.6.2 yamt .pic_maxsources = 64,
91 1.1.6.2 yamt .pic_name = "mv78xx0_pic",
92 1.1.6.2 yamt };
93 1.1.6.2 yamt
94 1.1.6.2 yamt
95 1.1.6.2 yamt /*
96 1.1.6.2 yamt * mv78xx0_intr_bootstrap:
97 1.1.6.2 yamt *
98 1.1.6.2 yamt * Initialize the rest of the interrupt subsystem, making it
99 1.1.6.2 yamt * ready to handle interrupts from devices.
100 1.1.6.2 yamt */
101 1.1.6.2 yamt void
102 1.1.6.2 yamt mv78xx0_intr_bootstrap(void)
103 1.1.6.2 yamt {
104 1.1.6.2 yamt extern void (*mvsoc_intr_init)(void);
105 1.1.6.2 yamt
106 1.1.6.2 yamt /* disable all interrupts */
107 1.1.6.2 yamt write_mlmbreg(MV78XX0_ICI_IRQIMER, 0);
108 1.1.6.2 yamt write_mlmbreg(MV78XX0_ICI_IRQIMLR, 0);
109 1.1.6.2 yamt write_mlmbreg(MV78XX0_ICI_IRQIMHR, 0);
110 1.1.6.2 yamt
111 1.1.6.2 yamt /* disable all bridge interrupts */
112 1.1.6.2 yamt write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
113 1.1.6.2 yamt
114 1.1.6.2 yamt mvsoc_intr_init = mv78xx0_intr_init;
115 1.1.6.2 yamt
116 1.1.6.2 yamt gpp_npins = 32;
117 1.1.6.2 yamt gpp_irqbase = 64; /* Main Low(32) + High(32) */
118 1.1.6.2 yamt }
119 1.1.6.2 yamt
120 1.1.6.2 yamt static void
121 1.1.6.2 yamt mv78xx0_intr_init(void)
122 1.1.6.2 yamt {
123 1.1.6.2 yamt
124 1.1.6.2 yamt pic_add(&mv78xx0_pic, 0);
125 1.1.6.2 yamt
126 1.1.6.2 yamt find_pending_irqs = mv78xx0_find_pending_irqs;
127 1.1.6.2 yamt }
128 1.1.6.2 yamt
129 1.1.6.2 yamt /* ARGSUSED */
130 1.1.6.2 yamt static void
131 1.1.6.2 yamt mv78xx0_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
132 1.1.6.2 yamt uint32_t irq_mask)
133 1.1.6.2 yamt {
134 1.1.6.2 yamt const size_t group = irqbase / 32;
135 1.1.6.2 yamt
136 1.1.6.2 yamt write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
137 1.1.6.2 yamt read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) | irq_mask);
138 1.1.6.2 yamt }
139 1.1.6.2 yamt
140 1.1.6.2 yamt /* ARGSUSED */
141 1.1.6.2 yamt static void
142 1.1.6.2 yamt mv78xx0_pic_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask)
143 1.1.6.2 yamt {
144 1.1.6.2 yamt const size_t group = irqbase / 32;
145 1.1.6.2 yamt
146 1.1.6.2 yamt write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
147 1.1.6.2 yamt read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) & ~irq_mask);
148 1.1.6.2 yamt }
149 1.1.6.2 yamt
150 1.1.6.2 yamt /* ARGSUSED */
151 1.1.6.2 yamt static void
152 1.1.6.2 yamt mv78xx0_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
153 1.1.6.2 yamt {
154 1.1.6.2 yamt uint32_t mlmbim;
155 1.1.6.2 yamt
156 1.1.6.2 yamt /* Also enable MbusL-Mbus Bridge Interrupt Mask, if irq is TimerX. */
157 1.1.6.2 yamt if (is->is_irq == MV78XX0_IRQ_TIMER0 ||
158 1.1.6.2 yamt is->is_irq == MV78XX0_IRQ_TIMER1 ||
159 1.1.6.2 yamt is->is_irq == MV78XX0_IRQ_TIMER2 ||
160 1.1.6.2 yamt is->is_irq == MV78XX0_IRQ_TIMER3) {
161 1.1.6.2 yamt mlmbim = read_mlmbreg(MVSOC_MLMB_MLMBIMR);
162 1.1.6.2 yamt mlmbim |= TIMER_IRQ2MLMBIMR(is->is_irq);
163 1.1.6.2 yamt write_mlmbreg(MVSOC_MLMB_MLMBIMR, mlmbim);
164 1.1.6.2 yamt }
165 1.1.6.2 yamt }
166 1.1.6.2 yamt
167 1.1.6.2 yamt static void
168 1.1.6.2 yamt mv78xx0_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
169 1.1.6.2 yamt {
170 1.1.6.2 yamt
171 1.1.6.2 yamt strlcpy(buf, sources[pic->pic_irqbase + irq], len);
172 1.1.6.2 yamt }
173 1.1.6.2 yamt
174 1.1.6.2 yamt /*
175 1.1.6.2 yamt * Called with interrupts disabled
176 1.1.6.2 yamt */
177 1.1.6.2 yamt static int
178 1.1.6.2 yamt mv78xx0_find_pending_irqs(void)
179 1.1.6.2 yamt {
180 1.1.6.2 yamt uint32_t pending;
181 1.1.6.2 yamt int ipl = 0;
182 1.1.6.2 yamt
183 1.1.6.2 yamt pending = read_mlmbreg(MV78XX0_ICI_MICR(0)) &
184 1.1.6.2 yamt read_mlmbreg(MV78XX0_ICI_IRQIMR(0));
185 1.1.6.2 yamt if (pending != 0)
186 1.1.6.2 yamt ipl = pic_mark_pending_sources(&mv78xx0_pic, 0, pending);
187 1.1.6.2 yamt
188 1.1.6.2 yamt pending = read_mlmbreg(MV78XX0_ICI_MICR(1)) &
189 1.1.6.2 yamt read_mlmbreg(MV78XX0_ICI_IRQIMR(1));
190 1.1.6.2 yamt if (pending != 0)
191 1.1.6.2 yamt ipl |= pic_mark_pending_sources(&mv78xx0_pic, 32, pending);
192 1.1.6.2 yamt
193 1.1.6.2 yamt return ipl;
194 1.1.6.2 yamt }
195 1.1.6.2 yamt
196 1.1.6.2 yamt /*
197 1.1.6.2 yamt * Clock functions
198 1.1.6.2 yamt */
199 1.1.6.2 yamt
200 1.1.6.2 yamt void
201 1.1.6.2 yamt mv78xx0_getclks(bus_addr_t iobase)
202 1.1.6.2 yamt {
203 1.1.6.2 yamt const static int sys2cpu_clk_ratio_m[] = /* Mul constant */
204 1.1.6.2 yamt { 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 6 };
205 1.1.6.2 yamt const static int sys2cpu_clk_ratio_n[] = /* Div constant */
206 1.1.6.2 yamt { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 };
207 1.1.6.2 yamt uint32_t reg;
208 1.1.6.2 yamt int x;
209 1.1.6.2 yamt
210 1.1.6.2 yamt #define MHz * 1000 * 1000
211 1.1.6.2 yamt
212 1.1.6.2 yamt reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_HIGH);
213 1.1.6.2 yamt switch (reg & 0x180) {
214 1.1.6.2 yamt case 0x000: mvTclk = 166666667; break;
215 1.1.6.2 yamt case 0x080: mvTclk = 200 MHz; break;
216 1.1.6.2 yamt default: mvTclk = 200 MHz; break;
217 1.1.6.2 yamt }
218 1.1.6.2 yamt
219 1.1.6.2 yamt reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_LOW);
220 1.1.6.2 yamt
221 1.1.6.2 yamt switch (reg & 0x0e0) {
222 1.1.6.2 yamt case 0x020: mvSysclk = 200 MHz; break;
223 1.1.6.2 yamt case 0x040: mvSysclk = 266666667; break;
224 1.1.6.2 yamt case 0x060: mvSysclk = 333333334; break;
225 1.1.6.2 yamt case 0x080: mvSysclk = 400 MHz; break;
226 1.1.6.2 yamt case 0x0a0: mvSysclk = 250 MHz; break;
227 1.1.6.2 yamt case 0x0c0: mvSysclk = 300 MHz; break;
228 1.1.6.2 yamt default: mvSysclk = 266666667; break;
229 1.1.6.2 yamt }
230 1.1.6.2 yamt
231 1.1.6.2 yamt x = (reg & 0xf00) >> 8;
232 1.1.6.2 yamt mvPclk = sys2cpu_clk_ratio_m[x] * mvSysclk / sys2cpu_clk_ratio_n[x];
233 1.1.6.2 yamt
234 1.1.6.2 yamt #undef MHz
235 1.1.6.2 yamt
236 1.1.6.2 yamt }
237