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