Browse Source

xtensa: remap io area defined in device tree

Use the simple-bus node to discover the io area, and remap the cached and
bypass io ranges. The parent-bus-address value of the first triplet in the
"ranges" property is used. This value is rounded down to the nearest 256MB
boundary. The length of the io area is fixed at 256MB; the "ranges" property
length value is ignored.

Other limitations: (1) only the first simple-bus node is considered, and (2)
only the first triplet of the "ranges" property is considered.

See ePAPR 1.1 §6.5 for the simple-bus node description, and §2.3.8 for the
"ranges" property description.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Baruch Siach 11 years ago
parent
commit
6cb971114f

+ 18 - 0
Documentation/xtensa/mmu.txt

@@ -44,3 +44,21 @@ After step 4, we jump to intended (linked) address of this code.
  40..5F -> 40         40..5F -> pc  -> pc  40..5F -> pc
  40..5F -> 40         40..5F -> pc  -> pc  40..5F -> pc
  20..3F -> 20  -> 20  20..3F -> 20
  20..3F -> 20  -> 20  20..3F -> 20
  00..1F -> 00  -> 00  00..1F -> 00
  00..1F -> 00  -> 00  00..1F -> 00
+
+The default location of IO peripherals is above 0xf0000000. This may change
+using a "ranges" property in a device tree simple-bus node. See ePAPR 1.1, §6.5
+for details on the syntax and semantic of simple-bus nodes. The following
+limitations apply:
+
+1. Only top level simple-bus nodes are considered
+
+2. Only one (first) simple-bus node is considered
+
+3. Empty "ranges" properties are not supported
+
+4. Only the first triplet in the "ranges" property is considered
+
+5. The parent-bus-address value is rounded down to the nearest 256MB boundary
+
+6. The IO area covers the entire 256MB segment of parent-bus-address; the
+   "ranges" triplet length field is ignored

+ 5 - 4
arch/xtensa/include/asm/initialize_mmu.h

@@ -26,6 +26,9 @@
 #include <asm/pgtable.h>
 #include <asm/pgtable.h>
 #include <asm/vectors.h>
 #include <asm/vectors.h>
 
 
+#define CA_BYPASS	(_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
+#define CA_WRITEBACK	(_PAGE_CA_WB     | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
+
 #ifdef __ASSEMBLY__
 #ifdef __ASSEMBLY__
 
 
 #define XTENSA_HWVERSION_RC_2009_0 230000
 #define XTENSA_HWVERSION_RC_2009_0 230000
@@ -80,8 +83,6 @@
 	/* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code
 	/* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code
 	 * and jump to the new mapping.
 	 * and jump to the new mapping.
 	 */
 	 */
-#define CA_BYPASS	(_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
-#define CA_WRITEBACK	(_PAGE_CA_WB     | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
 
 
 	srli	a3, a0, 27
 	srli	a3, a0, 27
 	slli	a3, a3, 27
 	slli	a3, a3, 27
@@ -124,12 +125,12 @@
 	witlb	a4, a5
 	witlb	a4, a5
 
 
 	movi	a5, XCHAL_KIO_CACHED_VADDR + 6
 	movi	a5, XCHAL_KIO_CACHED_VADDR + 6
-	movi	a4, XCHAL_KIO_PADDR + CA_WRITEBACK
+	movi	a4, XCHAL_KIO_DEFAULT_PADDR + CA_WRITEBACK
 	wdtlb	a4, a5
 	wdtlb	a4, a5
 	witlb	a4, a5
 	witlb	a4, a5
 
 
 	movi	a5, XCHAL_KIO_BYPASS_VADDR + 6
 	movi	a5, XCHAL_KIO_BYPASS_VADDR + 6
-	movi	a4, XCHAL_KIO_PADDR + CA_BYPASS
+	movi	a4, XCHAL_KIO_DEFAULT_PADDR + CA_BYPASS
 	wdtlb	a4, a5
 	wdtlb	a4, a5
 	witlb	a4, a5
 	witlb	a4, a5
 
 

+ 10 - 0
arch/xtensa/include/asm/io.h

@@ -24,6 +24,16 @@
 #define IO_SPACE_LIMIT ~0
 #define IO_SPACE_LIMIT ~0
 
 
 #ifdef CONFIG_MMU
 #ifdef CONFIG_MMU
