1 /*- 2 * Copyright (c) 2011 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Matt Thomas of 3am Software Foundry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 32 __KERNEL_RCSID(0, "$NetBSD: ar7100.c,v 1.4 2025/07/03 19:09:48 andvar Exp $"); 33 34 #define __INTR_PRIVATE 35 #include "pci.h" 36 #include "opt_memsize.h" 37 38 #include <sys/param.h> 39 #include <sys/device.h> 40 #include <sys/cpu.h> 41 42 #include <prop/proplib.h> 43 44 #include <mips/cpuregs.h> 45 #include <mips/atheros/include/platform.h> 46 #include <mips/atheros/include/ar9344reg.h> 47 48 #define AR7100_BASE_FREQ (40*1000*1000) 49 50 static const char * const ar7100_cpu_intrnames[] = { 51 [AR7100_CPU_IRQ_PCI] = "irq 0 (pci)", 52 [ARCHIP_CPU_IRQ_USB] = "irq 1 (usb)", 53 [ARCHIP_CPU_IRQ_GMAC0] = "irq 2 (gmac0)", 54 [ARCHIP_CPU_IRQ_GMAC1] = "irq 3 (gmac1)", 55 [ARCHIP_CPU_IRQ_MISC] = "irq 4 (misc)", 56 [ARCHIP_CPU_IRQ_TIMER] = "irq 5 (timer)", 57 }; 58 59 static const char * const ar7100_misc_intrnames[] = { 60 [AR7100_MISC_IRQ_TIMER] = "irq 0 (timer)", 61 [AR7100_MISC_IRQ_ERROR] = "irq 1 (error)", 62 [AR7100_MISC_IRQ_GPIO] = "irq 2 (gpio)", 63 [AR7100_MISC_IRQ_UART0] = "irq 3 (uart)", 64 [AR7100_MISC_IRQ_WDOG] = "irq 4 (wdog)", 65 [AR7100_MISC_IRQ_PC] = "irq 5 (pc)", 66 [AR7100_MISC_IRQ_OHCI] = "irq 6 (ohci)", 67 [AR7100_MISC_IRQ_DMA] = "irq 7 (dma)", 68 }; 69 70 static const struct ipl_sr_map ar7100_ipl_sr_map = { 71 .sr_bits = { 72 [IPL_NONE] = 0, 73 [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0, 74 [IPL_SOFTBIO] = MIPS_SOFT_INT_MASK_0, 75 [IPL_SOFTNET] = MIPS_SOFT_INT_MASK, 76 [IPL_SOFTSERIAL] = MIPS_SOFT_INT_MASK, 77 [IPL_BIO] = MIPS_SOFT_INT_MASK | 78 MIPS_INT_MASK_0 | /* PCI */ 79 MIPS_INT_MASK_1, /* USB */ 80 [IPL_NET] = MIPS_SOFT_INT_MASK | 81 MIPS_INT_MASK_0 | /* PCI */ 82 MIPS_INT_MASK_1 | /* USB */ 83 MIPS_INT_MASK_2 | /* GMAC0 */ 84 MIPS_INT_MASK_3, /* GMAC1 */ 85 [IPL_SERIAL] = MIPS_SOFT_INT_MASK | 86 MIPS_INT_MASK_0 | /* PCIE RC */ 87 MIPS_INT_MASK_1 | /* USB */ 88 MIPS_INT_MASK_2 | /* GMAC0 */ 89 MIPS_INT_MASK_3 | /* GMAC1 */ 90 MIPS_INT_MASK_4, /* MISC (UART0/1) */ 91 92 [IPL_SCHED] = MIPS_INT_MASK, /* EVERYTHING */ 93 [IPL_DDB] = MIPS_INT_MASK, /* EVERYTHING */ 94 [IPL_HIGH] = MIPS_INT_MASK, /* EVERYTHING */ 95 }, 96 }; 97 98 static void 99 ar7100_intr_init(void) 100 { 101 atheros_intr_init(); 102 } 103 104 static uint32_t 105 ar7100_get_memsize(void) 106 { 107 #ifdef MEMSIZE 108 return MEMSIZE; 109 #else 110 return 128*1024*1024; 111 #endif 112 } 113 114 static void 115 ar7100_wdog_reload(uint32_t period) 116 { 117 118 if (period == 0) { 119 PUTRESETREG(ARCHIP_RESET_WDOG_CTL, ARCHIP_WDOG_CTL_IGNORE); 120 PUTRESETREG(ARCHIP_RESET_WDOG_TIMER, 0); 121 } else { 122 PUTRESETREG(ARCHIP_RESET_WDOG_TIMER, period); 123 PUTRESETREG(ARCHIP_RESET_WDOG_CTL, ARCHIP_WDOG_CTL_RESET); 124 } 125 } 126 127 static void 128 ar7100_bus_init(void) 129 { 130 printf("resetctl = %#x\n", GETRESETREG(AR7100_RESET_RESETCTL)); 131 #if NPCI > 0 && 0 132 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_0) = 0x10000000; 133 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_1) = 0x11000000; 134 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_2) = 0x12000000; 135 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_3) = 0x13000000; 136 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_4) = 0x14000000; 137 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_5) = 0x15000000; 138 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_6) = 0x16000000; 139 REGVAL(ARCHIP_DDR_BASE + AR7100_PCI_WINDOW_7) = 0x07000000; 140 #endif 141 } 142 143 static void 144 ar7100_reset(void) 145 { 146 PUTRESETREG(AR7100_RESET_RESETCTL, ARCHIP_RESETCTL_FULL_CHIP_RESET); 147 } 148 149 static void 150 ar7100_get_freqs(struct arfreqs *freqs) 151 { 152 const uint32_t pll = GETPLLREG(ARCHIP_PLL_CPU_PLL_CONFIG); 153 const uint32_t ref_freq = AR7100_BASE_FREQ; 154 155 const uint32_t pll_freq = 156 ref_freq * (__SHIFTOUT(pll, AR7100_PLL_PLL_FB) + 1); 157 158 const uint32_t cpu_freq = 159 pll_freq / (__SHIFTOUT(pll, AR7100_CPU_PLL_CPU_DIV_SEL) + 1); 160 161 const uint32_t ddr_freq = 162 pll_freq / (__SHIFTOUT(pll, AR7100_CPU_PLL_DDR_DIV_SEL) + 1); 163 164 const uint32_t bus_freq = 165 cpu_freq / ((__SHIFTOUT(pll, AR7100_CPU_PLL_AHB_DIV) + 1) * 2); 166 167 freqs->freq_bus = bus_freq; 168 freqs->freq_cpu = cpu_freq; 169 freqs->freq_mem = ddr_freq; 170 freqs->freq_pll = pll_freq; 171 freqs->freq_ref = ref_freq; 172 } 173 174 static void 175 ar7100_device_register(device_t self, void *aux) 176 { 177 if (device_is_a(self, "com")) { 178 prop_number_t pn = 179 prop_number_create_unsigned_integer(atheros_get_bus_freq()); 180 KASSERT(pn != NULL); 181 prop_dictionary_set(device_properties(self), "frequency", pn); 182 prop_object_release(pn); 183 } 184 } 185 186 static int 187 ar7100_enable_device(const struct atheros_device *adv) 188 { 189 #if 0 190 if (adv->adv_mask && ((adv->adv_mask & info->config) == 0)) { 191 return -1; 192 } 193 #endif 194 if (adv->adv_reset) { 195 /* put device into reset */ 196 PUTRESETREG(AR7100_RESET_RESETCTL, 197 GETRESETREG(AR7100_RESET_RESETCTL) | adv->adv_reset); 198 199 delay(15000); /* XXX: tsleep? */ 200 201 /* take it out of reset */ 202 PUTRESETREG(AR7100_RESET_RESETCTL, 203 GETRESETREG(AR7100_RESET_RESETCTL) & ~adv->adv_reset); 204 205 delay(25); 206 } 207 if (adv->adv_enable) { 208 panic("%s: %s: enable not supported!", __func__, adv->adv_name); 209 #if 0 210 PUTRESETREG(AR7100_RESET_ENABLE, 211 GETRESETREG(AR7100_RESET_ENABLE) | adv->adv_enable); 212 #endif 213 } 214 return 0; 215 } 216 217 static const struct atheros_device ar7100_devices[] = { 218 { 219 .adv_name = "com", 220 .adv_addr = AR7100_UART_BASE, 221 .adv_size = 0x1000, 222 .adv_cirq = ARCHIP_CPU_IRQ_MISC, 223 .adv_mirq = AR7100_MISC_IRQ_UART0, 224 }, { 225 .adv_name = "arpci", 226 .adv_addr = AR7100_PCI_BASE, 227 .adv_size = 0x2000, 228 .adv_cirq = AR7100_CPU_IRQ_PCI, 229 .adv_mirq = -1, 230 .adv_reset = AR7100_RESETCTL_PCI_CORE_RESET, 231 }, { 232 .adv_name = "ohci", 233 .adv_addr = AR7100_OHCI_BASE, 234 .adv_size = 0x2000, 235 .adv_cirq = ARCHIP_CPU_IRQ_USB, 236 .adv_mirq = -1, 237 }, { 238 .adv_name = "ehci", 239 .adv_addr = AR7100_EHCI_BASE, 240 .adv_size = 0x2000, 241 .adv_cirq = ARCHIP_CPU_IRQ_USB, 242 .adv_mirq = -1, 243 }, { 244 .adv_name = "age", 245 .adv_addr = AR7100_GMAC0_BASE, 246 .adv_size = 0x2000, 247 .adv_cirq = ARCHIP_CPU_IRQ_GMAC0, 248 .adv_mirq = -1, 249 }, { 250 .adv_name = "age", 251 .adv_addr = AR7100_GMAC1_BASE, 252 .adv_size = 0x2000, 253 .adv_cirq = ARCHIP_CPU_IRQ_GMAC1, 254 .adv_mirq = -1, 255 }, { 256 .adv_name = NULL, 257 } 258 }; 259 260 const struct atheros_platformsw ar7100_platformsw = { 261 .apsw_intrsw = &atheros_intrsw, 262 .apsw_intr_init = ar7100_intr_init, 263 .apsw_cpu_intrnames = ar7100_cpu_intrnames, 264 .apsw_misc_intrnames = ar7100_misc_intrnames, 265 .apsw_cpu_nintrs = __arraycount(ar7100_cpu_intrnames), 266 .apsw_misc_nintrs = __arraycount(ar7100_misc_intrnames), 267 .apsw_cpuirq_misc = ARCHIP_CPU_IRQ_MISC, 268 .apsw_ipl_sr_map = &ar7100_ipl_sr_map, 269 270 .apsw_revision_id_addr = ARCHIP_RESET_BASE + ARCHIP_RESET_REVISION, 271 .apsw_uart0_base = AR7100_UART_BASE, 272 .apsw_misc_intstat = ARCHIP_RESET_BASE + ARCHIP_RESET_MISC_INTSTAT, 273 .apsw_misc_intmask = ARCHIP_RESET_BASE + ARCHIP_RESET_MISC_INTMASK, 274 275 /* 276 * CPU specific routines. 277 */ 278 .apsw_get_memsize = ar7100_get_memsize, 279 .apsw_wdog_reload = ar7100_wdog_reload, 280 .apsw_bus_init = ar7100_bus_init, 281 .apsw_reset = ar7100_reset, 282 283 .apsw_get_freqs = ar7100_get_freqs, 284 .apsw_device_register = ar7100_device_register, 285 .apsw_enable_device = ar7100_enable_device, 286 .apsw_devices = ar7100_devices, 287 }; 288