summaryrefslogtreecommitdiffstats
path: root/sys/arm/mv
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-14 19:18:58 +0000
committerian <ian@FreeBSD.org>2014-05-14 19:18:58 +0000
commit057c7452877929463827f58db062e6c8a7e70e1e (patch)
tree4d7e5652ad495e1d8b2080c968e1eaf2b8f0ffba /sys/arm/mv
parent21fbbde45943109155a62d78963119afc7f3f290 (diff)
downloadFreeBSD-src-057c7452877929463827f58db062e6c8a7e70e1e.zip
FreeBSD-src-057c7452877929463827f58db062e6c8a7e70e1e.tar.gz
MFC r257738, r259202, r258410, r260288, r260292, r260294, r260320, r260323,
r260326, r260327, r260331, r260333, r260340, r260371, r260372, r260373, r260374, r260375 Add common bus_space tag definition shared for most supported ARMv6/v7 SoCs. Correct license statements to reflect the fact that these files were all derived from sys/arm/mv/bus_space.c. In pmap_unmapdev(), remember the size, and use that as an argument to kva_free(), or we'd end up always passing it a size of 0 In pmap_mapdev(), first check whether a static mapping exists, Convert TI static device mapping to use the new arm_devmap_add_entry(), Use the common armv6 fdt_bus_tag defintion for tegra instead of a local copy. Eliminate use of fdt_immr_addr(), it's not needed for tegra Convert lpc from using fdt_immr style to arm_devmap_add_entry() to make static device mappings. Retire machine/fdt.h as a header used by MI code, as its function is now obsolete. This involves the following pieces: - Remove it entirely on PowerPC, where it is not used by MD code either - Remove all references to machine/fdt.h in non-architecture-specific code (aside from uart_cpu_fdt.c, shared by ARM and MIPS, and so is somewhat non-arch-specific). - Fix code relying on header pollution from machine/fdt.h includes - Legacy fdtbus.c (still used on x86 FDT systems) now passes resource requests to its parent (nexus). This allows x86 FDT devices to allocate both memory and IO requests and removes the last notionally MI use of fdtbus_bs_tag. - On those architectures that retain a machine/fdt.h, unused bits like FDT_MAP_IRQ and FDT_INTR_MAX have been removed. Add #include <machine/fdt.h> to a few files that used to get it via pollution Enable the mv cesa security/crypto device by providing the required property in the dts source, and adding the right devices to the kernel config. Remove dev/fdt/fdt_pci.c, which was code specific to Marvell ARM SoCs, related to setting up static device mappings. Since it was only used by arm/mv/mv_pci.c, it's now just static functions within that file, plus one public function that gets called only from arm/mv/mv_machdep.c. Switch RPi to using arm_devmap_add_entry() to set up static device mapping. Allow 'no static device mappings' to potentially work. Don't try to find a static mapping before calling pmap_mapdev(), that logic is now part of pmap_mapdev() and doesn't need to be duplicated here. Switch a10 to using arm_devmap_add_entry() to set up static device mapping.
Diffstat (limited to 'sys/arm/mv')
-rw-r--r--sys/arm/mv/mv_machdep.c9
-rw-r--r--sys/arm/mv/mv_pci.c173
-rw-r--r--sys/arm/mv/mvvar.h7
3 files changed, 183 insertions, 6 deletions
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index 9758cfb..a42c977 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/devmap.h>
+#include <machine/fdt.h>
#include <machine/machdep.h>
#include <arm/mv/mvreg.h> /* XXX */
@@ -293,11 +294,11 @@ out:
}
/*
- * Supply a default do-nothing implementation of fdt_pci_devmap() via a weak
+ * Supply a default do-nothing implementation of mv_pci_devmap() via a weak
* alias. Many Marvell platforms don't support a PCI interface, but to support
* those that do, we end up with a reference to this function below, in
* platform_devmap_init(). If "device pci" appears in the kernel config, the
- * real implementation of this function in dev/fdt/fdt_pci.c overrides the weak
+ * real implementation of this function in arm/mv/mv_pci.c overrides the weak
* alias defined here.
*/
int mv_default_fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap,
@@ -309,7 +310,7 @@ mv_default_fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap,
return (0);
}
-__weak_reference(mv_default_fdt_pci_devmap, fdt_pci_devmap);
+__weak_reference(mv_default_fdt_pci_devmap, mv_pci_devmap);
/*
* XXX: When device entry in devmap has pd_size smaller than section size,
@@ -378,7 +379,7 @@ initarm_devmap_init(void)
* XXX this should account for PCI and multiple ranges
* of a given kind.
*/
- if (fdt_pci_devmap(child, &fdt_devmap[i], MV_PCI_VA_IO_BASE,
+ if (mv_pci_devmap(child, &fdt_devmap[i], MV_PCI_VA_IO_BASE,
MV_PCI_VA_MEM_BASE) != 0)
return (ENXIO);
i += 2;
diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c
index ff12974..4660e5c 100644
--- a/sys/arm/mv/mv_pci.c
+++ b/sys/arm/mv/mv_pci.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/endian.h>
+#include <machine/fdt.h>
#include <machine/intr.h>
#include <vm/vm.h>
@@ -69,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include "ofw_bus_if.h"
#include "pcib_if.h"
+#include <machine/devmap.h>
#include <machine/resource.h>
#include <machine/bus.h>
@@ -82,6 +84,172 @@ __FBSDID("$FreeBSD$");
#define debugf(fmt, args...)
#endif
+/*
+ * Code and data related to fdt-based PCI configuration.
+ *
+ * This stuff used to be in dev/fdt/fdt_pci.c and fdt_common.h, but it was
+ * always Marvell-specific so that was deleted and the code now lives here.
+ */
+
+struct mv_pci_range {
+ u_long base_pci;
+ u_long base_parent;
+ u_long len;
+};
+
+#define FDT_RANGES_CELLS ((3 + 3 + 2) * 2)
+
+static void
+mv_pci_range_dump(struct mv_pci_range *range)
+{
+#ifdef DEBUG
+ printf("\n");
+ printf(" base_pci = 0x%08lx\n", range->base_pci);
+ printf(" base_par = 0x%08lx\n", range->base_parent);
+ printf(" len = 0x%08lx\n", range->len);
+#endif
+}
+
+static int
+mv_pci_ranges_decode(phandle_t node, struct mv_pci_range *io_space,
+ struct mv_pci_range *mem_space)
+{
+ pcell_t ranges[FDT_RANGES_CELLS];
+ struct mv_pci_range *pci_space;
+ pcell_t addr_cells, size_cells, par_addr_cells;
+ pcell_t *rangesptr;
+ pcell_t cell0, cell1, cell2;
+ int tuple_size, tuples, i, rv, offset_cells, len;
+
+ /*
+ * Retrieve 'ranges' property.
+ */
+ if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
+ return (EINVAL);
+ if (addr_cells != 3 || size_cells != 2)
+ return (ERANGE);
+
+ par_addr_cells = fdt_parent_addr_cells(node);
+ if (par_addr_cells > 3)
+ return (ERANGE);
+
+ len = OF_getproplen(node, "ranges");
+ if (len > sizeof(ranges))
+ return (ENOMEM);
+
+ if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
+ return (EINVAL);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
+ size_cells);
+ tuples = len / tuple_size;
+
+ /*
+ * Initialize the ranges so that we don't have to worry about
+ * having them all defined in the FDT. In particular, it is
+ * perfectly fine not to want I/O space on PCI busses.
+ */
+ bzero(io_space, sizeof(*io_space));
+ bzero(mem_space, sizeof(*mem_space));
+
+ rangesptr = &ranges[0];
+ offset_cells = 0;
+ for (i = 0; i < tuples; i++) {
+ cell0 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+ cell1 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+ cell2 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+
+ if (cell0 & 0x02000000) {
+ pci_space = mem_space;
+ } else if (cell0 & 0x01000000) {
+ pci_space = io_space;
+ } else {
+ rv = ERANGE;
+ goto out;
+ }
+
+ if (par_addr_cells == 3) {
+ /*
+ * This is a PCI subnode 'ranges'. Skip cell0 and
+ * cell1 of this entry and only use cell2.
+ */
+ offset_cells = 2;
+ rangesptr += offset_cells;
+ }
+
+ if (fdt_data_verify((void *)rangesptr, par_addr_cells -
+ offset_cells)) {
+ rv = ERANGE;
+ goto out;
+ }
+ pci_space->base_parent = fdt_data_get((void *)rangesptr,
+ par_addr_cells - offset_cells);
+ rangesptr += par_addr_cells - offset_cells;
+
+ if (fdt_data_verify((void *)rangesptr, size_cells)) {
+ rv = ERANGE;
+ goto out;
+ }
+ pci_space->len = fdt_data_get((void *)rangesptr, size_cells);
+ rangesptr += size_cells;
+
+ pci_space->base_pci = cell2;
+ }
+ rv = 0;
+out:
+ return (rv);
+}
+
+static int
+mv_pci_ranges(phandle_t node, struct mv_pci_range *io_space,
+ struct mv_pci_range *mem_space)
+{
+ int err;
+
+ debugf("Processing PCI node: %x\n", node);
+ if ((err = mv_pci_ranges_decode(node, io_space, mem_space)) != 0) {
+ debugf("could not decode parent PCI node 'ranges'\n");
+ return (err);
+ }
+
+ debugf("Post fixup dump:\n");
+ mv_pci_range_dump(io_space);
+ mv_pci_range_dump(mem_space);
+ return (0);
+}
+
+int
+mv_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap, vm_offset_t io_va,
+ vm_offset_t mem_va)
+{
+ struct mv_pci_range io_space, mem_space;
+ int error;
+
+ if ((error = mv_pci_ranges_decode(node, &io_space, &mem_space)) != 0)
+ return (error);
+
+ devmap->pd_va = (io_va ? io_va : io_space.base_parent);
+ devmap->pd_pa = io_space.base_parent;
+ devmap->pd_size = io_space.len;
+ devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ devmap->pd_cache = PTE_NOCACHE;
+ devmap++;
+
+ devmap->pd_va = (mem_va ? mem_va : mem_space.base_parent);
+ devmap->pd_pa = mem_space.base_parent;
+ devmap->pd_size = mem_space.len;
+ devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ devmap->pd_cache = PTE_NOCACHE;
+ return (0);
+}
+
+/*
+ * Code and data related to the Marvell pcib driver.
+ */
+
#define PCI_CFG_ENA (1U << 31)
#define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16)
#define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11)
@@ -911,13 +1079,13 @@ mv_pcib_route_interrupt(device_t bus, device_t dev, int pin)
static int
mv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc)
{
- struct fdt_pci_range io_space, mem_space;
+ struct mv_pci_range io_space, mem_space;
device_t dev;
int error;
dev = sc->sc_dev;
- if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) {
+ if ((error = mv_pci_ranges(node, &io_space, &mem_space)) != 0) {
device_printf(dev, "could not retrieve 'ranges' data\n");
return (error);
}
@@ -1025,3 +1193,4 @@ mv_pcib_release_msi(device_t dev, device_t child, int count, int *irqs)
return (0);
}
#endif
+
diff --git a/sys/arm/mv/mvvar.h b/sys/arm/mv/mvvar.h
index 54abf46..0b72dcb 100644
--- a/sys/arm/mv/mvvar.h
+++ b/sys/arm/mv/mvvar.h
@@ -46,6 +46,8 @@
#include <vm/pmap.h>
#include <machine/vm.h>
+#include <dev/ofw/openfirm.h>
+
#define MV_TYPE_PCI 0
#define MV_TYPE_PCIE 1
@@ -135,4 +137,9 @@ uint32_t mv_drbl_get_msg(int mnr, int dir, int unit);
int mv_msi_data(int irq, uint64_t *addr, uint32_t *data);
+struct arm_devmap_entry;
+
+int mv_pci_devmap(phandle_t, struct arm_devmap_entry *, vm_offset_t,
+ vm_offset_t);
+
#endif /* _MVVAR_H_ */
OpenPOWER on IntegriCloud