Statistics
| Branch: | Revision:

root / hw / musicpal.c @ 487414f1

History | View | Annotate | Download (39.1 kB)

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_ETH_BASE             0x80008000
24
#define MP_ETH_SIZE             0x00001000
25

    
26
#define MP_UART1_BASE           0x8000C840
27
#define MP_UART2_BASE           0x8000C940
28

    
29
#define MP_FLASHCFG_BASE        0x90006000
30
#define MP_FLASHCFG_SIZE        0x00001000
31

    
32
#define MP_AUDIO_BASE           0x90007000
33
#define MP_AUDIO_SIZE           0x00001000
34

    
35
#define MP_PIC_BASE             0x90008000
36
#define MP_PIC_SIZE             0x00001000
37

    
38
#define MP_PIT_BASE             0x90009000
39
#define MP_PIT_SIZE             0x00001000
40

    
41
#define MP_LCD_BASE             0x9000c000
42
#define MP_LCD_SIZE             0x00001000
43

    
44
#define MP_SRAM_BASE            0xC0000000
45
#define MP_SRAM_SIZE            0x00020000
46

    
47
#define MP_RAM_DEFAULT_SIZE     32*1024*1024
48
#define MP_FLASH_SIZE_MAX       32*1024*1024
49

    
50
#define MP_TIMER1_IRQ           4
51
/* ... */
52
#define MP_TIMER4_IRQ           7
53
#define MP_EHCI_IRQ             8
54
#define MP_ETH_IRQ              9
55
#define MP_UART1_IRQ            11
56
#define MP_UART2_IRQ            11
57
#define MP_GPIO_IRQ             12
58
#define MP_RTC_IRQ              28
59
#define MP_AUDIO_IRQ            30
60

    
61
static uint32_t gpio_in_state = 0xffffffff;
62
static uint32_t gpio_isr;
63
static uint32_t gpio_out_state;
64
static ram_addr_t sram_off;
65

    
66
/* Address conversion helpers */
67
static void *target2host_addr(uint32_t addr)
68
{
69
    if (addr < MP_SRAM_BASE) {
70
        if (addr >= MP_RAM_DEFAULT_SIZE)
71
            return NULL;
72
        return (void *)(phys_ram_base + addr);
73
    } else {
74
        if (addr >= MP_SRAM_BASE + MP_SRAM_SIZE)
75
            return NULL;
76
        return (void *)(phys_ram_base + sram_off + addr - MP_SRAM_BASE);
77
    }
78
}
79

    
80
static uint32_t host2target_addr(void *addr)
81
{
82
    if (addr < ((void *)phys_ram_base) + sram_off)
83
        return (unsigned long)addr - (unsigned long)phys_ram_base;
84
    else
85
        return (unsigned long)addr - (unsigned long)phys_ram_base -
86
            sram_off + MP_SRAM_BASE;
87
}
88

    
89

    
90
typedef enum i2c_state {
91
    STOPPED = 0,
92
    INITIALIZING,
93
    SENDING_BIT7,
94
    SENDING_BIT6,
95
    SENDING_BIT5,
96
    SENDING_BIT4,
97
    SENDING_BIT3,
98
    SENDING_BIT2,
99
    SENDING_BIT1,
100
    SENDING_BIT0,
101
    WAITING_FOR_ACK,
102
    RECEIVING_BIT7,
103
    RECEIVING_BIT6,
104
    RECEIVING_BIT5,
105
    RECEIVING_BIT4,
106
    RECEIVING_BIT3,
107
    RECEIVING_BIT2,
108
    RECEIVING_BIT1,
109
    RECEIVING_BIT0,
110
    SENDING_ACK
111
} i2c_state;
112

    
113
typedef struct i2c_interface {
114
    i2c_bus *bus;
115
    i2c_state state;
116
    int last_data;
117
    int last_clock;
118
    uint8_t buffer;
119
    int current_addr;
120
} i2c_interface;
121

    
122
static void i2c_enter_stop(i2c_interface *i2c)
123
{
124
    if (i2c->current_addr >= 0)
125
        i2c_end_transfer(i2c->bus);
126
    i2c->current_addr = -1;
127
    i2c->state = STOPPED;
128
}
129

    
130
static void i2c_state_update(i2c_interface *i2c, int data, int clock)
131
{
132
    if (!i2c)
133
        return;
134

    
135
    switch (i2c->state) {
136
    case STOPPED:
137
        if (data == 0 && i2c->last_data == 1 && clock == 1)
138
            i2c->state = INITIALIZING;
139
        break;
140

    
141
    case INITIALIZING:
142
        if (clock == 0 && i2c->last_clock == 1 && data == 0)
143
            i2c->state = SENDING_BIT7;
144
        else
145
            i2c_enter_stop(i2c);
146
        break;
147

    
148
    case SENDING_BIT7 ... SENDING_BIT0:
149
        if (clock == 0 && i2c->last_clock == 1) {
150
            i2c->buffer = (i2c->buffer << 1) | data;
151
            i2c->state++; /* will end up in WAITING_FOR_ACK */
152
        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
153
            i2c_enter_stop(i2c);
154
        break;
155

    
156
    case WAITING_FOR_ACK:
157
        if (clock == 0 && i2c->last_clock == 1) {
158
            if (i2c->current_addr < 0) {
159
                i2c->current_addr = i2c->buffer;
160
                i2c_start_transfer(i2c->bus, i2c->current_addr & 0xfe,
161
                                   i2c->buffer & 1);
162
            } else
163
                i2c_send(i2c->bus, i2c->buffer);
164
            if (i2c->current_addr & 1) {
165
                i2c->state = RECEIVING_BIT7;
166
                i2c->buffer = i2c_recv(i2c->bus);
167
            } else
168
                i2c->state = SENDING_BIT7;
169
        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
170
            i2c_enter_stop(i2c);
171
        break;
172

    
173
    case RECEIVING_BIT7 ... RECEIVING_BIT0:
174
        if (clock == 0 && i2c->last_clock == 1) {
175
            i2c->state++; /* will end up in SENDING_ACK */
176
            i2c->buffer <<= 1;
177
        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
178
            i2c_enter_stop(i2c);
179
        break;
180

    
181
    case SENDING_ACK:
182
        if (clock == 0 && i2c->last_clock == 1) {
183
            i2c->state = RECEIVING_BIT7;
184
            if (data == 0)
185
                i2c->buffer = i2c_recv(i2c->bus);
186
            else
187
                i2c_nack(i2c->bus);
188
        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
189
            i2c_enter_stop(i2c);
190
        break;
191
    }
192

    
193
    i2c->last_data = data;
194
    i2c->last_clock = clock;
195
}
196

    
197
static int i2c_get_data(i2c_interface *i2c)
198
{
199
    if (!i2c)
200
        return 0;
201

    
202
    switch (i2c->state) {
203
    case RECEIVING_BIT7 ... RECEIVING_BIT0:
204
        return (i2c->buffer >> 7);
205

    
206
    case WAITING_FOR_ACK:
207
    default:
208
        return 0;
209
    }
210
}
211

    
212
static i2c_interface *mixer_i2c;
213

    
214
#ifdef HAS_AUDIO
215

    
216
/* Audio register offsets */
217
#define MP_AUDIO_PLAYBACK_MODE  0x00
218
#define MP_AUDIO_CLOCK_DIV      0x18
219
#define MP_AUDIO_IRQ_STATUS     0x20
220
#define MP_AUDIO_IRQ_ENABLE     0x24
221
#define MP_AUDIO_TX_START_LO    0x28
222
#define MP_AUDIO_TX_THRESHOLD   0x2C
223
#define MP_AUDIO_TX_STATUS      0x38
224
#define MP_AUDIO_TX_START_HI    0x40
225

    
226
/* Status register and IRQ enable bits */
227
#define MP_AUDIO_TX_HALF        (1 << 6)
228
#define MP_AUDIO_TX_FULL        (1 << 7)
229

    
230
/* Playback mode bits */
231
#define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
232
#define MP_AUDIO_PLAYBACK_EN    (1 << 7)
233
#define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
234
#define MP_AUDIO_MONO           (1 << 14)
235

    
236
/* Wolfson 8750 I2C address */
237
#define MP_WM_ADDR              0x34
238

    
239
static const char audio_name[] = "mv88w8618";
240

    
241
typedef struct musicpal_audio_state {
242
    qemu_irq irq;
243
    uint32_t playback_mode;
244
    uint32_t status;
245
    uint32_t irq_enable;
246
    unsigned long phys_buf;
247
    int8_t *target_buffer;
248
    unsigned int threshold;
249
    unsigned int play_pos;
250
    unsigned int last_free;
251
    uint32_t clock_div;
252
    i2c_slave *wm;
253
} musicpal_audio_state;
254

    
255
static void audio_callback(void *opaque, int free_out, int free_in)
256
{
257
    musicpal_audio_state *s = opaque;
258
    int16_t *codec_buffer;
259
    int8_t *mem_buffer;
260
    int pos, block_size;
261

    
262
    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN))
263
        return;
264

    
265
    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
266
        free_out <<= 1;
267

    
268
    if (!(s->playback_mode & MP_AUDIO_MONO))
269
        free_out <<= 1;
270

    
271
    block_size = s->threshold/2;
272
    if (free_out - s->last_free < block_size)
273
        return;
274

    
275
    mem_buffer = s->target_buffer + s->play_pos;
276
    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
277
        if (s->playback_mode & MP_AUDIO_MONO) {
278
            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
279
            for (pos = 0; pos < block_size; pos += 2) {
280
                *codec_buffer++ = *(int16_t *)mem_buffer;
281
                *codec_buffer++ = *(int16_t *)mem_buffer;
282
                mem_buffer += 2;
283
            }
284
        } else
285
            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
286
                   (uint32_t *)mem_buffer, block_size);
287
    } else {
288
        if (s->playback_mode & MP_AUDIO_MONO) {
289
            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
290
            for (pos = 0; pos < block_size; pos++) {
291
                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
292
                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
293
            }
294
        } else {
295
            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
296
            for (pos = 0; pos < block_size; pos += 2) {
297
                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
298
                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
299
            }
300
        }
301
    }
302
    wm8750_dac_commit(s->wm);
303

    
304
    s->last_free = free_out - block_size;
305

    
306
    if (s->play_pos == 0) {
307
        s->status |= MP_AUDIO_TX_HALF;
308
        s->play_pos = block_size;
309
    } else {
310
        s->status |= MP_AUDIO_TX_FULL;
311
        s->play_pos = 0;
312
    }
313

    
314
    if (s->status & s->irq_enable)
315
        qemu_irq_raise(s->irq);
316
}
317

    
318
static void musicpal_audio_clock_update(musicpal_audio_state *s)
319
{
320
    int rate;
321

    
322
    if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ)
