Commit d47ede60933f265e558723096e67734db165bdae

Authored by balrog
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 {