|
1 /* |
|
2 * Toshiba TC6393XB I/O Controller. |
|
3 * Found in Sharp Zaurus SL-6000 (tosa) or some |
|
4 * Toshiba e-Series PDAs. |
|
5 * |
|
6 * Most features are currently unsupported!!! |
|
7 * |
|
8 * This code is licensed under the GNU GPL v2. |
|
9 */ |
|
10 #include "hw.h" |
|
11 #include "pxa.h" |
|
12 #include "devices.h" |
|
13 #include "flash.h" |
|
14 #include "gui.h" |
|
15 #include "pixel_ops.h" |
|
16 |
|
17 #define IRQ_TC6393_NAND 0 |
|
18 #define IRQ_TC6393_MMC 1 |
|
19 #define IRQ_TC6393_OHCI 2 |
|
20 #define IRQ_TC6393_SERIAL 3 |
|
21 #define IRQ_TC6393_FB 4 |
|
22 |
|
23 #define TC6393XB_NR_IRQS 8 |
|
24 |
|
25 #define TC6393XB_GPIOS 16 |
|
26 |
|
27 #define SCR_REVID 0x08 /* b Revision ID */ |
|
28 #define SCR_ISR 0x50 /* b Interrupt Status */ |
|
29 #define SCR_IMR 0x52 /* b Interrupt Mask */ |
|
30 #define SCR_IRR 0x54 /* b Interrupt Routing */ |
|
31 #define SCR_GPER 0x60 /* w GP Enable */ |
|
32 #define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */ |
|
33 #define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */ |
|
34 #define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */ |
|
35 #define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */ |
|
36 #define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */ |
|
37 #define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */ |
|
38 #define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */ |
|
39 #define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */ |
|
40 #define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */ |
|
41 #define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */ |
|
42 #define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */ |
|
43 #define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */ |
|
44 #define SCR_CCR 0x98 /* w Clock Control */ |
|
45 #define SCR_PLL2CR 0x9a /* w PLL2 Control */ |
|
46 #define SCR_PLL1CR 0x9c /* l PLL1 Control */ |
|
47 #define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */ |
|
48 #define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */ |
|
49 #define SCR_FER 0xe0 /* b Function Enable */ |
|
50 #define SCR_MCR 0xe4 /* w Mode Control */ |
|
51 #define SCR_CONFIG 0xfc /* b Configuration Control */ |
|
52 #define SCR_DEBUG 0xff /* b Debug */ |
|
53 |
|
54 #define NAND_CFG_COMMAND 0x04 /* w Command */ |
|
55 #define NAND_CFG_BASE 0x10 /* l Control Base Address */ |
|
56 #define NAND_CFG_INTP 0x3d /* b Interrupt Pin */ |
|
57 #define NAND_CFG_INTE 0x48 /* b Int Enable */ |
|
58 #define NAND_CFG_EC 0x4a /* b Event Control */ |
|
59 #define NAND_CFG_ICC 0x4c /* b Internal Clock Control */ |
|
60 #define NAND_CFG_ECCC 0x5b /* b ECC Control */ |
|
61 #define NAND_CFG_NFTC 0x60 /* b NAND Flash Transaction Control */ |
|
62 #define NAND_CFG_NFM 0x61 /* b NAND Flash Monitor */ |
|
63 #define NAND_CFG_NFPSC 0x62 /* b NAND Flash Power Supply Control */ |
|
64 #define NAND_CFG_NFDC 0x63 /* b NAND Flash Detect Control */ |
|
65 |
|
66 #define NAND_DATA 0x00 /* l Data */ |
|
67 #define NAND_MODE 0x04 /* b Mode */ |
|
68 #define NAND_STATUS 0x05 /* b Status */ |
|
69 #define NAND_ISR 0x06 /* b Interrupt Status */ |
|
70 #define NAND_IMR 0x07 /* b Interrupt Mask */ |
|
71 |
|
72 #define NAND_MODE_WP 0x80 |
|
73 #define NAND_MODE_CE 0x10 |
|
74 #define NAND_MODE_ALE 0x02 |
|
75 #define NAND_MODE_CLE 0x01 |
|
76 #define NAND_MODE_ECC_MASK 0x60 |
|
77 #define NAND_MODE_ECC_EN 0x20 |
|
78 #define NAND_MODE_ECC_READ 0x40 |
|
79 #define NAND_MODE_ECC_RST 0x60 |
|
80 |
|
81 struct tc6393xb_s { |
|
82 qemu_irq irq; |
|
83 qemu_irq *sub_irqs; |
|
84 struct { |
|
85 uint8_t ISR; |
|
86 uint8_t IMR; |
|
87 uint8_t IRR; |
|
88 uint16_t GPER; |
|
89 uint8_t GPI_SR[3]; |
|
90 uint8_t GPI_IMR[3]; |
|
91 uint8_t GPI_EDER[3]; |
|
92 uint8_t GPI_LIR[3]; |
|
93 uint8_t GP_IARCR[3]; |
|
94 uint8_t GP_IARLCR[3]; |
|
95 uint8_t GPI_BCR[3]; |
|
96 uint16_t GPA_IARCR; |
|
97 uint16_t GPA_IARLCR; |
|
98 uint16_t CCR; |
|
99 uint16_t PLL2CR; |
|
100 uint32_t PLL1CR; |
|
101 uint8_t DIARCR; |
|
102 uint8_t DBOCR; |
|
103 uint8_t FER; |
|
104 uint16_t MCR; |
|
105 uint8_t CONFIG; |
|
106 uint8_t DEBUG; |
|
107 } scr; |
|
108 uint32_t gpio_dir; |
|
109 uint32_t gpio_level; |
|
110 uint32_t prev_level; |
|
111 qemu_irq handler[TC6393XB_GPIOS]; |
|
112 qemu_irq *gpio_in; |
|
113 |
|
114 struct { |
|
115 uint8_t mode; |
|
116 uint8_t isr; |
|
117 uint8_t imr; |
|
118 } nand; |
|
119 int nand_enable; |
|
120 uint32_t nand_phys; |
|
121 struct nand_flash_s *flash; |
|
122 struct ecc_state_s ecc; |
|
123 |
|
124 DisplayState *ds; |
|
125 ram_addr_t vram_addr; |
|
126 uint32_t scr_width, scr_height; /* in pixels */ |
|
127 qemu_irq l3v; |
|
128 unsigned blank : 1, |
|
129 blanked : 1; |
|
130 }; |
|
131 |
|
132 qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s) |
|
133 { |
|
134 return s->gpio_in; |
|
135 } |
|
136 |
|
137 static void tc6393xb_gpio_set(void *opaque, int line, int level) |
|
138 { |
|
139 // struct tc6393xb_s *s = opaque; |
|
140 |
|
141 if (line > TC6393XB_GPIOS) { |
|
142 printf("%s: No GPIO pin %i\n", __FUNCTION__, line); |
|
143 return; |
|
144 } |
|
145 |
|
146 // FIXME: how does the chip reflect the GPIO input level change? |
|
147 } |
|
148 |
|
149 void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, |
|
150 qemu_irq handler) |
|
151 { |
|
152 if (line >= TC6393XB_GPIOS) { |
|
153 fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line); |
|
154 return; |
|
155 } |
|
156 |
|
157 s->handler[line] = handler; |
|
158 } |
|
159 |
|
160 static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s) |
|
161 { |
|
162 uint32_t level, diff; |
|
163 int bit; |
|
164 |
|
165 level = s->gpio_level & s->gpio_dir; |
|
166 |
|
167 for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { |
|
168 bit = ffs(diff) - 1; |
|
169 qemu_set_irq(s->handler[bit], (level >> bit) & 1); |
|
170 } |
|
171 |
|
172 s->prev_level = level; |
|
173 } |
|
174 |
|
175 qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s) |
|
176 { |
|
177 return s->l3v; |
|
178 } |
|
179 |
|
180 static void tc6393xb_l3v(void *opaque, int line, int level) |
|
181 { |
|
182 struct tc6393xb_s *s = opaque; |
|
183 s->blank = !level; |
|
184 fprintf(stderr, "L3V: %d\n", level); |
|
185 } |
|
186 |
|
187 static void tc6393xb_sub_irq(void *opaque, int line, int level) { |
|
188 struct tc6393xb_s *s = opaque; |
|
189 uint8_t isr = s->scr.ISR; |
|
190 if (level) |
|
191 isr |= 1 << line; |
|
192 else |
|
193 isr &= ~(1 << line); |
|
194 s->scr.ISR = isr; |
|
195 qemu_set_irq(s->irq, isr & s->scr.IMR); |
|
196 } |
|
197 |
|
198 #define SCR_REG_B(N) \ |
|
199 case SCR_ ##N: return s->scr.N |
|
200 #define SCR_REG_W(N) \ |
|
201 case SCR_ ##N: return s->scr.N; \ |
|
202 case SCR_ ##N + 1: return s->scr.N >> 8; |
|
203 #define SCR_REG_L(N) \ |
|
204 case SCR_ ##N: return s->scr.N; \ |
|
205 case SCR_ ##N + 1: return s->scr.N >> 8; \ |
|
206 case SCR_ ##N + 2: return s->scr.N >> 16; \ |
|
207 case SCR_ ##N + 3: return s->scr.N >> 24; |
|
208 #define SCR_REG_A(N) \ |
|
209 case SCR_ ##N(0): return s->scr.N[0]; \ |
|
210 case SCR_ ##N(1): return s->scr.N[1]; \ |
|
211 case SCR_ ##N(2): return s->scr.N[2] |
|
212 |
|
213 static uint32_t tc6393xb_scr_readb(struct tc6393xb_s *s, target_phys_addr_t addr) |
|
214 { |
|
215 switch (addr) { |
|
216 case SCR_REVID: |
|
217 return 3; |
|
218 case SCR_REVID+1: |
|
219 return 0; |
|
220 SCR_REG_B(ISR); |
|
221 SCR_REG_B(IMR); |
|
222 SCR_REG_B(IRR); |
|
223 SCR_REG_W(GPER); |
|
224 SCR_REG_A(GPI_SR); |
|
225 SCR_REG_A(GPI_IMR); |
|
226 SCR_REG_A(GPI_EDER); |
|
227 SCR_REG_A(GPI_LIR); |
|
228 case SCR_GPO_DSR(0): |
|
229 case SCR_GPO_DSR(1): |
|
230 case SCR_GPO_DSR(2): |
|
231 return (s->gpio_level >> ((addr - SCR_GPO_DSR(0)) * 8)) & 0xff; |
|
232 case SCR_GPO_DOECR(0): |
|
233 case SCR_GPO_DOECR(1): |
|
234 case SCR_GPO_DOECR(2): |
|
235 return (s->gpio_dir >> ((addr - SCR_GPO_DOECR(0)) * 8)) & 0xff; |
|
236 SCR_REG_A(GP_IARCR); |
|
237 SCR_REG_A(GP_IARLCR); |
|
238 SCR_REG_A(GPI_BCR); |
|
239 SCR_REG_W(GPA_IARCR); |
|
240 SCR_REG_W(GPA_IARLCR); |
|
241 SCR_REG_W(CCR); |
|
242 SCR_REG_W(PLL2CR); |
|
243 SCR_REG_L(PLL1CR); |
|
244 SCR_REG_B(DIARCR); |
|
245 SCR_REG_B(DBOCR); |
|
246 SCR_REG_B(FER); |
|
247 SCR_REG_W(MCR); |
|
248 SCR_REG_B(CONFIG); |
|
249 SCR_REG_B(DEBUG); |
|
250 } |
|
251 fprintf(stderr, "tc6393xb_scr: unhandled read at %08x\n", (uint32_t) addr); |
|
252 return 0; |
|
253 } |
|
254 #undef SCR_REG_B |
|
255 #undef SCR_REG_W |
|
256 #undef SCR_REG_L |
|
257 #undef SCR_REG_A |
|
258 |
|
259 #define SCR_REG_B(N) \ |
|
260 case SCR_ ##N: s->scr.N = value; return; |
|
261 #define SCR_REG_W(N) \ |
|
262 case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ |
|
263 case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); return |
|
264 #define SCR_REG_L(N) \ |
|
265 case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ |
|
266 case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); return; \ |
|
267 case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); return; \ |
|
268 case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); return; |
|
269 #define SCR_REG_A(N) \ |
|
270 case SCR_ ##N(0): s->scr.N[0] = value; return; \ |
|
271 case SCR_ ##N(1): s->scr.N[1] = value; return; \ |
|
272 case SCR_ ##N(2): s->scr.N[2] = value; return |
|
273 |
|
274 static void tc6393xb_scr_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) |
|
275 { |
|
276 switch (addr) { |
|
277 SCR_REG_B(ISR); |
|
278 SCR_REG_B(IMR); |
|
279 SCR_REG_B(IRR); |
|
280 SCR_REG_W(GPER); |
|
281 SCR_REG_A(GPI_SR); |
|
282 SCR_REG_A(GPI_IMR); |
|
283 SCR_REG_A(GPI_EDER); |
|
284 SCR_REG_A(GPI_LIR); |
|
285 case SCR_GPO_DSR(0): |
|
286 case SCR_GPO_DSR(1): |
|
287 case SCR_GPO_DSR(2): |
|
288 s->gpio_level = (s->gpio_level & ~(0xff << ((addr - SCR_GPO_DSR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DSR(0))*8)); |
|
289 tc6393xb_gpio_handler_update(s); |
|
290 return; |
|
291 case SCR_GPO_DOECR(0): |
|
292 case SCR_GPO_DOECR(1): |
|
293 case SCR_GPO_DOECR(2): |
|
294 s->gpio_dir = (s->gpio_dir & ~(0xff << ((addr - SCR_GPO_DOECR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DOECR(0))*8)); |
|
295 tc6393xb_gpio_handler_update(s); |
|
296 return; |
|
297 SCR_REG_A(GP_IARCR); |
|
298 SCR_REG_A(GP_IARLCR); |
|
299 SCR_REG_A(GPI_BCR); |
|
300 SCR_REG_W(GPA_IARCR); |
|
301 SCR_REG_W(GPA_IARLCR); |
|
302 SCR_REG_W(CCR); |
|
303 SCR_REG_W(PLL2CR); |
|
304 SCR_REG_L(PLL1CR); |
|
305 SCR_REG_B(DIARCR); |
|
306 SCR_REG_B(DBOCR); |
|
307 SCR_REG_B(FER); |
|
308 SCR_REG_W(MCR); |
|
309 SCR_REG_B(CONFIG); |
|
310 SCR_REG_B(DEBUG); |
|
311 } |
|
312 fprintf(stderr, "tc6393xb_scr: unhandled write at %08x: %02x\n", |
|
313 (uint32_t) addr, value & 0xff); |
|
314 } |
|
315 #undef SCR_REG_B |
|
316 #undef SCR_REG_W |
|
317 #undef SCR_REG_L |
|
318 #undef SCR_REG_A |
|
319 |
|
320 static void tc6393xb_nand_irq(struct tc6393xb_s *s) { |
|
321 qemu_set_irq(s->sub_irqs[IRQ_TC6393_NAND], |
|
322 (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr)); |
|
323 } |
|
324 |
|
325 static uint32_t tc6393xb_nand_cfg_readb(struct tc6393xb_s *s, target_phys_addr_t addr) { |
|
326 switch (addr) { |
|
327 case NAND_CFG_COMMAND: |
|
328 return s->nand_enable ? 2 : 0; |
|
329 case NAND_CFG_BASE: |
|
330 case NAND_CFG_BASE + 1: |
|
331 case NAND_CFG_BASE + 2: |
|
332 case NAND_CFG_BASE + 3: |
|
333 return s->nand_phys >> (addr - NAND_CFG_BASE); |
|
334 } |
|
335 fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr); |
|
336 return 0; |
|
337 } |
|
338 static void tc6393xb_nand_cfg_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) { |
|
339 switch (addr) { |
|
340 case NAND_CFG_COMMAND: |
|
341 s->nand_enable = (value & 0x2); |
|
342 return; |
|
343 case NAND_CFG_BASE: |
|
344 case NAND_CFG_BASE + 1: |
|
345 case NAND_CFG_BASE + 2: |
|
346 case NAND_CFG_BASE + 3: |
|
347 s->nand_phys &= ~(0xff << ((addr - NAND_CFG_BASE) * 8)); |
|
348 s->nand_phys |= (value & 0xff) << ((addr - NAND_CFG_BASE) * 8); |
|
349 return; |
|
350 } |
|
351 fprintf(stderr, "tc6393xb_nand_cfg: unhandled write at %08x: %02x\n", |
|
352 (uint32_t) addr, value & 0xff); |
|
353 } |
|
354 |
|
355 static uint32_t tc6393xb_nand_readb(struct tc6393xb_s *s, target_phys_addr_t addr) { |
|
356 switch (addr) { |
|
357 case NAND_DATA + 0: |
|
358 case NAND_DATA + 1: |
|
359 case NAND_DATA + 2: |
|
360 case NAND_DATA + 3: |
|
361 return nand_getio(s->flash); |
|
362 case NAND_MODE: |
|
363 return s->nand.mode; |
|
364 case NAND_STATUS: |
|
365 return 0x14; |
|
366 case NAND_ISR: |
|
367 return s->nand.isr; |
|
368 case NAND_IMR: |
|
369 return s->nand.imr; |
|
370 } |
|
371 fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr); |
|
372 return 0; |
|
373 } |
|
374 static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) { |
|
375 // fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n", |
|
376 // (uint32_t) addr, value & 0xff); |
|
377 switch (addr) { |
|
378 case NAND_DATA + 0: |
|
379 case NAND_DATA + 1: |
|
380 case NAND_DATA + 2: |
|
381 case NAND_DATA + 3: |
|
382 nand_setio(s->flash, value); |
|
383 s->nand.isr &= 1; |
|
384 tc6393xb_nand_irq(s); |
|
385 return; |
|
386 case NAND_MODE: |
|
387 s->nand.mode = value; |
|
388 nand_setpins(s->flash, |
|
389 value & NAND_MODE_CLE, |
|
390 value & NAND_MODE_ALE, |
|
391 !(value & NAND_MODE_CE), |
|
392 value & NAND_MODE_WP, |
|
393 0); // FIXME: gnd |
|
394 switch (value & NAND_MODE_ECC_MASK) { |
|
395 case NAND_MODE_ECC_RST: |
|
396 ecc_reset(&s->ecc); |
|
397 break; |
|
398 case NAND_MODE_ECC_READ: |
|
399 // FIXME |
|
400 break; |
|
401 case NAND_MODE_ECC_EN: |
|
402 ecc_reset(&s->ecc); |
|
403 } |
|
404 return; |
|
405 case NAND_ISR: |
|
406 s->nand.isr = value; |
|
407 tc6393xb_nand_irq(s); |
|
408 return; |
|
409 case NAND_IMR: |
|
410 s->nand.imr = value; |
|
411 tc6393xb_nand_irq(s); |
|
412 return; |
|
413 } |
|
414 fprintf(stderr, "tc6393xb_nand: unhandled write at %08x: %02x\n", |
|
415 (uint32_t) addr, value & 0xff); |
|
416 } |
|
417 |
|
418 #define BITS 8 |
|
419 #include "tc6393xb_template.h" |
|
420 #define BITS 15 |
|
421 #include "tc6393xb_template.h" |
|
422 #define BITS 16 |
|
423 #include "tc6393xb_template.h" |
|
424 #define BITS 24 |
|
425 #include "tc6393xb_template.h" |
|
426 #define BITS 32 |
|
427 #include "tc6393xb_template.h" |
|
428 |
|
429 static void tc6393xb_draw_graphic(struct tc6393xb_s *s, int full_update) |
|
430 { |
|
431 switch (ds_get_bits_per_pixel(s->ds)) { |
|
432 case 8: |
|
433 tc6393xb_draw_graphic8(s); |
|
434 break; |
|
435 case 15: |
|
436 tc6393xb_draw_graphic15(s); |
|
437 break; |
|
438 case 16: |
|
439 tc6393xb_draw_graphic16(s); |
|
440 break; |
|
441 case 24: |
|
442 tc6393xb_draw_graphic24(s); |
|
443 break; |
|
444 case 32: |
|
445 tc6393xb_draw_graphic32(s); |
|
446 break; |
|
447 default: |
|
448 printf("tc6393xb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds)); |
|
449 return; |
|
450 } |
|
451 |
|
452 dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); |
|
453 } |
|
454 |
|
455 static void tc6393xb_draw_blank(struct tc6393xb_s *s, int full_update) |
|
456 { |
|
457 int i, w; |
|
458 uint8_t *d; |
|
459 |
|
460 if (!full_update) |
|
461 return; |
|
462 |
|
463 w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); |
|
464 d = ds_get_data(s->ds); |
|
465 for(i = 0; i < s->scr_height; i++) { |
|
466 memset(d, 0, w); |
|
467 d += ds_get_linesize(s->ds); |
|
468 } |
|
469 |
|
470 dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); |
|
471 } |
|
472 |
|
473 static void tc6393xb_update_display(void *opaque) |
|
474 { |
|
475 struct tc6393xb_s *s = opaque; |
|
476 int full_update; |
|
477 |
|
478 if (s->scr_width == 0 || s->scr_height == 0) |
|
479 return; |
|
480 |
|
481 full_update = 0; |
|
482 if (s->blanked != s->blank) { |
|
483 s->blanked = s->blank; |
|
484 full_update = 1; |
|
485 } |
|
486 if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) { |
|
487 gui_resize_vt(s->ds, s->scr_width, s->scr_height); |
|
488 full_update = 1; |
|
489 } |
|
490 if (s->blanked) |
|
491 tc6393xb_draw_blank(s, full_update); |
|
492 else |
|
493 tc6393xb_draw_graphic(s, full_update); |
|
494 } |
|
495 |
|
496 |
|
497 static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { |
|
498 struct tc6393xb_s *s = opaque; |
|
499 |
|
500 switch (addr >> 8) { |
|
501 case 0: |
|
502 return tc6393xb_scr_readb(s, addr & 0xff); |
|
503 case 1: |
|
504 return tc6393xb_nand_cfg_readb(s, addr & 0xff); |
|
505 }; |
|
506 |
|
507 if ((addr &~0xff) == s->nand_phys && s->nand_enable) { |
|
508 // return tc6393xb_nand_readb(s, addr & 0xff); |
|
509 uint8_t d = tc6393xb_nand_readb(s, addr & 0xff); |
|
510 // fprintf(stderr, "tc6393xb_nand: read at %08x: %02hhx\n", (uint32_t) addr, d); |
|
511 return d; |
|
512 } |
|
513 |
|
514 // fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr); |
|
515 return 0; |
|
516 } |
|
517 |
|
518 static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) { |
|
519 struct tc6393xb_s *s = opaque; |
|
520 |
|
521 switch (addr >> 8) { |
|
522 case 0: |
|
523 tc6393xb_scr_writeb(s, addr & 0xff, value); |
|
524 return; |
|
525 case 1: |
|
526 tc6393xb_nand_cfg_writeb(s, addr & 0xff, value); |
|
527 return; |
|
528 }; |
|
529 |
|
530 if ((addr &~0xff) == s->nand_phys && s->nand_enable) |
|
531 tc6393xb_nand_writeb(s, addr & 0xff, value); |
|
532 else |
|
533 fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n", |
|
534 (uint32_t) addr, value & 0xff); |
|
535 } |
|
536 |
|
537 static uint32_t tc6393xb_readw(void *opaque, target_phys_addr_t addr) |
|
538 { |
|
539 return (tc6393xb_readb(opaque, addr) & 0xff) | |
|
540 (tc6393xb_readb(opaque, addr + 1) << 8); |
|
541 } |
|
542 |
|
543 static uint32_t tc6393xb_readl(void *opaque, target_phys_addr_t addr) |
|
544 { |
|
545 return (tc6393xb_readb(opaque, addr) & 0xff) | |
|
546 ((tc6393xb_readb(opaque, addr + 1) & 0xff) << 8) | |
|
547 ((tc6393xb_readb(opaque, addr + 2) & 0xff) << 16) | |
|
548 ((tc6393xb_readb(opaque, addr + 3) & 0xff) << 24); |
|
549 } |
|
550 |
|
551 static void tc6393xb_writew(void *opaque, target_phys_addr_t addr, uint32_t value) |
|
552 { |
|
553 tc6393xb_writeb(opaque, addr, value); |
|
554 tc6393xb_writeb(opaque, addr + 1, value >> 8); |
|
555 } |
|
556 |
|
557 static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t value) |
|
558 { |
|
559 tc6393xb_writeb(opaque, addr, value); |
|
560 tc6393xb_writeb(opaque, addr + 1, value >> 8); |
|
561 tc6393xb_writeb(opaque, addr + 2, value >> 16); |
|
562 tc6393xb_writeb(opaque, addr + 3, value >> 24); |
|
563 } |
|
564 |
|
565 struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq, DisplayState *ds) |
|
566 { |
|
567 int iomemtype; |
|
568 struct tc6393xb_s *s; |
|
569 CPUReadMemoryFunc *tc6393xb_readfn[] = { |
|
570 tc6393xb_readb, |
|
571 tc6393xb_readw, |
|
572 tc6393xb_readl, |
|
573 }; |
|
574 CPUWriteMemoryFunc *tc6393xb_writefn[] = { |
|
575 tc6393xb_writeb, |
|
576 tc6393xb_writew, |
|
577 tc6393xb_writel, |
|
578 }; |
|
579 |
|
580 s = (struct tc6393xb_s *) qemu_mallocz(sizeof(struct tc6393xb_s)); |
|
581 s->irq = irq; |
|
582 s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); |
|
583 |
|
584 s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1); |
|
585 s->blanked = 1; |
|
586 |
|
587 s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); |
|
588 |
|
589 s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76); |
|
590 |
|
591 iomemtype = cpu_register_io_memory(0, tc6393xb_readfn, |
|
592 tc6393xb_writefn, s); |
|
593 cpu_register_physical_memory(base, 0x10000, iomemtype); |
|
594 |
|
595 s->ds = gui_get_graphic_console( |
|
596 NULL, /* dev name */ |
|
597 tc6393xb_update_display, |
|
598 NULL, /* invalidate */ |
|
599 NULL, /* screen_dump */ |
|
600 s); |
|
601 |
|
602 if (s->ds != NULL) { |
|
603 s->vram_addr = qemu_ram_alloc(0x100000); |
|
604 cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr); |
|
605 s->scr_width = 480; |
|
606 s->scr_height = 640; |
|
607 |
|
608 } |
|
609 |
|
610 return s; |
|
611 } |