Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149739930
D4217.1790824913.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D4217.1790824913.diff
View Options
Index: sys/dev/uart/uart_cpu_fdt.c
===================================================================
--- sys/dev/uart/uart_cpu_fdt.c
+++ sys/dev/uart/uart_cpu_fdt.c
@@ -57,6 +57,8 @@
#ifdef __aarch64__
extern bus_space_tag_t fdtbus_bs_tag;
#endif
+static int uart_fdt_remap_addr(phandle_t node, u_long start, u_long size,
+ u_long *uart_addr);
/*
* UART console routines.
@@ -64,6 +66,13 @@
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
+/* Used by range translation code */
+struct simplebus_range {
+ uint64_t bus;
+ uint64_t host;
+ uint64_t size;
+};
+
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
@@ -215,13 +224,124 @@
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")) {
+ /* Remap UART physical address through simplebus ranges */
+ if (uart_fdt_remap_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));
}
+
+/* Limit size of stack buffers */
+#define MAX_RANGES 8
+#define MAX_CELLS_PER_RANGE 6
+
+static int
+uart_fdt_remap_addr(phandle_t node, u_long start, u_long size,
+ u_long *uart_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 UART */
+ node = OF_parent(node);
+
+ /* Work from the immediate parent of UART 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);
+ }
+ }
+
+ *uart_addr = start;
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Oct 1, 3:21 AM (20 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30054470
Default Alt Text
D4217.1790824913.diff (4 KB)
Attached To
Mode
D4217: Remap UART physical address through simple-bus ranges
Attached
Detach File
Event Timeline
Log In to Comment