NanoPayload

Annotated stage2/cpu_op.S

196:5dc17c3c1773
2016-05-14 Paul Boddie Let the power button switch between tasks, using an IRQ that occurs when the power button signal is low (edge-triggered IRQs do not seem to work). Introduced a general IRQ-clearing function.
paul@186 1
/*
paul@186 2
 * CPU-specific routines originally from U-Boot.
paul@186 3
 * See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c
paul@186 4
 * See: u-boot/arch/mips/include/asm/cacheops.h
paul@186 5
 *
paul@186 6
 * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
paul@186 7
 * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
paul@186 8
 *
paul@186 9
 * This program is free software; you can redistribute it and/or
paul@186 10
 * modify it under the terms of the GNU General Public License as
paul@186 11
 * published by the Free Software Foundation; either version 2 of
paul@186 12
 * the License, or (at your option) any later version.
paul@186 13
 *
paul@186 14
 * This program is distributed in the hope that it will be useful,
paul@186 15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@186 16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@186 17
 * GNU General Public License for more details.
paul@186 18
 *
paul@186 19
 * You should have received a copy of the GNU General Public License
paul@186 20
 * along with this program; if not, write to the Free Software
paul@186 21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@186 22
 * Boston, MA  02110-1301, USA
paul@186 23
 */
paul@186 24
paul@186 25
#include "mips.h"
paul@186 26
#include "paging.h"
paul@186 27
#include "sdram.h"
paul@186 28
paul@186 29
.text
paul@186 30
.globl flush_icache_tag
paul@186 31
.globl flush_icache_region
paul@186 32
.globl flush_icache_config
paul@186 33
.globl flush_dcache_region
paul@186 34
.globl handle_error_level
paul@186 35
.globl enable_interrupts
paul@186 36
.globl init_interrupts
paul@186 37
.globl invoke_task
paul@192 38
.globl enter_task
paul@186 39
.globl configure_tlb
paul@186 40
.globl map_page_set_index
paul@186 41
.globl map_page_index_op
paul@186 42
.globl map_page_op
paul@186 43
.set noreorder
paul@186 44
paul@186 45
paul@186 46
paul@186 47
flush_icache_tag:
paul@186 48
	mtc0 $zero, CP0_TAGLO
paul@186 49
	mtc0 $zero, CP0_TAGHI
paul@186 50
	jr $ra
paul@186 51
	nop
paul@186 52
paul@186 53
paul@186 54
paul@186 55
flush_icache_region:
paul@186 56
	cache Index_Store_Tag_I, 0($a0)
paul@186 57
	jr $ra
paul@186 58
	nop
paul@186 59
paul@186 60
paul@186 61
paul@186 62
flush_icache_config:
paul@186 63
	move $t3, $zero
paul@186 64
	mfc0 $t3, CP0_CONFIG, 7
paul@186 65
	nop
paul@186 66
	ori $t3, 2
paul@186 67
	mtc0 $t3, CP0_CONFIG, 7
paul@186 68
	jr $ra
paul@186 69
	nop
paul@186 70
paul@186 71
paul@186 72
paul@186 73
flush_dcache_region:
paul@186 74
	cache Index_Writeback_Inv_D, 0($a0)
paul@186 75
	jr $ra
paul@186 76
	nop
paul@186 77
paul@186 78
paul@186 79
paul@186 80
handle_error_level:
paul@186 81
	mfc0 $t3, CP0_STATUS
paul@188 82
	li $t4, ~STATUS_ERL
paul@186 83
	and $t3, $t3, $t4
paul@186 84
	mtc0 $t3, CP0_STATUS
paul@186 85
	jr $ra
paul@186 86
	nop
paul@186 87
paul@186 88
paul@186 89
paul@186 90
enable_interrupts:
paul@186 91
	mfc0 $t3, CP0_STATUS
paul@188 92
	ori $t3, $t3, STATUS_IRQ | STATUS_IE
paul@186 93
	mtc0 $t3, CP0_STATUS
paul@186 94
	jr $ra
paul@186 95
	nop
paul@186 96
paul@186 97
paul@186 98
paul@186 99
init_interrupts:
paul@186 100
paul@186 101
	/* Set exception registers. */
paul@186 102
paul@186 103
	mtc0 $zero, CP0_WATCHLO
