]> Git Repo - qemu.git/blob - hw/musicpal.c
Push AUD_init down to devices
[qemu.git] / hw / musicpal.c
1 /*
2  * Marvell MV88W8618 / Freecom MusicPal emulation.
3  *
4  * Copyright (c) 2008 Jan Kiszka
5  *
6  * This code is licenced under the GNU GPL v2.
7  */
8
9 #include "hw.h"
10 #include "arm-misc.h"
11 #include "devices.h"
12 #include "net.h"
13 #include "sysemu.h"
14 #include "boards.h"
15 #include "pc.h"
16 #include "qemu-timer.h"
17 #include "block.h"
18 #include "flash.h"
19 #include "console.h"
20 #include "audio/audio.h"
21 #include "i2c.h"
22
23 #define MP_MISC_BASE            0x80002000
24 #define MP_MISC_SIZE            0x00001000
25
26 #define MP_ETH_BASE             0x80008000
27 #define MP_ETH_SIZE             0x00001000
28
29 #define MP_WLAN_BASE            0x8000C000
30 #define MP_WLAN_SIZE            0x00000800
31
32 #define MP_UART1_BASE           0x8000C840
33 #define MP_UART2_BASE           0x8000C940
34
35 #define MP_GPIO_BASE            0x8000D000
36 #define MP_GPIO_SIZE            0x00001000
37
38 #define MP_FLASHCFG_BASE        0x90006000
39 #define MP_FLASHCFG_SIZE        0x00001000
40
41 #define MP_AUDIO_BASE           0x90007000
42 #define MP_AUDIO_SIZE           0x00001000
43
44 #define MP_PIC_BASE             0x90008000
45 #define MP_PIC_SIZE             0x00001000
46
47 #define MP_PIT_BASE             0x90009000
48 #define MP_PIT_SIZE             0x00001000
49
50 #define MP_LCD_BASE             0x9000c000
51 #define MP_LCD_SIZE             0x00001000
52
53 #define MP_SRAM_BASE            0xC0000000
54 #define MP_SRAM_SIZE            0x00020000
55
56 #define MP_RAM_DEFAULT_SIZE     32*1024*1024
57 #define MP_FLASH_SIZE_MAX       32*1024*1024
58
59 #define MP_TIMER1_IRQ           4
60 /* ... */
61 #define MP_TIMER4_IRQ           7
62 #define MP_EHCI_IRQ             8
63 #define MP_ETH_IRQ              9
64 #define MP_UART1_IRQ            11
65 #define MP_UART2_IRQ            11
66 #define MP_GPIO_IRQ             12
67 #define MP_RTC_IRQ              28
68 #define MP_AUDIO_IRQ            30
69
70 static uint32_t gpio_in_state = 0xffffffff;
71 static uint32_t gpio_isr;
72 static uint32_t gpio_out_state;
73 static ram_addr_t sram_off;
74
75 typedef enum i2c_state {
76     STOPPED = 0,
77     INITIALIZING,
78     SENDING_BIT7,
79     SENDING_BIT6,
80     SENDING_BIT5,
81     SENDING_BIT4,
82     SENDING_BIT3,
83     SENDING_BIT2,
84     SENDING_BIT1,
85     SENDING_BIT0,
86     WAITING_FOR_ACK,
87     RECEIVING_BIT7,
88     RECEIVING_BIT6,
89     RECEIVING_BIT5,
90     RECEIVING_BIT4,
91     RECEIVING_BIT3,
92     RECEIVING_BIT2,
93     RECEIVING_BIT1,
94     RECEIVING_BIT0,
95     SENDING_ACK
96 } i2c_state;
97
98 typedef struct i2c_interface {
99     i2c_bus *bus;
100     i2c_state state;
101     int last_data;
102     int last_clock;
103     uint8_t buffer;
104     int current_addr;
105 } i2c_interface;
106
107 static void i2c_enter_stop(i2c_interface *i2c)
108 {
109     if (i2c->current_addr >= 0)
110         i2c_end_transfer(i2c->bus);
111     i2c->current_addr = -1;
112     i2c->state = STOPPED;
113 }
114
115 static void i2c_state_update(i2c_interface *i2c, int data, int clock)
116 {
117     if (!i2c)
118         return;
119
120     switch (i2c->state) {
121     case STOPPED:
122         if (data == 0 && i2c->last_data == 1 && clock == 1)
123             i2c->state = INITIALIZING;
124         break;
125
126     case INITIALIZING:
127         if (clock == 0 && i2c->last_clock == 1 && data == 0)
128             i2c->state = SENDING_BIT7;
129         else
130             i2c_enter_stop(i2c);
131         break;
132
133     case SENDING_BIT7 ... SENDING_BIT0:
134         if (clock == 0 && i2c->last_clock == 1) {
135             i2c->buffer = (i2c->buffer << 1) | data;
136             i2c->state++; /* will end up in WAITING_FOR_ACK */
137         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
138             i2c_enter_stop(i2c);
139         break;
140
141     case WAITING_FOR_ACK:
142         if (clock == 0 && i2c->last_clock == 1) {
143             if (i2c->current_addr < 0) {
144                 i2c->current_addr = i2c->buffer;
145                 i2c_start_transfer(i2c->bus, i2c->current_addr & 0xfe,
146                                    i2c->buffer & 1);
147             } else
148                 i2c_send(i2c->bus, i2c->buffer);
149             if (i2c->current_addr & 1) {
150                 i2c->state = RECEIVING_BIT7;
151                 i2c->buffer = i2c_recv(i2c->bus);
152             } else
153                 i2c->state = SENDING_BIT7;
154         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
155             i2c_enter_stop(i2c);
156         break;
157
158     case RECEIVING_BIT7 ... RECEIVING_BIT0:
159         if (clock == 0 && i2c->last_clock == 1) {
160             i2c->state++; /* will end up in SENDING_ACK */
161             i2c->buffer <<= 1;
162         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
163             i2c_enter_stop(i2c);
164         break;
165
166     case SENDING_ACK:
167         if (clock == 0 && i2c->last_clock == 1) {
168             i2c->state = RECEIVING_BIT7;
169             if (data == 0)
170                 i2c->buffer = i2c_recv(i2c->bus);
171             else
172                 i2c_nack(i2c->bus);
173         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
174             i2c_enter_stop(i2c);
175         break;
176     }
177
178     i2c->last_data = data;
179     i2c->last_clock = clock;
180 }
181
182 static int i2c_get_data(i2c_interface *i2c)
183 {
184     if (!i2c)
185         return 0;
186
187     switch (i2c->state) {
188     case RECEIVING_BIT7 ... RECEIVING_BIT0:
189         return (i2c->buffer >> 7);
190
191     case WAITING_FOR_ACK:
192     default:
193         return 0;
194     }
195 }
196
197 static i2c_interface *mixer_i2c;
198
199 #ifdef HAS_AUDIO
200
201 /* Audio register offsets */
202 #define MP_AUDIO_PLAYBACK_MODE  0x00
203 #define MP_AUDIO_CLOCK_DIV      0x18
204 #define MP_AUDIO_IRQ_STATUS     0x20
205 #define MP_AUDIO_IRQ_ENABLE     0x24
206 #define MP_AUDIO_TX_START_LO    0x28
207 #define MP_AUDIO_TX_THRESHOLD   0x2C
208 #define MP_AUDIO_TX_STATUS      0x38
209 #define MP_AUDIO_TX_START_HI    0x40
210
211 /* Status register and IRQ enable bits */
212 #define MP_AUDIO_TX_HALF        (1 << 6)
213 #define MP_AUDIO_TX_FULL        (1 << 7)
214
215 /* Playback mode bits */
216 #define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
217 #define MP_AUDIO_PLAYBACK_EN    (1 << 7)
218 #define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
219 #define MP_AUDIO_MONO           (1 << 14)
220
221 /* Wolfson 8750 I2C address */
222 #define MP_WM_ADDR              0x34
223
224 static const char audio_name[] = "mv88w8618";
225
226 typedef struct musicpal_audio_state {
227     qemu_irq irq;
228     uint32_t playback_mode;
229     uint32_t status;
230     uint32_t irq_enable;
231     unsigned long phys_buf;
232     uint32_t target_buffer;
233     unsigned int threshold;
234     unsigned int play_pos;
235     unsigned int last_free;
236     uint32_t clock_div;
237     i2c_slave *wm;
238 } musicpal_audio_state;
239
240 static void audio_callback(void *opaque, int free_out, int free_in)
241 {
242     musicpal_audio_state *s = opaque;
243     int16_t *codec_buffer;
244     int8_t buf[4096];
245     int8_t *mem_buffer;
246     int pos, block_size;
247
248     if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN))
249         return;
250
251     if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
252         free_out <<= 1;
253
254     if (!(s->playback_mode & MP_AUDIO_MONO))
255         free_out <<= 1;
256
257     block_size = s->threshold/2;
258     if (free_out - s->last_free < block_size)
259         return;
260
261     if (block_size > 4096)
262         return;
263
264     cpu_physical_memory_read(s->target_buffer + s->play_pos, (void *)buf,
265                              block_size);
266     mem_buffer = buf;
267     if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
268         if (s->playback_mode & MP_AUDIO_MONO) {
269             codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
270             for (pos = 0; pos < block_size; pos += 2) {
271                 *codec_buffer++ = *(int16_t *)mem_buffer;
272                 *codec_buffer++ = *(int16_t *)mem_buffer;
273                 mem_buffer += 2;
274             }
275         } else
276             memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
277                    (uint32_t *)mem_buffer, block_size);
278     } else {
279         if (s->playback_mode & MP_AUDIO_MONO) {
280             codec_buffer = wm8750_dac_buffer(s->wm, block_size);
281             for (pos = 0; pos < block_size; pos++) {
282                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
283                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
284             }
285         } else {
286             codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
287             for (pos = 0; pos < block_size; pos += 2) {
288                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
289                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
290             }
291         }
292     }
293     wm8750_dac_commit(s->wm);
294
295     s->last_free = free_out - block_size;
296
297     if (s->play_pos == 0) {
298         s->status |= MP_AUDIO_TX_HALF;
299         s->play_pos = block_size;
300     } else {
301         s->status |= MP_AUDIO_TX_FULL;
302         s->play_pos = 0;
303     }
304
305     if (s->status & s->irq_enable)
306         qemu_irq_raise(s->irq);
307 }
308
309 static void musicpal_audio_clock_update(musicpal_audio_state *s)
310 {
311     int rate;
312
313     if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ)
314         rate = 24576000 / 64; /* 24.576MHz */
315     else
316         rate = 11289600 / 64; /* 11.2896MHz */
317
318     rate /= ((s->clock_div >> 8) & 0xff) + 1;
319
320     wm8750_set_bclk_in(s->wm, rate);
321 }
322
323 static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset)
324 {
325     musicpal_audio_state *s = opaque;
326
327     switch (offset) {
328     case MP_AUDIO_PLAYBACK_MODE:
329         return s->playback_mode;
330
331     case MP_AUDIO_CLOCK_DIV:
332         return s->clock_div;
333
334     case MP_AUDIO_IRQ_STATUS:
335         return s->status;
336
337     case MP_AUDIO_IRQ_ENABLE:
338         return s->irq_enable;
339
340     case MP_AUDIO_TX_STATUS:
341         return s->play_pos >> 2;
342
343     default:
344         return 0;
345     }
346 }
347
348 static void musicpal_audio_write(void *opaque, target_phys_addr_t offset,
349                                  uint32_t value)
350 {
351     musicpal_audio_state *s = opaque;
352
353     switch (offset) {
354     case MP_AUDIO_PLAYBACK_MODE:
355         if (value & MP_AUDIO_PLAYBACK_EN &&
356             !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
357             s->status = 0;
358             s->last_free = 0;
359             s->play_pos = 0;
360         }
361         s->playback_mode = value;
362         musicpal_audio_clock_update(s);
363         break;
364
365     case MP_AUDIO_CLOCK_DIV:
366         s->clock_div = value;
367         s->last_free = 0;
368         s->play_pos = 0;
369         musicpal_audio_clock_update(s);
370         break;
371
372     case MP_AUDIO_IRQ_STATUS:
373         s->status &= ~value;
374         break;
375
376     case MP_AUDIO_IRQ_ENABLE:
377         s->irq_enable = value;
378         if (s->status & s->irq_enable)
379             qemu_irq_raise(s->irq);
380         break;
381
382     case MP_AUDIO_TX_START_LO:
383         s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
384         s->target_buffer = s->phys_buf;
385         s->play_pos = 0;
386         s->last_free = 0;
387         break;
388
389     case MP_AUDIO_TX_THRESHOLD:
390         s->threshold = (value + 1) * 4;
391         break;
392
393     case MP_AUDIO_TX_START_HI:
394         s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
395         s->target_buffer = s->phys_buf;
396         s->play_pos = 0;
397         s->last_free = 0;
398         break;
399     }
400 }
401
402 static void musicpal_audio_reset(void *opaque)
403 {
404     musicpal_audio_state *s = opaque;
405
406     s->playback_mode = 0;
407     s->status = 0;
408     s->irq_enable = 0;
409 }
410
411 static CPUReadMemoryFunc *musicpal_audio_readfn[] = {
412     musicpal_audio_read,
413     musicpal_audio_read,
414     musicpal_audio_read
415 };
416
417 static CPUWriteMemoryFunc *musicpal_audio_writefn[] = {
418     musicpal_audio_write,
419     musicpal_audio_write,
420     musicpal_audio_write
421 };
422
423 static i2c_interface *musicpal_audio_init(qemu_irq irq)
424 {
425     musicpal_audio_state *s;
426     i2c_interface *i2c;
427     int iomemtype;
428
429     s = qemu_mallocz(sizeof(musicpal_audio_state));
430     s->irq = irq;
431
432     i2c = qemu_mallocz(sizeof(i2c_interface));
433     i2c->bus = i2c_init_bus();
434     i2c->current_addr = -1;
435
436     s->wm = wm8750_init(i2c->bus);
437     if (!s->wm)
438         return NULL;
439     i2c_set_slave_address(s->wm, MP_WM_ADDR);
440     wm8750_data_req_set(s->wm, audio_callback, s);
441
442     iomemtype = cpu_register_io_memory(0, musicpal_audio_readfn,
443                        musicpal_audio_writefn, s);
444     cpu_register_physical_memory(MP_AUDIO_BASE, MP_AUDIO_SIZE, iomemtype);
445
446     qemu_register_reset(musicpal_audio_reset, s);
447
448     return i2c;
449 }
450 #else  /* !HAS_AUDIO */
451 static i2c_interface *musicpal_audio_init(qemu_irq irq)
452 {
453     return NULL;
454 }
455 #endif /* !HAS_AUDIO */
456
457 /* Ethernet register offsets */
458 #define MP_ETH_SMIR             0x010
459 #define MP_ETH_PCXR             0x408
460 #define MP_ETH_SDCMR            0x448
461 #define MP_ETH_ICR              0x450
462 #define MP_ETH_IMR              0x458
463 #define MP_ETH_FRDP0            0x480
464 #define MP_ETH_FRDP1            0x484
465 #define MP_ETH_FRDP2            0x488
466 #define MP_ETH_FRDP3            0x48C
467 #define MP_ETH_CRDP0            0x4A0
468 #define MP_ETH_CRDP1            0x4A4
469 #define MP_ETH_CRDP2            0x4A8
470 #define MP_ETH_CRDP3            0x4AC
471 #define MP_ETH_CTDP0            0x4E0
472 #define MP_ETH_CTDP1            0x4E4
473 #define MP_ETH_CTDP2            0x4E8
474 #define MP_ETH_CTDP3            0x4EC
475
476 /* MII PHY access */
477 #define MP_ETH_SMIR_DATA        0x0000FFFF
478 #define MP_ETH_SMIR_ADDR        0x03FF0000
479 #define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
480 #define MP_ETH_SMIR_RDVALID     (1 << 27)
481
482 /* PHY registers */
483 #define MP_ETH_PHY1_BMSR        0x00210000
484 #define MP_ETH_PHY1_PHYSID1     0x00410000
485 #define MP_ETH_PHY1_PHYSID2     0x00610000
486
487 #define MP_PHY_BMSR_LINK        0x0004
488 #define MP_PHY_BMSR_AUTONEG     0x0008
489
490 #define MP_PHY_88E3015          0x01410E20
491
492 /* TX descriptor status */
493 #define MP_ETH_TX_OWN           (1 << 31)
494
495 /* RX descriptor status */
496 #define MP_ETH_RX_OWN           (1 << 31)
497
498 /* Interrupt cause/mask bits */
499 #define MP_ETH_IRQ_RX_BIT       0
500 #define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
501 #define MP_ETH_IRQ_TXHI_BIT     2
502 #define MP_ETH_IRQ_TXLO_BIT     3
503
504 /* Port config bits */
505 #define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
506
507 /* SDMA command bits */
508 #define MP_ETH_CMD_TXHI         (1 << 23)
509 #define MP_ETH_CMD_TXLO         (1 << 22)
510
511 typedef struct mv88w8618_tx_desc {
512     uint32_t cmdstat;
513     uint16_t res;
514     uint16_t bytes;
515     uint32_t buffer;
516     uint32_t next;
517 } mv88w8618_tx_desc;
518
519 typedef struct mv88w8618_rx_desc {
520     uint32_t cmdstat;
521     uint16_t bytes;
522     uint16_t buffer_size;
523     uint32_t buffer;
524     uint32_t next;
525 } mv88w8618_rx_desc;
526
527 typedef struct mv88w8618_eth_state {
528     qemu_irq irq;
529     uint32_t smir;
530     uint32_t icr;
531     uint32_t imr;
532     int mmio_index;
533     int vlan_header;
534     uint32_t tx_queue[2];
535     uint32_t rx_queue[4];
536     uint32_t frx_queue[4];
537     uint32_t cur_rx[4];
538     VLANClientState *vc;
539 } mv88w8618_eth_state;
540
541 static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
542 {
543     cpu_to_le32s(&desc->cmdstat);
544     cpu_to_le16s(&desc->bytes);
545     cpu_to_le16s(&desc->buffer_size);
546     cpu_to_le32s(&desc->buffer);
547     cpu_to_le32s(&desc->next);
548     cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
549 }
550
551 static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
552 {
553     cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
554     le32_to_cpus(&desc->cmdstat);
555     le16_to_cpus(&desc->bytes);
556     le16_to_cpus(&desc->buffer_size);
557     le32_to_cpus(&desc->buffer);
558     le32_to_cpus(&desc->next);
559 }
560
561 static int eth_can_receive(void *opaque)
562 {
563     return 1;
564 }
565
566 static void eth_receive(void *opaque, const uint8_t *buf, int size)
567 {
568     mv88w8618_eth_state *s = opaque;
569     uint32_t desc_addr;
570     mv88w8618_rx_desc desc;
571     int i;
572
573     for (i = 0; i < 4; i++) {
574         desc_addr = s->cur_rx[i];
575         if (!desc_addr)
576             continue;
577         do {
578             eth_rx_desc_get(desc_addr, &desc);
579             if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
580                 cpu_physical_memory_write(desc.buffer + s->vlan_header,
581                                           buf, size);
582                 desc.bytes = size + s->vlan_header;
583                 desc.cmdstat &= ~MP_ETH_RX_OWN;
584                 s->cur_rx[i] = desc.next;
585
586                 s->icr |= MP_ETH_IRQ_RX;
587                 if (s->icr & s->imr)
588                     qemu_irq_raise(s->irq);
589                 eth_rx_desc_put(desc_addr, &desc);
590                 return;
591             }
592             desc_addr = desc.next;
593         } while (desc_addr != s->rx_queue[i]);
594     }
595 }
596
597 static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
598 {
599     cpu_to_le32s(&desc->cmdstat);
600     cpu_to_le16s(&desc->res);
601     cpu_to_le16s(&desc->bytes);
602     cpu_to_le32s(&desc->buffer);
603     cpu_to_le32s(&desc->next);
604     cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
605 }
606
607 static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
608 {
609     cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
610     le32_to_cpus(&desc->cmdstat);
611     le16_to_cpus(&desc->res);
612     le16_to_cpus(&desc->bytes);
613     le32_to_cpus(&desc->buffer);
614     le32_to_cpus(&desc->next);
615 }
616
617 static void eth_send(mv88w8618_eth_state *s, int queue_index)
618 {
619     uint32_t desc_addr = s->tx_queue[queue_index];
620     mv88w8618_tx_desc desc;
621     uint8_t buf[2048];
622     int len;
623
624
625     do {
626         eth_tx_desc_get(desc_addr, &desc);
627         if (desc.cmdstat & MP_ETH_TX_OWN) {
628             len = desc.bytes;
629             if (len < 2048) {
630                 cpu_physical_memory_read(desc.buffer, buf, len);
631                 qemu_send_packet(s->vc, buf, len);
632             }
633             desc.cmdstat &= ~MP_ETH_TX_OWN;
634             s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
635             eth_tx_desc_put(desc_addr, &desc);
636         }
637         desc_addr = desc.next;
638     } while (desc_addr != s->tx_queue[queue_index]);
639 }
640
641 static uint32_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset)
642 {
643     mv88w8618_eth_state *s = opaque;
644
645     switch (offset) {
646     case MP_ETH_SMIR:
647         if (s->smir & MP_ETH_SMIR_OPCODE) {
648             switch (s->smir & MP_ETH_SMIR_ADDR) {
649             case MP_ETH_PHY1_BMSR:
650                 return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
651                        MP_ETH_SMIR_RDVALID;
652             case MP_ETH_PHY1_PHYSID1:
653                 return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
654             case MP_ETH_PHY1_PHYSID2:
655                 return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
656             default:
657                 return MP_ETH_SMIR_RDVALID;
658             }
659         }
660         return 0;
661
662     case MP_ETH_ICR:
663         return s->icr;
664
665     case MP_ETH_IMR:
666         return s->imr;
667
668     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
669         return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
670
671     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
672         return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
673
674     case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
675         return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
676
677     default:
678         return 0;
679     }
680 }
681
682 static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,
683                                 uint32_t value)
684 {
685     mv88w8618_eth_state *s = opaque;
686
687     switch (offset) {
688     case MP_ETH_SMIR:
689         s->smir = value;
690         break;
691
692     case MP_ETH_PCXR:
693         s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
694         break;
695
696     case MP_ETH_SDCMR:
697         if (value & MP_ETH_CMD_TXHI)
698             eth_send(s, 1);
699         if (value & MP_ETH_CMD_TXLO)
700             eth_send(s, 0);
701         if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr)
702             qemu_irq_raise(s->irq);
703         break;
704
705     case MP_ETH_ICR:
706         s->icr &= value;
707         break;
708
709     case MP_ETH_IMR:
710         s->imr = value;
711         if (s->icr & s->imr)
712             qemu_irq_raise(s->irq);
713         break;
714
715     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
716         s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
717         break;
718
719     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
720         s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
721             s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
722         break;
723
724     case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
725         s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
726         break;
727     }
728 }
729
730 static CPUReadMemoryFunc *mv88w8618_eth_readfn[] = {
731     mv88w8618_eth_read,
732     mv88w8618_eth_read,
733     mv88w8618_eth_read
734 };
735
736 static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {
737     mv88w8618_eth_write,
738     mv88w8618_eth_write,
739     mv88w8618_eth_write
740 };
741
742 static void eth_cleanup(VLANClientState *vc)
743 {
744     mv88w8618_eth_state *s = vc->opaque;
745
746     cpu_unregister_io_memory(s->mmio_index);
747
748     qemu_free(s);
749 }
750
751 static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
752 {
753     mv88w8618_eth_state *s;
754
755     qemu_check_nic_model(nd, "mv88w8618");
756
757     s = qemu_mallocz(sizeof(mv88w8618_eth_state));
758     s->irq = irq;
759     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
760                                  eth_receive, eth_can_receive,
761                                  eth_cleanup, s);
762     s->mmio_index = cpu_register_io_memory(0, mv88w8618_eth_readfn,
763                                            mv88w8618_eth_writefn, s);
764     cpu_register_physical_memory(base, MP_ETH_SIZE, s->mmio_index);
765 }
766
767 /* LCD register offsets */
768 #define MP_LCD_IRQCTRL          0x180
769 #define MP_LCD_IRQSTAT          0x184
770 #define MP_LCD_SPICTRL          0x1ac
771 #define MP_LCD_INST             0x1bc
772 #define MP_LCD_DATA             0x1c0
773
774 /* Mode magics */
775 #define MP_LCD_SPI_DATA         0x00100011
776 #define MP_LCD_SPI_CMD          0x00104011
777 #define MP_LCD_SPI_INVALID      0x00000000
778
779 /* Commmands */
780 #define MP_LCD_INST_SETPAGE0    0xB0
781 /* ... */
782 #define MP_LCD_INST_SETPAGE7    0xB7
783
784 #define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
785
786 typedef struct musicpal_lcd_state {
787     uint32_t mode;
788     uint32_t irqctrl;
789     int page;
790     int page_off;
791     DisplayState *ds;
792     uint8_t video_ram[128*64/8];
793 } musicpal_lcd_state;
794
795 static uint32_t lcd_brightness;
796
797 static uint8_t scale_lcd_color(uint8_t col)
798 {
799     int tmp = col;
800
801     switch (lcd_brightness) {
802     case 0x00000007: /* 0 */
803         return 0;
804
805     case 0x00020000: /* 1 */
806         return (tmp * 1) / 7;
807
808     case 0x00020001: /* 2 */
809         return (tmp * 2) / 7;
810
811     case 0x00040000: /* 3 */
812         return (tmp * 3) / 7;
813
814     case 0x00010006: /* 4 */
815         return (tmp * 4) / 7;
816
817     case 0x00020005: /* 5 */
818         return (tmp * 5) / 7;
819
820     case 0x00040003: /* 6 */
821         return (tmp * 6) / 7;
822
823     case 0x00030004: /* 7 */
824     default:
825         return col;
826     }
827 }
828
829 #define SET_LCD_PIXEL(depth, type) \
830 static inline void glue(set_lcd_pixel, depth) \
831         (musicpal_lcd_state *s, int x, int y, type col) \
832 { \
833     int dx, dy; \
834     type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
835 \
836     for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
837         for (dx = 0; dx < 3; dx++, pixel++) \
838             *pixel = col; \
839 }
840 SET_LCD_PIXEL(8, uint8_t)
841 SET_LCD_PIXEL(16, uint16_t)
842 SET_LCD_PIXEL(32, uint32_t)
843
844 #include "pixel_ops.h"
845
846 static void lcd_refresh(void *opaque)
847 {
848     musicpal_lcd_state *s = opaque;
849     int x, y, col;
850
851     switch (ds_get_bits_per_pixel(s->ds)) {
852     case 0:
853         return;
854 #define LCD_REFRESH(depth, func) \
855     case depth: \
856         col = func(scale_lcd_color((MP_LCD_TEXTCOLOR >> 16) & 0xff), \
857                    scale_lcd_color((MP_LCD_TEXTCOLOR >> 8) & 0xff), \
858                    scale_lcd_color(MP_LCD_TEXTCOLOR & 0xff)); \
859         for (x = 0; x < 128; x++) \
860             for (y = 0; y < 64; y++) \
861                 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) \
862                     glue(set_lcd_pixel, depth)(s, x, y, col); \
863                 else \
864                     glue(set_lcd_pixel, depth)(s, x, y, 0); \
865         break;
866     LCD_REFRESH(8, rgb_to_pixel8)
867     LCD_REFRESH(16, rgb_to_pixel16)
868     LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
869                      rgb_to_pixel32bgr : rgb_to_pixel32))
870     default:
871         hw_error("unsupported colour depth %i\n",
872                   ds_get_bits_per_pixel(s->ds));
873     }
874
875     dpy_update(s->ds, 0, 0, 128*3, 64*3);
876 }
877
878 static void lcd_invalidate(void *opaque)
879 {
880 }
881
882 static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset)
883 {
884     musicpal_lcd_state *s = opaque;
885
886     switch (offset) {
887     case MP_LCD_IRQCTRL:
888         return s->irqctrl;
889
890     default:
891         return 0;
892     }
893 }
894
895 static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset,
896                                uint32_t value)
897 {
898     musicpal_lcd_state *s = opaque;
899
900     switch (offset) {
901     case MP_LCD_IRQCTRL:
902         s->irqctrl = value;
903         break;
904
905     case MP_LCD_SPICTRL:
906         if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD)
907             s->mode = value;
908         else
909             s->mode = MP_LCD_SPI_INVALID;
910         break;
911
912     case MP_LCD_INST:
913         if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
914             s->page = value - MP_LCD_INST_SETPAGE0;
915             s->page_off = 0;
916         }
917         break;
918
919     case MP_LCD_DATA:
920         if (s->mode == MP_LCD_SPI_CMD) {
921             if (value >= MP_LCD_INST_SETPAGE0 &&
922                 value <= MP_LCD_INST_SETPAGE7) {
923                 s->page = value - MP_LCD_INST_SETPAGE0;
924                 s->page_off = 0;
925             }
926         } else if (s->mode == MP_LCD_SPI_DATA) {
927             s->video_ram[s->page*128 + s->page_off] = value;
928             s->page_off = (s->page_off + 1) & 127;
929         }
930         break;
931     }
932 }
933
934 static CPUReadMemoryFunc *musicpal_lcd_readfn[] = {
935     musicpal_lcd_read,
936     musicpal_lcd_read,
937     musicpal_lcd_read
938 };
939
940 static CPUWriteMemoryFunc *musicpal_lcd_writefn[] = {
941     musicpal_lcd_write,
942     musicpal_lcd_write,
943     musicpal_lcd_write
944 };
945
946 static void musicpal_lcd_init(void)
947 {
948     musicpal_lcd_state *s;
949     int iomemtype;
950
951     s = qemu_mallocz(sizeof(musicpal_lcd_state));
952     iomemtype = cpu_register_io_memory(0, musicpal_lcd_readfn,
953                                        musicpal_lcd_writefn, s);
954     cpu_register_physical_memory(MP_LCD_BASE, MP_LCD_SIZE, iomemtype);
955
956     s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
957                                  NULL, NULL, s);
958     qemu_console_resize(s->ds, 128*3, 64*3);
959 }
960
961 /* PIC register offsets */
962 #define MP_PIC_STATUS           0x00
963 #define MP_PIC_ENABLE_SET       0x08
964 #define MP_PIC_ENABLE_CLR       0x0C
965
966 typedef struct mv88w8618_pic_state
967 {
968     uint32_t level;
969     uint32_t enabled;
970     qemu_irq parent_irq;
971 } mv88w8618_pic_state;
972
973 static void mv88w8618_pic_update(mv88w8618_pic_state *s)
974 {
975     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
976 }
977
978 static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
979 {
980     mv88w8618_pic_state *s = opaque;
981
982     if (level)
983         s->level |= 1 << irq;
984     else
985         s->level &= ~(1 << irq);
986     mv88w8618_pic_update(s);
987 }
988
989 static uint32_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset)
990 {
991     mv88w8618_pic_state *s = opaque;
992
993     switch (offset) {
994     case MP_PIC_STATUS:
995         return s->level & s->enabled;
996
997     default:
998         return 0;
999     }
1000 }
1001
1002 static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset,
1003                                 uint32_t value)
1004 {
1005     mv88w8618_pic_state *s = opaque;
1006
1007     switch (offset) {
1008     case MP_PIC_ENABLE_SET:
1009         s->enabled |= value;
1010         break;
1011
1012     case MP_PIC_ENABLE_CLR:
1013         s->enabled &= ~value;
1014         s->level &= ~value;
1015         break;
1016     }
1017     mv88w8618_pic_update(s);
1018 }
1019
1020 static void mv88w8618_pic_reset(void *opaque)
1021 {
1022     mv88w8618_pic_state *s = opaque;
1023
1024     s->level = 0;
1025     s->enabled = 0;
1026 }
1027
1028 static CPUReadMemoryFunc *mv88w8618_pic_readfn[] = {
1029     mv88w8618_pic_read,
1030     mv88w8618_pic_read,
1031     mv88w8618_pic_read
1032 };
1033
1034 static CPUWriteMemoryFunc *mv88w8618_pic_writefn[] = {
1035     mv88w8618_pic_write,
1036     mv88w8618_pic_write,
1037     mv88w8618_pic_write
1038 };
1039
1040 static qemu_irq *mv88w8618_pic_init(uint32_t base, qemu_irq parent_irq)
1041 {
1042     mv88w8618_pic_state *s;
1043     int iomemtype;
1044     qemu_irq *qi;
1045
1046     s = qemu_mallocz(sizeof(mv88w8618_pic_state));
1047     qi = qemu_allocate_irqs(mv88w8618_pic_set_irq, s, 32);
1048     s->parent_irq = parent_irq;
1049     iomemtype = cpu_register_io_memory(0, mv88w8618_pic_readfn,
1050                                        mv88w8618_pic_writefn, s);
1051     cpu_register_physical_memory(base, MP_PIC_SIZE, iomemtype);
1052
1053     qemu_register_reset(mv88w8618_pic_reset, s);
1054
1055     return qi;
1056 }
1057
1058 /* PIT register offsets */
1059 #define MP_PIT_TIMER1_LENGTH    0x00
1060 /* ... */
1061 #define MP_PIT_TIMER4_LENGTH    0x0C
1062 #define MP_PIT_CONTROL          0x10
1063 #define MP_PIT_TIMER1_VALUE     0x14
1064 /* ... */
1065 #define MP_PIT_TIMER4_VALUE     0x20
1066 #define MP_BOARD_RESET          0x34
1067
1068 /* Magic board reset value (probably some watchdog behind it) */
1069 #define MP_BOARD_RESET_MAGIC    0x10000
1070
1071 typedef struct mv88w8618_timer_state {
1072     ptimer_state *timer;
1073     uint32_t limit;
1074     int freq;
1075     qemu_irq irq;
1076 } mv88w8618_timer_state;
1077
1078 typedef struct mv88w8618_pit_state {
1079     void *timer[4];
1080     uint32_t control;
1081 } mv88w8618_pit_state;
1082
1083 static void mv88w8618_timer_tick(void *opaque)
1084 {
1085     mv88w8618_timer_state *s = opaque;
1086
1087     qemu_irq_raise(s->irq);
1088 }
1089
1090 static void *mv88w8618_timer_init(uint32_t freq, qemu_irq irq)
1091 {
1092     mv88w8618_timer_state *s;
1093     QEMUBH *bh;
1094
1095     s = qemu_mallocz(sizeof(mv88w8618_timer_state));
1096     s->irq = irq;
1097     s->freq = freq;
1098
1099     bh = qemu_bh_new(mv88w8618_timer_tick, s);
1100     s->timer = ptimer_init(bh);
1101
1102     return s;
1103 }
1104
1105 static uint32_t mv88w8618_pit_read(void *opaque, target_phys_addr_t offset)
1106 {
1107     mv88w8618_pit_state *s = opaque;
1108     mv88w8618_timer_state *t;
1109
1110     switch (offset) {
1111     case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
1112         t = s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
1113         return ptimer_get_count(t->timer);
1114
1115     default:
1116         return 0;
1117     }
1118 }
1119
1120 static void mv88w8618_pit_write(void *opaque, target_phys_addr_t offset,
1121                                 uint32_t value)
1122 {
1123     mv88w8618_pit_state *s = opaque;
1124     mv88w8618_timer_state *t;
1125     int i;
1126
1127     switch (offset) {
1128     case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
1129         t = s->timer[offset >> 2];
1130         t->limit = value;
1131         ptimer_set_limit(t->timer, t->limit, 1);
1132         break;
1133
1134     case MP_PIT_CONTROL:
1135         for (i = 0; i < 4; i++) {
1136             if (value & 0xf) {
1137                 t = s->timer[i];
1138                 ptimer_set_limit(t->timer, t->limit, 0);
1139                 ptimer_set_freq(t->timer, t->freq);
1140                 ptimer_run(t->timer, 0);
1141             }
1142             value >>= 4;
1143         }
1144         break;
1145
1146     case MP_BOARD_RESET:
1147         if (value == MP_BOARD_RESET_MAGIC)
1148             qemu_system_reset_request();
1149         break;
1150     }
1151 }
1152
1153 static CPUReadMemoryFunc *mv88w8618_pit_readfn[] = {
1154     mv88w8618_pit_read,
1155     mv88w8618_pit_read,
1156     mv88w8618_pit_read
1157 };
1158
1159 static CPUWriteMemoryFunc *mv88w8618_pit_writefn[] = {
1160     mv88w8618_pit_write,
1161     mv88w8618_pit_write,
1162     mv88w8618_pit_write
1163 };
1164
1165 static void mv88w8618_pit_init(uint32_t base, qemu_irq *pic, int irq)
1166 {
1167     int iomemtype;
1168     mv88w8618_pit_state *s;
1169
1170     s = qemu_mallocz(sizeof(mv88w8618_pit_state));
1171
1172     /* Letting them all run at 1 MHz is likely just a pragmatic
1173      * simplification. */
1174     s->timer[0] = mv88w8618_timer_init(1000000, pic[irq]);
1175     s->timer[1] = mv88w8618_timer_init(1000000, pic[irq + 1]);
1176     s->timer[2] = mv88w8618_timer_init(1000000, pic[irq + 2]);
1177     s->timer[3] = mv88w8618_timer_init(1000000, pic[irq + 3]);
1178
1179     iomemtype = cpu_register_io_memory(0, mv88w8618_pit_readfn,
1180                                        mv88w8618_pit_writefn, s);
1181     cpu_register_physical_memory(base, MP_PIT_SIZE, iomemtype);
1182 }
1183
1184 /* Flash config register offsets */
1185 #define MP_FLASHCFG_CFGR0    0x04
1186
1187 typedef struct mv88w8618_flashcfg_state {
1188     uint32_t cfgr0;
1189 } mv88w8618_flashcfg_state;
1190
1191 static uint32_t mv88w8618_flashcfg_read(void *opaque,
1192                                         target_phys_addr_t offset)
1193 {
1194     mv88w8618_flashcfg_state *s = opaque;
1195
1196     switch (offset) {
1197     case MP_FLASHCFG_CFGR0:
1198         return s->cfgr0;
1199
1200     default:
1201         return 0;
1202     }
1203 }
1204
1205 static void mv88w8618_flashcfg_write(void *opaque, target_phys_addr_t offset,
1206                                      uint32_t value)
1207 {
1208     mv88w8618_flashcfg_state *s = opaque;
1209
1210     switch (offset) {
1211     case MP_FLASHCFG_CFGR0:
1212         s->cfgr0 = value;
1213         break;
1214     }
1215 }
1216
1217 static CPUReadMemoryFunc *mv88w8618_flashcfg_readfn[] = {
1218     mv88w8618_flashcfg_read,
1219     mv88w8618_flashcfg_read,
1220     mv88w8618_flashcfg_read
1221 };
1222
1223 static CPUWriteMemoryFunc *mv88w8618_flashcfg_writefn[] = {
1224     mv88w8618_flashcfg_write,
1225     mv88w8618_flashcfg_write,
1226     mv88w8618_flashcfg_write
1227 };
1228
1229 static void mv88w8618_flashcfg_init(uint32_t base)
1230 {
1231     int iomemtype;
1232     mv88w8618_flashcfg_state *s;
1233
1234     s = qemu_mallocz(sizeof(mv88w8618_flashcfg_state));
1235
1236     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
1237     iomemtype = cpu_register_io_memory(0, mv88w8618_flashcfg_readfn,
1238                        mv88w8618_flashcfg_writefn, s);
1239     cpu_register_physical_memory(base, MP_FLASHCFG_SIZE, iomemtype);
1240 }
1241
1242 /* Misc register offsets */
1243 #define MP_MISC_BOARD_REVISION  0x18
1244
1245 #define MP_BOARD_REVISION       0x31
1246
1247 static uint32_t musicpal_misc_read(void *opaque, target_phys_addr_t offset)
1248 {
1249     switch (offset) {
1250     case MP_MISC_BOARD_REVISION:
1251         return MP_BOARD_REVISION;
1252
1253     default:
1254         return 0;
1255     }
1256 }
1257
1258 static void musicpal_misc_write(void *opaque, target_phys_addr_t offset,
1259                                 uint32_t value)
1260 {
1261 }
1262
1263 static CPUReadMemoryFunc *musicpal_misc_readfn[] = {
1264     musicpal_misc_read,
1265     musicpal_misc_read,
1266     musicpal_misc_read,
1267 };
1268
1269 static CPUWriteMemoryFunc *musicpal_misc_writefn[] = {
1270     musicpal_misc_write,
1271     musicpal_misc_write,
1272     musicpal_misc_write,
1273 };
1274
1275 static void musicpal_misc_init(void)
1276 {
1277     int iomemtype;
1278
1279     iomemtype = cpu_register_io_memory(0, musicpal_misc_readfn,
1280                                        musicpal_misc_writefn, NULL);
1281     cpu_register_physical_memory(MP_MISC_BASE, MP_MISC_SIZE, iomemtype);
1282 }
1283
1284 /* WLAN register offsets */
1285 #define MP_WLAN_MAGIC1          0x11c
1286 #define MP_WLAN_MAGIC2          0x124
1287
1288 static uint32_t mv88w8618_wlan_read(void *opaque, target_phys_addr_t offset)
1289 {
1290     switch (offset) {
1291     /* Workaround to allow loading the binary-only wlandrv.ko crap
1292      * from the original Freecom firmware. */
1293     case MP_WLAN_MAGIC1:
1294         return ~3;
1295     case MP_WLAN_MAGIC2:
1296         return -1;
1297
1298     default:
1299         return 0;
1300     }
1301 }
1302
1303 static void mv88w8618_wlan_write(void *opaque, target_phys_addr_t offset,
1304                                  uint32_t value)
1305 {
1306 }
1307
1308 static CPUReadMemoryFunc *mv88w8618_wlan_readfn[] = {
1309     mv88w8618_wlan_read,
1310     mv88w8618_wlan_read,
1311     mv88w8618_wlan_read,
1312 };
1313
1314 static CPUWriteMemoryFunc *mv88w8618_wlan_writefn[] = {
1315     mv88w8618_wlan_write,
1316     mv88w8618_wlan_write,
1317     mv88w8618_wlan_write,
1318 };
1319
1320 static void mv88w8618_wlan_init(uint32_t base)
1321 {
1322     int iomemtype;
1323
1324     iomemtype = cpu_register_io_memory(0, mv88w8618_wlan_readfn,
1325                                        mv88w8618_wlan_writefn, NULL);
1326     cpu_register_physical_memory(base, MP_WLAN_SIZE, iomemtype);
1327 }
1328
1329 /* GPIO register offsets */
1330 #define MP_GPIO_OE_LO           0x008
1331 #define MP_GPIO_OUT_LO          0x00c
1332 #define MP_GPIO_IN_LO           0x010
1333 #define MP_GPIO_ISR_LO          0x020
1334 #define MP_GPIO_OE_HI           0x508
1335 #define MP_GPIO_OUT_HI          0x50c
1336 #define MP_GPIO_IN_HI           0x510
1337 #define MP_GPIO_ISR_HI          0x520
1338
1339 /* GPIO bits & masks */
1340 #define MP_GPIO_WHEEL_VOL       (1 << 8)
1341 #define MP_GPIO_WHEEL_VOL_INV   (1 << 9)
1342 #define MP_GPIO_WHEEL_NAV       (1 << 10)
1343 #define MP_GPIO_WHEEL_NAV_INV   (1 << 11)
1344 #define MP_GPIO_LCD_BRIGHTNESS  0x00070000
1345 #define MP_GPIO_BTN_FAVORITS    (1 << 19)
1346 #define MP_GPIO_BTN_MENU        (1 << 20)
1347 #define MP_GPIO_BTN_VOLUME      (1 << 21)
1348 #define MP_GPIO_BTN_NAVIGATION  (1 << 22)
1349 #define MP_GPIO_I2C_DATA_BIT    29
1350 #define MP_GPIO_I2C_DATA        (1 << MP_GPIO_I2C_DATA_BIT)
1351 #define MP_GPIO_I2C_CLOCK_BIT   30
1352
1353 /* LCD brightness bits in GPIO_OE_HI */
1354 #define MP_OE_LCD_BRIGHTNESS    0x0007
1355
1356 static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset)
1357 {
1358     switch (offset) {
1359     case MP_GPIO_OE_HI: /* used for LCD brightness control */
1360         return lcd_brightness & MP_OE_LCD_BRIGHTNESS;
1361
1362     case MP_GPIO_OUT_LO:
1363         return gpio_out_state & 0xFFFF;
1364     case MP_GPIO_OUT_HI:
1365         return gpio_out_state >> 16;
1366
1367     case MP_GPIO_IN_LO:
1368         return gpio_in_state & 0xFFFF;
1369     case MP_GPIO_IN_HI:
1370         /* Update received I2C data */
1371         gpio_in_state = (gpio_in_state & ~MP_GPIO_I2C_DATA) |
1372                         (i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT);
1373         return gpio_in_state >> 16;
1374
1375     case MP_GPIO_ISR_LO:
1376         return gpio_isr & 0xFFFF;
1377     case MP_GPIO_ISR_HI:
1378         return gpio_isr >> 16;
1379
1380     default:
1381         return 0;
1382     }
1383 }
1384
1385 static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset,
1386                                 uint32_t value)
1387 {
1388     switch (offset) {
1389     case MP_GPIO_OE_HI: /* used for LCD brightness control */
1390         lcd_brightness = (lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
1391                          (value & MP_OE_LCD_BRIGHTNESS);
1392         break;
1393
1394     case MP_GPIO_OUT_LO:
1395         gpio_out_state = (gpio_out_state & 0xFFFF0000) | (value & 0xFFFF);
1396         break;
1397     case MP_GPIO_OUT_HI:
1398         gpio_out_state = (gpio_out_state & 0xFFFF) | (value << 16);
1399         lcd_brightness = (lcd_brightness & 0xFFFF) |
1400                          (gpio_out_state & MP_GPIO_LCD_BRIGHTNESS);
1401         i2c_state_update(mixer_i2c,
1402                          (gpio_out_state >> MP_GPIO_I2C_DATA_BIT) & 1,
1403                          (gpio_out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
1404         break;
1405
1406     }
1407 }
1408
1409 static CPUReadMemoryFunc *musicpal_gpio_readfn[] = {
1410     musicpal_gpio_read,
1411     musicpal_gpio_read,
1412     musicpal_gpio_read,
1413 };
1414
1415 static CPUWriteMemoryFunc *musicpal_gpio_writefn[] = {
1416     musicpal_gpio_write,
1417     musicpal_gpio_write,
1418     musicpal_gpio_write,
1419 };
1420
1421 static void musicpal_gpio_init(void)
1422 {
1423     int iomemtype;
1424
1425     iomemtype = cpu_register_io_memory(0, musicpal_gpio_readfn,
1426                                        musicpal_gpio_writefn, NULL);
1427     cpu_register_physical_memory(MP_GPIO_BASE, MP_GPIO_SIZE, iomemtype);
1428 }
1429
1430 /* Keyboard codes & masks */
1431 #define KEY_RELEASED            0x80
1432 #define KEY_CODE                0x7f
1433
1434 #define KEYCODE_TAB             0x0f
1435 #define KEYCODE_ENTER           0x1c
1436 #define KEYCODE_F               0x21
1437 #define KEYCODE_M               0x32
1438
1439 #define KEYCODE_EXTENDED        0xe0
1440 #define KEYCODE_UP              0x48
1441 #define KEYCODE_DOWN            0x50
1442 #define KEYCODE_LEFT            0x4b
1443 #define KEYCODE_RIGHT           0x4d
1444
1445 static void musicpal_key_event(void *opaque, int keycode)
1446 {
1447     qemu_irq irq = opaque;
1448     uint32_t event = 0;
1449     static int kbd_extended;
1450
1451     if (keycode == KEYCODE_EXTENDED) {
1452         kbd_extended = 1;
1453         return;
1454     }
1455
1456     if (kbd_extended)
1457         switch (keycode & KEY_CODE) {
1458         case KEYCODE_UP:
1459             event = MP_GPIO_WHEEL_NAV | MP_GPIO_WHEEL_NAV_INV;
1460             break;
1461
1462         case KEYCODE_DOWN:
1463             event = MP_GPIO_WHEEL_NAV;
1464             break;
1465
1466         case KEYCODE_LEFT:
1467             event = MP_GPIO_WHEEL_VOL | MP_GPIO_WHEEL_VOL_INV;
1468             break;
1469
1470         case KEYCODE_RIGHT:
1471             event = MP_GPIO_WHEEL_VOL;
1472             break;
1473         }
1474     else {
1475         switch (keycode & KEY_CODE) {
1476         case KEYCODE_F:
1477             event = MP_GPIO_BTN_FAVORITS;
1478             break;
1479
1480         case KEYCODE_TAB:
1481             event = MP_GPIO_BTN_VOLUME;
1482             break;
1483
1484         case KEYCODE_ENTER:
1485             event = MP_GPIO_BTN_NAVIGATION;
1486             break;
1487
1488         case KEYCODE_M:
1489             event = MP_GPIO_BTN_MENU;
1490             break;
1491         }
1492         /* Do not repeat already pressed buttons */
1493         if (!(keycode & KEY_RELEASED) && !(gpio_in_state & event))
1494             event = 0;
1495     }
1496
1497     if (event) {
1498         if (keycode & KEY_RELEASED) {
1499             gpio_in_state |= event;
1500         } else {
1501             gpio_in_state &= ~event;
1502             gpio_isr = event;
1503             qemu_irq_raise(irq);
1504         }
1505     }
1506
1507     kbd_extended = 0;
1508 }
1509
1510 static struct arm_boot_info musicpal_binfo = {
1511     .loader_start = 0x0,
1512     .board_id = 0x20e,
1513 };
1514
1515 static void musicpal_init(ram_addr_t ram_size, int vga_ram_size,
1516                const char *boot_device,
1517                const char *kernel_filename, const char *kernel_cmdline,
1518                const char *initrd_filename, const char *cpu_model)
1519 {
1520     CPUState *env;
1521     qemu_irq *pic;
1522     int index;
1523     unsigned long flash_size;
1524
1525     if (!cpu_model)
1526         cpu_model = "arm926";
1527
1528     env = cpu_init(cpu_model);
1529     if (!env) {
1530         fprintf(stderr, "Unable to find CPU definition\n");
1531         exit(1);
1532     }
1533     pic = arm_pic_init_cpu(env);
1534
1535     /* For now we use a fixed - the original - RAM size */
1536     cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
1537                                  qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
1538
1539     sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
1540     cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
1541
1542     pic = mv88w8618_pic_init(MP_PIC_BASE, pic[ARM_PIC_CPU_IRQ]);
1543     mv88w8618_pit_init(MP_PIT_BASE, pic, MP_TIMER1_IRQ);
1544
1545     if (serial_hds[0])
1546         serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
1547                    serial_hds[0], 1);
1548     if (serial_hds[1])
1549         serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
1550                    serial_hds[1], 1);
1551
1552     /* Register flash */
1553     index = drive_get_index(IF_PFLASH, 0, 0);
1554     if (index != -1) {
1555         flash_size = bdrv_getlength(drives_table[index].bdrv);
1556         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
1557             flash_size != 32*1024*1024) {
1558             fprintf(stderr, "Invalid flash image size\n");
1559             exit(1);
1560         }
1561
1562         /*
1563          * The original U-Boot accesses the flash at 0xFE000000 instead of
1564          * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
1565          * image is smaller than 32 MB.
1566          */
1567         pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
1568                               drives_table[index].bdrv, 0x10000,
1569                               (flash_size + 0xffff) >> 16,
1570                               MP_FLASH_SIZE_MAX / flash_size,
1571                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
1572                               0x5555, 0x2AAA);
1573     }
1574     mv88w8618_flashcfg_init(MP_FLASHCFG_BASE);
1575
1576     musicpal_lcd_init();
1577
1578     qemu_add_kbd_event_handler(musicpal_key_event, pic[MP_GPIO_IRQ]);
1579
1580     mv88w8618_eth_init(&nd_table[0], MP_ETH_BASE, pic[MP_ETH_IRQ]);
1581
1582     mixer_i2c = musicpal_audio_init(pic[MP_AUDIO_IRQ]);
1583
1584     mv88w8618_wlan_init(MP_WLAN_BASE);
1585
1586     musicpal_misc_init();
1587     musicpal_gpio_init();
1588
1589     musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
1590     musicpal_binfo.kernel_filename = kernel_filename;
1591     musicpal_binfo.kernel_cmdline = kernel_cmdline;
1592     musicpal_binfo.initrd_filename = initrd_filename;
1593     arm_load_kernel(env, &musicpal_binfo);
1594 }
1595
1596 QEMUMachine musicpal_machine = {
1597     .name = "musicpal",
1598     .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
1599     .init = musicpal_init,
1600 };
This page took 0.109048 seconds and 4 git commands to generate.