linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support
@ 2018-01-24  1:47 Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 1/6] MIPS: Allow board to override TLB initialization Florian Fainelli
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Ralf Baechle, Kevin Cernekee, James Hogan,
	Paul Burton, Matt Redfearn, Maciej W. Rozycki, Huacai Chen,
	Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

Hi all,

This patch series brings Broadcom's eXtended KSEG0/1 to the upstream
Linux/MIPS kernel. The intent is that on a lot of BMIPS-based STB chips
we have between 512MB, 1Gb and 2GB of RAM available, and because of the
inflexibility of the unmapped area we access more than 256MB of RAM, which
is inefficient since w need to use the TLB for the upper memory region.

With these changes, we no longer have to, we can access up to 1GB of DRAM
through KSEG0/1 along with specific processor extensions.

I have tried my best to make this as runtime based as possible, and surprisingly, did not run into many places where KSEG0/1 would be referenced from assembly.

Unfortunately, after forward porting these changes from our downstream kernel
to the upstream kernel, I am now seeing the following early crash, any
pointers/clues welcome!

Anything up to patch 5 should not break other platforms, if it does, that's
bad and it needs to be fixed.

Original work from Kevin Cernekee (hey!)

[    0.000000] Linux version 4.15.0-rc7+ (ff944844@stbirv-lnx-1) (gcc version 6.3.0 (crosstool-NG )) #60 SMP Tue Jan 23 17:29:41 PST 2018
[    0.000000] CPU0 revision is: 00025a11 (Broadcom BMIPS5000)
[    0.000000] FPU revision is: 00130001
[    0.000000] MIPS: machine is Broadcom BCM97425SVMB
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 10000000 @ 00000000 (usable)
[    0.000000]  memory: 30000000 @ 20000000 (usable)
[    0.000000]  memory: 40000000 @ 90000000 (usable)
[    0.000000] earlycon: ns16550a0 at MMIO32 0x10406b00 (options '')
[    0.000000] bootconsole [ns16550a0] enabled
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 64 bytes.
[    0.000000] Primary data cache 32kB, 4-way, VIPT, no aliases, linesize 32 bytes
[    0.000000] MIPS secondary cache 256kB, 8-way, linesize 128 bytes.
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x000000004fffffff]
[    0.000000]   HighMem  [mem 0x0000000050000000-0x00000000cfffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x000000000fffffff]
[    0.000000]   node   0: [mem 0x0000000020000000-0x000000004fffffff]
[    0.000000]   node   0: [mem 0x0000000090000000-0x00000000cfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x00000000cfffffff]
[    0.000000] random: get_random_bytes called from start_kernel+0xa4/0x4f8 with crng_init=0
[    0.000000] percpu: Embedded 16 pages/cpu @(ptrval) s35216 r8192 d22128 u65536
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 521728
[    0.000000] Kernel command line: console=ttyS0,115200 earlycon
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Memory: 2042464K/2097152K available (7879K kernel code, 301K rwdata, 1564K rodata, 17000K init, 288K bss, 54688K reserved, 0K cma-reserved, 1048576K highmem)
[    0.000000] SLUB: HWalign=128, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
[    0.000000] Kernel bug detected[#1]:
[    0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.15.0-rc7+ #60
[    0.000000] $ 0   : 00000000 10000000 00000000 00000000
[    0.000000] $ 4   : cfc03700 cfc03700 ffffffff cfc03704
[    0.000000] $ 8   : 00000000 807b6330 00000110 00000114
[    0.000000] $12   : 00000001 00000000 ffffff80 00000000
[    0.000000] $16   : cfc03600 81c87060 cfc03700 cfc06000
[    0.000000] $20   : cfc03700 80960000 80960000 ffffffec
[    0.000000] $24   : 00000010 00000340                  
[    0.000000] $28   : 8094c000 8094dd70 cfc06000 8005a93c
[    0.000000] Hi    : 00000090
[    0.000000] Lo    : 0000000d
[    0.000000] epc   : 80148fb8 kfree+0x23c/0x240
[    0.000000] ra    : 8005a93c apply_wqattrs_prepare+0x12c/0x1f4
[    0.000000] Status: 10000002 KERNEL EXL 
[    0.000000] Cause : 00808024 (ExcCode 09)
[    0.000000] PrId  : 00025a11 (Broadcom BMIPS5000)
[    0.000000] Modules linked in:
[    0.000000] Process swapper/0 (pid: 0, threadinfo=(ptrval), task=(ptrval), tls=00000000)
[    0.000000] *HwTLS: 77f06490
[    0.000000] Stack : cfc06000 81a34348 80960000 8005a698 cfc06000 01400000 80960000 cfc03600
[    0.000000]         cfc03680 cfc03380 cfc06000 cfc03700 80960000 8005a93c 80892f3e 8095fa80
[    0.000000]         80960000 834b2744 80960000 cfc06000 cfc06008 81a34340 01400000 8005aa4c
[    0.000000]         80915270 00000000 8095faa0 80960000 80960000 8005aed0 00000200 00000002
[    0.000000]         cfc06060 80892f30 01400000 cfc03380 80960000 cfc06010 00000002 8005c828
[    0.000000]         ...
[    0.000000] Call Trace:
[    0.000000] [<(ptrval)>] kfree+0x23c/0x240
[    0.000000] [<(ptrval)>] apply_wqattrs_prepare+0x12c/0x1f4
[    0.000000] [<(ptrval)>] apply_workqueue_attrs_locked+0x48/0xb8
[    0.000000] [<(ptrval)>] apply_workqueue_attrs+0x34/0x60
[    0.000000] [<(ptrval)>] __alloc_workqueue_key+0x180/0x518
[    0.000000] [<(ptrval)>] workqueue_init_early+0x298/0x398
[    0.000000] [<(ptrval)>] start_kernel+0x2e0/0x4f8
[    0.000000] [<(ptrval)>] kernel_entry+0x20/0x60
[    0.000000] Code: 30420001  1440ffed  00000000 <000c000d> 27bdffc8  afb20024  afb10020  afbf0034  afb50030 
[    0.000000] 
[    0.000000] ---[ end trace 08e528f695e5791e ]---
[    0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
[    0.000000] ---[ end Kernel panic - not syncing: Attempted to kill the idle task!


Florian Fainelli (6):
  MIPS: Allow board to override TLB initialization
  MIPS: Allow platforms to override mapping/unmapping coherent
  MIPS: BMIPS: Avoid referencing CKSEG1
  MIPS: Prepare for supporting eXtended KSEG0/1
  MIPS: BMIPS: Handshake with CFE
  MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01)

 arch/mips/Kconfig                                  |   2 +
 arch/mips/bmips/Makefile                           |   2 +-
 arch/mips/bmips/memory.c                           | 427 +++++++++++++++++++++
 arch/mips/bmips/setup.c                            |  78 ++++
 arch/mips/include/asm/addrspace.h                  |   8 +
 arch/mips/include/asm/cpu-features.h               |   8 +
 arch/mips/include/asm/cpu.h                        |   1 +
 arch/mips/include/asm/io.h                         |  18 +-
 arch/mips/include/asm/mach-bmips/dma-coherence.h   |   6 +
 arch/mips/include/asm/mach-bmips/ioremap.h         |  26 +-
 .../include/asm/mach-bmips/kernel-entry-init.h     |  18 +
 arch/mips/include/asm/mach-bmips/spaces.h          | 102 +++++
 arch/mips/include/asm/mach-generic/dma-coherence.h |  16 +
 arch/mips/include/asm/page.h                       |   4 +
 arch/mips/include/asm/traps.h                      |   1 +
 arch/mips/kernel/bmips_vec.S                       |   6 +-
 arch/mips/kernel/cpu-probe.c                       |   3 +-
 arch/mips/kernel/traps.c                           |   6 +-
 arch/mips/mm/dma-default.c                         |  10 +-
 arch/mips/mm/ioremap.c                             |  16 +-
 20 files changed, 712 insertions(+), 46 deletions(-)
 create mode 100644 arch/mips/bmips/memory.c
 create mode 100644 arch/mips/include/asm/mach-bmips/kernel-entry-init.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH RFC 1/6] MIPS: Allow board to override TLB initialization
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 2/6] MIPS: Allow platforms to override mapping/unmapping coherent Florian Fainelli
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Florian Fainelli, Ralf Baechle, Kevin Cernekee,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

Some boards may have to override how the TLB initialization is done,
e.g: to support eXtended Kseg0/1 features on Broadcom BMIPS boards.
Allow this to happen by providing a board_tlb_init() hook.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/mips/include/asm/traps.h | 1 +
 arch/mips/kernel/traps.c      | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h
index f41cf3ee82a7..66c9c855be6e 100644
--- a/arch/mips/include/asm/traps.h
+++ b/arch/mips/include/asm/traps.h
@@ -26,6 +26,7 @@ extern void (*board_ejtag_handler_setup)(void);
 extern void (*board_bind_eic_interrupt)(int irq, int regset);
 extern void (*board_ebase_setup)(void);
 extern void (*board_cache_error_setup)(void);
+extern void (*board_tlb_init)(void);
 
 extern int register_nmi_notifier(struct notifier_block *nb);
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 5d19ed07e99d..b03864eb8213 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -106,6 +106,7 @@ void (*board_ejtag_handler_setup)(void);
 void (*board_bind_eic_interrupt)(int irq, int regset);
 void (*board_ebase_setup)(void);
 void(*board_cache_error_setup)(void);
+void (*board_tlb_init)(void);
 
 static void show_raw_backtrace(unsigned long reg29)
 {
@@ -2230,7 +2231,10 @@ void per_cpu_trap_init(bool is_boot_cpu)
 	/* Boot CPU's cache setup in setup_arch(). */
 	if (!is_boot_cpu)
 		cpu_cache_init();
-	tlb_init();
+	if (board_tlb_init)
+		board_tlb_init();
+	else
+		tlb_init();
 	TLBMISS_HANDLER_SETUP();
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH RFC 2/6] MIPS: Allow platforms to override mapping/unmapping coherent
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 1/6] MIPS: Allow board to override TLB initialization Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1 Florian Fainelli
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Florian Fainelli, Ralf Baechle, Kevin Cernekee,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

