1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "libqtest-single.h"
12
13
14#define RASPI3_DMA_BASE 0x3f007000
15#define RASPI3_IC_BASE 0x3f00b200
16
17
18
19
20#define BCM2708_DMA_CS 0
21#define BCM2708_DMA_ACTIVE (1 << 0)
22#define BCM2708_DMA_INT (1 << 2)
23
24#define BCM2708_DMA_ADDR 0x04
25
26#define BCM2708_DMA_INT_STATUS 0xfe0
27
28
29#define BCM2708_DMA_INT_EN (1 << 0)
30#define BCM2708_DMA_D_INC (1 << 4)
31#define BCM2708_DMA_S_INC (1 << 8)
32
33
34#define IRQ_PENDING_BASIC 0x00
35#define IRQ_GPU_PENDING1_AGGR (1 << 8)
36#define IRQ_PENDING_1 0x04
37#define IRQ_ENABLE_1 0x10
38
39
40#define SCB_ADDR 256
41#define S_ADDR 32
42#define D_ADDR 64
43#define TXFR_LEN 32
44const uint32_t check_data = 0x12345678;
45
46static void bcm2835_dma_test_interrupt(int dma_c, int irq_line)
47{
48 uint64_t dma_base = RASPI3_DMA_BASE + dma_c * 0x100;
49 int gpu_irq_line = 16 + irq_line;
50
51
52 writel(RASPI3_IC_BASE + IRQ_ENABLE_1, 1 << gpu_irq_line);
53 int isr = readl(dma_base + BCM2708_DMA_INT_STATUS);
54 g_assert_cmpint(isr, ==, 0);
55 uint32_t reg0 = readl(dma_base + BCM2708_DMA_CS);
56 g_assert_cmpint(reg0, ==, 0);
57 uint32_t ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
58 g_assert_cmpint(ic_pending, ==, 0);
59 uint32_t gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
60 g_assert_cmpint(gpu_pending1, ==, 0);
61
62
63 writel(SCB_ADDR + 0, BCM2708_DMA_S_INC | BCM2708_DMA_D_INC |
64 BCM2708_DMA_INT_EN);
65 writel(SCB_ADDR + 4, S_ADDR);
66 writel(SCB_ADDR + 8, D_ADDR);
67 writel(SCB_ADDR + 12, TXFR_LEN);
68 writel(dma_base + BCM2708_DMA_ADDR, SCB_ADDR);
69
70 writel(S_ADDR, check_data);
71 for (int word = S_ADDR + 4; word < S_ADDR + TXFR_LEN; word += 4) {
72 writel(word, ~check_data);
73 }
74
75 writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_ACTIVE);
76
77
78 uint32_t data = readl(D_ADDR);
79 g_assert_cmpint(data, ==, check_data);
80 for (int word = D_ADDR + 4; word < D_ADDR + TXFR_LEN; word += 4) {
81 data = readl(word);
82 g_assert_cmpint(data, ==, ~check_data);
83 }
84
85
86 isr = readl(RASPI3_DMA_BASE + BCM2708_DMA_INT_STATUS);
87 g_assert_cmpint(isr, ==, 1 << dma_c);
88
89 ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
90 g_assert_cmpint(ic_pending, ==, IRQ_GPU_PENDING1_AGGR);
91
92 gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
93 g_assert_cmpint(gpu_pending1, ==, 1 << gpu_irq_line);
94
95
96 writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_INT);
97}
98
99static void bcm2835_dma_test_interrupts(void)
100{
101
102 bcm2835_dma_test_interrupt(0, 0);
103 bcm2835_dma_test_interrupt(10, 10);
104 bcm2835_dma_test_interrupt(11, 11);
105 bcm2835_dma_test_interrupt(14, 11);
106}
107
108int main(int argc, char **argv)
109{
110 int ret;
111 g_test_init(&argc, &argv, NULL);
112 qtest_add_func("/bcm2835/dma/test_interrupts",
113 bcm2835_dma_test_interrupts);
114 qtest_start("-machine raspi3b");
115 ret = g_test_run();
116 qtest_end();
117 return ret;
118}
119