323
        rate = 24576000 / 64; /* 24.576MHz */
324
    else
325
        rate = 11289600 / 64; /* 11.2896MHz */
326

    
327
    rate /= ((s->clock_div >> 8) & 0xff) + 1;
328

    
329
    wm8750_set_bclk_in(s->wm, rate);
330
}
331

    
332
static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset)
333
{
334
    musicpal_audio_state *s = opaque;
335

    
336
    switch (offset) {
337
    case MP_AUDIO_PLAYBACK_MODE:
338
        return s->playback_mode;
339

    
340
    case MP_AUDIO_CLOCK_DIV:
341
        return s->clock_div;
342

    
343
    case MP_AUDIO_IRQ_STATUS:
344
        return s->status;
345

    
346
    case MP_AUDIO_IRQ_ENABLE:
347
        return s->irq_enable;
348

    
349
    case MP_AUDIO_TX_STATUS:
350
        return s->play_pos >> 2;
351

    
352
    default:
353
        return 0;
354
    }
355
}
356

    
357
static void musicpal_audio_write(void *opaque, target_phys_addr_t offset,
358
                                 uint32_t value)
359
{
360
    musicpal_audio_state *s = opaque;
361

    
362
    switch (offset) {
363
    case MP_AUDIO_PLAYBACK_MODE:
364
        if (value & MP_AUDIO_PLAYBACK_EN &&
365
            !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
366
            s->status = 0;
367
            s->last_free = 0;
368
            s->play_pos = 0;
369
        }
370
        s->playback_mode = value;
371
        musicpal_audio_clock_update(s);
372
        break;
373

    
374
    case MP_AUDIO_CLOCK_DIV:
375
        s->clock_div = value;
376
        s->last_free = 0;
377
        s->play_pos = 0;
378
        musicpal_audio_clock_update(s);
379
        break;
380

    
381
    case MP_AUDIO_IRQ_STATUS:
382
        s->status &= ~value;
383
        break;
384

    
385
    case MP_AUDIO_IRQ_ENABLE:
386
        s->irq_enable = value;
387
        if (s->status & s->irq_enable)
388
            qemu_irq_raise(s->irq);
389
        break;
390

    
391
    case MP_AUDIO_TX_START_LO:
392
        s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
393
        s->target_buffer = target2host_addr(s->phys_buf);
394
        s->play_pos = 0;
395
        s->last_free = 0;
396
        break;
397

    
398
    case MP_AUDIO_TX_THRESHOLD:
399
        s->threshold = (value + 1) * 4;
400
        break;
401

    
402
    case MP_AUDIO_TX_START_HI:
403
        s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
404
        s->target_buffer = target2host_addr(s->phys_buf);
405
        s->play_pos = 0;
406
        s->last_free = 0;
407
        break;
408
    }
409
}
410

    
411
static void musicpal_audio_reset(void *opaque)
412
{
413
    musicpal_audio_state *s = opaque;
414

    
415
    s->playback_mode = 0;
416
    s->status = 0;
417
    s->irq_enable = 0;
418
}
419

    
420
static CPUReadMemoryFunc *musicpal_audio_readfn[] = {
421
    musicpal_audio_read,
422
    musicpal_audio_read,
423
    musicpal_audio_read
424
};
425

    
426
static CPUWriteMemoryFunc *musicpal_audio_writefn[] = {
427
    musicpal_audio_write,
428
    musicpal_audio_write,
429
    musicpal_audio_write
430
};
431

    
432
static i2c_interface *musicpal_audio_init(uint32_t base, qemu_irq irq)
433
{
434
    AudioState *audio;
435
    musicpal_audio_state *s;
436
    i2c_interface *i2c;
437
    int iomemtype;
438

    
439
    audio = AUD_init();
440
    if (!audio) {
441
        AUD_log(audio_name, "No audio state\n");
442
        return NULL;
443
    }
444

    
445
    s = qemu_mallocz(sizeof(musicpal_audio_state));
446
    s->irq = irq;
447

    
448
    i2c = qemu_mallocz(sizeof(i2c_interface));
449
    i2c->bus = i2c_init_bus();
450
    i2c->current_addr = -1;
451

    
452
    s->wm = wm8750_init(i2c->bus, audio);
453
    if (!s->wm)
454
        return NULL;
455
    i2c_set_slave_address(s->wm, MP_WM_ADDR);
456
    wm8750_data_req_set(s->wm, audio_callback, s);
457

    
458
    iomemtype = cpu_register_io_memory(0, musicpal_audio_readfn,
459
                       musicpal_audio_writefn, s);
460
    cpu_register_physical_memory(base, MP_AUDIO_SIZE, iomemtype);
461

    
462
    qemu_register_reset(musicpal_audio_reset, s);
463

    
464
    return i2c;
465
}
466
#else  /* !HAS_AUDIO */
467
static i2c_interface *musicpal_audio_init(uint32_t base, qemu_irq irq)
468
{
469
    return NULL;
470
}
471
#endif /* !HAS_AUDIO */
472

    
473
/* Ethernet register offsets */
474
#define MP_ETH_SMIR             0x010
475
#define MP_ETH_PCXR             0x408
476
#define MP_ETH_SDCMR            0x448
477
#define MP_ETH_ICR              0x450
478
#define MP_ETH_IMR              0x458
479
#define MP_ETH_FRDP0            0x480
480
#define MP_ETH_FRDP1            0x484
481
#define MP_ETH_FRDP2            0x488
482
#define MP_ETH_FRDP3            0x48C
483
#define MP_ETH_CRDP0            0x4A0
484
#define MP_ETH_CRDP1            0x4A4
485
#define MP_ETH_CRDP2            0x4A8
486
#define MP_ETH_CRDP3            0x4AC
487
#define MP_ETH_CTDP0            0x4E0
488
#define MP_ETH_CTDP1            0x4E4
489
#define MP_ETH_CTDP2            0x4E8
490
#define MP_ETH_CTDP3            0x4EC
491

    
492
/* MII PHY access */
493
#define MP_ETH_SMIR_DATA        0x0000FFFF
494
#define MP_ETH_SMIR_ADDR        0x03FF0000
495
#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
496
#define MP_ETH_SMIR_RDVALID     (1 << 27)
497

    
498
/* PHY registers */
499
#define MP_ETH_PHY1_BMSR        0x00210000
500
#define MP_ETH_PHY1_PHYSID1     0x00410000
501
#define MP_ETH_PHY1_PHYSID2     0x00610000
502

    
503
#define MP_PHY_BMSR_LINK        0x0004
504
#define MP_PHY_BMSR_AUTONEG     0x0008
505

    
506
#define MP_PHY_88E3015          0x01410E20
507

    
508
/* TX descriptor status */
509
#define MP_ETH_TX_OWN           (1 << 31)
510

    
511
/* RX descriptor status */
512
#define MP_ETH_RX_OWN           (1 << 31)
513

    
514
/* Interrupt cause/mask bits */
515
#define MP_ETH_IRQ_RX_BIT       0
516
#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
517
#define MP_ETH_IRQ_TXHI_BIT     2
518
#define MP_ETH_IRQ_TXLO_BIT     3
519

    
520
/* Port config bits */
521
#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
522

    
523
/* SDMA command bits */
524
#define MP_ETH_CMD_TXHI         (1 << 23)
525
#define MP_ETH_CMD_TXLO         (1 << 22)
526

    
527
typedef struct mv88w8618_tx_desc {
528
    uint32_t cmdstat;
529
    uint16_t res;
530
    uint16_t bytes;
531
    uint32_t buffer;
532
    uint32_t next;
533
} mv88w8618_tx_desc;
534

    
535
typedef struct mv88w8618_rx_desc {
536
    uint32_t cmdstat;
537
    uint16_t bytes;
538
    uint16_t buffer_size;
539
    uint32_t buffer;
540
    uint32_t next;
541
} mv88w8618_rx_desc;
542

    
543
typedef struct mv88w8618_eth_state {
544
    qemu_irq irq;
545
    uint32_t smir;
546
    uint32_t icr;
547
    uint32_t imr;
548
    int vlan_header;
549
    mv88w8618_tx_desc *tx_queue[2];
550
    mv88w8618_rx_desc *rx_queue[4];
551
    mv88w8618_rx_desc *frx_queue[4];
552
    mv88w8618_rx_desc *cur_rx[4];
553
    VLANClientState *vc;
554
} mv88w8618_eth_state;
555

    
556
static int eth_can_receive(void *opaque)
557
{
558
    return 1;
559
}
560

    
561
static void eth_receive(void *opaque, const uint8_t *buf, int size)
562
{
563
    mv88w8618_eth_state *s = opaque;
564
    mv88w8618_rx_desc *desc;
565
    int i;
566

    
567
    for (i = 0; i < 4; i++) {
568
        desc = s->cur_rx[i];
569
        if (!desc)
570
            continue;
571
        do {
572
            if (le32_to_cpu(desc->cmdstat) & MP_ETH_RX_OWN &&
573
                le16_to_cpu(desc->buffer_size) >= size) {
574
                memcpy(target2host_addr(le32_to_cpu(desc->buffer) +
575
                                        s->vlan_header),
576
                       buf, size);
577
                desc->bytes = cpu_to_le16(size + s->vlan_header);
578
                desc->cmdstat &= cpu_to_le32(~MP_ETH_RX_OWN);
579
                s->cur_rx[i] = target2host_addr(le32_to_cpu(desc->next));
580

    
581
                s->icr |= MP_ETH_IRQ_RX;
582
                if (s->icr & s->imr)
583
                    qemu_irq_raise(s->irq);
584
                return;
585
            }
586
            desc = target2host_addr(le32_to_cpu(desc->next));
587
        } while (desc != s->rx_queue[i]);
588
    }
589
}
590

    
591
static void eth_send(mv88w8618_eth_state *s, int queue_index)
592
{
593
    mv88w8618_tx_desc *desc = s->tx_queue[queue_index];
594

    
595
    do {
596
        if (le32_to_cpu(desc->cmdstat) & MP_ETH_TX_OWN) {
597
            qemu_send_packet(s->vc,
598
                             target2host_addr(le32_to_cpu(desc->buffer)),
599
                             le16_to_cpu(desc->bytes));
600
            desc->cmdstat &= cpu_to_le32(~MP_ETH_TX_OWN);
601
            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
602
        }
603
        desc = target2host_addr(le32_to_cpu(desc->next));
604
    } while (desc != s->tx_queue[queue_index]);
605
}
606

    
607
static uint32_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset)
608
{
609
    mv88w8618_eth_state *s = opaque;
610

    
611
    switch (offset) {
612
    case MP_ETH_SMIR:
613
        if (s->smir & MP_ETH_SMIR_OPCODE) {
614
            switch (s->smir & MP_ETH_SMIR_ADDR) {
615
            case MP_ETH_PHY1_BMSR:
616
                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
617
                       MP_ETH_SMIR_RDVALID;
618
            case MP_ETH_PHY1_PHYSID1:
619
                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
620
            case MP_ETH_PHY1_PHYSID2:
621
                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
622
            default:
623
                return MP_ETH_SMIR_RDVALID;
624
            }
625
        }
626
        return 0;
627

    
628
    case MP_ETH_ICR:
629
        return s->icr;
630

    
631
    case MP_ETH_IMR:
632
        return s->imr;
633

    
634
    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
635
        return host2target_addr(s->frx_queue[(offset - MP_ETH_FRDP0)/4]);
636

    
637
    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
638
        return host2target_addr(s->rx_queue[(offset - MP_ETH_CRDP0)/4]);
639

    
640
    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
641
        return host2target_addr(s->tx_queue[(offset - MP_ETH_CTDP0)/4]);
642

    
643
    default:
644
        return 0;
645
    }
646
}
647

    
648
static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,
649
                                uint32_t value)
