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