We never have to export ppc_set_irq.
[qemu] / hw / sh7750.c
1 /*
2  * SH7750 device
3  *
4  * Copyright (c) 2005 Samuel Tardieu
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include <stdio.h>
25 #include <assert.h>
26 #include "vl.h"
27 #include "sh7750_regs.h"
28 #include "sh7750_regnames.h"
29
30 #define NB_DEVICES 4
31
32 typedef struct SH7750State {
33     /* CPU */
34     CPUSH4State *cpu;
35     /* Peripheral frequency in Hz */
36     uint32_t periph_freq;
37     /* SDRAM controller */
38     uint16_t rfcr;
39     /* IO ports */
40     uint16_t gpioic;
41     uint32_t pctra;
42     uint32_t pctrb;
43     uint16_t portdira;          /* Cached */
44     uint16_t portpullupa;       /* Cached */
45     uint16_t portdirb;          /* Cached */
46     uint16_t portpullupb;       /* Cached */
47     uint16_t pdtra;
48     uint16_t pdtrb;
49     uint16_t periph_pdtra;      /* Imposed by the peripherals */
50     uint16_t periph_portdira;   /* Direction seen from the peripherals */
51     uint16_t periph_pdtrb;      /* Imposed by the peripherals */
52     uint16_t periph_portdirb;   /* Direction seen from the peripherals */
53     sh7750_io_device *devices[NB_DEVICES];      /* External peripherals */
54
55     uint16_t icr;
56     uint16_t ipra;
57     uint16_t iprb;
58     uint16_t iprc;
59     uint16_t iprd;
60     uint32_t intpri00;
61     uint32_t intmsk00;
62     /* Cache */
63     uint32_t ccr;
64
65 } SH7750State;
66
67
68 /**********************************************************************
69  I/O ports
70 **********************************************************************/
71
72 int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
73 {
74     int i;
75
76     for (i = 0; i < NB_DEVICES; i++) {
77         if (s->devices[i] == NULL) {
78             s->devices[i] = device;
79             return 0;
80         }
81     }
82     return -1;
83 }
84
85 static uint16_t portdir(uint32_t v)
86 {
87 #define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
88     return
89         EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
90         EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
91         EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
92         EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
93         EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
94         EVENPORTMASK(0);
95 }
96
97 static uint16_t portpullup(uint32_t v)
98 {
99 #define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
100     return
101         ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
102         ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
103         ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
104         ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
105         ODDPORTMASK(1) | ODDPORTMASK(0);
106 }
107
108 static uint16_t porta_lines(SH7750State * s)
109 {
110     return (s->portdira & s->pdtra) |   /* CPU */
111         (s->periph_portdira & s->periph_pdtra) |        /* Peripherals */
112         (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
113 }
114
115 static uint16_t portb_lines(SH7750State * s)
116 {
117     return (s->portdirb & s->pdtrb) |   /* CPU */
118         (s->periph_portdirb & s->periph_pdtrb) |        /* Peripherals */
119         (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
120 }
121
122 static void gen_port_interrupts(SH7750State * s)
123 {
124     /* XXXXX interrupts not generated */
125 }
126
127 static void porta_changed(SH7750State * s, uint16_t prev)
128 {
129     uint16_t currenta, changes;
130     int i, r = 0;
131
132 #if 0
133     fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
134             prev, porta_lines(s));
135     fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
136 #endif
137     currenta = porta_lines(s);
138     if (currenta == prev)
139         return;
140     changes = currenta ^ prev;
141
142     for (i = 0; i < NB_DEVICES; i++) {
143         if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
144             r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
145                                                &s->periph_pdtra,
146                                                &s->periph_portdira,
147                                                &s->periph_pdtrb,
148                                                &s->periph_portdirb);
149         }
150     }
151
152     if (r)
153         gen_port_interrupts(s);
154 }
155
156 static void portb_changed(SH7750State * s, uint16_t prev)
157 {
158     uint16_t currentb, changes;
159     int i, r = 0;
160
161     currentb = portb_lines(s);
162     if (currentb == prev)
163         return;
164     changes = currentb ^ prev;
165
166     for (i = 0; i < NB_DEVICES; i++) {
167         if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
168             r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
169                                                &s->periph_pdtra,
170                                                &s->periph_portdira,
171                                                &s->periph_pdtrb,
172                                                &s->periph_portdirb);
173         }
174     }
175
176     if (r)
177         gen_port_interrupts(s);
178 }
179
180 /**********************************************************************
181  Memory
182 **********************************************************************/
183
184 static void error_access(const char *kind, target_phys_addr_t addr)
185 {
186     fprintf(stderr, "%s to %s (0x%08x) not supported\n",
187             kind, regname(addr), addr);
188 }
189
190 static void ignore_access(const char *kind, target_phys_addr_t addr)
191 {
192     fprintf(stderr, "%s to %s (0x%08x) ignored\n",
193             kind, regname(addr), addr);
194 }
195
196 static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
197 {
198     switch (addr) {
199     default:
200         error_access("byte read", addr);
201         assert(0);
202     }
203 }
204
205 static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
206 {
207     SH7750State *s = opaque;
208
209     switch (addr) {
210     case SH7750_FRQCR_A7:
211         return 0;
212     case SH7750_RFCR_A7:
213         fprintf(stderr,
214                 "Read access to refresh count register, incrementing\n");
215         return s->rfcr++;
216     case SH7750_PDTRA_A7:
217         return porta_lines(s);
218     case SH7750_PDTRB_A7:
219         return portb_lines(s);
220     case 0x1fd00000:
221         return s->icr;
222     case 0x1fd00004:
223         return s->ipra;
224     case 0x1fd00008:
225         return s->iprb;
226     case 0x1fd0000c:
227         return s->iprc;
228     case 0x1fd00010:
229         return s->iprd;
230     default:
231         error_access("word read", addr);
232         assert(0);
233     }
234 }
235
236 static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr)
237 {
238     SH7750State *s = opaque;
239
240     switch (addr) {
241     case SH7750_MMUCR_A7:
242         return s->cpu->mmucr;
243     case SH7750_PTEH_A7:
244         return s->cpu->pteh;
245     case SH7750_PTEL_A7:
246         return s->cpu->ptel;
247     case SH7750_TTB_A7:
248         return s->cpu->ttb;
249     case SH7750_TEA_A7:
250         return s->cpu->tea;
251     case SH7750_TRA_A7:
252         return s->cpu->tra;
253     case SH7750_EXPEVT_A7:
254         return s->cpu->expevt;
255     case SH7750_INTEVT_A7:
256         return s->cpu->intevt;
257     case SH7750_CCR_A7:
258         return s->ccr;
259     case 0x1f000030:            /* Processor version PVR */
260         return 0x00050000;      /* SH7750R */
261     case 0x1f000040:            /* Processor version CVR */
262         return 0x00110000;      /* Minimum caches */
263     case 0x1f000044:            /* Processor version PRR */
264         return 0x00000100;      /* SH7750R */
265     case 0x1e080000:
266         return s->intpri00;
267     case 0x1e080020:
268         return 0;
269     case 0x1e080040:
270         return s->intmsk00;
271     case 0x1e080060:
272         return 0;
273     default:
274         error_access("long read", addr);
275         assert(0);
276     }
277 }
278
279 static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
280                               uint32_t mem_value)
281 {
282     switch (addr) {
283         /* PRECHARGE ? XXXXX */
284     case SH7750_PRECHARGE0_A7:
285     case SH7750_PRECHARGE1_A7:
286         ignore_access("byte write", addr);
287         return;
288     default:
289         error_access("byte write", addr);
290         assert(0);
291     }
292 }
293
294 static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
295                               uint32_t mem_value)
296 {
297     SH7750State *s = opaque;
298     uint16_t temp;
299
300     switch (addr) {
301         /* SDRAM controller */
302     case SH7750_BCR2_A7:
303     case SH7750_BCR3_A7:
304     case SH7750_RTCOR_A7:
305     case SH7750_RTCNT_A7:
306     case SH7750_RTCSR_A7:
307         ignore_access("word write", addr);
308         return;
309         /* IO ports */
310     case SH7750_PDTRA_A7:
311         temp = porta_lines(s);
312         s->pdtra = mem_value;
313         porta_changed(s, temp);
314         return;
315     case SH7750_PDTRB_A7:
316         temp = portb_lines(s);
317         s->pdtrb = mem_value;
318         portb_changed(s, temp);
319         return;
320     case SH7750_RFCR_A7:
321         fprintf(stderr, "Write access to refresh count register\n");
322         s->rfcr = mem_value;
323         return;
324     case SH7750_GPIOIC_A7:
325         s->gpioic = mem_value;
326         if (mem_value != 0) {
327             fprintf(stderr, "I/O interrupts not implemented\n");
328             assert(0);
329         }
330         return;
331     case 0x1fd00000:
332         s->icr = mem_value;
333         return;
334     case 0x1fd00004:
335         s->ipra = mem_value;
336         return;
337     case 0x1fd00008:
338         s->iprb = mem_value;
339         return;
340     case 0x1fd0000c:
341         s->iprc = mem_value;
342         return;
343     case 0x1fd00010:
344         s->iprd = mem_value;
345         return;
346     default:
347         error_access("word write", addr);
348         assert(0);
349     }
350 }
351
352 static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
353                               uint32_t mem_value)
354 {
355     SH7750State *s = opaque;
356     uint16_t temp;
357
358     switch (addr) {
359         /* SDRAM controller */
360     case SH7750_BCR1_A7:
361     case SH7750_BCR4_A7:
362     case SH7750_WCR1_A7:
363     case SH7750_WCR2_A7:
364     case SH7750_WCR3_A7:
365     case SH7750_MCR_A7:
366         ignore_access("long write", addr);
367         return;
368         /* IO ports */
369     case SH7750_PCTRA_A7:
370         temp = porta_lines(s);
371         s->pctra = mem_value;
372         s->portdira = portdir(mem_value);
373         s->portpullupa = portpullup(mem_value);
374         porta_changed(s, temp);
375         return;
376     case SH7750_PCTRB_A7:
377         temp = portb_lines(s);
378         s->pctrb = mem_value;
379         s->portdirb = portdir(mem_value);
380         s->portpullupb = portpullup(mem_value);
381         portb_changed(s, temp);
382         return;
383     case SH7750_MMUCR_A7:
384         s->cpu->mmucr = mem_value;
385         return;
386     case SH7750_PTEH_A7:
387         s->cpu->pteh = mem_value;
388         return;
389     case SH7750_PTEL_A7:
390         s->cpu->ptel = mem_value;
391         return;
392     case SH7750_TTB_A7:
393         s->cpu->ttb = mem_value;
394         return;
395     case SH7750_TEA_A7:
396         s->cpu->tea = mem_value;
397         return;
398     case SH7750_TRA_A7:
399         s->cpu->tra = mem_value & 0x000007ff;
400         return;
401     case SH7750_EXPEVT_A7:
402         s->cpu->expevt = mem_value & 0x000007ff;
403         return;
404     case SH7750_INTEVT_A7:
405         s->cpu->intevt = mem_value & 0x000007ff;
406         return;
407     case SH7750_CCR_A7:
408         s->ccr = mem_value;
409         return;
410     case 0x1e080000:
411         s->intpri00 = mem_value;
412         return;
413     case 0x1e080020:
414         return;
415     case 0x1e080040:
416         s->intmsk00 = mem_value;
417         return;
418     case 0x1e080060:
419         return;
420     default:
421         error_access("long write", addr);
422         assert(0);
423     }
424 }
425
426 static CPUReadMemoryFunc *sh7750_mem_read[] = {
427     sh7750_mem_readb,
428     sh7750_mem_readw,
429     sh7750_mem_readl
430 };
431
432 static CPUWriteMemoryFunc *sh7750_mem_write[] = {
433     sh7750_mem_writeb,
434     sh7750_mem_writew,
435     sh7750_mem_writel
436 };
437
438 SH7750State *sh7750_init(CPUSH4State * cpu)
439 {
440     SH7750State *s;
441     int sh7750_io_memory;
442
443     s = qemu_mallocz(sizeof(SH7750State));
444     s->cpu = cpu;
445     s->periph_freq = 60000000;  /* 60MHz */
446     sh7750_io_memory = cpu_register_io_memory(0,
447                                               sh7750_mem_read,
448                                               sh7750_mem_write, s);
449     cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
450
451     sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]);
452     sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
453                    s->periph_freq, serial_hds[1]);
454
455     tmu012_init(0x1fd80000,
456                 TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
457                 s->periph_freq);
458     tmu012_init(0x1e100000, 0, s->periph_freq);
459     return s;
460 }