1 /* $NetBSD: apple_platform.c,v 1.4 2021/09/13 23:30:52 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: apple_platform.c,v 1.4 2021/09/13 23:30:52 jmcneill Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/cpu.h> 35 #include <sys/device.h> 36 #include <sys/termios.h> 37 38 #include <dev/fdt/fdtvar.h> 39 #include <arm/fdt/arm_fdtvar.h> 40 41 #include <uvm/uvm_extern.h> 42 43 #include <machine/bootconfig.h> 44 45 #include <net/if_ether.h> 46 47 #include <dev/pci/pcivar.h> 48 #include <machine/pci_machdep.h> 49 50 #include <arm/cpufunc.h> 51 52 #include <arm/cortex/gtmr_var.h> 53 54 #include <arm/arm/psci.h> 55 #include <arm/fdt/psci_fdtvar.h> 56 57 #include <libfdt.h> 58 59 #include <arch/evbarm/fdt/platform.h> 60 61 extern struct bus_space arm_generic_bs_tag; 62 63 static struct bus_space apple_nonposted_bs_tag; 64 65 struct arm32_bus_dma_tag apple_coherent_dma_tag; 66 static struct arm32_dma_range apple_coherent_ranges[] = { 67 [0] = { 68 .dr_sysbase = 0, 69 .dr_busbase = 0, 70 .dr_len = UINTPTR_MAX, 71 .dr_flags = _BUS_DMAMAP_COHERENT, 72 } 73 }; 74 75 static int 76 apple_nonposted_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag, 77 bus_space_handle_t *bshp) 78 { 79 if (flag == 0) { 80 flag |= _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED; 81 } 82 83 return bus_space_map(&arm_generic_bs_tag, bpa, size, flag, bshp); 84 } 85 86 static void 87 apple_platform_bootstrap(void) 88 { 89 extern struct arm32_bus_dma_tag arm_generic_dma_tag; 90 91 apple_nonposted_bs_tag = arm_generic_bs_tag; 92 apple_nonposted_bs_tag.bs_map = apple_nonposted_bs_map; 93 94 apple_coherent_dma_tag = arm_generic_dma_tag; 95 apple_coherent_dma_tag._ranges = apple_coherent_ranges; 96 apple_coherent_dma_tag._nranges = __arraycount(apple_coherent_ranges); 97 98 arm_fdt_cpu_bootstrap(); 99 } 100 101 static void 102 apple_platform_init_attach_args(struct fdt_attach_args *faa) 103 { 104 faa->faa_bst = &apple_nonposted_bs_tag; 105 faa->faa_dmat = &apple_coherent_dma_tag; 106 } 107 108 static const struct pmap_devmap * 109 apple_platform_devmap(void) 110 { 111 /* Size this to hold possible entries for the UART and SMP spin-table */ 112 static struct pmap_devmap devmap[] = { 113 DEVMAP_ENTRY_END, 114 DEVMAP_ENTRY_END, 115 DEVMAP_ENTRY_END 116 }; 117 bus_addr_t uart_base; 118 vaddr_t devmap_va = KERNEL_IO_VBASE; 119 u_int devmap_index = 0; 120 uint64_t release_addr; 121 int phandle; 122 123 phandle = fdtbus_get_stdout_phandle(); 124 if (phandle > 0 && fdtbus_get_reg(phandle, 0, &uart_base, NULL) == 0) { 125 devmap[devmap_index].pd_pa = DEVMAP_ALIGN(uart_base); 126 devmap[devmap_index].pd_va = DEVMAP_ALIGN(devmap_va); 127 devmap[devmap_index].pd_size = DEVMAP_SIZE(L3_SIZE); 128 devmap[devmap_index].pd_prot = VM_PROT_READ | VM_PROT_WRITE; 129 devmap[devmap_index].pd_flags = PMAP_DEV_SO; 130 devmap_va = DEVMAP_SIZE(devmap[devmap_index].pd_va + 131 devmap[devmap_index].pd_size); 132 devmap_index++; 133 } 134 135 /* XXX hopefully all release addresses are in the same 2M */ 136 phandle = OF_finddevice("/cpus/cpu@1"); 137 if (phandle > 0 && 138 of_getprop_uint64(phandle, "cpu-release-addr", &release_addr) == 0) { 139 devmap[devmap_index].pd_pa = DEVMAP_ALIGN(release_addr); 140 devmap[devmap_index].pd_va = DEVMAP_ALIGN(devmap_va); 141 devmap[devmap_index].pd_size = DEVMAP_SIZE(L2_SIZE); 142 devmap[devmap_index].pd_prot = VM_PROT_READ | VM_PROT_WRITE; 143 devmap[devmap_index].pd_flags = PMAP_WRITE_BACK; 144 devmap_va = DEVMAP_SIZE(devmap[devmap_index].pd_va + 145 devmap[devmap_index].pd_size); 146 devmap_index++; 147 } 148 149 return devmap; 150 } 151 152 static u_int 153 arm_platform_uart_freq(void) 154 { 155 return 0; 156 } 157 158 static int 159 apple_platform_get_mac_address(pci_chipset_tag_t pc, pcitag_t tag, 160 uint8_t *eaddr) 161 { 162 int b, d, f; 163 int bridge, len; 164 u_int bdf; 165 166 const int pcie = of_find_bycompat(OF_finddevice("/"), "apple,pcie"); 167 if (pcie == -1) { 168 return -1; 169 } 170 171 /* Convert PCI tag to encoding of phys.hi for PCI-PCI bridge regs */ 172 pci_decompose_tag(pc, tag, &b, &d, &f); 173 bdf = (b << 16) | (d << 11) | (f << 8); 174 175 for (bridge = OF_child(pcie); bridge; bridge = OF_peer(bridge)) { 176 const int ethernet = 177 of_find_firstchild_byname(bridge, "ethernet"); 178 if (ethernet == -1) { 179 continue; 180 } 181 const u_int *data = fdtbus_get_prop(ethernet, "reg", &len); 182 if (data == NULL || len < 4) { 183 continue; 184 } 185 if (bdf != be32toh(data[0])) { 186 continue; 187 } 188 189 return OF_getprop(ethernet, "local-mac-address", 190 eaddr, ETHER_ADDR_LEN); 191 } 192 193 return -1; 194 } 195 196 static void 197 apple_platform_device_register(device_t self, void *aux) 198 { 199 prop_dictionary_t prop = device_properties(self); 200 uint8_t eaddr[ETHER_ADDR_LEN]; 201 int len; 202 203 if (device_is_a(self, "cpu")) { 204 struct fdt_attach_args * const faa = aux; 205 bus_addr_t cpuid; 206 207 if (fdtbus_get_reg(faa->faa_phandle, 0, &cpuid, NULL) != 0) { 208 cpuid = 0; 209 } 210 211 /* 212 * On Apple M1 (and hopefully later models), AFF2 is 0 for 213 * efficiency and 1 for performance cores. Use this value 214 * to provide a fake DMIPS/MHz value -- the actual number 215 * only matters in relation to the value presented by other 216 * cores. 217 */ 218 const u_int aff2 = __SHIFTOUT(cpuid, MPIDR_AFF2); 219 prop_dictionary_set_uint32(prop, "capacity_dmips_mhz", aff2); 220 return; 221 } 222 223 if (device_is_a(self, "bge") && 224 device_is_a(device_parent(self), "pci")) { 225 struct pci_attach_args * const pa = aux; 226 227 len = apple_platform_get_mac_address(pa->pa_pc, pa->pa_tag, 228 eaddr); 229 if (len == ETHER_ADDR_LEN) { 230 prop_dictionary_set_bool(prop, "without-seeprom", true); 231 prop_dictionary_set_data(prop, "mac-address", eaddr, 232 sizeof(eaddr)); 233 } 234 return; 235 } 236 } 237 238 static const struct arm_platform apple_arm_platform = { 239 .ap_devmap = apple_platform_devmap, 240 .ap_bootstrap = apple_platform_bootstrap, 241 .ap_init_attach_args = apple_platform_init_attach_args, 242 .ap_reset = psci_fdt_reset, 243 .ap_delay = gtmr_delay, 244 .ap_uart_freq = arm_platform_uart_freq, 245 .ap_device_register = apple_platform_device_register, 246 .ap_mpstart = arm_fdt_cpu_mpstart, 247 }; 248 249 ARM_PLATFORM(apple_arm, "apple,arm-platform", &apple_arm_platform); 250