+
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+extern unsigned long xtensa_kio_paddr;
+
+static inline unsigned long xtensa_get_kio_paddr(void)
+{
+	return xtensa_kio_paddr;
+}
+#endif
+
 /*
 /*
  * Return the virtual address for the specified bus memory.
  * Return the virtual address for the specified bus memory.
  * Note that we currently don't support any address outside the KIO segment.
  * Note that we currently don't support any address outside the KIO segment.

+ 7 - 1
arch/xtensa/include/asm/vectors.h

@@ -22,9 +22,15 @@
 
 
 #define XCHAL_KIO_CACHED_VADDR		0xe0000000
 #define XCHAL_KIO_CACHED_VADDR		0xe0000000
 #define XCHAL_KIO_BYPASS_VADDR		0xf0000000
 #define XCHAL_KIO_BYPASS_VADDR		0xf0000000
-#define XCHAL_KIO_PADDR			0xf0000000
+#define XCHAL_KIO_DEFAULT_PADDR		0xf0000000
 #define XCHAL_KIO_SIZE			0x10000000
 #define XCHAL_KIO_SIZE			0x10000000
 
 
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#define XCHAL_KIO_PADDR			xtensa_get_kio_paddr()
+#else
+#define XCHAL_KIO_PADDR			XCHAL_KIO_DEFAULT_PADDR
+#endif
+
 #if defined(CONFIG_MMU)
 #if defined(CONFIG_MMU)
 
 
 /* Will Become VECBASE */
 /* Will Become VECBASE */

+ 37 - 0
arch/xtensa/kernel/setup.c

@@ -212,6 +212,42 @@ static int __init parse_bootparam(const bp_tag_t* tag)
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 bool __initdata dt_memory_scan = false;
 bool __initdata dt_memory_scan = false;
 
 
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
+EXPORT_SYMBOL(xtensa_kio_paddr);
+
+static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
+		int depth, void *data)
+{
+	const __be32 *ranges;
+	unsigned long len;
+
+	if (depth > 1)
+		return 0;
+
+	if (!of_flat_dt_is_compatible(node, "simple-bus"))
+		return 0;
+
+	ranges = of_get_flat_dt_prop(node, "ranges", &len);
+	if (!ranges)
+		return 1;
+	if (len == 0)
+		return 1;
+
+	xtensa_kio_paddr = of_read_ulong(ranges+1, 1);
+	/* round down to nearest 256MB boundary */
+	xtensa_kio_paddr &= 0xf0000000;
+
+	return 1;
+}
+#else
+static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
+		int depth, void *data)
+{
+	return 1;
+}
+#endif
+
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
 {
 	if (!dt_memory_scan)
 	if (!dt_memory_scan)
@@ -232,6 +268,7 @@ void __init early_init_devtree(void *params)
 		dt_memory_scan = true;
 		dt_memory_scan = true;
 
 
 	early_init_dt_scan(params);
 	early_init_dt_scan(params);
+	of_scan_flat_dt(xtensa_dt_io_area, NULL);
 
 
 	if (!command_line[0])
 	if (!command_line[0])
 		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);

+ 16 - 0
arch/xtensa/mm/mmu.c

@@ -13,6 +13,8 @@
 #include <asm/tlbflush.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/mmu_context.h>
 #include <asm/page.h>
 #include <asm/page.h>
+#include <asm/initialize_mmu.h>
+#include <asm/io.h>
 
 
 void __init paging_init(void)
 void __init paging_init(void)
 {
 {
@@ -37,6 +39,20 @@ void init_mmu(void)
 	set_itlbcfg_register(0);
 	set_itlbcfg_register(0);
 	set_dtlbcfg_register(0);
 	set_dtlbcfg_register(0);
 #endif
 #endif
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+	/*
+	 * Update the IO area mapping in case xtensa_kio_paddr has changed
+	 */
+	write_dtlb_entry(__pte(xtensa_kio_paddr + CA_WRITEBACK),
+			XCHAL_KIO_CACHED_VADDR + 6);
+	write_itlb_entry(__pte(xtensa_kio_paddr + CA_WRITEBACK),
+			XCHAL_KIO_CACHED_VADDR + 6);
+	write_dtlb_entry(__pte(xtensa_kio_paddr + CA_BYPASS),
+			XCHAL_KIO_BYPASS_VADDR + 6);
+	write_itlb_entry(__pte(xtensa_kio_paddr + CA_BYPASS),
+			XCHAL_KIO_BYPASS_VADDR + 6);
+#endif
+
 	local_flush_tlb_all();
 	local_flush_tlb_all();
 
 
 	/* Set rasid register to a known value. */
 	/* Set rasid register to a known value. */