Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/apple Sync with OpenBSD



details:   https://anonhg.NetBSD.org/src/rev/563925ea9b34
branches:  trunk
changeset: 365828:563925ea9b34
user:      skrll <skrll%NetBSD.org@localhost>
date:      Wed Apr 27 08:03:06 2022 +0000

description:
Sync with OpenBSD

- port initialisation and device power up. Latter requires the SMC
  GPIO controller which is WIP.

While here
- improve the MSI vector search algorithm; and
- spinkle some BITS(3)

diffstat:

 sys/arch/arm/apple/apple_pcie.c |  360 +++++++++++++++++++++++++++++++--------
 1 files changed, 287 insertions(+), 73 deletions(-)

diffs (truncated from 497 to 300 lines):

diff -r 58578a37c669 -r 563925ea9b34 sys/arch/arm/apple/apple_pcie.c
--- a/sys/arch/arm/apple/apple_pcie.c   Wed Apr 27 07:59:18 2022 +0000
+++ b/sys/arch/arm/apple/apple_pcie.c   Wed Apr 27 08:03:06 2022 +0000
@@ -1,4 +1,5 @@
-/* $NetBSD: apple_pcie.c,v 1.5 2021/09/14 01:33:19 jmcneill Exp $ */
+/* $NetBSD: apple_pcie.c,v 1.6 2022/04/27 08:03:06 skrll Exp $ */
+/*     $OpenBSD: aplpcie.c,v 1.13 2022/04/06 18:59:26 naddy Exp $      */
 
 /*-
  * Copyright (c) 2021 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -26,8 +27,25 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * Copyright (c) 2021 Mark Kettenis <kettenis%openbsd.org@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.
+ */
+
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: apple_pcie.c,v 1.5 2021/09/14 01:33:19 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: apple_pcie.c,v 1.6 2022/04/27 08:03:06 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -46,17 +64,44 @@
 #include <arm/pci/pci_msi_machdep.h>
 #include <arm/fdt/pcihost_fdtvar.h>
 
-#define        PCIE_MSI_CTRL           0x0124
-#define         PCIE_MSI_CTRL_EN       (1U << 0)
-#define         PCIE_MSI_CTRL_32       (5U << 4)
-#define        PCIE_MSI_REMAP          0x0128
-#define        PCIE_MSI_DOORBELL       0x0168
+#define PCIE_CORE_LANE_CONF(port)      (0x84000 + (port) * 0x4000)
+#define  PCIE_CORE_LANE_CONF_REFCLK0REQ        __BIT(0)
+#define  PCIE_CORE_LANE_CONF_REFCLK1REQ        __BIT(1)
+#define  PCIE_CORE_LANE_CONF_REFCLK0ACK        __BIT(2)
+#define  PCIE_CORE_LANE_CONF_REFCLK1ACK        __BIT(3)
+#define  PCIE_CORE_LANE_CONF_REFCLK0EN __BIT(9)
+#define  PCIE_CORE_LANE_CONF_REFCLK1EN __BIT(10)
+#define PCIE_CORE_LANE_CTRL(port)      (0x84004 + (port) * 0x4000)
+#define  PCIE_CORE_LANE_CTRL_CFGACC    __BIT(15)
+
+#define PCIE_PORT_LTSSM_CTRL           0x0080
+#define  PCIE_PORT_LTSSM_CTRL_START    __BIT(0)
+#define        PCIE_PORT_MSI_CTRL              0x0124
+#define         PCIE_PORT_MSI_CTRL_EN          __BIT(0)
+#define         PCIE_PORT_MSI_CTRL_32          __SHIFTIN(5U, __BITS(7,4))
+#define        PCIE_PORT_MSI_REMAP             0x0128
+#define        PCIE_PORT_MSI_DOORBELL          0x0168
+#define PCIE_PORT_LINK_STAT            0x0208
+#define  PCIE_PORT_LINK_STAT_UP                __BIT(0)
+#define PCIE_PORT_APPCLK               0x0800
+#define  PCIE_PORT_APPCLK_EN           __BIT(0)
+#define  PCIE_PORT_APPCLK_CGDIS                __BIT(8)
+#define PCIE_PORT_STAT                 0x0804
+#define  PCIE_PORT_STAT_READY          __BIT(0)
+#define PCIE_PORT_REFCLK               0x0810
+#define  PCIE_PORT_REFCLK_EN           __BIT(0)
+#define  PCIE_PORT_REFCLK_CGDIS                __BIT(8)
+#define PCIE_PORT_PERST                        0x0814
+#define  PCIE_PORT_PERST_DIS           __BIT(0)
 
 extern struct bus_space arm_generic_bs_tag;
 
 struct apple_pcie_softc {
        struct pcihost_softc    sc_pcihost;
 
+       bus_space_tag_t         sc_rc_bst;
+       bus_space_handle_t      sc_rc_bsh;
+
        int                     sc_phandle;
        struct arm_pci_msi      sc_msi;
        u_int                   sc_msi_start;
@@ -81,6 +126,176 @@
        DEVICE_COMPAT_EOL
 };
 