In preparation for allowing support for Broadcom's eXtended Kseg0/1
feature, allow platforms to override how coherent DMA mappings are done
by providing plat_map_coherent() and plat_unmap_coherent() hooks, which
default to the current implementation with CAC/UNCAC unless changed.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/mips/include/asm/mach-generic/dma-coherence.h | 16 ++++++++++++++++
 arch/mips/mm/dma-default.c                         | 10 +++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index e6e7dfa15801..42a1546e7d10 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -98,4 +98,20 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 #endif
 #endif /* CONFIG_SWIOTLB */
 
+#ifndef plat_map_coherent
+static inline int plat_map_coherent(dma_addr_t handle, void *cac_va, size_t size,
+				    void **uncac_va, gfp_t gfp)
+{
+	*uncac_va = UNCAC_ADDR(cac_va);
+	return 0;
+}
+#endif
+
+#ifndef plat_unmap_coherent
+static inline void *plat_unmap_coherent(void *addr)
+{
+	return CAC_ADDR(addr);
+}
+#endif
+
 #endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index e3e94d05f0fd..f82f00dcc841 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -151,7 +151,11 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
 	if (!(attrs & DMA_ATTR_NON_CONSISTENT) &&
 	    !plat_device_is_coherent(dev)) {
 		dma_cache_wback_inv((unsigned long) ret, size);
-		ret = UNCAC_ADDR(ret);
+		if (plat_map_coherent(*dma_handle, ret, PFN_ALIGN(size),
+				      &ret, gfp)) {
+			free_pages((unsigned long)ret, size);
+			ret = NULL;
+		}
 	}
 
 	return ret;
@@ -167,7 +171,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 	plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
 
 	if (!(attrs & DMA_ATTR_NON_CONSISTENT) && !plat_device_is_coherent(dev))
-		addr = CAC_ADDR(addr);
+		addr = (unsigned long)plat_unmap_coherent(vaddr);
 
 	page = virt_to_page((void *) addr);
 
@@ -187,7 +191,7 @@ static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 	int ret = -ENXIO;
 
 	if (!plat_device_is_coherent(dev))
-		addr = CAC_ADDR(addr);
+		addr = (unsigned long)plat_unmap_coherent((void *)addr);
 
 	pfn = page_to_pfn(virt_to_page((void *)addr));
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 1/6] MIPS: Allow board to override TLB initialization Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 2/6] MIPS: Allow platforms to override mapping/unmapping coherent Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-02-02 17:38   ` Maciej W. Rozycki
  2018-01-24  1:47 ` [PATCH RFC 4/6] MIPS: Prepare for supporting eXtended KSEG0/1 Florian Fainelli
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Florian Fainelli, Ralf Baechle, Kevin Cernekee,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

bmips_smp_movevec() references the CKSEG1 constant, which is about to be
updated in order to support processors that might enable eXtended
KSEG0/1. In doing so, we will generate a reference to a function, which
is obviously not permissible within assembly. Fortunately,
bmips_smp_movevec() is only used on BMIPS4350 which does not support
eXtended KSEG0/1.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/mips/kernel/bmips_vec.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S
index 921a5fa55da6..10ea69f3859f 100644
--- a/arch/mips/kernel/bmips_vec.S
+++ b/arch/mips/kernel/bmips_vec.S
@@ -39,7 +39,7 @@
 
 LEAF(bmips_smp_movevec)
 	la	k0, 1f
