~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/musicpal.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-22 10:13:17 UTC
  • mfrom: (1.2.1 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090322101317-iigjtnu5qil35dtb
Tags: 0.10.1-1
[ Aurelien Jarno ]
* New upstream stable release:
  - patches/80_stable-branch.patch: remove.
* debian/control: 
  - Remove depends on proll.
  - Move depends on device-tree-compiler to build-depends.
  - Bump Standards-Version to 3.8.1 (no changes).
* patches/82_qemu-img_decimal.patch: new patch from upstream to make
  qemu-img accept sizes with decimal values (closes: bug#501400).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
};