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/5a36fce2d7d8
branches:  trunk
changeset: 985595:5a36fce2d7d8
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 8c3c12518bdf -r 5a36fce2d7d8 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