650
{
651
    mv88w8618_eth_state *s = opaque;
652

    
653
    switch (offset) {
654
    case MP_ETH_SMIR:
655
        s->smir = value;
656
        break;
657

    
658
    case MP_ETH_PCXR:
659
        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
660
        break;
661

    
662
    case MP_ETH_SDCMR:
663
        if (value & MP_ETH_CMD_TXHI)
664
            eth_send(s, 1);
665
        if (value & MP_ETH_CMD_TXLO)
666
            eth_send(s, 0);
667
        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr)
668
            qemu_irq_raise(s->irq);
669
        break;
670

    
671
    case MP_ETH_ICR:
672
        s->icr &= value;
673
        break;
674

    
675
    case MP_ETH_IMR:
676
        s->imr = value;
677
        if (s->icr & s->imr)
678
            qemu_irq_raise(s->irq);
679
        break;
680

    
681
    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
682
        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = target2host_addr(value);
683
        break;
684

    
685
    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
686
        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
687
            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = target2host_addr(value);
688
        break;
689

    
690
    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
691
        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = target2host_addr(value);
692
        break;
693
    }
694
}
695

    
696
static CPUReadMemoryFunc *mv88w8618_eth_readfn[] = {
697
    mv88w8618_eth_read,
698
    mv88w8618_eth_read,
699
    mv88w8618_eth_read
700
};
701

    
702
static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {
703
    mv88w8618_eth_write,
704
    mv88w8618_eth_write,
705
    mv88w8618_eth_write
706
};
707

    
708
static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
709
{
710
    mv88w8618_eth_state *s;
711
    int iomemtype;
712

    
713
    qemu_check_nic_model(nd, "mv88w8618");
714

    
715
    s = qemu_mallocz(sizeof(mv88w8618_eth_state));
716
    s->irq = irq;
717
    s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
718
                                 eth_receive, eth_can_receive, s);
