Add support for BCM4378 as implemented on the Apple M1. This chip seems
authorpatrick <patrick@openbsd.org>
Fri, 26 Feb 2021 12:28:45 +0000 (12:28 +0000)
committerpatrick <patrick@openbsd.org>
Fri, 26 Feb 2021 12:28:45 +0000 (12:28 +0000)
to use a different set of PCIE2REG registers.  Accessing the "old" ones
even leads to faults.  There are two surprises though.  One is that it
seems that the interrupt status register always returns 0, and the other
one is that we receive the interrupts way too early, but both can be
worked around for now.

sys/dev/pci/if_bwfm_pci.c
sys/dev/pci/if_bwfm_pci.h

index 27d53b3..4aed671 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bwfm_pci.c,v 1.48 2021/02/26 11:22:10 patrick Exp $        */
+/*     $OpenBSD: if_bwfm_pci.c,v 1.49 2021/02/26 12:28:45 patrick Exp $        */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -200,6 +200,8 @@ int          bwfm_pci_detach(struct device *, int);
 int             bwfm_pci_intr(void *);
 void            bwfm_pci_intr_enable(struct bwfm_pci_softc *);
 void            bwfm_pci_intr_disable(struct bwfm_pci_softc *);
+uint32_t        bwfm_pci_intr_status(struct bwfm_pci_softc *);
+void            bwfm_pci_intr_ack(struct bwfm_pci_softc *, uint32_t);
 void            bwfm_pci_hostready(struct bwfm_pci_softc *);
 int             bwfm_pci_load_microcode(struct bwfm_pci_softc *, const u_char *,
                    size_t, const u_char *, size_t);
@@ -1067,8 +1069,14 @@ void
 bwfm_pci_ring_bell(struct bwfm_pci_softc *sc,
     struct bwfm_pci_msgring *ring)
 {
-       bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_H2D_MAILBOX_0, 1);
+       struct bwfm_softc *bwfm = (void *)sc;
+
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_0, 1);
+       else
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_H2D_MAILBOX_0, 1);
 }
 
 void
@@ -1516,11 +1524,9 @@ bwfm_pci_buscore_reset(struct bwfm_softc *bwfm)
                }
        }
 
-       reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_MAILBOXINT);
+       reg = bwfm_pci_intr_status(sc);
        if (reg != 0xffffffff)
-               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-                   BWFM_PCI_PCIE2REG_MAILBOXINT, reg);
+               bwfm_pci_intr_ack(sc, reg);
 
        return 0;
 }
@@ -1884,23 +1890,34 @@ int
 bwfm_pci_intr(void *v)
 {
        struct bwfm_pci_softc *sc = (void *)v;
+       struct bwfm_softc *bwfm = (void *)sc;
        struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
        struct mbuf_list ml = MBUF_LIST_INITIALIZER();
-       uint32_t status;
+       uint32_t status, mask;
 
-       if ((status = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_MAILBOXINT)) == 0)
+       if (!sc->sc_initialized)
+               return 0;
+
+       status = bwfm_pci_intr_status(sc);
+       /* FIXME: interrupt status seems to be zero? */
+       if (status == 0 && bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               status |= BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB;
+       if (status == 0)
                return 0;
 
        bwfm_pci_intr_disable(sc);
-       bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_MAILBOXINT, status);
+       bwfm_pci_intr_ack(sc, status);
 
-       if (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
-           BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1))
+       if (bwfm->sc_chip.ch_chip != BRCM_CC_4378_CHIP_ID &&
+           (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
+           BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1)))
                printf("%s: handle MB data\n", __func__);
 