-	li	k1, CKSEG1
+	li	k1, 0xa0000000
 	or	k0, k1
 	jr	k0
 
@@ -58,7 +58,7 @@ LEAF(bmips_smp_movevec)
 	mfc0	k1, $22, 3
 	srl	k1, 16
 	andi	k1, 0x8000
-	or	k1, CKSEG1 | BMIPS_RELO_VECTOR_CONTROL_0
+	or	k1, 0xa0000000 | BMIPS_RELO_VECTOR_CONTROL_0
 	or	k0, k1
 	li	k1, 0xa0080000
 	sw	k1, 0(k0)
@@ -67,7 +67,7 @@ LEAF(bmips_smp_movevec)
 	wait
 
 	la	k0, bmips_reset_nmi_vec
-	li	k1, CKSEG1
+	li	k1, 0xa0000000
 	or	k0, k1
 	jr	k0
 END(bmips_smp_movevec)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH RFC 4/6] MIPS: Prepare for supporting eXtended KSEG0/1
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
                   ` (2 preceding siblings ...)
  2018-01-24  1:47 ` [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1 Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 5/6] MIPS: BMIPS: Handshake with CFE Florian Fainelli
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Florian Fainelli, Ralf Baechle, Kevin Cernekee,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

Prepare the core MIPS files to support Broadcom's eXtended KSEG0/1:

- add MIPS_CPU_XKS01 feature flag
- flag BMIPS4380/5000/5200 with MIPS_CPU_XKS01
- update ioremap and CAC_ADDR() checks

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/mips/include/asm/cpu-features.h |  8 ++++++++
 arch/mips/include/asm/cpu.h          |  1 +
 arch/mips/include/asm/io.h           | 18 ++++++++++--------
 arch/mips/include/asm/page.h         |  4 ++++
 arch/mips/kernel/cpu-probe.c         |  3 ++-
 arch/mips/mm/ioremap.c               | 16 +++++++++-------
 6 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 721b698bfe3c..43e1163921a9 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -623,4 +623,12 @@
 #define cpu_guest_has_dyn_maar	(cpu_data[0].guest.options_dyn & MIPS_CPU_MAAR)
 #endif
 
+#if defined(CONFIG_XKS01)
+#ifndef cpu_has_xks01
+# define cpu_has_xks01		(cpu_data[0].options & MIPS_CPU_XKS01)
+#endif
+#else
+# define cpu_has_xks01		0
+#endif /* CONFIG_XKS01 */
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index d39324c4adf1..298356b9f7e6 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -418,6 +418,7 @@ enum cpu_type_enum {
 				MBIT_ULL(54)	/* CPU shares FTLB RAM with another */
 #define MIPS_CPU_SHARED_FTLB_ENTRIES \
 				MBIT_ULL(55)	/* CPU shares FTLB entries with another */
+#define MIPS_CPU_XKS01		MBIT_ULL(56)	/* CPU has eXtended KSEG0/1 */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 0cbf3af37eca..9f4ac0c394be 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -206,14 +206,16 @@ static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long si
 		if (!size || last_addr < phys_addr)
 			return NULL;
 
-		/*
-		 * Map uncached objects in the low 512MB of address
-		 * space using KSEG1.
-		 */
-		if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
-		    flags == _CACHE_UNCACHED)
-			return (void __iomem *)
-				(unsigned long)CKSEG1ADDR(phys_addr);
+		if (likely(!cpu_has_xks01)) {
+			/*
+			 * Map uncached objects in the low 512MB of address
+			 * space using KSEG1.
+			 */
+			if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
+			    flags == _CACHE_UNCACHED)
+				return (void __iomem *)
+					(unsigned long)CKSEG1ADDR(phys_addr);
+		}
 	}
 
 	return __ioremap(offset, size, flags);
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index ad461216b5a1..7b8eea14b80e 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -252,8 +252,12 @@ extern int __virt_addr_valid(const volatile void *kaddr);
 	 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
 	 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_XKS01
+#define CAC_ADDR(addr)		({ BUG(); NULL; })
+#else
 #define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
 #define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
+#endif
 
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index cf3fd549e16d..200087ce9963 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1760,6 +1760,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 			__cpu_name[cpu] = "Broadcom BMIPS4380";
 			set_elf_platform(cpu, "bmips4380");
 			c->options |= MIPS_CPU_RIXI;
+			c->options |= MIPS_CPU_XKS01;
 		} else {
 			c->cputype = CPU_BMIPS4350;
 			__cpu_name[cpu] = "Broadcom BMIPS4350";
@@ -1775,7 +1776,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 		else
 			__cpu_name[cpu] = "Broadcom BMIPS5000";
 		set_elf_platform(cpu, "bmips5000");
-		c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI;
+		c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI | MIPS_CPU_XKS01;
 		break;
 	}
 }
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index 1986e09fb457..f8fd14188909 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -128,13 +128,15 @@ void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long
 	if (!size || last_addr < phys_addr)
 		return NULL;
 