719
    iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,
720
                                       mv88w8618_eth_writefn, s);
721
    cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);
722
}
723

    
724
/* LCD register offsets */
725
#define MP_LCD_IRQCTRL          0x180
726
#define MP_LCD_IRQSTAT          0x184
727
#define MP_LCD_SPICTRL          0x1ac
728
#define MP_LCD_INST             0x1bc
729
#define MP_LCD_DATA             0x1c0
730

    
731
/* Mode magics */
732
#define MP_LCD_SPI_DATA         0x00100011
733
#define MP_LCD_SPI_CMD          0x00104011
734
#define MP_LCD_SPI_INVALID      0x00000000
735

    
736
/* Commmands */
737
#define MP_LCD_INST_SETPAGE0    0xB0
738
/* ... */
739
#define MP_LCD_INST_SETPAGE7    0xB7
740

    
741
#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
742

    
743
typedef struct musicpal_lcd_state {
744
    uint32_t mode;
745
    uint32_t irqctrl;
746
    int page;
747
    int page_off;
748
    DisplayState *ds;
749
    uint8_t video_ram[128*64/8];
750
} musicpal_lcd_state;
751

    
752
static uint32_t lcd_brightness;
753

    
754
static uint8_t scale_lcd_color(uint8_t col)
755
{
756
    int tmp = col;
757

    
758
    switch (lcd_brightness) {
759
    case 0x00000007: /* 0 */
760
        return 0;
761

    
762
    case 0x00020000: /* 1 */
763
        return (tmp * 1) / 7;
764

    
765
    case 0x00020001: /* 2 */
766
        return (tmp * 2) / 7;
767

    
768
    case 0x00040000: /* 3 */
769
        return (tmp * 3) / 7;
770

    
771
    case 0x00010006: /* 4 */
772
        return (tmp * 4) / 7;
773

    
774
    case 0x00020005: /* 5 */
775
        return (tmp * 5) / 7;
776

    
777
    case 0x00040003: /* 6 */
778
        return (tmp * 6) / 7;
779

    
780
    case 0x00030004: /* 7 */
781
    default:
782
        return col;
783
    }
784
}
785

    
786
#define SET_LCD_PIXEL(depth, type) \
787
static inline void glue(set_lcd_pixel, depth) \
788
        (musicpal_lcd_state *s, int x, int y, type col) \
