Page MenuHomeFreeBSD

D4217.1790655933.diff
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

D4217.1790655933.diff

Index: sys/dev/fdt/simplebus.h
===================================================================
--- sys/dev/fdt/simplebus.h
+++ sys/dev/fdt/simplebus.h
@@ -61,4 +61,6 @@
const char *name, int unit, struct simplebus_devinfo *di);
struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev, phandle_t node,
struct simplebus_devinfo *di);
+int simplebus_get_base_addr(phandle_t node, u_long start, u_long size,
+ u_long *phys_addr);
#endif /* _FDT_SIMPLEBUS_H */
Index: sys/dev/fdt/simplebus.c
===================================================================
--- sys/dev/fdt/simplebus.c
+++ sys/dev/fdt/simplebus.c
@@ -39,6 +39,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/fdt/simplebus.h>
+#include <dev/fdt/fdt_common.h>
/*
* Bus interface.
@@ -421,3 +422,108 @@
rv += bus_print_child_footer(bus, child);
return (rv);
}
+
+/* Limit size of stack buffers */
+#define MAX_RANGES 8
+#define MAX_CELLS_PER_RANGE 6
+
+/* Calculate absolute physical base address of a device node */
+int
+simplebus_get_base_addr(phandle_t node, u_long start, u_long size,
+ u_long *phys_addr)
+{
+ struct simplebus_range ranges[MAX_RANGES];
+ cell_t base_ranges[MAX_CELLS_PER_RANGE * MAX_RANGES];
+ ssize_t nbase_ranges, rv;
+ int i, j, k, nranges;
+ pcell_t addr_cells, host_address_cells, size_cells;
+ u_long end;
+
+ end = start + size - 1;
+ /* Get parent bus of the node */
+ node = OF_parent(node);
+
+ /* Work from the immediate parent of the device node up to the root node
+ * translating the base address through 'ranges' properties of every
+ * simple-bus parent, the same way simplebus_alloc_resource() does it.
+ */
+ for (; node != 0; node = OF_parent(node)) {
+ if (!fdt_is_compatible(node, "simple-bus"))
+ continue;
+
+ rv = OF_getencprop(node, "#address-cells", &addr_cells,
+ sizeof(addr_cells));
+ if (rv <= 0)
+ addr_cells = 2; /* Default size used by simplebus */
+
+ rv = OF_getencprop(OF_parent(node), "#address-cells",
+ &host_address_cells, sizeof(host_address_cells));
+ if (rv <= 0)
+ host_address_cells = 2; /* Default size */
+
+ rv = OF_getencprop(node, "#size-cells", &size_cells,
+ sizeof(size_cells));
+ if (rv <= 0)
+ size_cells = 1; /* Default size */
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges < 0)
+ return (-1);
+
+ if (nbase_ranges == 0) {
+ /* Empty ranges; property means 1:1 mapping */
+ continue;
+ }
+
+ nranges = nbase_ranges / sizeof(cell_t) /
+ (addr_cells + host_address_cells + size_cells);
+
+ if (nranges == 0 || (nranges > MAX_RANGES))
+ return (-1);
+
+ /* Copy ranges data into local buffer */
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ /* Parse bus and host addresses along with sizes */
+ for (i = 0, j = 0; i < nranges; i++) {
+ ranges[i].bus = 0;
+ for (k = 0; k < addr_cells; k++) {
+ ranges[i].bus <<= 32;
+ ranges[i].bus |= base_ranges[j++];
+ }
+ ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ ranges[i].host <<= 32;
+ ranges[i].host |= base_ranges[j++];
+ }
+ ranges[i].size = 0;
+ for (k = 0; k < size_cells; k++) {
+ ranges[i].size <<= 32;
+ ranges[i].size |= base_ranges[j++];
+ }
+ }
+
+ /* Remap through ranges property */
+ for (i = 0; i < nranges; i++) {
+ if (start >= ranges[i].bus && end <
+ (ranges[i].bus + ranges[i].size)) {
+ /* Found matching range entry */
+ start -= ranges[i].bus;
+ start += ranges[i].host;
+ end -= ranges[i].bus;
+ end += ranges[i].host;
+ break;
+ }
+ }
+
+ if (i == nranges) {
+ /* Could not find corresponding range entry */
+ printf("%s: address space translation error\n",
+ __func__);
+ return (-1);
+ }
+ }
+
+ *phys_addr = start;
+ return (0);
+}
Index: sys/dev/uart/uart_cpu_fdt.c
===================================================================
--- sys/dev/uart/uart_cpu_fdt.c
+++ sys/dev/uart/uart_cpu_fdt.c
@@ -47,6 +47,7 @@
#endif
#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/uart/uart.h>
@@ -215,13 +216,20 @@
di->bas.bst = uart_bus_space_mem;
err = fdt_regsize(node, &start, &size);
- if (err)
+ if (err != 0)
return (ENXIO);
- err = fdt_get_range(OF_parent(node), 0, &pbase, &psize);
- if (err)
- pbase = 0;
- start += pbase;
+ if (fdt_is_compatible(OF_parent(node), "simple-bus")) {
+ /* Get the physical base address of UART registers */
+ if (simplebus_get_base_addr(node, start, size, &start))
+ return (ENXIO);
+ } else {
+ err = fdt_get_range(OF_parent(node), 0, &pbase, &psize);
+ if (err != 0)
+ pbase = 0;
+
+ start += pbase;
+ }
return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
}

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 29, 4:25 AM (21 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29998792
Default Alt Text
D4217.1790655933.diff (4 KB)

Event Timeline