+#define RREAD4(sc, reg)                                                \
+    (bus_space_read_4((sc)->sc_rc_bst, (sc)->sc_rc_bsh, (reg)))
+#define RWRITE4(sc, reg, val)                                  \
+    bus_space_write_4((sc)->sc_rc_bst, (sc)->sc_rc_bsh, (reg), (val))
+#define RSET4(sc, reg, bits)                           \
+    RWRITE4((sc), (reg), RREAD4((sc), (reg)) | (bits))
+#define RCLR4(sc, reg, bits)                           \
+    RWRITE4((sc), (reg), RREAD4((sc), (reg)) & ~(bits))
+
+
+static void
+apple_pcie_setup_port(struct apple_pcie_softc *sc, int phandle)
+{
+       const bus_space_tag_t bst = sc->sc_pcihost.sc_bst;
+       const device_t dev = sc->sc_pcihost.sc_dev;
+       const int parent = sc->sc_pcihost.sc_phandle;
+       char regname[sizeof("portX")];
+       bus_space_handle_t bsh;
+       bus_addr_t addr;
+       bus_size_t size;
+       int error;
+       int timo;
+       int len;
+
+       const u_int *reg = fdtbus_get_prop(phandle, "reg", &len);
+       if (len != 5 * sizeof(uint32_t)) {
+               aprint_error(": couldn't get port number\n");
+       }
+
+       u_int portno = __SHIFTOUT(be32toh(reg[0]), __BITS(13,11));
+       snprintf(regname, sizeof(regname), "port%u", portno);
+
+       if (fdtbus_get_reg_byname(parent, regname, &addr, &size) != 0) {
+               aprint_error(": couldn't get %s regs\n", regname);
+               return;
+       }
+       error = bus_space_map(bst, addr, size, 0, &bsh);
+       if (error != 0) {
+               aprint_error(": couldn't map %s regs\n", regname);
+               return;
+       }
+
+#define PREAD4(bst, bsh, reg)                                  \
+    bus_space_read_4((bst), (bsh), (reg))
+#define PWRITE4(bst, bsh, reg, val)                            \
+    bus_space_write_4((bst), (bsh), (reg), (val))
+#define PSET4(bst, bsh, reg, bits)                             \
+    PWRITE4((bst), (bsh), (reg), PREAD4((bst), (bsh), (reg)) | (bits))
+#define PCLR4(bst, bsh, reg, bits)                             \
+    PWRITE4((bst), (bsh), (reg), PREAD4((bst), (bsh), (reg)) & ~(bits))
+
+       /* Doorbell address must be below 4GB */
+       KASSERT((sc->sc_msi_addr & ~0xffffffffUL) == 0);
+
+       int pwren_gpiolen, reset_gpiolen;
+
+       pwren_gpiolen = OF_getproplen(phandle, "pwren-gpios");
+       reset_gpiolen = OF_getproplen(phandle, "reset-gpios");
+       if (reset_gpiolen <= 0)
+               return;
+
+       /*
+        * Set things up such that we can share the 32 available MSIs
+        * across all ports.
+        */
+       PWRITE4(bst, bsh, PCIE_PORT_MSI_CTRL,
+           PCIE_PORT_MSI_CTRL_32 | PCIE_PORT_MSI_CTRL_EN);
+       PWRITE4(bst, bsh, PCIE_PORT_MSI_REMAP, 0);
+       PWRITE4(bst, bsh, PCIE_PORT_MSI_DOORBELL,
+           __SHIFTOUT(sc->sc_msi_addr, __BITS(31, 0)));
+
+       /* Check if the link is already up. */
+       uint32_t stat = PREAD4(bst, bsh, PCIE_PORT_LINK_STAT);
+       if (stat & PCIE_PORT_LINK_STAT_UP) {
+               aprint_debug_dev(dev, "link already up\n");
+               return;
+       }
+       aprint_debug_dev(dev, "bringing link up\n");
+
+       PSET4(bst, bsh, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_EN);
+
+       struct fdtbus_gpio_pin *gpio_reset = fdtbus_gpio_acquire(phandle,
+           "reset-gpios", GPIO_PIN_OUTPUT);
+
+        if (gpio_reset == NULL) {
+               aprint_debug_dev(dev, "failed to get reset-gpios\n");
+               return;
+       }
+
+       fdtbus_gpio_write(gpio_reset, 1);
+
+       /* Power up the device if necessary. */
+       if (pwren_gpiolen > 0) {
+               struct fdtbus_gpio_pin *gpio_pwren = fdtbus_gpio_acquire(phandle,
+                   "pwren-gpios", GPIO_PIN_OUTPUT);
+
+               if (gpio_pwren == NULL) {
+                       aprint_debug_dev(dev, "failed to get pwren-gpios\n");
+                       return;
+               }
+
+               fdtbus_gpio_write(gpio_pwren, 1);
+       }
+
+       /* Setup Refclk. */
+       RSET4(sc, PCIE_CORE_LANE_CTRL(portno), PCIE_CORE_LANE_CTRL_CFGACC);
+       RSET4(sc, PCIE_CORE_LANE_CONF(portno), PCIE_CORE_LANE_CONF_REFCLK0REQ);
+       for (timo = 500; timo > 0; timo--) {
+               stat = RREAD4(sc, PCIE_CORE_LANE_CONF(portno));
+               if (stat & PCIE_CORE_LANE_CONF_REFCLK0ACK)
+                       break;
+               delay(100);
+       }
+       RSET4(sc, PCIE_CORE_LANE_CONF(portno), PCIE_CORE_LANE_CONF_REFCLK1REQ);
+       for (timo = 500; timo > 0; timo--) {
+               stat = RREAD4(sc, PCIE_CORE_LANE_CONF(portno));
+               if (stat & PCIE_CORE_LANE_CONF_REFCLK1ACK)
+                       break;
+               delay(100);
+       }
+       RCLR4(sc, PCIE_CORE_LANE_CTRL(portno), PCIE_CORE_LANE_CTRL_CFGACC);
+       RSET4(sc, PCIE_CORE_LANE_CONF(portno),
+           PCIE_CORE_LANE_CONF_REFCLK0EN | PCIE_CORE_LANE_CONF_REFCLK1EN);
+       PSET4(bst, bsh, PCIE_PORT_REFCLK, PCIE_PORT_REFCLK_EN);
+
+       /*
+        * PERST# must remain asserted for at least 100us after the
+        * reference clock becomes stable.  But also has to remain
+        * active at least 100ms after power up.
+        */
+       if (pwren_gpiolen > 0)
+               delay(100000);
+       else
+               delay(100);
+
+       /* Deassert PERST#. */
+       PSET4(bst, bsh, PCIE_PORT_PERST, PCIE_PORT_PERST_DIS);
+       fdtbus_gpio_write(gpio_reset, 0);
+
+       for (timo = 2500; timo > 0; timo--) {
+               stat = PREAD4(bst, bsh, PCIE_PORT_STAT);
+               if (stat & PCIE_PORT_STAT_READY)
+                       break;
+               delay(100);
+       }
+       if ((stat & PCIE_PORT_STAT_READY) == 0) {
+               aprint_debug_dev(dev, "link up\n");
+               return;
+       }
+
+       PCLR4(bst, bsh, PCIE_PORT_REFCLK, PCIE_PORT_REFCLK_CGDIS);
+       PCLR4(bst, bsh, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_CGDIS);
+
+       /* Bring up the link. */
+       PWRITE4(bst, bsh, PCIE_PORT_LTSSM_CTRL, PCIE_PORT_LTSSM_CTRL_START);
+       for (timo = 1000; timo > 0; timo--) {
+               stat = PREAD4(bst, bsh, PCIE_PORT_LINK_STAT);
+               if (stat & PCIE_PORT_LINK_STAT_UP)
+                       break;
+               delay(100);
+       }
+
+#undef PREAD4
+#undef PWRITE4
+#undef PCLR4
+#undef PSET4
+
+       bus_space_unmap(bst, bsh, size);
+}
+
 static int
 apple_pcie_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -96,18 +311,23 @@
        struct pcihost_softc * const sc = &asc->sc_pcihost;
        struct fdt_attach_args * const faa = aux;
        const int phandle = faa->faa_phandle;