-	/*
-	 * Map uncached objects in the low 512mb of address space using KSEG1,
-	 * otherwise map using page tables.
-	 */
-	if (IS_LOW512(phys_addr) && IS_LOW512(last_addr) &&
-	    flags == _CACHE_UNCACHED)
-		return (void __iomem *) CKSEG1ADDR(phys_addr);
+	if (likely(!cpu_has_xks01)) {
+		/*
+		 * Map uncached objects in the low 512mb of address space using
+		 * KSEG1, otherwise map using page tables.
+		 */
+		if (IS_LOW512(phys_addr) && IS_LOW512(last_addr) &&
+		    flags == _CACHE_UNCACHED)
+			return (void __iomem *) CKSEG1ADDR(phys_addr);
+	}
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH RFC 5/6] MIPS: BMIPS: Handshake with CFE
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
                   ` (3 preceding siblings ...)
  2018-01-24  1:47 ` [PATCH RFC 4/6] MIPS: Prepare for supporting eXtended KSEG0/1 Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-01-24  1:47 ` [PATCH RFC 6/6] MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01) Florian Fainelli
  2018-01-26  8:31 ` [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Steven J. Hill
  6 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Ralf Baechle, Kevin Cernekee, Florian Fainelli,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

Handshake with CFE and retrieve the environment variable DRAM0_SIZE,
which will tell us, on Broadcom STB chips, the amount of populated RAM
that we have on the first memory controller (aka MEMC0). This is
necessary in order to know how and if we can make use of eXtended
KSEG0/1.

Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
 arch/mips/bmips/setup.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c
index 3b6f687f177c..d1b7b8b82ae1 100644
--- a/arch/mips/bmips/setup.c
+++ b/arch/mips/bmips/setup.c
@@ -19,6 +19,7 @@
 #include <linux/of_platform.h>
 #include <linux/libfdt.h>
 #include <linux/smp.h>
+#include <linux/kernel.h>
 #include <asm/addrspace.h>
 #include <asm/bmips.h>
 #include <asm/bootinfo.h>
@@ -28,12 +29,18 @@
 #include <asm/smp-ops.h>
 #include <asm/time.h>
 #include <asm/traps.h>
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
 
 #define RELO_NORMAL_VEC		BIT(18)
 
 #define REG_BCM6328_OTP		((void __iomem *)CKSEG1ADDR(0x1000062c))
 #define BCM6328_TP1_DISABLED	BIT(9)
 
+unsigned long __initdata cfe_seal;
+unsigned long __initdata cfe_entry;
+unsigned long __initdata cfe_handle;
+
 static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
 
 struct bmips_quirk {
@@ -123,9 +130,45 @@ static const struct bmips_quirk bmips_quirk_list[] = {
 	{ },
 };
 
+static unsigned long dram0_size_mb;
+
+extern void bmips_tlb_init(void);
+
+static char __initdata cfe_buf[COMMAND_LINE_SIZE];
+
+static inline int __init parse_ulong(const char *buf, unsigned long *val)
+{
+	char *endp;
+	unsigned long tmp;
+
+	tmp = simple_strtoul(buf, &endp, 0);
+	if (*endp == 0) {
+		*val = tmp;
+		return 0;
+	}
+
+	return -1;
+}
+
+#define FETCH(name, fn, arg) do { \
+	if (cfe_getenv(name, cfe_buf, COMMAND_LINE_SIZE) == CFE_OK) { \
+		fn(cfe_buf, arg); \
+        } \
+        } while (0)
+
+static void __init __maybe_unused cfe_read_configuration(void)
+{
+	if (cfe_seal != CFE_EPTSEAL)
+		return;
+
+	FETCH("DRAM0_SIZE", parse_ulong, &dram0_size_mb);
+}
+
 void __init prom_init(void)
 {
+	cfe_init(cfe_handle, cfe_entry);
 	bmips_cpu_setup();
+	cfe_read_configuration();
 	register_bmips_smp_ops();
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH RFC 6/6] MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01)
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
                   ` (4 preceding siblings ...)
  2018-01-24  1:47 ` [PATCH RFC 5/6] MIPS: BMIPS: Handshake with CFE Florian Fainelli
@ 2018-01-24  1:47 ` Florian Fainelli
  2018-01-26  8:31 ` [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Steven J. Hill
  6 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-24  1:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Ralf Baechle, Kevin Cernekee, Florian Fainelli,
	James Hogan, Paul Burton, Matt Redfearn, Maciej W. Rozycki,
	Huacai Chen, Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

From: Florian Fainelli <florian.fainelli@broadcom.com>

We need to implement a few things in order for XKS01 to work:

- a coherent allocator is needed for some portions of the memory space,
  this is loosely inspired from an old ARM implementation
- we need to obtain how much DRAM we have on our first memory controller
  (MEMC0) which is what govers how big the extended region can be
- a bunch of ioremap and dma-coherent functions need to be re-defined to
  take our special ranges into account

Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
 arch/mips/Kconfig                                  |   2 +
 arch/mips/bmips/Makefile                           |   2 +-
 arch/mips/bmips/memory.c                           | 427 +++++++++++++++++++++
 arch/mips/bmips/setup.c                            |  35 ++
 arch/mips/include/asm/addrspace.h                  |   8 +
 arch/mips/include/asm/mach-bmips/dma-coherence.h   |   6 +
 arch/mips/include/asm/mach-bmips/ioremap.h         |  26 +-
 .../include/asm/mach-bmips/kernel-entry-init.h     |  18 +
 arch/mips/include/asm/mach-bmips/spaces.h          | 102 +++++
 9 files changed, 603 insertions(+), 23 deletions(-)
 create mode 100644 arch/mips/bmips/memory.c
 create mode 100644 arch/mips/include/asm/mach-bmips/kernel-entry-init.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 659e0079487f..b7c0306c9051 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -234,6 +234,7 @@ config BMIPS_GENERIC
 	select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
 	select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
 	select HARDIRQS_SW_RESEND
+	select FW_CFE
 	help
 	  Build a generic DT-based kernel image that boots on select
 	  BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top
@@ -1690,6 +1691,7 @@ config CPU_BMIPS
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_CPUFREQ
 	select MIPS_EXTERNAL_TIMER
+	select XKS01
 	help
 	  Support for BMIPS32/3300/4350/4380 and BMIPS5000 processors.
 
diff --git a/arch/mips/bmips/Makefile b/arch/mips/bmips/Makefile
index a393955cba08..990dc814b7d8 100644
--- a/arch/mips/bmips/Makefile
+++ b/arch/mips/bmips/Makefile
@@ -1 +1 @@
-obj-y		+= setup.o irq.o dma.o
+obj-y		+= setup.o irq.o dma.o memory.o
diff --git a/arch/mips/bmips/memory.c b/arch/mips/bmips/memory.c
new file mode 100644
index 000000000000..847954b8686e
--- /dev/null
+++ b/arch/mips/bmips/memory.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/compiler.h>
+#include <linux/atomic.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <linux/init_task.h>
+
+#include <asm/page.h>
+#include <asm/pgtable-32.h>
+#include <asm/pgtable-bits.h>
+#include <asm/addrspace.h>
+#include <asm/tlbflush.h>
+#include <asm/r4kcache.h>
+
+#include <spaces.h>
+
+/*
+ * Override default behavior to allow cached access to all valid DRAM ranges
+ */
+int __uncached_access(struct file *file, unsigned long addr)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+	if (addr >= 0x10000000 && addr < UPPERMEM_START)
+		return 1;
+	if (addr >= 0xa0000000)
+		return 1;
+	return 0;
+}
+
+/***********************************************************************
+ * Wired TLB mappings for upper memory support
+ ***********************************************************************/
+
+#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
+/* (PFN << 6) | GLOBAL | VALID | DIRTY | cacheability */
+#define ENTRYLO_CACHED(paddr)	(((paddr) >> 6) | (0x07) | (0x03 << 3))
+#define ENTRYLO_UNCACHED(paddr)	(((paddr) >> 6) | (0x07) | (0x02 << 3))
+
+/* GLOBAL | !VALID */
+#define ENTRYLO_INVALID()	(0x01)
+
+struct tlb_entry {
+	unsigned long entrylo0;
+	unsigned long entrylo1;
+	unsigned long entryhi;
+	unsigned long pagemask;
+};
+
+static struct tlb_entry __maybe_unused uppermem_mappings[] = {
+{
+	.entrylo0		= ENTRYLO_CACHED(TLB_UPPERMEM_PA),
+	.entrylo1		= ENTRYLO_INVALID(),
+	.entryhi		= TLB_UPPERMEM_VA,
+	.pagemask		= PM_256M,
+},
+};
+
+static inline void brcm_write_tlb_entry(int idx, unsigned long entrylo0,
+					unsigned long entrylo1,
+					unsigned long entryhi,
+					unsigned long pagemask)
+{
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	write_c0_entryhi(entryhi);
+	write_c0_pagemask(pagemask);
+	write_c0_index(idx);
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	tlbw_use_hazard();
+}
+
+/*
+ * This function is used instead of add_wired_entry(), because it does not
+ * have any external dependencies and is not marked __init
+ */
+static inline void brcm_add_wired_entry(unsigned long entrylo0,
+					unsigned long entrylo1,
+					unsigned long entryhi,
+					unsigned long pagemask)
+{
+	int i = read_c0_wired();
+	write_c0_wired(i + 1);
+	brcm_write_tlb_entry(i, entrylo0, entrylo1, entryhi, pagemask);
+}
+
+extern void build_tlb_refill_handler(void);
+extern void tlb_init(void);
+
+void bmips_tlb_init(void)
+{
+	if (!cpu_has_xks01) {
+		tlb_init();
+		return;
+	}
+
+	if (smp_processor_id() == 0) {
+		int i;
+		struct tlb_entry *e = uppermem_mappings;
+
+		tlb_init();
+		for (i = 0; i < ARRAY_SIZE(uppermem_mappings); i++, e++)
+			brcm_add_wired_entry(e->entrylo0, e->entrylo1,
+				e->entryhi, e->pagemask);
+		write_c0_pagemask(PM_DEFAULT_MASK);
+	} else {
+		/* bypass tlb_init() / probe_tlb() for secondary CPU */
+		cpu_data[smp_processor_id()].tlbsize = cpu_data[0].tlbsize;
+		build_tlb_refill_handler();
+	}
+}
+
+/*
+ * Initialize upper memory TLB entries
+ *
+ * On TP1 this must happen before we set up $sp/$gp .  It is always
+ * possible for stacks, task_structs, thread_info's, and other
+ * important structures to be allocated out of upper memory so
+ * this happens early on.
+ */
+asmlinkage void plat_wired_tlb_setup(void)
+{
+	int __maybe_unused i, tlbsz;
+
+	if (!cpu_has_xks01)
+		return;
+
+	/* Flush TLB.  local_flush_tlb_all() is not available yet. */
+	write_c0_entrylo0(0);
+	write_c0_entrylo1(0);
+	write_c0_pagemask(PM_DEFAULT_MASK);
+	write_c0_wired(0);
+
+	tlbsz = (read_c0_config1() >> 25) & 0x3f;
+	for (i = 0; i <= tlbsz; i++) {
+		write_c0_entryhi(UNIQUE_ENTRYHI(i));
+		write_c0_index(i);
+		mtc0_tlbw_hazard();
+		tlb_write_indexed();
+		tlbw_use_hazard();
+	}
+
+	write_c0_wired(0);
+	mtc0_tlbw_hazard();
+
+	for (i = 0; i < ARRAY_SIZE(uppermem_mappings); i++) {
+		struct tlb_entry *e = &uppermem_mappings[i];
+		brcm_add_wired_entry(e->entrylo0, e->entrylo1, e->entryhi,
+			e->pagemask);
+	}
+
+	write_c0_pagemask(PM_DEFAULT_MASK);
+}
+
+/***********************************************************************
+ * Special allocator for coherent (uncached) memory
+ * (Required for >256MB upper memory)
+ ***********************************************************************/
+
+#define CONSISTENT_DMA_SIZE	(CONSISTENT_END - CONSISTENT_BASE)
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> \
+	PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> \
+	PGDIR_SHIFT)
+#define NUM_CONSISTENT_PTES	(CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+
+/*
+ * These are the page tables (4MB each) covering uncached, DMA consistent
+ * allocations
+ */
+static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
+static DEFINE_SPINLOCK(consistent_lock);
+
+struct bmips_vm_region {
+	struct list_head	vm_list;
+	unsigned long		vm_start;
+	unsigned long		vm_end;
+	void			*vm_cac_va;
+	int			vm_active;
+};
+
+static struct bmips_vm_region consistent_head = {
+	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
+	.vm_start	= CONSISTENT_BASE,
+	.vm_end		= CONSISTENT_END,
+};
+
+static struct bmips_vm_region *
+bmips_vm_region_alloc(struct bmips_vm_region *head, size_t size, gfp_t gfp)
+{
+	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	unsigned long flags;
+	struct bmips_vm_region *c, *new;
+
+	new = kmalloc(sizeof(struct bmips_vm_region), gfp);
+	if (!new)
+		goto out;
+
+	spin_lock_irqsave(&consistent_lock, flags);
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if ((addr + size) < addr)
+			goto nospc;
+		if ((addr + size) <= c->vm_start)
+			goto found;
+		addr = c->vm_end;
+		if (addr > end)
+			goto nospc;
+	}
+
+found:
+	/*
+	 * Insert this entry _before_ the one we found.
+	 */
+	list_add_tail(&new->vm_list, &c->vm_list);
+	new->vm_start = addr;
+	new->vm_end = addr + size;
+	new->vm_active = 1;
+
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	return new;
+
+nospc:
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	kfree(new);
+out:
+	return NULL;
+}
+
+static struct bmips_vm_region *bmips_vm_region_find(struct bmips_vm_region *head,
+	unsigned long addr)
+{
+	struct bmips_vm_region *c;
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if (c->vm_active && c->vm_start == addr)
+			goto out;
+	}
+	c = NULL;
+out:
+	return c;
+}
+
+static int __init consistent_init(void)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	int ret = 0, i = 0;
+	u32 base = CONSISTENT_BASE;
+
+	do {
+		pgd = pgd_offset(&init_mm, base);
+		pud = pud_alloc(&init_mm, pgd, base);
+		if (!pud) {
+			pr_err("%s: no pud tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+		pmd = pmd_alloc(&init_mm, pud, base);
+		if (!pmd) {
+			pr_err("%s: no pmd tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+
+		pte = pte_alloc_kernel(pmd, base);
+		if (!pte) {
+			pr_err("%s: no pte tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+
+		consistent_pte[i++] = pte;
+		base += (1 << PGDIR_SHIFT);
+	} while (base < CONSISTENT_END);
+
+	return ret;
+}
+
+core_initcall(consistent_init);
+
+int plat_map_coherent(dma_addr_t dma_handle, void *cac_va, size_t size,
+		      void **uncac_va, gfp_t gfp)
+{
+	struct bmips_vm_region *c;
+	struct page *page;
+	pte_t *pte;
+	int idx;
+	u32 off;
+
+	c = bmips_vm_region_alloc(&consistent_head, size, gfp);
+	if (!c)
+		return -EINVAL;
+
+	c->vm_cac_va = cac_va;
+
+	page = virt_to_page(cac_va);
+	idx = CONSISTENT_PTE_INDEX(c->vm_start);
+	off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
+	pte = consistent_pte[idx] + off;
+
+	pr_debug("map addr %08lx idx %x off %x pte %p\n",
+		c->vm_start, idx, off, pte);
+
+	do {
+		if (off >= PTRS_PER_PTE) {
+			off = 0;
+			BUG_ON(idx >= NUM_CONSISTENT_PTES - 1);
+			pte = consistent_pte[++idx];
+		}
+
+		BUG_ON(!pte_none(*pte));
+		set_pte(pte, mk_pte(page, PAGE_KERNEL_UNCACHED));
+		page++;
+		pte++;
+		off++;
+	} while (size -= PAGE_SIZE);
+
+	*uncac_va = (void *)c->vm_start;
+	return 0;
+}
+
+void *plat_unmap_coherent(void *vaddr)
+{
+	struct bmips_vm_region *c;
+	unsigned long flags, addr;
+	void *ret = NULL;
+	pte_t *pte;
+	int idx;
+	u32 off;
+
+	spin_lock_irqsave(&consistent_lock, flags);
+	c = bmips_vm_region_find(&consistent_head, (unsigned long)vaddr);
+	if (!c) {
+		spin_unlock_irqrestore(&consistent_lock, flags);
+		pr_err("%s: invalid VA %p\n", __func__, vaddr);
+		return NULL;
+	}
+	c->vm_active = 0;
+	spin_unlock_irqrestore(&consistent_lock, flags);
+
+	ret = c->vm_cac_va;
+	addr = c->vm_start;
+
+	idx = CONSISTENT_PTE_INDEX(addr);
+	off = CONSISTENT_OFFSET(addr) & (PTRS_PER_PTE-1);
+	pte = consistent_pte[idx] + off;
+
+	pr_debug("unmap addr %08lx idx %x off %x pte %p\n",
+		addr, idx, off, pte);
+
+	do {
+		if (off >= PTRS_PER_PTE) {
+			off = 0;
+			BUG_ON(idx >= NUM_CONSISTENT_PTES - 1);
+			pte = consistent_pte[++idx];
+		}
+
+		pte_clear(&init_mm, addr, pte);
+		pte++;
+		off++;
+		addr += PAGE_SIZE;
+	} while (addr < c->vm_end);
+	flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+	spin_lock_irqsave(&consistent_lock, flags);
+	list_del(&c->vm_list);
+	spin_unlock_irqrestore(&consistent_lock, flags);
+
+	kfree(c);
+
+	return ret;
+}
+
+void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+	unsigned long flags)
+{
+	/* sanity check */
+	if ((offset + size - 1) < offset ||
+	    !size ||
+	    offset > max(KSEG0_SIZE, KSEG1_SIZE))
+		return NULL;
+
+	/* !XKS01, XKS01: uncached access to EBI/registers @ PA 1000_0000 */
+	if (offset >= 0x10000000 &&
+	    (offset + size) <= 0x20000000 &&
+	    flags == _CACHE_UNCACHED)
+		return (void *)(KSEG1 + offset);
+
+	/* !XKS01, XKS01: easy cached access to some DRAM */
+	if ((offset + size) <= KSEG0_SIZE &&
+	    flags == _CACHE_CACHABLE_NONCOHERENT)
+		return (void *)(KSEG0 + offset);
+
+	/* !XKS01 only: easy uncached access to some DRAM */
+	if ((offset + size) <= KSEG1_SIZE &&
+	    flags == _CACHE_UNCACHED)
+		return (void *)(KSEG1 + offset);
+
+	/* anything else gets mapped using page tables */
+	return NULL;
+}
+EXPORT_SYMBOL(plat_ioremap);
+
+int plat_iounmap(const volatile void __iomem *addr)
+{
+	phys_addr_t va = (unsigned long)addr;
+
+	if (va >= KSEG0 && va < (KSEG0 + KSEG0_SIZE))
+		return 1;
+	if (va >= KSEG1 && va < (KSEG1 + KSEG1_SIZE))
+		return 1;
+	return 0;
+}
+EXPORT_SYMBOL(plat_iounmap);
diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c
index d1b7b8b82ae1..4f565f2df977 100644
--- a/arch/mips/bmips/setup.c
+++ b/arch/mips/bmips/setup.c
@@ -134,6 +134,39 @@ static unsigned long dram0_size_mb;
 
 extern void bmips_tlb_init(void);
 
+static void bmips_add_memory_regions(void)
+{
+	board_tlb_init = bmips_tlb_init;
+
+	do {
+		unsigned long dram0_mb = dram0_size_mb, mb;
+
+		mb = min(dram0_mb, BRCM_MAX_LOWER_MB);
+		dram0_mb -= mb;
+
+		add_memory_region(0, mb << 20, BOOT_MEM_RAM);
+		if (!dram0_mb)
+			break;
+
+		if (cpu_has_xks01) {
+			mb = min(dram0_mb, BRCM_MAX_UPPER_MB);
+			dram0_mb -= mb;
+
+			plat_wired_tlb_setup();
+			add_memory_region(UPPERMEM_START, mb << 20, BOOT_MEM_RAM);
+			if (!dram0_mb)
+				break;
+		}
+
+#ifdef CONFIG_HIGHMEM
+		add_memory_region(HIGHMEM_START, dram0_mb << 20, BOOT_MEM_RAM);
+		break;
+#endif
+		/* Linux memory */
+		mb = dram0_size_mb - dram0_mb;
+	} while (0);
+}
+
 static char __initdata cfe_buf[COMMAND_LINE_SIZE];
 
 static inline int __init parse_ulong(const char *buf, unsigned long *val)
@@ -230,6 +263,8 @@ void __init plat_mem_setup(void)
 			q->quirk_fn();
 		}
 	}
+
+	bmips_add_memory_regions();
 }
 
 void __init device_tree_init(void)
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 4856adc8906e..f66e2f90c604 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -96,13 +96,21 @@
  */
 #define KUSEG			0x00000000
 #define KSEG0			0x80000000
+#ifdef CONFIG_XKS01
+#define KSEG1			plat_kseg1()
+#else
 #define KSEG1			0xa0000000
+#endif
 #define KSEG2			0xc0000000
 #define KSEG3			0xe0000000
 
 #define CKUSEG			0x00000000
 #define CKSEG0			0x80000000
+#ifdef CONFIG_XKS01
+#define CKSEG1			plat_kseg1()
+#else
 #define CKSEG1			0xa0000000
+#endif
 #define CKSEG2			0xc0000000
 #define CKSEG3			0xe0000000
 
diff --git a/arch/mips/include/asm/mach-bmips/dma-coherence.h b/arch/mips/include/asm/mach-bmips/dma-coherence.h
index b56380066573..9fbb6355fd8d 100644
--- a/arch/mips/include/asm/mach-bmips/dma-coherence.h
+++ b/arch/mips/include/asm/mach-bmips/dma-coherence.h
@@ -37,6 +37,12 @@ static inline int plat_device_is_coherent(struct device *dev)
 
 #define plat_post_dma_flush	bmips_post_dma_flush
 
+#define plat_map_coherent	plat_map_coherent
+extern int plat_map_coherent(dma_addr_t handle, void *cac_va, size_t size,
+			     void **uncac_va, gfp_t gfp);
+#define plat_unmap_coherent	plat_unmap_coherent
+extern void *plat_unmap_coherent(void *addr);
+
 #include <asm/mach-generic/dma-coherence.h>
 
 #endif /* __ASM_MACH_BMIPS_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-bmips/ioremap.h b/arch/mips/include/asm/mach-bmips/ioremap.h
index 52632ebc705f..e3333d1e52c6 100644
--- a/arch/mips/include/asm/mach-bmips/ioremap.h
+++ b/arch/mips/include/asm/mach-bmips/ioremap.h
@@ -9,26 +9,8 @@ static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t
 	return phys_addr;
 }
 