789
{ \
790
    int dx, dy; \
791
    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
792
\
793
    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
794
        for (dx = 0; dx < 3; dx++, pixel++) \
795
            *pixel = col; \
796
}
797
SET_LCD_PIXEL(8, uint8_t)
798
SET_LCD_PIXEL(16, uint16_t)
799
SET_LCD_PIXEL(32, uint32_t)
800

    
801
#include "pixel_ops.h"
802

    
803
static void lcd_refresh(void *opaque)
804
{
805
    musicpal_lcd_state *s = opaque;
806
    int x, y, col;
807

    
808
    switch (ds_get_bits_per_pixel(s->ds)) {
809
    case 0:
810
        return;
811
#define LCD_REFRESH(depth, func) \
812
    case depth: \
813
        col = func(scale_lcd_color((MP_LCD_TEXTCOLOR >> 16) & 0xff), \
814
                   scale_lcd_color((MP_LCD_TEXTCOLOR >> 8) & 0xff), \
815
                   scale_lcd_color(MP_LCD_TEXTCOLOR & 0xff)); \
816
        for (x = 0; x < 128; x++) \
817
            for (y = 0; y < 64; y++) \
818
                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) \
819
                    glue(set_lcd_pixel, depth)(s, x, y, col); \
820
                else \
821
                    glue(set_lcd_pixel, depth)(s, x, y, 0); \
822
        break;
823
    LCD_REFRESH(8, rgb_to_pixel8)
824
    LCD_REFRESH(16, rgb_to_pixel16)
825
    LCD_REFRESH(32, rgb_to_pixel32)
826
    default:
827
        cpu_abort(cpu_single_env, "unsupported colour depth %i\n",
828
                  ds_get_bits_per_pixel(s->ds));
829
    }
830

    
831
    dpy_update(s->ds, 0, 0, 128*3, 64*3);
832
}
833

    
834
static void lcd_invalidate(void *opaque)
835
{
836
}
837

    
838
static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset)
839
{
840
    musicpal_lcd_state *s = opaque;
841

    
842
    switch (offset) {
843
    case MP_LCD_IRQCTRL:
844
        return s->irqctrl;
845

    
846
    default:
847
        return 0;
848
    }
849
}
850

    
851
static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset,
852
                               uint32_t value)
853
{
854
    musicpal_lcd_state *s = opaque;
855

    
856
    switch (offset) {
857
    case MP_LCD_IRQCTRL:
858
        s->irqctrl = value;
859
        break;
860

    
861
    case MP_LCD_SPICTRL:
862
        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD)
863
            s->mode = value;
864
        else
865
            s->mode = MP_LCD_SPI_INVALID;
866
        break;
867

    
868
    case MP_LCD_INST:
869
        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
870
            s->page = value - MP_LCD_INST_SETPAGE0;
871
            s->page_off = 0;
872
        }
873
        break;
874

    
875
    case MP_LCD_DATA:
876
        if (s->mode == MP_LCD_SPI_CMD) {
877
            if (value >= MP_LCD_INST_SETPAGE0 &&
878
                value <= MP_LCD_INST_SETPAGE7) {
879
                s->page = value - MP_LCD_INST_SETPAGE0;
880
                s->page_off = 0;
881
            }
882
        } else if (s->mode == MP_LCD_SPI_DATA) {
883
            s->video_ram[s->page*128 + s->page_off] = value;
884
            s->page_off = (s->page_off + 1) & 127;
885
        }
886
        break;
887
    }
888
}
889

    
890
static CPUReadMemoryFunc *musicpal_lcd_readfn[] = {
891
    musicpal_lcd_read,
892
    musicpal_lcd_read,
893
    musicpal_lcd_read
894
};
895

    
896
static CPUWriteMemoryFunc *musicpal_lcd_writefn[] = {
897
    musicpal_lcd_write,
898
    musicpal_lcd_write,
899
    musicpal_lcd_write
900
};
901

    
902
static void musicpal_lcd_init(uint32_t base)
903
{
904
    musicpal_lcd_state *s;
905
    int iomemtype;
906

    
907
    s = qemu_mallocz(sizeof(musicpal_lcd_state));
908
    iomemtype = cpu_register_io_memory(0, musicpal_lcd_readfn,
909
                                       musicpal_lcd_writefn, s);
910
    cpu_register_physical_memory(base, MP_LCD_SIZE, iomemtype);
911

    
912
    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
913
                                 NULL, NULL, s);
914
    qemu_console_resize(s->ds, 128*3, 64*3);
915
}
916

    
917
/* PIC register offsets */
918
#define MP_PIC_STATUS           0x00
919
#define MP_PIC_ENABLE_SET       0x08
920
#define MP_PIC_ENABLE_CLR       0x0C
921

    
922
typedef struct mv88w8618_pic_state
923
{
924
    uint32_t level;
925
    uint32_t enabled;
926
    qemu_irq parent_irq;
927
} mv88w8618_pic_state;
928

    
929
static void mv88w8618_pic_update(mv88w8618_pic_state *s)
930
{
931
    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
932
}
933

    
934
static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
935
{
936
    mv88w8618_pic_state *s = opaque;
937

    
938
    if (level)
939
        s->level |= 1 << irq;
940
    else
941
        s->level &= ~(1 << irq);
942
    mv88w8618_pic_update(s);
943
}
944

    
945
static uint32_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset)
946
{
947
    mv88w8618_pic_state *s = opaque;
948

    
949
    switch (offset) {
950
    case MP_PIC_STATUS:
951
        return s->level & s->enabled;
952

    
953
    default:
954
        return 0;
955
    }
956
}
957

    
958
static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset,
959
                                uint32_t value)
