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