Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/nvidia Add PCI Extended Configuration support f...
details: https://anonhg.NetBSD.org/src/rev/392d53043d46
branches: trunk
changeset: 341687:392d53043d46
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Tue Nov 17 22:01:39 2015 +0000
description:
Add PCI Extended Configuration support for tegrapcie(4).
Similar to the acpimcfg code, this only maps the extended configuration
space into KVA for known busses.
diffstat:
sys/arch/arm/nvidia/tegra_pcie.c | 87 ++++++++++++++++++++++++++++++++++-----
1 files changed, 75 insertions(+), 12 deletions(-)
diffs (177 lines):
diff -r f51375619534 -r 392d53043d46 sys/arch/arm/nvidia/tegra_pcie.c
--- a/sys/arch/arm/nvidia/tegra_pcie.c Tue Nov 17 20:19:55 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_pcie.c Tue Nov 17 22:01:39 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_pcie.c,v 1.11 2015/11/17 00:08:33 jakllsch Exp $ */
+/* $NetBSD: tegra_pcie.c,v 1.12 2015/11/17 22:01:39 jakllsch Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include "locators.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.11 2015/11/17 00:08:33 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.12 2015/11/17 22:01:39 jakllsch Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -55,6 +55,9 @@
static int tegra_pcie_match(device_t, cfdata_t, void *);
static void tegra_pcie_attach(device_t, device_t, void *);
+#define TEGRA_PCIE_NBUS 256
+#define TEGRA_PCIE_ECFB (1<<(12 - 8)) /* extended conf frags per bus */
+
struct tegra_pcie_ih {
int (*ih_callback)(void *);
void *ih_arg;
@@ -68,7 +71,6 @@
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh_afi;
bus_space_handle_t sc_bsh_rpconf;
- bus_space_handle_t sc_bsh_conf;
int sc_intr;
struct arm32_pci_chipset sc_pc;
@@ -79,12 +81,18 @@
TAILQ_HEAD(, tegra_pcie_ih) sc_intrs;
u_int sc_intrgen;
+
+ bus_space_handle_t sc_bsh_extc[TEGRA_PCIE_NBUS-1][TEGRA_PCIE_ECFB];
};
static int tegra_pcie_intr(void *);
static void tegra_pcie_init(pci_chipset_tag_t, void *);
static void tegra_pcie_enable(struct tegra_pcie_softc *);
static void tegra_pcie_setup(struct tegra_pcie_softc * const);
+static void tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const,
+ uint, uint);
+static void tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const, uint);
+static void tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const);
static void tegra_pcie_attach_hook(device_t, device_t,
struct pcibus_attach_args *);
@@ -138,9 +146,7 @@
if (bus_space_map(sc->sc_bst, TEGRA_PCIE_RPCONF_BASE,
TEGRA_PCIE_RPCONF_SIZE, 0, &sc->sc_bsh_rpconf) != 0)
panic("couldn't map PCIE root ports");
- if (bus_space_map(sc->sc_bst, TEGRA_PCIE_CONF_BASE,
- TEGRA_PCIE_CONF_SIZE, 0, &sc->sc_bsh_conf) != 0)
- panic("couldn't map PCIE configuration");
+ tegra_pcie_conf_map_buses(sc);
TAILQ_INIT(&sc->sc_intrs);
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
@@ -339,6 +345,51 @@
AFI_INTR_MASK_REG, AFI_INTR_MASK_INT);
}
+static void
+tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const sc, uint bus,
+ uint frg)
+{
+ bus_addr_t a;
+
+ KASSERT(bus >= 1);
+ KASSERT(bus < TEGRA_PCIE_NBUS);
+ KASSERT(frg < TEGRA_PCIE_ECFB);
+
+ if (sc->sc_bsh_extc[bus-1][frg] != 0) {
+ device_printf(sc->sc_dev, "bus %u fragment %#x already "
+ "mapped\n", bus, frg);
+ return;
+ }
+
+ a = TEGRA_PCIE_EXTC_BASE + (bus << 16) + (frg << 24);
+ if (bus_space_map(sc->sc_bst, a, 1 << 16, 0,
+ &sc->sc_bsh_extc[bus-1][frg]) != 0)
+ device_printf(sc->sc_dev, "couldn't map PCIE "
+ "configuration for bus %u fragment %#x", bus, frg);
+}
+
+/* map non-non-extended configuration space for full bus range */
+static void
+tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const sc, uint bus)
+{
+ uint i;
+
+ for (i = 1; i < TEGRA_PCIE_ECFB; i++) {
+ tegra_pcie_conf_frag_map(sc, bus, i);
+ }
+}
+
+/* map non-extended configuration space for full bus range */
+static void
+tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const sc)
+{
+ uint b;
+
+ for (b = 1; b < TEGRA_PCIE_NBUS; b++) {
+ tegra_pcie_conf_frag_map(sc, b, 0);
+ }
+}
+
void
tegra_pcie_init(pci_chipset_tag_t pc, void *priv)
{
@@ -364,6 +415,12 @@
tegra_pcie_attach_hook(device_t parent, device_t self,
struct pcibus_attach_args *pba)
{
+ const pci_chipset_tag_t pc = pba->pba_pc;
+ struct tegra_pcie_softc * const sc = pc->pc_conf_v;
+
+ if (pba->pba_bus >= 1) {
+ tegra_pcie_conf_map_bus(sc, pba->pba_bus);
+ }
}
static int
@@ -402,16 +459,19 @@
tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
+ if (b >= TEGRA_PCIE_NBUS)
+ return (pcireg_t) -1;
+
if (b == 0) {
if (d >= 2 || f != 0)
return (pcireg_t) -1;
reg = d * 0x1000 + offset;
bsh = sc->sc_bsh_rpconf;
} else {
- if ((unsigned int)offset >= PCI_CONF_SIZE)
+ reg = (d << 11) | (f << 8) | (offset & 0xff);
+ bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf];
+ if (bsh == 0)
return (pcireg_t) -1;
- reg = tag | offset;
- bsh = sc->sc_bsh_conf;
}
return bus_space_read_4(sc->sc_bst, bsh, reg);
@@ -430,16 +490,19 @@
tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
+ if (b >= TEGRA_PCIE_NBUS)
+ return;
+
if (b == 0) {
if (d >= 2 || f != 0)
return;
reg = d * 0x1000 + offset;
bsh = sc->sc_bsh_rpconf;
} else {
- if ((unsigned int)offset >= PCI_CONF_SIZE)
+ reg = (d << 11) | (f << 8) | (offset & 0xff);
+ bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf];
+ if (bsh == 0)
return;
- reg = tag | offset;
- bsh = sc->sc_bsh_conf;
}
bus_space_write_4(sc->sc_bst, bsh, reg, val);
Home |
Main Index |
Thread Index |
Old Index