Skip to content

Commit 8e02c3b

Browse files
committed
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: Jiaxun Yang <jiaxun.yang@flygoat.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 614d7e9 commit 8e02c3b

File tree

7 files changed

+37
-17
lines changed

7 files changed

+37
-17
lines changed

arch/loongarch/include/asm/addrspace.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ extern unsigned long vm_map_base;
3737
#define UNCACHE_BASE CSR_DMW0_BASE
3838
#endif
3939

40+
#ifndef WRITECOMBINE_BASE
41+
#define WRITECOMBINE_BASE CSR_DMW2_BASE
42+
#endif
43+
4044
#define DMW_PABITS 48
4145
#define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1)
4246

arch/loongarch/include/asm/io.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
2525
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
2626
unsigned long prot_val)
2727
{
28-
if (prot_val & _CACHE_CC)
28+
switch (prot_val & _CACHE_MASK) {
29+
case _CACHE_CC:
2930
return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
30-
else
31+
case _CACHE_SUC:
3132
return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
33+
case _CACHE_WUC:
34+
return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset);
35+
default:
36+
return NULL;
37+
}
3238
}
3339

3440
#define ioremap(offset, size) \

arch/loongarch/include/asm/loongarch.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@
877877
#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */
878878
#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */
879879

880-
/* Direct Map window 0/1 */
880+
/* Direct Map window 0/1/2/3 */
881881
#define CSR_DMW0_PLV0 _CONST64_(1 << 0)
882882
#define CSR_DMW0_VSEG _CONST64_(0x8000)
883883
#define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS)
@@ -889,6 +889,14 @@
889889
#define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS)
890890
#define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
891891

892+
#define CSR_DMW2_PLV0 _CONST64_(1 << 0)
893+
#define CSR_DMW2_MAT _CONST64_(2 << 4)
894+
#define CSR_DMW2_VSEG _CONST64_(0xa000)
895+
#define CSR_DMW2_BASE (CSR_DMW2_VSEG << DMW_PABITS)
896+
#define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0)
897+
898+
#define CSR_DMW3_INIT 0x0
899+
892900
/* Performance Counter registers */
893901
#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */
894902
#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */

arch/loongarch/include/asm/stackframe.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@
3838
cfi_restore \reg \offset \docfi
3939
.endm
4040

41+
.macro SETUP_DMWINS temp
42+
li.d \temp, CSR_DMW0_INIT # WUC, PLV0, 0x8000 xxxx xxxx xxxx
43+
csrwr \temp, LOONGARCH_CSR_DMWIN0
44+
li.d \temp, CSR_DMW1_INIT # CAC, PLV0, 0x9000 xxxx xxxx xxxx
45+
csrwr \temp, LOONGARCH_CSR_DMWIN1
46+
li.d \temp, CSR_DMW2_INIT # WUC, PLV0, 0xa000 xxxx xxxx xxxx
47+
csrwr \temp, LOONGARCH_CSR_DMWIN2
48+
li.d \temp, CSR_DMW3_INIT # 0x0, unused
49+
csrwr \temp, LOONGARCH_CSR_DMWIN3
50+
.endm
51+
4152
/* Jump to the runtime virtual address. */
4253
.macro JUMP_VIRT_ADDR temp1 temp2
4354
li.d \temp1, CACHE_BASE

arch/loongarch/kernel/head.S

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
4444
SYM_CODE_START(kernel_entry) # kernel entry point
4545

4646
/* Config direct window and set PG */
47-
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx
48-
csrwr t0, LOONGARCH_CSR_DMWIN0
49-
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
50-
csrwr t0, LOONGARCH_CSR_DMWIN1
51-
47+
SETUP_DMWINS t0
5248
JUMP_VIRT_ADDR t0, t1
5349

5450
/* Enable PG */
@@ -124,11 +120,8 @@ SYM_CODE_END(kernel_entry)
124120
* function after setting up the stack and tp registers.
125121
*/
126122
SYM_CODE_START(smpboot_entry)
127-
li.d t0, CSR_DMW0_INIT # UC, PLV0
128-
csrwr t0, LOONGARCH_CSR_DMWIN0
129-
li.d t0, CSR_DMW1_INIT # CA, PLV0
130-
csrwr t0, LOONGARCH_CSR_DMWIN1
131123

124+
SETUP_DMWINS t0
132125
JUMP_VIRT_ADDR t0, t1
133126

134127
#ifdef CONFIG_PAGE_SIZE_4KB

arch/loongarch/power/suspend_asm.S

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter)
7373
* Reload all of the registers and return.
7474
*/
7575
SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
76-
li.d t0, CSR_DMW0_INIT # UC, PLV0
77-
csrwr t0, LOONGARCH_CSR_DMWIN0
78-
li.d t0, CSR_DMW1_INIT # CA, PLV0
79-
csrwr t0, LOONGARCH_CSR_DMWIN1
80-
76+
SETUP_DMWINS t0
8177
JUMP_VIRT_ADDR t0, t1
8278

8379
/* Enable PG */

drivers/firmware/efi/libstub/loongarch.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
7474
/* Config Direct Mapping */
7575
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
7676
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
77+
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
78+
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3);
7779

7880
real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
7981

0 commit comments

Comments
 (0)