-static inline int is_bmips_internal_registers(phys_addr_t offset)
-{
-	if (offset >= 0xfff80000)
-		return 1;
-
-	return 0;
-}
-
-static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
-					 unsigned long flags)
-{
-	if (is_bmips_internal_registers(offset))
-		return (void __iomem *)offset;
-
-	return NULL;
-}
-
-static inline int plat_iounmap(const volatile void __iomem *addr)
-{
-	return is_bmips_internal_registers((unsigned long)addr);
-}
+extern void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+		        unsigned long flags);
+extern int plat_iounmap(const volatile void __iomem *addr);
 
-#endif /* __ASM_MACH_BMIPS_IOREMAP_H */
+#endif /* __ASM_MACH_BMIPS_GENERIC_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-bmips/kernel-entry-init.h b/arch/mips/include/asm/mach-bmips/kernel-entry-init.h
new file mode 100644
index 000000000000..48a6768cd664
--- /dev/null
+++ b/arch/mips/include/asm/mach-bmips/kernel-entry-init.h
@@ -0,0 +1,18 @@
+#ifndef __ASM_MACH_BMIPS_GENERIC_KERNEL_ENTRY_H
+#define __ASM_MACH_BMIPS_GENERIC_KERNEL_ENTRY_H
+
+	.macro kernel_entry_setup
+
+	# save arguments for CFE callback
+	sw      a0, cfe_handle
+	sw      a2, cfe_entry
+	sw      a3, cfe_seal
+
+	jal     bmips_enable_xks01
+
+	.endm
+
+	.macro  smp_slave_setup
+	.endm
+
+#endif /* __ASM_MACH_BMIPS_GENERIC_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-bmips/spaces.h b/arch/mips/include/asm/mach-bmips/spaces.h
index c59b28fd9e1d..439e05a80ac9 100644
--- a/arch/mips/include/asm/mach-bmips/spaces.h
+++ b/arch/mips/include/asm/mach-bmips/spaces.h
@@ -13,6 +13,108 @@
 /* Avoid collisions with system base register (SBR) region on BMIPS3300 */
 #include <asm/bmips-spaces.h>
 