paul@188 104
	li $t3, CAUSE_IV	/* IV = 1 (use 0x80000200 for interrupts) */
paul@186 105
	mtc0 $t3, CP0_CAUSE
paul@186 106
	mfc0 $t4, CP0_STATUS
paul@188 107
	li $t3, ~STATUS_BEV
paul@186 108
	and $t3, $t3, $t4
paul@186 109
	mtc0 $t3, CP0_STATUS
paul@186 110
	jr $ra
paul@186 111
	nop
paul@186 112
paul@186 113
paul@186 114
paul@186 115
/* (u8 asid, u32 *base, u32 *stack_pointer) */
paul@186 116
paul@186 117
invoke_task:
paul@186 118
	mtc0 $a0, CP0_ENTRYHI
paul@186 119
	nop
paul@186 120
	move $t4, $a2		/* use arguments before they are overwritten */
paul@186 121
	lw $sp, 0($t4)		/* set the stack pointer */
paul@186 122
	move $t3, $a1		/* load parameters from the stored registers */
paul@186 123
	lw $a0, 16($t3)
paul@186 124
	lw $a1, 20($t3)
paul@186 125
	lw $a2, 24($t3)
paul@186 126
	lw $a3, 28($t3)
paul@186 127
	lw $t9, 100($t3)
paul@186 128
	lw $gp, 104($t3)
paul@186 129
	mtc0 $t9, CP0_EPC
paul@192 130
paul@192 131
enter_task:
paul@186 132
	mfc0 $t3, CP0_STATUS
paul@192 133
	ori $t3, $t3, STATUS_EXL | STATUS_UM
paul@196 134
	/* li $t4, STATUS_CP0	** flag resides in the upper 16 bits, needed... */
paul@196 135
	/* or $t3, $t3, $t4	** for debugging by accessing CP0 in user mode */
paul@186 136
	mtc0 $t3, CP0_STATUS
paul@186 137
	eret
paul@186 138
	nop
paul@186 139
paul@186 140
paul@186 141
paul@186 142
configure_tlb:
paul@186 143
	mtc0 $zero, CP0_CONTEXT
paul@191 144
	mtc0 $a0, CP0_WIRED	/* first random entry is defined by the parameter */
paul@186 145
	mfc0 $v0, CP0_CONFIG	/* return the limit */
paul@186 146
	jr $ra
paul@186 147
	nop
paul@186 148
paul@186 149
paul@186 150
paul@186 151
/* (u32 index) */
paul@186 152
paul@186 153
map_page_set_index:
paul@186 154
	mtc0 $a0, CP0_INDEX
paul@186 155
	jr $ra
paul@186 156
	nop
paul@186 157
paul@186 158
paul@186 159
paul@186 160
/* (u32 lower, u32 upper, u32 start, u32 pagemask) */
paul@186 161
paul@186 162
map_page_index_op:
paul@186 163
	jal map_page_op_setup
paul@186 164
	nop
paul@186 165
paul@186 166
	tlbwi
paul@186 167
	jr $ra
paul@186 168
	nop
paul@186 169
paul@186 170
paul@186 171
paul@186 172
/* (u32 lower, u32 upper, u32 start, u32 pagemask) */
paul@186 173
paul@186 174
map_page_op:
paul@186 175
	jal map_page_op_setup
paul@186 176
	nop
paul@186 177
paul@186 178
	tlbwr
paul@186 179
	jr $ra
paul@186 180
	nop
paul@186 181
paul@186 182
paul@186 183
paul@186 184
/* (u32 lower, u32 upper, u32 start, u32 pagemask) */
paul@186 185
paul@186 186
map_page_op_setup:
paul@186 187
	mtc0 $a3, CP0_PAGEMASK
paul@186 188
paul@186 189
	/* Set physical address. */
paul@186 190
paul@186 191
	mtc0 $a0, CP0_ENTRYLO0
paul@186 192
	mtc0 $a1, CP0_ENTRYLO1
paul@186 193
paul@186 194
	/* Set virtual address. */
paul@186 195
paul@186 196
	mtc0 $a2, CP0_ENTRYHI
paul@186 197
	jr $ra
paul@186 198
	nop
paul@186 199
paul@186 200
paul@186 201
paul@186 202
.set reorder