-       bus_addr_t cs_addr;
-       bus_size_t cs_size;
+       bus_addr_t cs_addr, rc_addr;
+       bus_size_t cs_size, rc_size;
        int error;
 
-       if (fdtbus_get_reg(phandle, 0, &cs_addr, &cs_size) != 0) {
-               aprint_error(": couldn't get registers\n");
+       if (fdtbus_get_reg_byname(phandle, "config", &cs_addr, &cs_size) != 0) {
+               aprint_error(": couldn't get registers (%s)\n", "config");
+               return;
+       }
+
+       if (fdtbus_get_reg_byname(phandle, "rc", &rc_addr, &rc_size) != 0) {
+               aprint_error(": couldn't get registers (%s)\n", "rc");
                return;
        }
 
        sc->sc_dev = self;
        sc->sc_dmat = faa->faa_dmat;
-       sc->sc_bst = faa->faa_bst;
+       sc->sc_bst = asc->sc_rc_bst = faa->faa_bst;
        /*
         * Create a new bus tag for PCIe devices that does not inherit the
         * nonposted MMIO flag from the host controller.
@@ -116,7 +336,15 @@
        sc->sc_phandle = phandle;
        error = bus_space_map(faa->faa_bst, cs_addr, cs_size, 0, &sc->sc_bsh);
        if (error) {
-               aprint_error(": couldn't map registers: %d\n", error);
+               aprint_error(": couldn't map registers (%s): %d\n", "config",
+                   error);



Home | Main Index | Thread Index | Old Index