+#include <linux/const.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cpu.h>
+
+/*
+ * 1024MB Broadcom 256+768 virtual address map
+ *
+ * 8000_0000 - 8fff_ffff: 256MB RAM @ 0000_0000, cached
+ * 9000_0000 - 9fff_ffff: 256MB EBI/Registers @ 1000_0000, uncached
+ * a000_0000 - cfff_ffff: 768MB RAM @ 2000_0000, cached
+ * d000_0000 - dfff_ffff: TBD
+ * e000_0000 - ff1f_7fff: vmalloc region
+ * ff1f_8000 - ff1f_ffff: FIXMAP
+ * ff40_0000 - ff7f_ffff: CONSISTENT region
+ *
+ * PA 5000_0000 and above are accessed through HIGHMEM (BMIPS5000 only).
+ */
+#define TLB_UPPERMEM_VA         _AC(0xc0000000, UL)
+#define TLB_UPPERMEM_PA         _AC(0x40000000, UL)
+
+#ifndef __ASSEMBLY__
+static inline unsigned long kseg0_size(void)
+{
+	switch (read_c0_prid() & PRID_IMP_MASK) {
+	case PRID_IMP_BMIPS5000:
+	case PRID_IMP_BMIPS5200:
+		return _AC(0x40000000, UL);
+	default:
+		return _AC(0x20000000, UL);
+	}
+}
+
+static inline unsigned long kseg1_size(void)
+{
+	switch (read_c0_prid() & PRID_IMP_MASK) {
+	case PRID_IMP_BMIPS5000:
+	case PRID_IMP_BMIPS5200:
+		return _AC(0x0, UL);
+	default:
+		return _AC(0x20000000, UL);
+	}
+}
+
+static inline unsigned long map_base(void)
+{
+	switch (read_c0_prid() & PRID_IMP_MASK) {
+	case PRID_IMP_BMIPS5000:
+	case PRID_IMP_BMIPS5200:
+		return _AC(0xe0000000, UL);
+	default:
+		return _AC(0xc0000000, UL);
+	}
+}
+
+static inline unsigned long brcm_max_upper_mb(void)
+{
+	switch (read_c0_prid() & PRID_IMP_MASK) {
+	case PRID_IMP_BMIPS5000:
+	case PRID_IMP_BMIPS5200:
+		return _AC(768, UL);
+	default:
+		return _AC(0, UL);
+	}
+}
+
+static inline unsigned long plat_kseg1(void)
+{
+	switch (read_c0_prid() & PRID_IMP_MASK) {
+	case PRID_IMP_BMIPS5000:
+	case PRID_IMP_BMIPS5200:
+		return 0x80000000;
+	default:
+		return 0xa0000000;
+	}
+}
+
+#define KSEG0_SIZE              kseg0_size()
+#define KSEG1_SIZE		kseg1_size()
+#define MAP_BASE		map_base()
+/* BASE and END must be 4MB-aligned (PGDIR_SIZE) */
+#define CONSISTENT_BASE         _AC(0xff400000, UL)
+#define CONSISTENT_END          _AC(0xff800000, UL)
+#define BRCM_MAX_UPPER_MB       brcm_max_upper_mb()
+#else
+
+#define TLB_UPPERMEM_VA         _AC(0xc0000000, UL)
+#define TLB_UPPERMEM_PA         _AC(0x40000000, UL)
+#define KSEG0_SIZE              _AC(0x40000000, UL)
+#define KSEG1_SIZE              _AC(0x00000000, UL)
+#define MAP_BASE                _AC(0xe0000000, UL)
+/* BASE and END must be 4MB-aligned (PGDIR_SIZE) */
+#define CONSISTENT_BASE         _AC(0xff400000, UL)
+#define CONSISTENT_END          _AC(0xff800000, UL)
+#define BRCM_MAX_UPPER_MB       _AC(768, UL)
+#endif
+
+#define BRCM_MAX_LOWER_MB	_AC(256, UL)
+
+#define UPPERMEM_START		_AC(0x20000000, UL)
+#define HIGHMEM_START		(UPPERMEM_START + (BRCM_MAX_UPPER_MB << 20))
+
 #include <asm/mach-generic/spaces.h>
 
 #endif /* __ASM_BMIPS_SPACES_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support
  2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
                   ` (5 preceding siblings ...)
  2018-01-24  1:47 ` [PATCH RFC 6/6] MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01) Florian Fainelli
