aboutsummaryrefslogtreecommitdiff
path: root/tcl/target/esp32c6.cfg
blob: e1ef10a85214027bc17d3aa04249d1f3fb7c444d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# SPDX-License-Identifier: GPL-2.0-or-later
#

# Source the ESP common configuration file.
source [find target/esp_common.cfg]

# Target specific global variables
set _CHIPNAME 					"riscv"
set _CPUTAPID 					0x0000dc25
set _ESP_ARCH					"riscv"
set _ONLYCPU					1
set _ESP_SMP_TARGET				0
set _ESP_SMP_BREAK 				0
set _ESP_EFUSE_MAC_ADDR_REG  	0x600B0844

# Target specific functions should be implemented for each riscv chips.
proc riscv_wdt_disable { } {
    # Halt event can occur during config phase (before "init" is done).
    # Ignore it since mww commands don't work at that time.
    if { [string compare [command mode] config] == 0 } {
        return
    }

    # Timer Group 0 & 1 WDTs
    mww 0x60008064 0x50D83AA1
    mww 0x60008048 0
    mww 0x60009064 0x50D83AA1
    mww 0x60009048 0
    # LP_WDT_RTC
    mww 0x600b1c18 0x50D83AA1
    mww 0x600B1C00 0
    # LP_WDT_SWD
    mww 0x600b1c20 0x50D83AA1
    mww 0x600b1c1c 0x40000000
}

proc riscv_soc_reset { } {
	global _RISCV_DMCONTROL _RISCV_SB_CS _RISCV_SB_ADDR0 _RISCV_SB_DATA0

    riscv dmi_write $_RISCV_DMCONTROL 		0x80000001
    riscv dmi_write $_RISCV_SB_CS 			0x48000
    riscv dmi_write $_RISCV_SB_ADDR0 		0x600b1034
    riscv dmi_write $_RISCV_SB_DATA0		0x80000000
    # clear dmactive to clear sbbusy otherwise debug module gets stuck
    riscv dmi_write $_RISCV_DMCONTROL 		0

    riscv dmi_write $_RISCV_SB_CS 			0x48000
    riscv dmi_write $_RISCV_SB_ADDR0 		0x600b1038
    riscv dmi_write $_RISCV_SB_DATA0 		0x10000000

    # clear dmactive to clear sbbusy otherwise debug module gets stuck
    riscv dmi_write $_RISCV_DMCONTROL 		0
    riscv dmi_write $_RISCV_DMCONTROL 		0x40000001
    # Here debugger reads dmstatus as 0xc03a2

    # Wait for the reset to happen
    sleep 10
    poll
    # Here debugger reads dmstatus as 0x3a2

    # Disable the watchdogs again
    riscv_wdt_disable

    # Here debugger reads anyhalted and allhalted bits as set (0x3a2)
    # We will clean allhalted state by resuming the core.
    riscv dmi_write $_RISCV_DMCONTROL 		0x40000001

    # Put the hart back into reset state. Note that we need to keep haltreq set.
    riscv dmi_write $_RISCV_DMCONTROL 		0x80000003
}

proc riscv_memprot_is_enabled { } {
	global _RISCV_ABS_CMD _RISCV_ABS_DATA0

	# If IRAM/DRAM split is enabled TOR address match mode is used.
    # If IRAM/DRAM split is disabled NAPOT mode is used.
	# In order to determine if the IRAM/DRAM regions are protected against RWX/RW,
	# it is necessary to first read the mode and then apply the appropriate method for checking.
	# We can understand the mode reading pmp5cfg in pmpcfg1 register.
	# If it is none we know that pmp6cfg and pmp7cfg is in TOR mode.

	# Read pmpcfg1 and extract into 8-bit variables.
	riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
	set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]

	set pmp5cfg [expr {($pmpcfg1 >> (8 * 1)) & 0xFF}]
	set pmp6cfg [expr {($pmpcfg1 >> (8 * 2)) & 0xFF}]
	set pmp7cfg [expr {($pmpcfg1 >> (8 * 3)) & 0xFF}]

	set IRAM_LOW 	0x40800000
	set IRAM_HIGH 	0x40880000
	set DRAM_LOW 	0x40800000
	set DRAM_HIGH 	0x40880000
	set PMP_RWX     0x07
	set PMP_RW     	0x03
	set PMP_A		[expr {($pmp5cfg >> 3) & 0x03}]

	if {$PMP_A == 0} {
		# TOR mode used to protect valid address space.

		# Read PMPADDR 5-7
		riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
		set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
		riscv dmi_write $_RISCV_ABS_CMD 0x2203b6
		set pmpaddr6 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
		riscv dmi_write $_RISCV_ABS_CMD 0x2203b7
		set pmpaddr7 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

		# The lock bit remains unset during the execution of the 2nd stage bootloader.
		# Thus we do not perform a lock bit check for IRAM and DRAM regions.

		# Check OpenOCD can write and execute from IRAM.
		if {$pmpaddr5 >= $IRAM_LOW && $pmpaddr6 <= $IRAM_HIGH} {
			if {($pmp5cfg & $PMP_RWX) != 0 || ($pmp6cfg & $PMP_RWX) != $PMP_RWX} {
				return 1
			}
		}

		# Check OpenOCD can read/write  entire DRAM region.
		if {$pmpaddr7 >= $DRAM_LOW && $pmpaddr7 <= $DRAM_HIGH} {
			if {($pmp7cfg & $PMP_RW) != $PMP_RW} {
				return 1
			}
		}
	} elseif {$PMP_A == 3} {
		# NAPOT mode used to protect valid address space.

		# Read PMPADDR 5
		riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
		set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0]}]

		# Expected value written to the pmpaddr5
		set pmpaddr_napot [expr {($IRAM_LOW | (($IRAM_HIGH - $IRAM_LOW - 1) >> 1)) >> 2}]
		if {($pmpaddr_napot != $pmpaddr5) ||  ($pmp5cfg & $PMP_RWX) != $PMP_RWX} {
			return 1
		}
	}

	return 0
}

create_esp_target $_ESP_ARCH