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