@ 2018-01-26  8:31 ` Steven J. Hill
  2018-01-29 20:10   ` Florian Fainelli
  6 siblings, 1 reply; 10+ messages in thread
From: Steven J. Hill @ 2018-01-26  8:31 UTC (permalink / raw)
  To: Florian Fainelli, linux-mips; +Cc: open list, David Daney

On 01/23/2018 07:47 PM, Florian Fainelli wrote:

[...]

> 
> Florian Fainelli (6):
>   MIPS: Allow board to override TLB initialization
>   MIPS: Allow platforms to override mapping/unmapping coherent
>   MIPS: BMIPS: Avoid referencing CKSEG1
>   MIPS: Prepare for supporting eXtended KSEG0/1
>   MIPS: BMIPS: Handshake with CFE
>   MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01)
> 
I have tested these with your previous "MIPS: generic dma-coherence
inclusion" patchset on our Octeon III platforms with PCIe and saw
no issues. Thanks.

Steve


Tested-by: Steven J. Hill <steven.hill@cavium.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support
  2018-01-26  8:31 ` [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Steven J. Hill
@ 2018-01-29 20:10   ` Florian Fainelli
  0 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2018-01-29 20:10 UTC (permalink / raw)
  To: Steven J. Hill, linux-mips; +Cc: open list, David Daney

On 01/26/2018 12:31 AM, Steven J. Hill wrote:
> On 01/23/2018 07:47 PM, Florian Fainelli wrote:
> 
> [...]
> 
>>
>> Florian Fainelli (6):
>>   MIPS: Allow board to override TLB initialization
>>   MIPS: Allow platforms to override mapping/unmapping coherent
>>   MIPS: BMIPS: Avoid referencing CKSEG1
>>   MIPS: Prepare for supporting eXtended KSEG0/1
>>   MIPS: BMIPS: Handshake with CFE
>>   MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01)
>>
> I have tested these with your previous "MIPS: generic dma-coherence
> inclusion" patchset on our Octeon III platforms with PCIe and saw
> no issues. Thanks.

Good, thanks for testing, at least I did not intentionally break other
platforms, now if I could this to work on 4.15 or newer, that'd be great.
--
Florian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1
  2018-01-24  1:47 ` [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1 Florian Fainelli
@ 2018-02-02 17:38   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2018-02-02 17:38 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: linux-mips, Florian Fainelli, Ralf Baechle, Kevin Cernekee,
	James Hogan, Paul Burton, Matt Redfearn, Huacai Chen,
	Kate Stewart, Greg Kroah-Hartman, Marcin Nowakowski,
	Andrew Morton, Eric W. Biederman, Ingo Molnar, David Howells,
	Kees Cook, Thomas Meyer, Bryan O'Donoghue, Robin Murphy,
	Michal Hocko, Lucas Stach, Vladimir Murzin, Bart Van Assche,
	open list

On Tue, 23 Jan 2018, Florian Fainelli wrote:

> bmips_smp_movevec() references the CKSEG1 constant, which is about to be
> updated in order to support processors that might enable eXtended
> KSEG0/1. In doing so, we will generate a reference to a function, which
> is obviously not permissible within assembly. Fortunately,
> bmips_smp_movevec() is only used on BMIPS4350 which does not support
> eXtended KSEG0/1.

 Can you please avoid replacing the macro with a hardcoded magic number 
though, so that it retains the high-level meaning?

 Define another macro, say MIPS_ARCH_CKSEG1, and use it here instead, and 
possibly elsewhere too.  You could complement it with BMIPS_XKS01_CKSEG1 
if necessary too (I haven't thoroughly looked through your patches).

  Maciej

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-02-02 17:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-24  1:47 [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Florian Fainelli
2018-01-24  1:47 ` [PATCH RFC 1/6] MIPS: Allow board to override TLB initialization Florian Fainelli
2018-01-24  1:47 ` [PATCH RFC 2/6] MIPS: Allow platforms to override mapping/unmapping coherent Florian Fainelli
2018-01-24  1:47 ` [PATCH RFC 3/6] MIPS: BMIPS: Avoid referencing CKSEG1 Florian Fainelli
2018-02-02 17:38   ` Maciej W. Rozycki
2018-01-24  1:47 ` [PATCH RFC 4/6] MIPS: Prepare for supporting eXtended KSEG0/1 Florian Fainelli
2018-01-24  1:47 ` [PATCH RFC 5/6] MIPS: BMIPS: Handshake with CFE Florian Fainelli
2018-01-24  1:47 ` [PATCH RFC 6/6] MIPS: BMIPS: Add support for eXtended KSEG0/1 (XKS01) Florian Fainelli
2018-01-26  8:31 ` [PATCH RFC 0/6] MIPS: Broadcom eXtended KSEG0/1 support Steven J. Hill
2018-01-29 20:10   ` Florian Fainelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).