Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add initial support for Apple M1.
details: https://anonhg.NetBSD.org/src/rev/d3f655d504fb
branches: trunk
changeset: 1023271:d3f655d504fb
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Aug 30 23:26:26 2021 +0000
description:
Add initial support for Apple M1.
Currently supported devices:
- Interrupt controller
- IOMMU
- PCIe (USB3 and ethernet)
- Reboot via watchdog
- Framebuffer console
diffstat:
sys/arch/arm/apple/apple_dart.c | 630 +++++++++++++++++++++++++++++++++++
sys/arch/arm/apple/apple_intc.c | 516 ++++++++++++++++++++++++++++
sys/arch/arm/apple/apple_pcie.c | 554 ++++++++++++++++++++++++++++++
sys/arch/arm/apple/apple_platform.c | 213 +++++++++++
sys/arch/arm/apple/apple_wdog.c | 119 ++++++
sys/arch/arm/apple/files.apple | 30 +
sys/arch/evbarm/conf/GENERIC64 | 12 +-
sys/arch/evbarm/conf/files.generic64 | 3 +-
8 files changed, 2074 insertions(+), 3 deletions(-)
diffs (truncated from 2170 to 300 lines):
diff -r 1e35364173ab -r d3f655d504fb sys/arch/arm/apple/apple_dart.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/apple/apple_dart.c Mon Aug 30 23:26:26 2021 +0000
@@ -0,0 +1,630 @@
+/* $NetBSD: apple_dart.c,v 1.1 2021/08/30 23:26:26 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2021 Mark Kettenis <kettenis%openbsd.org@localhost>
+ * Copyright (c) 2021 Jared McNeill <jmcneill%invisible.ca@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+//#define APPLE_DART_DEBUG
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: apple_dart.c,v 1.1 2021/08/30 23:26:26 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <sys/vmem.h>
+
+#include <arm/cpufunc.h>
+
+#include <dev/fdt/fdtvar.h>
+
+/*
+ * DT node to bus_dma tag mappings
+ */
+
+bus_dma_tag_t apple_dart_iommu_lookup(int);
+
+struct apple_dart_iommu {
+ int phandle;
+ bus_dma_tag_t dmat;
+ LIST_ENTRY(apple_dart_iommu) next;
+};
+
+static LIST_HEAD(, apple_dart_iommu) apple_dart_iommus =
+ LIST_HEAD_INITIALIZER(apple_dart_iommus);
+
+static void
+apple_dart_iommu_register(int phandle, bus_dma_tag_t dmat)
+{
+ struct apple_dart_iommu *iommu;
+
+ iommu = kmem_alloc(sizeof(*iommu), KM_SLEEP);
+ iommu->phandle = phandle;
+ iommu->dmat = dmat;
+ LIST_INSERT_HEAD(&apple_dart_iommus, iommu, next);
+}
+
+bus_dma_tag_t
+apple_dart_iommu_lookup(int phandle)
+{
+ struct apple_dart_iommu *iommu;
+
+ LIST_FOREACH(iommu, &apple_dart_iommus, next) {
+ if (iommu->phandle == phandle) {
+ return iommu->dmat;
+ }
+ }
+
+ panic("Couldn't find IOMMU for node 0x%x", phandle);
+}
+
+/*
+ * DART registers
+ */
+#define DART_TLB_OP 0x0020
+#define DART_TLB_OP_FLUSH __BIT(20)
+#define DART_TLB_OP_BUSY __BIT(2)
+#define DART_TLB_OP_SIDMASK 0x0034
+#define DART_ERR_STATUS 0x0040
+#define DART_ERR_ADDRL 0x0050
+#define DART_ERR_ADDRH 0x0054
+#define DART_CONFIG(sid) (0x0100 + (sid) * 0x4)
+#define DART_CONFIG_TXEN __BIT(7)
+#define DART_TTBR(sid, idx) (0x0200 + (sid) * 0x10 + (idx) * 0x4)
+#define DART_TTBR_VALID __BIT(31)
+#define DART_TTBR_SHIFT 12
+
+#define DART_APERTURE_START 0x00100000
+#define DART_APERTURE_SIZE 0x3fe00000
+#define DART_PAGE_SIZE 16384
+#define DART_PAGE_MASK (DART_PAGE_SIZE - 1)
+
+#define DART_L1_TABLE 0xb
+#define DART_L2_INVAL 0x0
+#define DART_L2_PAGE 0x3
+
+#define DART_ROUND_PAGE(pa) (((pa) + DART_PAGE_MASK) & ~DART_PAGE_MASK)
+#define DART_TRUNC_PAGE(pa) ((pa) & ~DART_PAGE_MASK)
+
+static const struct device_compatible_entry compat_data[] = {
+ { .compat = "apple,dart-m1", .value = 16 },
+ DEVICE_COMPAT_EOL
+};
+
+static struct arm32_dma_range apple_dart_dma_ranges[] = {
+ [0] = {
+ .dr_sysbase = 0,
+ .dr_busbase = 0,
+ .dr_len = UINTPTR_MAX,
+ .dr_flags = _BUS_DMAMAP_COHERENT,
+ }
+};
+
+struct apple_dart_map_state {
+ bus_addr_t ams_dva;
+ bus_size_t ams_len;
+};
+
+struct apple_dart_dma {
+ bus_dmamap_t dma_map;
+ bus_dma_segment_t dma_seg;
+ bus_size_t dma_size;
+ void *dma_kva;
+};
+
+#define DART_DMA_MAP(_dma) ((_dma)->dma_map)
+#define DART_DMA_LEN(_dma) ((_dma)->dma_size)
+#define DART_DMA_DVA(_dma) ((_dma)->dma_map->dm_segs[0].ds_addr)
+#define DART_DMA_KVA(_dma) ((_dma)->dma_kva)
+
+struct apple_dart_softc {
+ device_t sc_dev;
+ int sc_phandle;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ bus_dma_tag_t sc_dmat;
+
+ uint64_t sc_sid_mask;
+ u_int sc_nsid;
+
+ vmem_t *sc_dvamap;
+
+ struct apple_dart_dma *sc_l1;
+ struct apple_dart_dma **sc_l2;
+ u_int sc_nl2;
+
+ struct arm32_bus_dma_tag sc_bus_dmat;
+};
+
+#define DART_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define DART_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+static void
+apple_dart_flush_tlb(struct apple_dart_softc *sc)
+{
+ dsb(sy);
+ isb();
+
+ DART_WRITE(sc, DART_TLB_OP_SIDMASK, sc->sc_sid_mask);
+ DART_WRITE(sc, DART_TLB_OP, DART_TLB_OP_FLUSH);
+ while ((DART_READ(sc, DART_TLB_OP) & DART_TLB_OP_BUSY) != 0) {
+ __asm volatile ("yield" ::: "memory");
+ }
+}
+
+static struct apple_dart_dma *
+apple_dart_dma_alloc(bus_dma_tag_t dmat, bus_size_t size, bus_size_t align)
+{
+ struct apple_dart_dma *dma;
+ int nsegs, error;
+
+ dma = kmem_zalloc(sizeof(*dma), KM_SLEEP);
+ dma->dma_size = size;
+
+ error = bus_dmamem_alloc(dmat, size, align, 0, &dma->dma_seg, 1,
+ &nsegs, BUS_DMA_WAITOK);
+ if (error != 0) {
+ goto destroy;
+ }
+
+ error = bus_dmamem_map(dmat, &dma->dma_seg, nsegs, size,
+ &dma->dma_kva, BUS_DMA_WAITOK | BUS_DMA_NOCACHE);
+ if (error != 0) {
+ goto free;
+ }
+
+ error = bus_dmamap_create(dmat, size, 1, size, 0,
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &dma->dma_map);
+ if (error != 0) {
+ goto dmafree;
+ }
+
+ error = bus_dmamap_load(dmat, dma->dma_map, dma->dma_kva, size,
+ NULL, BUS_DMA_WAITOK);
+ if (error != 0) {
+ goto unmap;
+ }
+
+ memset(dma->dma_kva, 0, size);
+
+ return dma;
+
+destroy:
+ bus_dmamap_destroy(dmat, dma->dma_map);
+unmap:
+ bus_dmamem_unmap(dmat, dma->dma_kva, size);
+free:
+ bus_dmamem_free(dmat, &dma->dma_seg, 1);
+dmafree:
+ kmem_free(dma, sizeof(*dma));
+ return NULL;
+}
+
+static int
+apple_dart_intr(void *priv)
+{
+ struct apple_dart_softc * const sc = priv;
+ char fdt_path[128];
+ uint64_t addr;
+ uint32_t status;
+
+ status = DART_READ(sc, DART_ERR_STATUS);
+ addr = DART_READ(sc, DART_ERR_ADDRL);
+ addr |= (uint64_t)DART_READ(sc, DART_ERR_ADDRH) << 32;
+ DART_WRITE(sc, DART_ERR_STATUS, status);
+
+ fdtbus_get_path(sc->sc_phandle, fdt_path, sizeof(fdt_path));
+
+ printf("%s (%s): error addr 0x%016lx status 0x%08x\n",
+ device_xname(sc->sc_dev), fdt_path, addr, status);
+
+ return 1;
+}
+
+static volatile uint64_t *
+apple_dart_lookup_tte(struct apple_dart_softc *sc, bus_addr_t dva)
+{
+ int idx = dva / DART_PAGE_SIZE;
+ int l2_idx = idx / (DART_PAGE_SIZE / sizeof(uint64_t));
+ int tte_idx = idx % (DART_PAGE_SIZE / sizeof(uint64_t));
+ volatile uint64_t *l2;
+
+ l2 = DART_DMA_KVA(sc->sc_l2[l2_idx]);
+ return &l2[tte_idx];
+}
+
+static void
+apple_dart_unload_map(struct apple_dart_softc *sc, bus_dmamap_t map)
+{
+ struct apple_dart_map_state *ams = map->_dm_iommu;
+ volatile uint64_t *tte;
+ int seg;
+
+ /* For each segment */
+ for (seg = 0; seg < map->dm_nsegs; seg++) {
+ u_long len, dva;
+
+ if (ams[seg].ams_len == 0) {
+ continue;
+ }
+
+ dva = ams[seg].ams_dva;
+ len = ams[seg].ams_len;
+
+ while (len > 0) {
+ tte = apple_dart_lookup_tte(sc, dva);
+ *tte = DART_L2_INVAL;
+
+ dva += DART_PAGE_SIZE;
+ len -= DART_PAGE_SIZE;
+ }
+
+ vmem_xfree(sc->sc_dvamap, ams[seg].ams_dva, ams[seg].ams_len);
+
+ ams[seg].ams_dva = 0;
+ ams[seg].ams_len = 0;
+ }
+
+ apple_dart_flush_tlb(sc);
+}
+
+static int
+apple_dart_load_map(struct apple_dart_softc *sc, bus_dmamap_t map)
+{
+ struct apple_dart_map_state *ams = map->_dm_iommu;
+ volatile uint64_t *tte;
+ int seg, error;
+
Home |
Main Index |
Thread Index |
Old Index