960
{
961
    mv88w8618_pic_state *s = opaque;
962

    
963
    switch (offset) {
964
    case MP_PIC_ENABLE_SET:
965
        s->enabled |= value;
966
        break;
967

    
968
    case MP_PIC_ENABLE_CLR:
969
        s->enabled &= ~value;
970
        s->level &= ~value;
971
        break;
972
    }
973
    mv88w8618_pic_update(s);
974
}
975

    
976
static void mv88w8618_pic_reset(void *opaque)
977
{
978
    mv88w8618_pic_state *s = opaque;
979

    
980
    s->level = 0;
981
    s->enabled = 0;
982
}
983

    
984
static CPUReadMemoryFunc *mv88w8618_pic_readfn[] = {
985
    mv88w8618_pic_read,
986
    mv88w8618_pic_read,
987
    mv88w8618_pic_read
988
};
989

    
990
static CPUWriteMemoryFunc *mv88w8618_pic_writefn[] = {
991
    mv88w8618_pic_write,
992
    mv88w8618_pic_write,
993
    mv88w8618_pic_write
994
};
995

    
996
static qemu_irq *mv88w8618_pic_init(uint32_t base, qemu_irq parent_irq)
997
{
998
    mv88w8618_pic_state *s;
999
    int iomemtype;
1000
    qemu_irq *qi;
1001

    
1002
    s = qemu_mallocz(sizeof(mv88w8618_pic_state));
1003
    qi = qemu_allocate_irqs(mv88w8618_pic_set_irq, s, 32);
1004
    s->parent_irq = parent_irq;
1005
    iomemtype = cpu_register_io_memory(0, mv88w8618_pic_readfn,
1006
                                       mv88w8618_pic_writefn, s);
1007
    cpu_register_physical_memory(base, MP_PIC_SIZE, iomemtype);
1008

    
1009
    qemu_register_reset(mv88w8618_pic_reset, s);
1010

    
1011
    return qi;
1012
}
1013

    
1014
/* PIT register offsets */
1015
#define MP_PIT_TIMER1_LENGTH    0x00
1016
/* ... */
1017
#define MP_PIT_TIMER4_LENGTH    0x0C
1018
#define MP_PIT_CONTROL          0x10
1019
#define MP_PIT_TIMER1_VALUE     0x14
1020
/* ... */
1021
#define MP_PIT_TIMER4_VALUE     0x20
1022
#define MP_BOARD_RESET          0x34
1023

    
1024
/* Magic board reset value (probably some watchdog behind it) */
1025
#define MP_BOARD_RESET_MAGIC    0x10000
1026

    
1027
typedef struct mv88w8618_timer_state {
1028
    ptimer_state *timer;
1029
    uint32_t limit;
1030
    int freq;
1031
    qemu_irq irq;
1032
} mv88w8618_timer_state;
1033

    
1034
typedef struct mv88w8618_pit_state {
1035
    void *timer[4];
1036
    uint32_t control;
1037
} mv88w8618_pit_state;
1038

    
1039
static void mv88w8618_timer_tick(void *opaque)
1040
{
1041
    mv88w8618_timer_state *s = opaque;
1042

    
1043
    qemu_irq_raise(s->irq);
1044
}
1045

    
1046
static void *mv88w8618_timer_init(uint32_t freq, qemu_irq irq)
1047
{
1048
    mv88w8618_timer_state *s;
1049
    QEMUBH *bh;
1050

    
1051
    s = qemu_mallocz(sizeof(mv88w8618_timer_state));
1052
    s->irq = irq;
1053
    s->freq = freq;
1054

    
1055
    bh = qemu_bh_new(mv88w8618_timer_tick, s);
1056
    s->timer = ptimer_init(bh);
1057

    
1058
    return s;
1059
}
1060

    
1061
static uint32_t mv88w8618_pit_read(void *opaque, target_phys_addr_t offset)
1062
{
1063
    mv88w8618_pit_state *s = opaque;
1064
    mv88w8618_timer_state *t;
1065

    
1066
    switch (offset) {
1067
    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
1068
        t = s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
1069
        return ptimer_get_count(t->timer);
1070

    
1071
    default:
1072
        return 0;
1073
    }
1074
}
1075

    
1076
static void mv88w8618_pit_write(void *opaque, target_phys_addr_t offset,
1077
                                uint32_t value)
1078
{
1079
    mv88w8618_pit_state *s = opaque;
1080
    mv88w8618_timer_state *t;
1081
    int i;
1082

    
1083
    switch (offset) {
1084
    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
1085
        t = s->timer[offset >> 2];
1086
        t->limit = value;
1087
        ptimer_set_limit(t->timer, t->limit, 1);
1088
        break;
1089

    
1090
    case MP_PIT_CONTROL:
1091
        for (i = 0; i < 4; i++) {
1092
            if (value & 0xf) {
1093
                t = s->timer[i];
1094
                ptimer_set_limit(t->timer, t->limit, 0);
1095
                ptimer_set_freq(t->timer, t->freq);
1096
                ptimer_run(t->timer, 0);
1097
            }
1098
            value >>= 4;
1099
        }
1100
        break;
1101

    
1102
    case MP_BOARD_RESET:
1103
        if (value == MP_BOARD_RESET_MAGIC)
1104
            qemu_system_reset_request();
1105
        break;
1106
    }
1107
}
1108

    
1109
static CPUReadMemoryFunc *mv88w8618_pit_readfn[] = {
1110
    mv88w8618_pit_read,
1111
    mv88w8618_pit_read,
1112
    mv88w8618_pit_read
1113
};
1114

    
1115
static CPUWriteMemoryFunc *mv88w8618_pit_writefn[] = {
1116
    mv88w8618_pit_write,
1117
    mv88w8618_pit_write,
1118
    mv88w8618_pit_write
1119
};
1120

    
1121
static void mv88w8618_pit_init(uint32_t base, qemu_irq *pic, int irq)
1122
{
1123
    int iomemtype;
1124
    mv88w8618_pit_state *s;
1125

    
1126
    s = qemu_mallocz(sizeof(mv88w8618_pit_state));
1127

    
1128
    /* Letting them all run at 1 MHz is likely just a pragmatic
1129
     * simplification. */
1130
    s->timer[0] = mv88w8618_timer_init(1000000, pic[irq]);
1131
    s->timer[1] = mv88w8618_timer_init(1000000, pic[irq + 1]);
1132
    s->timer[2] = mv88w8618_timer_init(1000000, pic[irq + 2]);
1133
    s->timer[3] = mv88w8618_timer_init(1000000, pic[irq + 3]);
1134

    
1135
    iomemtype = cpu_register_io_memory(0, mv88w8618_pit_readfn,
1136
                                       mv88w8618_pit_writefn, s);
1137
    cpu_register_physical_memory(base, MP_PIT_SIZE, iomemtype);
1138
}
1139

    
1140
/* Flash config register offsets */
1141
#define MP_FLASHCFG_CFGR0    0x04
1142

    
1143
typedef struct mv88w8618_flashcfg_state {
1144
    uint32_t cfgr0;
1145
} mv88w8618_flashcfg_state;
1146

    
1147
static uint32_t mv88w8618_flashcfg_read(void *opaque,
1148
                                        target_phys_addr_t offset)
1149
{
1150
    mv88w8618_flashcfg_state *s = opaque;
1151

    
1152
    switch (offset) {
1153
    case MP_FLASHCFG_CFGR0:
1154
        return s->cfgr0;
1155

    
1156
    default:
1157
        return 0;
1158
    }
1159
}
1160

    
1161
static void mv88w8618_flashcfg_write(void *opaque, target_phys_addr_t offset,
1162
                                     uint32_t value)
