Commit d47ede60933f265e558723096e67734db165bdae
1 parent
c6d86a33
sh4: Add r2d onboard FPGA IRQ controller (Takashi YOSHII).
This adds IRQ controller in FPGA on r2d, and use it for CF. Signed-off-by: Takashi YOSHII <takasi-y@ops.dti.ne.jp> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5926 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
63 additions
and
5 deletions
hw/r2d.c
@@ -34,12 +34,14 @@ | @@ -34,12 +34,14 @@ | ||
34 | 34 | ||
35 | #define SM501_VRAM_SIZE 0x800000 | 35 | #define SM501_VRAM_SIZE 0x800000 |
36 | 36 | ||
37 | +#define PA_IRLMSK 0x00 | ||
37 | #define PA_POWOFF 0x30 | 38 | #define PA_POWOFF 0x30 |
38 | #define PA_VERREG 0x32 | 39 | #define PA_VERREG 0x32 |
39 | #define PA_OUTPORT 0x36 | 40 | #define PA_OUTPORT 0x36 |
40 | 41 | ||
41 | typedef struct { | 42 | typedef struct { |
42 | uint16_t bcr; | 43 | uint16_t bcr; |
44 | + uint16_t irlmsk; | ||
43 | uint16_t irlmon; | 45 | uint16_t irlmon; |
44 | uint16_t cfctl; | 46 | uint16_t cfctl; |
45 | uint16_t cfpow; | 47 | uint16_t cfpow; |
@@ -60,13 +62,60 @@ typedef struct { | @@ -60,13 +62,60 @@ typedef struct { | ||
60 | uint16_t inport; | 62 | uint16_t inport; |
61 | uint16_t outport; | 63 | uint16_t outport; |
62 | uint16_t bverreg; | 64 | uint16_t bverreg; |
65 | + | ||
66 | +/* output pin */ | ||
67 | + qemu_irq irl; | ||
63 | } r2d_fpga_t; | 68 | } r2d_fpga_t; |
64 | 69 | ||
70 | +enum r2d_fpga_irq { | ||
71 | + PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T, | ||
72 | + SDCARD, PCI_INTA, PCI_INTB, EXT, TP, | ||
73 | + NR_IRQS | ||
74 | +}; | ||
75 | + | ||
76 | +static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = { | ||
77 | + [CF_IDE] = { 1, 1<<9 }, | ||
78 | + [CF_CD] = { 2, 1<<8 }, | ||
79 | + [PCI_INTA] = { 9, 1<<14 }, | ||
80 | + [PCI_INTB] = { 10, 1<<13 }, | ||
81 | + [PCI_INTC] = { 3, 1<<12 }, | ||
82 | + [PCI_INTD] = { 0, 1<<11 }, | ||
83 | + [SM501] = { 4, 1<<10 }, | ||
84 | + [KEY] = { 5, 1<<6 }, | ||
85 | + [RTC_A] = { 6, 1<<5 }, | ||
86 | + [RTC_T] = { 7, 1<<4 }, | ||
87 | + [SDCARD] = { 8, 1<<7 }, | ||
88 | + [EXT] = { 11, 1<<0 }, | ||
89 | + [TP] = { 12, 1<<15 }, | ||
90 | +}; | ||
91 | + | ||
92 | +static void update_irl(r2d_fpga_t *fpga) | ||
93 | +{ | ||
94 | + int i, irl = 15; | ||
95 | + for (i = 0; i < NR_IRQS; i++) | ||
96 | + if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk) | ||
97 | + if (irqtab[i].irl < irl) | ||
98 | + irl = irqtab[i].irl; | ||
99 | + qemu_set_irq(fpga->irl, irl ^ 15); | ||
100 | +} | ||
101 | + | ||
102 | +static void r2d_fpga_irq_set(void *opaque, int n, int level) | ||
103 | +{ | ||
104 | + r2d_fpga_t *fpga = opaque; | ||
105 | + if (level) | ||
106 | + fpga->irlmon |= irqtab[n].msk; | ||
107 | + else | ||
108 | + fpga->irlmon &= ~irqtab[n].msk; | ||
109 | + update_irl(fpga); | ||
110 | +} | ||
111 | + | ||
65 | static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) | 112 | static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) |
66 | { | 113 | { |
67 | r2d_fpga_t *s = opaque; | 114 | r2d_fpga_t *s = opaque; |
68 | 115 | ||
69 | switch (addr) { | 116 | switch (addr) { |
117 | + case PA_IRLMSK: | ||
118 | + return s->irlmsk; | ||
70 | case PA_OUTPORT: | 119 | case PA_OUTPORT: |
71 | return s->outport; | 120 | return s->outport; |
72 | case PA_POWOFF: | 121 | case PA_POWOFF: |
@@ -84,6 +133,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -84,6 +133,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) | ||
84 | r2d_fpga_t *s = opaque; | 133 | r2d_fpga_t *s = opaque; |
85 | 134 | ||
86 | switch (addr) { | 135 | switch (addr) { |
136 | + case PA_IRLMSK: | ||
137 | + s->irlmsk = value; | ||
138 | + update_irl(s); | ||
139 | + break; | ||
87 | case PA_OUTPORT: | 140 | case PA_OUTPORT: |
88 | s->outport = value; | 141 | s->outport = value; |
89 | break; | 142 | break; |
@@ -108,18 +161,21 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { | @@ -108,18 +161,21 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { | ||
108 | NULL, | 161 | NULL, |
109 | }; | 162 | }; |
110 | 163 | ||
111 | -static void r2d_fpga_init(target_phys_addr_t base) | 164 | +static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl) |
112 | { | 165 | { |
113 | int iomemtype; | 166 | int iomemtype; |
114 | r2d_fpga_t *s; | 167 | r2d_fpga_t *s; |
115 | 168 | ||
116 | s = qemu_mallocz(sizeof(r2d_fpga_t)); | 169 | s = qemu_mallocz(sizeof(r2d_fpga_t)); |
117 | if (!s) | 170 | if (!s) |
118 | - return; | 171 | + return NULL; |
172 | + | ||
173 | + s->irl = irl; | ||
119 | 174 | ||
120 | iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, | 175 | iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, |
121 | r2d_fpga_writefn, s); | 176 | r2d_fpga_writefn, s); |
122 | cpu_register_physical_memory(base, 0x40, iomemtype); | 177 | cpu_register_physical_memory(base, 0x40, iomemtype); |
178 | + return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS); | ||
123 | } | 179 | } |
124 | 180 | ||
125 | static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | 181 | static void r2d_init(ram_addr_t ram_size, int vga_ram_size, |
@@ -130,6 +186,7 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | @@ -130,6 +186,7 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | ||
130 | CPUState *env; | 186 | CPUState *env; |
131 | struct SH7750State *s; | 187 | struct SH7750State *s; |
132 | ram_addr_t sdram_addr, sm501_vga_ram_addr; | 188 | ram_addr_t sdram_addr, sm501_vga_ram_addr; |
189 | + qemu_irq *irq; | ||
133 | 190 | ||
134 | if (!cpu_model) | 191 | if (!cpu_model) |
135 | cpu_model = "SH7751R"; | 192 | cpu_model = "SH7751R"; |
@@ -144,15 +201,16 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | @@ -144,15 +201,16 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | ||
144 | sdram_addr = qemu_ram_alloc(SDRAM_SIZE); | 201 | sdram_addr = qemu_ram_alloc(SDRAM_SIZE); |
145 | cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); | 202 | cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); |
146 | /* Register peripherals */ | 203 | /* Register peripherals */ |
147 | - r2d_fpga_init(0x04000000); | ||
148 | s = sh7750_init(env); | 204 | s = sh7750_init(env); |
205 | + irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); | ||
206 | + | ||
149 | sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); | 207 | sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); |
150 | sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, | 208 | sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, |
151 | serial_hds[2]); | 209 | serial_hds[2]); |
152 | 210 | ||
153 | /* onboard CF (True IDE mode, Master only). */ | 211 | /* onboard CF (True IDE mode, Master only). */ |
154 | - mmio_ide_init(0x14001000, 0x1400080c, NULL, 1, | ||
155 | - drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); | 212 | + mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, |
213 | + drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); | ||
156 | 214 | ||
157 | /* Todo: register on board registers */ | 215 | /* Todo: register on board registers */ |
158 | { | 216 | { |