1 # Testsuite for the ARM reference interrupt controller.
2 # This testsuite tries to exercise just about every aspect of this
3 # component simulation.
5 # Copyright (C) 1999 Red Hat
7 if {! $sidtarget(arm)} then { untested "hw-interrupt-arm/ref not available"; return }
9 # The number of available regular interrupt lines.
12 # A convenience variable.
13 set all_ones 0xFFFFFFFF
15 set test "sid configuration"
16 sid_config_component_test "arm-intr.conf" \
17 "load [sid_find_file libinterrupt.la] interrupt_component_library" \
18 "hw-interrupt-arm/ref"
23 if {[sid_start "arm-intr.conf"]} {
31 # A pin we use again, and again, and again.
32 set probe_pin [sid_cmd "sid::pin::new"]
35 # Set up an array of triggerpoint sensor pins (connected to the victim).
36 # Maintain another array that counts the number of times the triggerpoints are hit.
38 catch {unset watchpins triggercount}
40 {interrupt fast-interrupt irq-raw-status irq-enable-register fiq-raw-status fiq-enable-register} {
41 set test "establish a triggerpoint for watchable state variable: $watchable"
42 set watchpins($watchable) [sid_cmd "sid::pin::new"]
43 sid_cmd "set triggercount($watchable) 0"
45 "set hook_driven_h4($watchpins($watchable)) {global triggercount driven_h4_value; incr triggercount($watchable) }"
47 # Some limited URL encoding hacks.
48 # see sid/include/sidwatchutil.h for the rules.
49 regsub -all -- "-" $watchable "%2D" watchEnc
50 set result [sid_cmd "sid::component::connect_pin $victim watch:${watchEnc}:change $watchpins($watchable)"]
51 set w [sid_cmd "sid::component::attribute_names_in_category $victim watchable"]
52 if {$result == "ok"} { pass $test } else { fail "$test -- $result" }
56 # There are no attributes for this component, but let's do this for good measure.
57 set test "attribute list"
58 sid_assert_success "sid::component::attribute_names $victim"
61 # Check for presence of output pins.
62 set test "get fast-irq pin"
63 sid_assert_success "sid::component::find_pin $victim fast-interrupt"
64 set test "get irq pin"
65 sid_assert_success "sid::component::find_pin $victim interrupt"
68 # Check for presence of input pins. Record the names given to them by
69 # the Tcl bridge--we use them later.
70 set test "get reset pin"
71 if {[set reset_pin [sid_cmd "sid::component::find_pin $victim reset"]] != ""} {
77 set test "get fast interrupt source pin"
78 if {[set firq_source [sid_cmd "sid::component::find_pin $victim fast-interrupt-source"]] != ""} {
84 # Check for all 32 interrupt input lines.
85 for {set i 0} {$i < $numLines} {incr i} {
86 set test "get interrupt-source-$i pin"
87 if {[set irq_source($i) [sid_cmd "sid::component::find_pin $victim interrupt-source-$i"]] != ""} {
95 # Check for the presence of the register set (a named bus). Record the
96 # name given to it by sid_cmd, as we'll use it throughout this
98 set test "get irq-register bus"
99 if {[set irqbus [sid_cmd "sid::component::find_bus $victim irq-registers"]] != ""} {
105 set test "get fiq-register bus"
106 if {[set fiqbus [sid_cmd "sid::component::find_bus $victim fiq-registers"]] != ""} {
114 # Write to reserved fields. Just make sure these do nothing.
115 foreach location {0x0 0x1} {
116 set test "writing to reserved irq-register (offset $location)"
117 sid_assert_success "sid::bus::write_h4_l4 $irqbus $location $all_ones"
119 foreach location {0x0 0x4} {
120 set test "writing to reserved fiq-register (offset $location)"
121 sid_assert_success "sid::bus::write_h4_l4 $fiqbus $location $all_ones"
124 # Read from reserved fields. Again, ensure nothing bad happens.
125 foreach location {0xC 0x10} {
126 set test "reading from reserved irq-register (offset $location)"
127 sid_assert_success "sid::bus::read_h4_l4 $irqbus $location"
129 foreach location {0x10C} {
130 set test "reading from reserved fiq-register (offset $location)"
131 sid_assert_success "sid::bus::read_h4_l4 $fiqbus $location"
134 set test "Save state"
135 set state [sid_cmd "sid::component::attribute_value $victim state-snapshot"]
136 if {$state != ""} then { pass $test } else { fail $test }
138 # Allow interrupts from any source.
139 # This is a basic version of the more complete testing that happens
140 # further on in this script.
142 foreach pattern {0x0 0x12345678 0x55555555 0xAAAAAAAA 0xFFFFFFFF} {
143 set test "disable all interrupt lines"
144 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
146 set test "validate all interrupt lines are disabled"
147 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
149 set status [lindex $result 0]
150 if {[lindex $result 0] == "ok"} {
151 if {[lindex $result 1] == 0} { pass $test } else { fail $test }
153 fail "$test (bus error)"
156 set test "initialise set of enabled interrupt lines"
157 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 $pattern"
159 set test "validate set of enabled interrupt lines"
160 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
161 set status [lindex $result 0]
162 if {[lindex $result 0] == "ok"} {
163 if {[lindex $result 1] == $pattern} { pass $test } else { fail $test }
165 fail "$test (bus error)"
169 set test "Repeat Save state"
170 set rpstate [sid_cmd "sid::component::attribute_value $victim state-snapshot"]
171 set comp_res [string compare $state $rpstate]
172 if {$comp_res != 0} then { pass $test } else { fail $test }
174 set test "Restore State"
175 set ok [sid_cmd "sid::component::set_attribute_value $victim state-snapshot [list $state]"]
176 if {$ok == "ok"} then { pass $test } else { fail $test }
178 # At the completion of this test, all interrupts *should* be enabled.
181 # Generate an interrupt on each of the regular interrupt lines.
182 # Once it is acknowledged, suspend the interrupt source.
184 # This is a double nested loop -- 32*32 tests are performed to make
185 # sure that other interrupt lines going high does not invoke an
186 # interrupt (ie. to ensure that the masking works correctly for all
189 sid_cmd "set hook_driven_h4($probe_pin) {
190 global driven_h4_value interrupted
191 # Make the pin values sensible.
192 # The pin values are normally negated in the controller to make it
193 # easy to connect this component to related CPUs like the ARM7.
194 if \[expr \$driven_h4_value == 0\] {
201 sid_cmd "sid::component::connect_pin $victim interrupt $probe_pin"
204 for {set i 0} {$i < $numLines} {incr i} {
205 set test "disable all interrupt lines"
206 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
208 set test "validate all interrupt lines are disabled"
209 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
210 if {[lindex $result 0] == "ok"} {
211 set val [lindex $result 1]
218 fail "$test -- [lindex $result 0]"
221 set test "enable interrupt line $i"
222 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 [expr 1 << $i]"
224 set test "validate only interrupt line $i is enabled"
225 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
226 if {[lindex $result 0] == "ok"} {
227 if {[lindex $result 1] != [expr 1 << $i]} {
233 fail "$test -- [lindex $result 0]"
236 for {set j 0} {$j < $numLines} {incr j} {
237 sid_cmd "set interrupted 0"
239 # Raise an interrupt on interrupt line `j'.
240 sid_cmd "sid::pin::driven_h4 $irq_source($j) 1"
242 if {$i == $j} { set test "permitting" } else { set test "masking" }
243 append test " interrupt from interrupt $j when enabling interrupt $i only"
245 set result [sid_cmd "set interrupted"]
246 if {$result == "1"} {
249 set test "bit $i is set in the masked status register"
250 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0"]
251 if {[lindex $result 0] == "ok"} {
252 if {[lindex $result 1] != [expr 1 << $i]} {
259 fail "$test -- [lindex $result 0]"
275 # Lower the interrupt source.
276 sid_cmd "sid::pin::driven_h4 $irq_source($j) 0"
279 if {!$failures} { pass "interrupt masking" }
280 sid_cmd "sid::component::disconnect_pin $victim interrupt $probe_pin"
282 # Disable the fast interrupt.
283 set test "disable fast interrupt"
284 sid_assert_success "sid::bus::write_h4_l4 $fiqbus 0xC $all_ones"
286 set test "validate fast interrupt disabled"
287 set result [sid_cmd "sid::bus::read_h4_l4 $fiqbus 0x8"]
288 set status [lindex $result 0]
289 if {$status == "ok"} {
290 if {[lindex $result 1] == "0"} { pass $test } else { fail $test }
292 fail "$test (bus error; status $status)"
295 # Enable the fast interrupt.
296 set test "enable fast interrupt"
297 sid_assert_success "sid::bus::write_h4_l4 $fiqbus 0x8 1"
299 set test "validate fast interrupt is enabled"
300 set result [sid_cmd "sid::bus::read_h4_l4 $fiqbus 0x8"]
301 set status [lindex $result 0]
302 if {$status == "ok"} {
305 fail "$test (bus error; status $status)"
308 # Generate a fast interrupt.
309 set test "fast interrupt"
311 sid_cmd "set interrupted 0"
312 sid_cmd "sid::component::connect_pin $victim fast-interrupt $probe_pin"
313 sid_cmd "sid::pin::driven_h4 $firq_source 1"
314 if {[sid_cmd "set interrupted"] == 1} {
320 # Clear the interrupt.
321 sid_cmd "sid::pin::driven_h4 $firq_source 0"
322 sid_cmd "sid::component::disconnect_pin $victim fast-interrupt $probe_pin"
325 # Test the programmed interrupt. After writing to the appropriate
326 # register in the interrupt controller, there should be a pending
327 # interrupt from interrupt no. 1.
329 sid_cmd "set interrupted 0"
331 set test "disable all interrupt lines"
332 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
334 set test "enable interrupt line 1 only"
335 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 2"
336 sid_cmd "sid::pin::driven_h4 $irq_source(1) 0"
338 sid_cmd "sid::component::connect_pin $victim interrupt $probe_pin"
339 set result [sid_cmd "set interrupted"]
341 # Invoke the programmed interrupt by writing to the software IRQ register.
342 set test "programmed interrupt"
343 sid_cmd "sid::bus::write_h4_l4 $irqbus 0x10 2"
344 if {[sid_cmd "set interrupted"] == 1} { pass $test } else { fail $test }
347 # Test if triggerpoints fired correctly.
349 set test "interrupt triggerpoint fired 69 times"
350 set count [sid_cmd "set triggercount(interrupt)"]
351 if {$count == "69"} { pass $test } else { fail "$test; fired $count times" }
353 set test "fast-interrupt triggerpoint fired 3 times"
354 set count [sid_cmd "set triggercount(fast-interrupt)"]
355 if {$count == "3"} { pass $test } else { fail "$test; fired $count times" }
357 set test "irq-raw-status triggerpoint fired 2049 times"
358 set count [sid_cmd "set triggercount(irq-raw-status)"]
359 if {$count == "2049"} { pass $test } else { fail "$test; fired $count times" }
361 set test "irq-enable-register triggerpoint fired 73 times"
362 set count [sid_cmd "set triggercount(irq-enable-register)"]
363 if {$count == "73"} { pass $test } else { fail "$test; fired count times" }
365 set test "fiq-raw-status triggerpoint fired twice"
366 set count [sid_cmd "set triggercount(fiq-raw-status)"]
367 if {$count == "2"} { pass $test } else { fail "$test; fired $count times" }
369 set test "fiq-enable-register triggerpoint fired once"
370 set count [sid_cmd "set triggercount(fiq-enable-register)"]
371 if {$count == "1"} { pass $test } else { fail "$test; fired $count times" }
373 catch {unset watchpins triggercount}
377 if {[sid_stop]} { pass $test } else { fail $test ; return }
379 # zap temp file if tests were successful
381 if {$exit_status == "0"} {
382 file delete "arm-intr.conf"