1163
{
1164
    mv88w8618_flashcfg_state *s = opaque;
1165

    
1166
    switch (offset) {
1167
    case MP_FLASHCFG_CFGR0:
1168
        s->cfgr0 = value;
1169
        break;
1170
    }
1171
}
1172

    
1173
static CPUReadMemoryFunc *mv88w8618_flashcfg_readfn[] = {
1174
    mv88w8618_flashcfg_read,
1175
    mv88w8618_flashcfg_read,
1176
    mv88w8618_flashcfg_read
1177
};
1178

    
1179
static CPUWriteMemoryFunc *mv88w8618_flashcfg_writefn[] = {
1180
    mv88w8618_flashcfg_write,
1181
    mv88w8618_flashcfg_write,
1182
    mv88w8618_flashcfg_write
1183
};
1184

    
1185
static void mv88w8618_flashcfg_init(uint32_t base)
1186
{
1187
    int iomemtype;
1188
    mv88w8618_flashcfg_state *s;
1189

    
1190
    s = qemu_mallocz(sizeof(mv88w8618_flashcfg_state));
1191

    
1192
    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
1193
    iomemtype = cpu_register_io_memory(0, mv88w8618_flashcfg_readfn,
1194
                       mv88w8618_flashcfg_writefn, s);
1195
    cpu_register_physical_memory(base, MP_FLASHCFG_SIZE, iomemtype);
1196
}
1197

    
1198
/* Various registers in the 0x80000000 domain */
1199
#define MP_BOARD_REVISION       0x2018
1200

    
1201
#define MP_WLAN_MAGIC1          0xc11c
1202
#define MP_WLAN_MAGIC2          0xc124
1203

    
1204
#define MP_GPIO_OE_LO           0xd008
1205
#define MP_GPIO_OUT_LO          0xd00c
1206
#define MP_GPIO_IN_LO           0xd010
1207
#define MP_GPIO_ISR_LO          0xd020
1208
#define MP_GPIO_OE_HI           0xd508
1209
#define MP_GPIO_OUT_HI          0xd50c
1210
#define MP_GPIO_IN_HI           0xd510
1211
#define MP_GPIO_ISR_HI          0xd520
1212

    
1213
/* GPIO bits & masks */
1214
#define MP_GPIO_WHEEL_VOL       (1 << 8)
1215
#define MP_GPIO_WHEEL_VOL_INV   (1 << 9)
1216
#define MP_GPIO_WHEEL_NAV       (1 << 10)
1217
#define MP_GPIO_WHEEL_NAV_INV   (1 << 11)
1218
#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
1219
#define MP_GPIO_BTN_FAVORITS    (1 << 19)
1220
#define MP_GPIO_BTN_MENU        (1 << 20)
1221
#define MP_GPIO_BTN_VOLUME      (1 << 21)
1222
#define MP_GPIO_BTN_NAVIGATION  (1 << 22)
1223
#define MP_GPIO_I2C_DATA_BIT    29
1224
#define MP_GPIO_I2C_DATA        (1 << MP_GPIO_I2C_DATA_BIT)
1225
#define MP_GPIO_I2C_CLOCK_BIT   30
1226

    
1227
/* LCD brightness bits in GPIO_OE_HI */
1228
#define MP_OE_LCD_BRIGHTNESS    0x0007
1229

    
1230
static uint32_t musicpal_read(void *opaque, target_phys_addr_t offset)
1231
{
1232
    switch (offset) {
1233
    case MP_BOARD_REVISION:
1234
        return 0x0031;
1235

    
1236
    case MP_GPIO_OE_HI: /* used for LCD brightness control */
1237
        return lcd_brightness & MP_OE_LCD_BRIGHTNESS;
1238

    
1239
    case MP_GPIO_OUT_LO:
1240
        return gpio_out_state & 0xFFFF;
1241
    case MP_GPIO_OUT_HI:
1242
        return gpio_out_state >> 16;
1243

    
1244
    case MP_GPIO_IN_LO:
1245
        return gpio_in_state & 0xFFFF;
1246
    case MP_GPIO_IN_HI:
1247
        /* Update received I2C data */
1248
        gpio_in_state = (gpio_in_state & ~MP_GPIO_I2C_DATA) |
1249
                        (i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT);
1250
        return gpio_in_state >> 16;
1251

    
1252
    case MP_GPIO_ISR_LO:
1253
        return gpio_isr & 0xFFFF;
1254
    case MP_GPIO_ISR_HI:
1255
        return gpio_isr >> 16;
1256

    
1257
    /* Workaround to allow loading the binary-only wlandrv.ko crap
1258
     * from the original Freecom firmware. */
1259
    case MP_WLAN_MAGIC1:
1260
        return ~3;
1261
    case MP_WLAN_MAGIC2:
1262
        return -1;
1263

    
1264
    default:
1265
        return 0;
1266
    }
1267
}
1268

    
1269
static void musicpal_write(void *opaque, target_phys_addr_t offset,
1270
                           uint32_t value)