-       if (status & BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB) {
+       mask = BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB;
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               mask = BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB;
+
+       if (status & mask) {
                bwfm_pci_ring_rx(sc, &sc->sc_rx_complete, &ml);
                bwfm_pci_ring_rx(sc, &sc->sc_tx_complete, &ml);
                bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete, &ml);
@@ -1920,28 +1937,73 @@ bwfm_pci_intr(void *v)
 void
 bwfm_pci_intr_enable(struct bwfm_pci_softc *sc)
 {
-       bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_MAILBOXMASK,
-           BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
-           BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 |
-           BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB);
+       struct bwfm_softc *bwfm = (void *)sc;
+
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_MAILBOXMASK,
+                   BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB);
+       else
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_MAILBOXMASK,
+                   BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
+                   BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 |
+                   BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB);
 }
 
 void
 bwfm_pci_intr_disable(struct bwfm_pci_softc *sc)
 {
-       bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_MAILBOXMASK, 0);
+       struct bwfm_softc *bwfm = (void *)sc;
+
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_MAILBOXMASK, 0);
+       else
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_MAILBOXMASK, 0);
+}
+
+uint32_t
+bwfm_pci_intr_status(struct bwfm_pci_softc *sc)
+{
+       struct bwfm_softc *bwfm = (void *)sc;
+
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_MAILBOXINT);
+       else
+               return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_MAILBOXINT);
+}
+
+void
+bwfm_pci_intr_ack(struct bwfm_pci_softc *sc, uint32_t status)
+{
+       struct bwfm_softc *bwfm = (void *)sc;
+
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_MAILBOXINT, status);
+       else
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_MAILBOXINT, status);
 }
 
 void
 bwfm_pci_hostready(struct bwfm_pci_softc *sc)
 {
+       struct bwfm_softc *bwfm = (void *)sc;
+
        if ((sc->sc_shared_flags & BWFM_SHARED_INFO_HOSTRDY_DB1) == 0)
                return;
 
-       bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
-           BWFM_PCI_PCIE2REG_H2D_MAILBOX_1, 1);
+       if (bwfm->sc_chip.ch_chip == BRCM_CC_4378_CHIP_ID)
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_1, 1);
+       else
+               bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
+                   BWFM_PCI_PCIE2REG_H2D_MAILBOX_1, 1);
 }
 
 /* Msgbuf protocol implementation */
index 0e42df6..d045ca8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bwfm_pci.h,v 1.5 2021/02/26 00:19:41 patrick Exp $ */
+/*     $OpenBSD: if_bwfm_pci.h,v 1.6 2021/02/26 12:28:46 patrick Exp $ */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
                 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H2_DB1 |   \
                 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H3_DB0 |   \
                 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H3_DB1)
-
 #define BWFM_PCI_PCIE2REG_CONFIGADDR           0x120
 #define BWFM_PCI_PCIE2REG_CONFIGDATA           0x124
 #define BWFM_PCI_PCIE2REG_H2D_MAILBOX_0                0x140
 #define BWFM_PCI_PCIE2REG_H2D_MAILBOX_1                0x144
 
+#define BWFM_PCI_64_PCIE2REG_INTMASK           0xC14
+#define BWFM_PCI_64_PCIE2REG_MAILBOXINT                0xC30
+#define BWFM_PCI_64_PCIE2REG_MAILBOXMASK       0xC34
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H0_DB0 1
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H0_DB1 2
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H1_DB0 4
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H1_DB1 8
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H2_DB0 0x10
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H2_DB1 0x20
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H3_DB0 0x40
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H3_DB1 0x80
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H4_DB0 0x100
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H4_DB1 0x200
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H5_DB0 0x400
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H5_DB1 0x800
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H6_DB0 0x1000
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H6_DB1 0x2000
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H7_DB0 0x4000
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H7_DB1 0x8000
+#define  BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB                   \
+               (BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H0_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H0_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H1_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H1_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H2_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H2_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H3_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H3_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H4_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H4_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H5_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H5_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H6_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H6_DB1 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H7_DB0 |        \
+                BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H7_DB1)
+#define BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_0     0xA20
+#define BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_1     0xA24
+
 #define BWFM_PCI_CFGREG_STATUS_CMD             0x004
 #define BWFM_PCI_CFGREG_PM_CSR                 0x04C
 #define BWFM_PCI_CFGREG_MSI_CAP                        0x058