Commit 8e02c3b7 authored by Huacai Chen's avatar Huacai Chen

LoongArch: Add writecombine support for DMW-based ioremap()

Currently, only TLB-based ioremap() support writecombine, so add the
counterpart for DMW-based ioremap() with help of DMW2. The base address
(WRITECOMBINE_BASE) is configured as 0xa000000000000000.

DMW3 is unused by kernel now, however firmware may leave garbage in them
and interfere kernel's address mapping. So clear it as necessary.

BTW, centralize the DMW configuration to macro SETUP_DMWINS.
Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 614d7e99
...@@ -37,6 +37,10 @@ extern unsigned long vm_map_base; ...@@ -37,6 +37,10 @@ extern unsigned long vm_map_base;
#define UNCACHE_BASE CSR_DMW0_BASE #define UNCACHE_BASE CSR_DMW0_BASE
#endif #endif
#ifndef WRITECOMBINE_BASE
#define WRITECOMBINE_BASE CSR_DMW2_BASE
#endif
#define DMW_PABITS 48 #define DMW_PABITS 48
#define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1) #define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1)
......
...@@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size); ...@@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size, static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val) unsigned long prot_val)
{ {
if (prot_val & _CACHE_CC) switch (prot_val & _CACHE_MASK) {
case _CACHE_CC:
return (void __iomem *)(unsigned long)(CACHE_BASE + offset); return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
else case _CACHE_SUC:
return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset); return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
case _CACHE_WUC:
return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset);
default:
return NULL;
}
} }
#define ioremap(offset, size) \ #define ioremap(offset, size) \
......
...@@ -877,7 +877,7 @@ ...@@ -877,7 +877,7 @@
#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ #define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */
#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ #define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */
/* Direct Map window 0/1 */ /* Direct Map window 0/1/2/3 */
#define CSR_DMW0_PLV0 _CONST64_(1 << 0) #define CSR_DMW0_PLV0 _CONST64_(1 << 0)
#define CSR_DMW0_VSEG _CONST64_(0x8000) #define CSR_DMW0_VSEG _CONST64_(0x8000)
#define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS) #define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS)
...@@ -889,6 +889,14 @@ ...@@ -889,6 +889,14 @@
#define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS)
#define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
#define CSR_DMW2_PLV0 _CONST64_(1 << 0)
#define CSR_DMW2_MAT _CONST64_(2 << 4)
#define CSR_DMW2_VSEG _CONST64_(0xa000)
#define CSR_DMW2_BASE (CSR_DMW2_VSEG << DMW_PABITS)
#define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0)
#define CSR_DMW3_INIT 0x0
/* Performance Counter registers */ /* Performance Counter registers */
#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */
#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */
......
...@@ -38,6 +38,17 @@ ...@@ -38,6 +38,17 @@
cfi_restore \reg \offset \docfi cfi_restore \reg \offset \docfi
.endm .endm
.macro SETUP_DMWINS temp
li.d \temp, CSR_DMW0_INIT # WUC, PLV0, 0x8000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN0
li.d \temp, CSR_DMW1_INIT # CAC, PLV0, 0x9000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN1
li.d \temp, CSR_DMW2_INIT # WUC, PLV0, 0xa000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN2
li.d \temp, CSR_DMW3_INIT # 0x0, unused
csrwr \temp, LOONGARCH_CSR_DMWIN3
.endm
/* Jump to the runtime virtual address. */ /* Jump to the runtime virtual address. */
.macro JUMP_VIRT_ADDR temp1 temp2 .macro JUMP_VIRT_ADDR temp1 temp2
li.d \temp1, CACHE_BASE li.d \temp1, CACHE_BASE
......
...@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); ...@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
SYM_CODE_START(kernel_entry) # kernel entry point SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */ /* Config direct window and set PG */
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx SETUP_DMWINS t0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN1
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ /* Enable PG */
...@@ -124,11 +120,8 @@ SYM_CODE_END(kernel_entry) ...@@ -124,11 +120,8 @@ SYM_CODE_END(kernel_entry)
* function after setting up the stack and tp registers. * function after setting up the stack and tp registers.
*/ */
SYM_CODE_START(smpboot_entry) SYM_CODE_START(smpboot_entry)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWINS t0
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB #ifdef CONFIG_PAGE_SIZE_4KB
......
...@@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) ...@@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter)
* Reload all of the registers and return. * Reload all of the registers and return.
*/ */
SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL) SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
li.d t0, CSR_DMW0_INIT # UC, PLV0 SETUP_DMWINS t0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ /* Enable PG */
......
...@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, ...@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
/* Config Direct Mapping */ /* Config Direct Mapping */
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3);
real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment