From owner-dev-commits-src-branches@freebsd.org Tue Sep 7 12:09:43 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 097D0662431; Tue, 7 Sep 2021 12:09:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4H3kbV5YP4z4rrL; Tue, 7 Sep 2021 12:09:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 432F5123A3; Tue, 7 Sep 2021 12:09:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 187C9g5M087252; Tue, 7 Sep 2021 12:09:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 187C9g8s087251; Tue, 7 Sep 2021 12:09:42 GMT (envelope-from git) Date: Tue, 7 Sep 2021 12:09:42 GMT Message-Id: <202109071209.187C9g8s087251@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Jessica Clarke Subject: git: 15a5871387ca - stable/13 - pci_dw: Support modern "unroll" iATU mode MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jrtc27 X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 15a5871387caeaba7303c47a899b984ac49d4a90 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Sep 2021 12:09:43 -0000 The branch stable/13 has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=15a5871387caeaba7303c47a899b984ac49d4a90 commit 15a5871387caeaba7303c47a899b984ac49d4a90 Author: Jessica Clarke AuthorDate: 2021-07-21 04:50:50 +0000 Commit: Jessica Clarke CommitDate: 2021-09-07 12:06:48 +0000 pci_dw: Support modern "unroll" iATU mode This supersedes the old legacy mode where a viewport register was used to mux multiple regions behind a single set of registers, and is used on the SiFive FU740. Reviewed by: mmel MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D31029 (cherry picked from commit f240dfff229d1f1ff502f59901ef2b9364ca55d9) --- sys/dev/pci/pci_dw.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++-- sys/dev/pci/pci_dw.h | 18 ++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/sys/dev/pci/pci_dw.c b/sys/dev/pci/pci_dw.c index e4211a70a80b..525c5fcf9cd5 100644 --- a/sys/dev/pci/pci_dw.c +++ b/sys/dev/pci/pci_dw.c @@ -73,6 +73,11 @@ __FBSDID("$FreeBSD$"); #define DBI_RD2(sc, reg) pci_dw_dbi_rd2((sc)->dev, reg) #define DBI_RD4(sc, reg) pci_dw_dbi_rd4((sc)->dev, reg) +#define IATU_UR_WR4(sc, reg, val) \ + bus_write_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg), (val)) +#define IATU_UR_RD4(sc, reg) \ + bus_read_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg)) + #define PCI_BUS_SHIFT 20 #define PCI_SLOT_SHIFT 15 #define PCI_FUNC_SHIFT 12 @@ -168,9 +173,52 @@ pci_dw_check_dev(struct pci_dw_softc *sc, u_int bus, u_int slot, u_int func, return (true); } -/* Map one uoutbound ATU region */ +static bool +pci_dw_detect_atu_unroll(struct pci_dw_softc *sc) +{ + return (DBI_RD4(sc, DW_IATU_VIEWPORT) == 0xFFFFFFFFU); +} + static int -pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type, +pci_dw_map_out_atu_unroll(struct pci_dw_softc *sc, int idx, int type, + uint64_t pa, uint64_t pci_addr, uint32_t size) +{ + uint32_t reg; + int i; + + if (size == 0) + return (0); + + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_BASE_ADDR), + pa & 0xFFFFFFFF); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_BASE_ADDR), + (pa >> 32) & 0xFFFFFFFF); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LIMIT_ADDR), + (pa + size - 1) & 0xFFFFFFFF); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_TARGET_ADDR), + pci_addr & 0xFFFFFFFF); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_TARGET_ADDR), + (pci_addr >> 32) & 0xFFFFFFFF); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL1), + IATU_CTRL1_TYPE(type)); + IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL2), + IATU_CTRL2_REGION_EN); + + /* Wait until setup becomes valid */ + for (i = 10; i > 0; i--) { + reg = IATU_UR_RD4(sc, DW_IATU_UR_REG(idx, CTRL2)); + if (reg & IATU_CTRL2_REGION_EN) + return (0); + DELAY(5); + } + + device_printf(sc->dev, + "Cannot map outbound region %d in unroll mode iATU\n", idx); + return (ETIMEDOUT); +} + +static int +pci_dw_map_out_atu_legacy(struct pci_dw_softc *sc, int idx, int type, uint64_t pa, uint64_t pci_addr, uint32_t size) { uint32_t reg; @@ -195,11 +243,25 @@ pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type, return (0); DELAY(5); } + device_printf(sc->dev, - "Cannot map outbound region(%d) in iATU\n", idx); + "Cannot map outbound region %d in legacy mode iATU\n", idx); return (ETIMEDOUT); } +/* Map one outbound ATU region */ +static int +pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type, + uint64_t pa, uint64_t pci_addr, uint32_t size) +{ + if (sc->iatu_ur_res) + return (pci_dw_map_out_atu_unroll(sc, idx, type, pa, + pci_addr, size)); + else + return (pci_dw_map_out_atu_legacy(sc, idx, type, pa, + pci_addr, size)); +} + static int pci_dw_setup_hw(struct pci_dw_softc *sc) { @@ -580,6 +642,7 @@ pci_dw_init(device_t dev) { struct pci_dw_softc *sc; int rv, rid; + bool unroll_mode; sc = device_get_softc(dev); sc->dev = dev; @@ -660,6 +723,36 @@ pci_dw_init(device_t dev) if (rv != 0) goto out; + unroll_mode = pci_dw_detect_atu_unroll(sc); + if (bootverbose) + device_printf(dev, "Using iATU %s mode\n", + unroll_mode ? "unroll" : "legacy"); + if (unroll_mode) { + rid = 0; + rv = ofw_bus_find_string_index(sc->node, "reg-names", "atu", &rid); + if (rv == 0) { + sc->iatu_ur_res = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->iatu_ur_res == NULL) { + device_printf(dev, + "Cannot allocate iATU space (rid: %d)\n", + rid); + rv = ENXIO; + goto out; + } + sc->iatu_ur_offset = 0; + sc->iatu_ur_size = rman_get_size(sc->iatu_ur_res); + } else if (rv == ENOENT) { + sc->iatu_ur_res = sc->dbi_res; + sc->iatu_ur_offset = DW_DEFAULT_IATU_UR_DBI_OFFSET; + sc->iatu_ur_size = DW_DEFAULT_IATU_UR_DBI_SIZE; + } else { + device_printf(dev, "Cannot get iATU space memory\n"); + rv = ENXIO; + goto out; + } + } + rv = pci_dw_setup_hw(sc); if (rv != 0) goto out; diff --git a/sys/dev/pci/pci_dw.h b/sys/dev/pci/pci_dw.h index c2c9249449bb..51c4169f74d2 100644 --- a/sys/dev/pci/pci_dw.h +++ b/sys/dev/pci/pci_dw.h @@ -63,6 +63,7 @@ #define DW_MISC_CONTROL_1 0x8BC #define DBI_RO_WR_EN (1 << 0) +/* Legacy (pre-4.80) iATU mode */ #define DW_IATU_VIEWPORT 0x900 #define IATU_REGION_INBOUND (1U << 31) #define IATU_REGION_INDEX(x) ((x) & 0x7) @@ -80,6 +81,20 @@ #define DW_IATU_LWR_TARGET_ADDR 0x918 #define DW_IATU_UPPER_TARGET_ADDR 0x91C +/* Modern (4.80+) "unroll" iATU mode */ +#define DW_IATU_UR_STEP 0x200 +#define DW_IATU_UR_REG(r, n) (r) * DW_IATU_UR_STEP + IATU_UR_##n +#define IATU_UR_CTRL1 0x00 +#define IATU_UR_CTRL2 0x04 +#define IATU_UR_LWR_BASE_ADDR 0x08 +#define IATU_UR_UPPER_BASE_ADDR 0x0C +#define IATU_UR_LIMIT_ADDR 0x10 +#define IATU_UR_LWR_TARGET_ADDR 0x14 +#define IATU_UR_UPPER_TARGET_ADDR 0x18 + +#define DW_DEFAULT_IATU_UR_DBI_OFFSET 0x300000 +#define DW_DEFAULT_IATU_UR_DBI_SIZE 0x1000 + struct pci_dw_softc { struct ofw_pci_softc ofw_pci; /* Must be first */ @@ -101,6 +116,9 @@ struct pci_dw_softc { int num_lanes; int num_viewport; + struct resource *iatu_ur_res; /* NB: May be dbi_res */ + bus_addr_t iatu_ur_offset; + bus_size_t iatu_ur_size; bus_addr_t cfg_pa; /* PA of config memoty */ bus_size_t cfg_size; /* size of config region */