1271
{
1272
    switch (offset) {
1273
    case MP_GPIO_OE_HI: /* used for LCD brightness control */
1274
        lcd_brightness = (lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
1275
                         (value & MP_OE_LCD_BRIGHTNESS);
1276
        break;
1277

    
1278
    case MP_GPIO_OUT_LO:
1279
        gpio_out_state = (gpio_out_state & 0xFFFF0000) | (value & 0xFFFF);
1280
        break;
1281
    case MP_GPIO_OUT_HI:
1282
        gpio_out_state = (gpio_out_state & 0xFFFF) | (value << 16);
1283
        lcd_brightness = (lcd_brightness & 0xFFFF) |
1284
                         (gpio_out_state & MP_GPIO_LCD_BRIGHTNESS);
1285
        i2c_state_update(mixer_i2c,
1286
                         (gpio_out_state >> MP_GPIO_I2C_DATA_BIT) & 1,
1287
                         (gpio_out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
1288
        break;
1289

    
1290
    }
1291
}
1292

    
1293
/* Keyboard codes & masks */
1294
#define KEY_RELEASED            0x80
1295
#define KEY_CODE                0x7f
1296

    
1297
#define KEYCODE_TAB             0x0f
1298
#define KEYCODE_ENTER           0x1c
1299
#define KEYCODE_F               0x21
1300
#define KEYCODE_M               0x32
1301

    
1302
#define KEYCODE_EXTENDED        0xe0
1303
#define KEYCODE_UP              0x48
1304
#define KEYCODE_DOWN            0x50
1305
#define KEYCODE_LEFT            0x4b
1306
#define KEYCODE_RIGHT           0x4d
1307

    
1308
static void musicpal_key_event(void *opaque, int keycode)
1309
{
1310
    qemu_irq irq = opaque;
1311
    uint32_t event = 0;
1312
    static int kbd_extended;
1313

    
1314
    if (keycode == KEYCODE_EXTENDED) {
1315
        kbd_extended = 1;
1316
        return;
1317
    }
1318

    
1319
    if (kbd_extended)
1320
        switch (keycode & KEY_CODE) {
1321
        case KEYCODE_UP:
1322
            event = MP_GPIO_WHEEL_NAV | MP_GPIO_WHEEL_NAV_INV;
1323
            break;
1324

    
1325
        case KEYCODE_DOWN:
1326
            event = MP_GPIO_WHEEL_NAV;
1327
            break;
1328

    
1329
        case KEYCODE_LEFT:
1330
            event = MP_GPIO_WHEEL_VOL | MP_GPIO_WHEEL_VOL_INV;
1331
            break;
1332

    
1333
        case KEYCODE_RIGHT:
1334
            event = MP_GPIO_WHEEL_VOL;
1335
            break;
1336
        }
1337
    else {
1338
        switch (keycode & KEY_CODE) {
1339
        case KEYCODE_F:
1340
            event = MP_GPIO_BTN_FAVORITS;
1341
            break;
1342

    
1343
        case KEYCODE_TAB:
1344
            event = MP_GPIO_BTN_VOLUME;
1345
            break;
1346

    
1347
        case KEYCODE_ENTER:
1348
            event = MP_GPIO_BTN_NAVIGATION;
1349
            break;
1350

    
1351
        case KEYCODE_M:
1352
            event = MP_GPIO_BTN_MENU;
1353
            break;
1354
        }
1355
        /* Do not repeat already pressed buttons */
1356
        if (!(keycode & KEY_RELEASED) && !(gpio_in_state & event))
1357
            event = 0;
1358
    }
1359

    
1360
    if (event) {
1361
        if (keycode & KEY_RELEASED) {
1362
            gpio_in_state |= event;
1363
        } else {
1364
            gpio_in_state &= ~event;
1365
            gpio_isr = event;
1366
            qemu_irq_raise(irq);
1367
        }
1368
    }
1369

    
1370
    kbd_extended = 0;
1371
}
1372

    
1373
static CPUReadMemoryFunc *musicpal_readfn[] = {
1374
    musicpal_read,
1375
    musicpal_read,
1376
    musicpal_read,
1377
};
1378

    
1379
static CPUWriteMemoryFunc *musicpal_writefn[] = {
1380
    musicpal_write,
1381
    musicpal_write,
1382
    musicpal_write,
1383
};
1384

    
1385
static struct arm_boot_info musicpal_binfo = {
1386
    .loader_start = 0x0,
1387
    .board_id = 0x20e,
1388
};
1389

    
1390
static void musicpal_init(ram_addr_t ram_size, int vga_ram_size,
1391
               const char *boot_device,
1392
               const char *kernel_filename, const char *kernel_cmdline,
1393
               const char *initrd_filename, const char *cpu_model)
1394
{
1395
    CPUState *env;
1396
    qemu_irq *pic;
1397
    int index;
1398
    int iomemtype;
1399
    unsigned long flash_size;
1400

    
1401
    if (!cpu_model)
1402
        cpu_model = "arm926";
1403

    
1404
    env = cpu_init(cpu_model);
1405
    if (!env) {
1406
        fprintf(stderr, "Unable to find CPU definition\n");
1407
        exit(1);
1408
    }
1409
    pic = arm_pic_init_cpu(env);
1410

    
1411
    /* For now we use a fixed - the original - RAM size */
1412
    cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
1413
                                 qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
1414

    
1415
    sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
1416
    cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
1417

    
1418
    /* Catch various stuff not handled by separate subsystems */
1419
    iomemtype = cpu_register_io_memory(0, musicpal_readfn,
1420
                                       musicpal_writefn, env);
1421
    cpu_register_physical_memory(0x80000000, 0x10000, iomemtype);
1422

    
1423
    pic = mv88w8618_pic_init(MP_PIC_BASE, pic[ARM_PIC_CPU_IRQ]);
1424
    mv88w8618_pit_init(MP_PIT_BASE, pic, MP_TIMER1_IRQ);
1425

    
1426
    if (serial_hds[0])
1427
        serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
1428
                   serial_hds[0], 1);
1429
    if (serial_hds[1])
1430
        serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
1431
                   serial_hds[1], 1);
1432

    
1433
    /* Register flash */
1434
    index = drive_get_index(IF_PFLASH, 0, 0);
1435
    if (index != -1) {
1436
        flash_size = bdrv_getlength(drives_table[index].bdrv);
1437
        if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
1438
            flash_size != 32*1024*1024) {
1439
            fprintf(stderr, "Invalid flash image size\n");
1440
            exit(1);
1441
        }
1442

    
1443
        /*
1444
         * The original U-Boot accesses the flash at 0xFE000000 instead of
1445
         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
1446
         * image is smaller than 32 MB.
1447
         */
1448
        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
1449
                              drives_table[index].bdrv, 0x10000,
1450
                              (flash_size + 0xffff) >> 16,
1451
                              MP_FLASH_SIZE_MAX / flash_size,
1452
                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
1453
                              0x5555, 0x2AAA);
1454
    }
1455
    mv88w8618_flashcfg_init(MP_FLASHCFG_BASE);
1456

    
1457
    musicpal_lcd_init(MP_LCD_BASE);
1458

    
1459
    qemu_add_kbd_event_handler(musicpal_key_event, pic[MP_GPIO_IRQ]);
1460

    
1461
    mv88w8618_eth_init(&nd_table[0], MP_ETH_BASE, pic[MP_ETH_IRQ]);
1462

    
1463
    mixer_i2c = musicpal_audio_init(MP_AUDIO_BASE, pic[MP_AUDIO_IRQ]);
1464

    
1465
    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
1466
    musicpal_binfo.kernel_filename = kernel_filename;
1467
    musicpal_binfo.kernel_cmdline = kernel_cmdline;
1468
    musicpal_binfo.initrd_filename = initrd_filename;
1469
    arm_load_kernel(env, &musicpal_binfo);
1470
}
1471

    
1472
QEMUMachine musicpal_machine = {
1473
    .name = "musicpal",
1474
    .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
1475
    .init = musicpal_init,
1476
    .ram_require = MP_RAM_DEFAULT_SIZE + MP_SRAM_SIZE +
1477
            MP_FLASH_SIZE_MAX + RAMSIZE_FIXED,
1478
};