Statistics
| Branch: | Revision:

root / hw / nseries.c @ 069de562

History | View | Annotate | Download (31.5 kB)

1
/*
2
 * Nokia N-series internet tablets.
3
 *
4
 * Copyright (C) 2007 Nokia Corporation
5
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License as
9
 * published by the Free Software Foundation; either version 2 or
10
 * (at your option) version 3 of the License.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20
 * MA 02111-1307 USA
21
 */
22

    
23
#include "qemu-common.h"
24
#include "sysemu.h"
25
#include "omap.h"
26
#include "arm-misc.h"
27
#include "irq.h"
28
#include "console.h"
29
#include "boards.h"
30
#include "i2c.h"
31
#include "devices.h"
32
#include "flash.h"
33
#include "hw.h"
34

    
35
/* Nokia N8x0 support */
36
struct n800_s {
37
    struct omap_mpu_state_s *cpu;
38

    
39
    struct rfbi_chip_s blizzard;
40
    struct {
41
        void *opaque;
42
        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
43
        struct uwire_slave_s *chip;
44
    } ts;
45
    i2c_bus *i2c;
46

    
47
    int keymap[0x80];
48

    
49
    struct tusb_s *usb;
50
    void *retu;
51
    void *tahvo;
52
};
53

    
54
/* GPIO pins */
55
#define N8X0_TUSB_ENABLE_GPIO                0
56
#define N800_MMC2_WP_GPIO                8
57
#define N800_UNKNOWN_GPIO0                9        /* out */
58
#define N800_UNKNOWN_GPIO1                10        /* out */
59
#define N800_CAM_TURN_GPIO                12
60
#define N810_GPS_RESET_GPIO                12
61
#define N800_BLIZZARD_POWERDOWN_GPIO        15
62
#define N800_MMC1_WP_GPIO                23
63
#define N8X0_ONENAND_GPIO                26
64
#define N810_BLIZZARD_RESET_GPIO        30
65
#define N800_UNKNOWN_GPIO2                53        /* out */
66
#define N8X0_TUSB_INT_GPIO                58
67
#define N8X0_BT_WKUP_GPIO                61
68
#define N8X0_STI_GPIO                        62
69
#define N8X0_CBUS_SEL_GPIO                64
70
#define N8X0_CBUS_DAT_GPIO                65
71
#define N8X0_CBUS_CLK_GPIO                66
72
#define N8X0_WLAN_IRQ_GPIO                87
73
#define N8X0_BT_RESET_GPIO                92
74
#define N8X0_TEA5761_CS_GPIO                93
75
#define N800_UNKNOWN_GPIO                94
76
#define N810_TSC_RESET_GPIO                94
77
#define N800_CAM_ACT_GPIO                95
78
#define N810_GPS_WAKEUP_GPIO                95
79
#define N8X0_MMC_CS_GPIO                96
80
#define N8X0_WLAN_PWR_GPIO                97
81
#define N8X0_BT_HOST_WKUP_GPIO                98
82
#define N800_UNKNOWN_GPIO3                101        /* out */
83
#define N810_KB_LOCK_GPIO                102
84
#define N800_TSC_TS_GPIO                103
85
#define N810_TSC_TS_GPIO                106
86
#define N8X0_HEADPHONE_GPIO                107
87
#define N8X0_RETU_GPIO                        108
88
#define N800_TSC_KP_IRQ_GPIO                109
89
#define N810_KEYBOARD_GPIO                109
90
#define N800_BAT_COVER_GPIO                110
91
#define N810_SLIDE_GPIO                        110
92
#define N8X0_TAHVO_GPIO                        111
93
#define N800_UNKNOWN_GPIO4                112        /* out */
94
#define N810_SLEEPX_LED_GPIO                112
95
#define N810_TSC_UNKNOWN_GPIO                118        /* out */
96
#define N800_TSC_RESET_GPIO                119        /* ? */
97
#define N8X0_TMP105_GPIO                125
98

    
99
/* Config */
100
#define XLDR_LL_UART                        1
101

    
102
/* Addresses on the I2C bus */
103
#define N8X0_TMP105_ADDR                0x48
104
#define N8X0_MENELAUS_ADDR                0x72
105

    
106
/* Chipselects on GPMC NOR interface */
107
#define N8X0_ONENAND_CS                        0
108
#define N8X0_USB_ASYNC_CS                1
109
#define N8X0_USB_SYNC_CS                4
110

    
111
static void n800_mmc_cs_cb(void *opaque, int line, int level)
112
{
113
    /* TODO: this seems to actually be connected to the menelaus, to
114
     * which also both MMC slots connect.  */
115
    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
116

    
117
    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
118
}
119

    
120
static void n8x0_gpio_setup(struct n800_s *s)
121
{
122
    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
123
    omap2_gpio_out_set(s->cpu->gpif, N8X0_MMC_CS_GPIO, mmc_cs[0]);
124

    
125
    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
126
}
127

    
128
static void n8x0_nand_setup(struct n800_s *s)
129
{
130
    /* Either ec40xx or ec48xx are OK for the ID */
131
    omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
132
                    onenand_base_unmap,
133
                    onenand_init(0xec4800, 1,
134
                            omap2_gpio_in_get(s->cpu->gpif,
135
                                    N8X0_ONENAND_GPIO)[0]));
136
}
137

    
138
static void n8x0_i2c_setup(struct n800_s *s)
139
{
140
    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0];
141

    
142
    /* Attach the CPU on one end of our I2C bus.  */
143
    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
144

    
145
    /* Attach a menelaus PM chip */
146
    i2c_set_slave_address(
147
                    twl92230_init(s->i2c,
148
                            s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]),
149
                    N8X0_MENELAUS_ADDR);
150

    
151
    /* Attach a TMP105 PM chip (A0 wired to ground) */
152
    i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N8X0_TMP105_ADDR);
153
}
154

    
155
/* Touchscreen and keypad controller */
156
static struct mouse_transform_info_s n800_pointercal = {
157
    .x = 800,
158
    .y = 480,
159
    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
160
};
161

    
162
static struct mouse_transform_info_s n810_pointercal = {
163
    .x = 800,
164
    .y = 480,
165
    .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
166
};
167

    
168
#define RETU_KEYCODE        61        /* F3 */
169

    
170
static void n800_key_event(void *opaque, int keycode)
171
{
172
    struct n800_s *s = (struct n800_s *) opaque;
173
    int code = s->keymap[keycode & 0x7f];
174

    
175
    if (code == -1) {
176
        if ((keycode & 0x7f) == RETU_KEYCODE)
177
            retu_key_event(s->retu, !(keycode & 0x80));
178
        return;
179
    }
180

    
181
    tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
182
}
183

    
184
static const int n800_keys[16] = {
185
    -1,
186
    72,        /* Up */
187
    63,        /* Home (F5) */
188
    -1,
189
    75,        /* Left */
190
    28,        /* Enter */
191
    77,        /* Right */
192
    -1,
193
    1,        /* Cycle (ESC) */
194
    80,        /* Down */
195
    62,        /* Menu (F4) */
196
    -1,
197
    66,        /* Zoom- (F8) */
198
    64,        /* FS (F6) */
199
    65,        /* Zoom+ (F7) */
200
    -1,
201
};
202

    
203
static void n800_tsc_kbd_setup(struct n800_s *s)
204
{
205
    int i;
206

    
207
    /* XXX: are the three pins inverted inside the chip between the
208
     * tsc and the cpu (N4111)?  */
209
    qemu_irq penirq = 0;        /* NC */
210
    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
211
    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
212

    
213
    s->ts.chip = tsc2301_init(penirq, kbirq, dav, 0);
214
    s->ts.opaque = s->ts.chip->opaque;
215
    s->ts.txrx = tsc210x_txrx;
216

    
217
    for (i = 0; i < 0x80; i ++)
218
        s->keymap[i] = -1;
219
    for (i = 0; i < 0x10; i ++)
220
        if (n800_keys[i] >= 0)
221
            s->keymap[n800_keys[i]] = i;
222

    
223
    qemu_add_kbd_event_handler(n800_key_event, s);
224

    
225
    tsc210x_set_transform(s->ts.chip, &n800_pointercal);
226
}
227

    
228
static void n810_tsc_setup(struct n800_s *s)
229
{
230
    qemu_irq pintdav = omap2_gpio_in_get(s->cpu->gpif, N810_TSC_TS_GPIO)[0];
231

    
232
    s->ts.opaque = tsc2005_init(pintdav);
233
    s->ts.txrx = tsc2005_txrx;
234

    
235
    tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
236
}
237

    
238
/* LCD MIPI DBI-C controller (URAL) */
239
struct mipid_s {
240
    int resp[4];
241
    int param[4];
242
    int p;
243
    int pm;
244
    int cmd;
245

    
246
    int sleep;
247
    int booster;
248
    int te;
249
    int selfcheck;
250
    int partial;
251
    int normal;
252
    int vscr;
253
    int invert;
254
    int onoff;
255
    int gamma;
256
    uint32_t id;
257
};
258

    
259
static void mipid_reset(struct mipid_s *s)
260
{
261
    if (!s->sleep)
262
        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
263

    
264
    s->pm = 0;
265
    s->cmd = 0;
266

    
267
    s->sleep = 1;
268
    s->booster = 0;
269
    s->selfcheck =
270
            (1 << 7) |        /* Register loading OK.  */
271
            (1 << 5) |        /* The chip is attached.  */
272
            (1 << 4);        /* Display glass still in one piece.  */
273
    s->te = 0;
274
    s->partial = 0;
275
    s->normal = 1;
276
    s->vscr = 0;
277
    s->invert = 0;
278
    s->onoff = 1;
279
    s->gamma = 0;
280
}
281

    
282
static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
283
{
284
    struct mipid_s *s = (struct mipid_s *) opaque;
285
    uint8_t ret;
286

    
287
    if (len > 9)
288
        cpu_abort(cpu_single_env, "%s: FIXME: bad SPI word width %i\n",
289
                        __FUNCTION__, len);
290

    
291
    if (s->p >= sizeof(s->resp) / sizeof(*s->resp))
292
        ret = 0;
293
    else
294
        ret = s->resp[s->p ++];
295
    if (s->pm --> 0)
296
        s->param[s->pm] = cmd;
297
    else
298
        s->cmd = cmd;
299

    
300
    switch (s->cmd) {
301
    case 0x00:        /* NOP */
302
        break;
303

    
304
    case 0x01:        /* SWRESET */
305
        mipid_reset(s);
306
        break;
307

    
308
    case 0x02:        /* BSTROFF */
309
        s->booster = 0;
310
        break;
311
    case 0x03:        /* BSTRON */
312
        s->booster = 1;
313
        break;
314

    
315
    case 0x04:        /* RDDID */
316
        s->p = 0;
317
        s->resp[0] = (s->id >> 16) & 0xff;
318
        s->resp[1] = (s->id >>  8) & 0xff;
319
        s->resp[2] = (s->id >>  0) & 0xff;
320
        break;
321

    
322
    case 0x06:        /* RD_RED */
323
    case 0x07:        /* RD_GREEN */
324
        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
325
         * for the bootloader one needs to change this.  */
326
    case 0x08:        /* RD_BLUE */
327
        s->p = 0;
328
        /* TODO: return first pixel components */
329
        s->resp[0] = 0x01;
330
        break;
331

    
332
    case 0x09:        /* RDDST */
333
        s->p = 0;
334
        s->resp[0] = s->booster << 7;
335
        s->resp[1] = (5 << 4) | (s->partial << 2) |
336
                (s->sleep << 1) | s->normal;
337
        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
338
                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
339
        s->resp[3] = s->gamma << 6;
340
        break;
341

    
342
    case 0x0a:        /* RDDPM */
343
        s->p = 0;
344
        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
345
                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
346
        break;
347
    case 0x0b:        /* RDDMADCTR */
348
        s->p = 0;
349
        s->resp[0] = 0;
350
        break;
351
    case 0x0c:        /* RDDCOLMOD */
352
        s->p = 0;
353
        s->resp[0] = 5;        /* 65K colours */
354
        break;
355
    case 0x0d:        /* RDDIM */
356
        s->p = 0;
357
        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
358
        break;
359
    case 0x0e:        /* RDDSM */
360
        s->p = 0;
361
        s->resp[0] = s->te << 7;
362
        break;
363
    case 0x0f:        /* RDDSDR */
364
        s->p = 0;
365
        s->resp[0] = s->selfcheck;
366
        break;
367

    
368
    case 0x10:        /* SLPIN */
369
        s->sleep = 1;
370
        break;
371
    case 0x11:        /* SLPOUT */
372
        s->sleep = 0;
373
        s->selfcheck ^= 1 << 6;        /* POFF self-diagnosis Ok */
374
        break;
375

    
376
    case 0x12:        /* PTLON */
377
        s->partial = 1;
378
        s->normal = 0;
379
        s->vscr = 0;
380
        break;
381
    case 0x13:        /* NORON */
382
        s->partial = 0;
383
        s->normal = 1;
384
        s->vscr = 0;
385
        break;
386

    
387
    case 0x20:        /* INVOFF */
388
        s->invert = 0;
389
        break;
390
    case 0x21:        /* INVON */
391
        s->invert = 1;
392
        break;
393

    
394
    case 0x22:        /* APOFF */
395
    case 0x23:        /* APON */
396
        goto bad_cmd;
397

    
398
    case 0x25:        /* WRCNTR */
399
        if (s->pm < 0)
400
            s->pm = 1;
401
        goto bad_cmd;
402

    
403
    case 0x26:        /* GAMSET */
404
        if (!s->pm)
405
            s->gamma = ffs(s->param[0] & 0xf) - 1;
406
        else if (s->pm < 0)
407
            s->pm = 1;
408
        break;
409

    
410
    case 0x28:        /* DISPOFF */
411
        s->onoff = 0;
412
        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
413
        break;
414
    case 0x29:        /* DISPON */
415
        s->onoff = 1;
416
        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
417
        break;
418

    
419
    case 0x2a:        /* CASET */
420
    case 0x2b:        /* RASET */
421
    case 0x2c:        /* RAMWR */
422
    case 0x2d:        /* RGBSET */
423
    case 0x2e:        /* RAMRD */
424
    case 0x30:        /* PTLAR */
425
    case 0x33:        /* SCRLAR */
426
        goto bad_cmd;
427

    
428
    case 0x34:        /* TEOFF */
429
        s->te = 0;
430
        break;
431
    case 0x35:        /* TEON */
432
        if (!s->pm)
433
            s->te = 1;
434
        else if (s->pm < 0)
435
            s->pm = 1;
436
        break;
437

    
438
    case 0x36:        /* MADCTR */
439
        goto bad_cmd;
440

    
441
    case 0x37:        /* VSCSAD */
442
        s->partial = 0;
443
        s->normal = 0;
444
        s->vscr = 1;
445
        break;
446

    
447
    case 0x38:        /* IDMOFF */
448
    case 0x39:        /* IDMON */
449
    case 0x3a:        /* COLMOD */
450
        goto bad_cmd;
451

    
452
    case 0xb0:        /* CLKINT / DISCTL */
453
    case 0xb1:        /* CLKEXT */
454
        if (s->pm < 0)
455
            s->pm = 2;
456
        break;
457

    
458
    case 0xb4:        /* FRMSEL */
459
        break;
460

    
461
    case 0xb5:        /* FRM8SEL */
462
    case 0xb6:        /* TMPRNG / INIESC */
463
    case 0xb7:        /* TMPHIS / NOP2 */
464
    case 0xb8:        /* TMPREAD / MADCTL */
465
    case 0xba:        /* DISTCTR */
466
    case 0xbb:        /* EPVOL */
467
        goto bad_cmd;
468

    
469
    case 0xbd:        /* Unknown */
470
        s->p = 0;
471
        s->resp[0] = 0;
472
        s->resp[1] = 1;
473
        break;
474

    
475
    case 0xc2:        /* IFMOD */
476
        if (s->pm < 0)
477
            s->pm = 2;
478
        break;
479

    
480
    case 0xc6:        /* PWRCTL */
481
    case 0xc7:        /* PPWRCTL */
482
    case 0xd0:        /* EPWROUT */
483
    case 0xd1:        /* EPWRIN */
484
    case 0xd4:        /* RDEV */
485
    case 0xd5:        /* RDRR */
486
        goto bad_cmd;
487

    
488
    case 0xda:        /* RDID1 */
489
        s->p = 0;
490
        s->resp[0] = (s->id >> 16) & 0xff;
491
        break;
492
    case 0xdb:        /* RDID2 */
493
        s->p = 0;
494
        s->resp[0] = (s->id >>  8) & 0xff;
495
        break;
496
    case 0xdc:        /* RDID3 */
497
        s->p = 0;
498
        s->resp[0] = (s->id >>  0) & 0xff;
499
        break;
500

    
501
    default:
502
    bad_cmd:
503
        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
504
        break;
505
    }
506

    
507
    return ret;
508
}
509

    
510
static void *mipid_init(void)
511
{
512
    struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s));
513

    
514
    s->id = 0x838f03;
515
    mipid_reset(s);
516

    
517
    return s;
518
}
519

    
520
static void n8x0_spi_setup(struct n800_s *s)
521
{
522
    void *tsc = s->ts.opaque;
523
    void *mipid = mipid_init();
524

    
525
    omap_mcspi_attach(s->cpu->mcspi[0], s->ts.txrx, tsc, 0);
526
    omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
527
}
528

    
529
/* This task is normally performed by the bootloader.  If we're loading
530
 * a kernel directly, we need to enable the Blizzard ourselves.  */
531
static void n800_dss_init(struct rfbi_chip_s *chip)
532
{
533
    uint8_t *fb_blank;
534

    
535
    chip->write(chip->opaque, 0, 0x2a);                /* LCD Width register */
536
    chip->write(chip->opaque, 1, 0x64);
537
    chip->write(chip->opaque, 0, 0x2c);                /* LCD HNDP register */
538
    chip->write(chip->opaque, 1, 0x1e);
539
    chip->write(chip->opaque, 0, 0x2e);                /* LCD Height 0 register */
540
    chip->write(chip->opaque, 1, 0xe0);
541
    chip->write(chip->opaque, 0, 0x30);                /* LCD Height 1 register */
542
    chip->write(chip->opaque, 1, 0x01);
543
    chip->write(chip->opaque, 0, 0x32);                /* LCD VNDP register */
544
    chip->write(chip->opaque, 1, 0x06);
545
    chip->write(chip->opaque, 0, 0x68);                /* Display Mode register */
546
    chip->write(chip->opaque, 1, 1);                /* Enable bit */
547

    
548
    chip->write(chip->opaque, 0, 0x6c);        
549
    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
550
    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
551
    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
552
    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
553
    chip->write(chip->opaque, 1, 0x1f);                /* Input X End Position */
554
    chip->write(chip->opaque, 1, 0x03);                /* Input X End Position */
555
    chip->write(chip->opaque, 1, 0xdf);                /* Input Y End Position */
556
    chip->write(chip->opaque, 1, 0x01);                /* Input Y End Position */
557
    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
558
    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
559
    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
560
    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
561
    chip->write(chip->opaque, 1, 0x1f);                /* Output X End Position */
562
    chip->write(chip->opaque, 1, 0x03);                /* Output X End Position */
563
    chip->write(chip->opaque, 1, 0xdf);                /* Output Y End Position */
564
    chip->write(chip->opaque, 1, 0x01);                /* Output Y End Position */
565
    chip->write(chip->opaque, 1, 0x01);                /* Input Data Format */
566
    chip->write(chip->opaque, 1, 0x01);                /* Data Source Select */
567

    
568
    fb_blank = memset(qemu_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
569
    /* Display Memory Data Port */
570
    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
571
    free(fb_blank);
572
}
573

    
574
static void n8x0_dss_setup(struct n800_s *s, DisplayState *ds)
575
{
576
    s->blizzard.opaque = s1d13745_init(0, ds);
577
    s->blizzard.block = s1d13745_write_block;
578
    s->blizzard.write = s1d13745_write;
579
    s->blizzard.read = s1d13745_read;
580

    
581
    omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
582
}
583

    
584
static void n8x0_cbus_setup(struct n800_s *s)
585
{
586
    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0];
587
    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0];
588
    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0];
589

    
590
    struct cbus_s *cbus = cbus_init(dat_out);
591

    
592
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk);
593
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat);
594
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel);
595

    
596
    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
597
    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
598
}
599

    
600
static void n8x0_usb_power_cb(void *opaque, int line, int level)
601
{
602
    struct n800_s *s = opaque;
603

    
604
    tusb6010_power(s->usb, level);
605
}
606

    
607
static void n8x0_usb_setup(struct n800_s *s)
608
{
609
    qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0];
610
    qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0];
611
    struct tusb_s *tusb = tusb6010_init(tusb_irq);
612

    
613
    /* Using the NOR interface */
614
    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS,
615
                    tusb6010_async_io(tusb), 0, 0, tusb);
616
    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS,
617
                    tusb6010_sync_io(tusb), 0, 0, tusb);
618

    
619
    s->usb = tusb;
620
    omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
621
}
622

    
623
/* This task is normally performed by the bootloader.  If we're loading
624
 * a kernel directly, we need to set up GPMC mappings ourselves.  */
625
static void n800_gpmc_init(struct n800_s *s)
626
{
627
    uint32_t config7 =
628
            (0xf << 8) |        /* MASKADDRESS */
629
            (1 << 6) |                /* CSVALID */
630
            (4 << 0);                /* BASEADDRESS */
631

    
632
    cpu_physical_memory_write(0x6800a078,                /* GPMC_CONFIG7_0 */
633
                    (void *) &config7, sizeof(config7));
634
}
635

    
636
/* Setup sequence done by the bootloader */
637
static void n8x0_boot_init(void *opaque)
638
{
639
    struct n800_s *s = (struct n800_s *) opaque;
640
    uint32_t buf;
641

    
642
    /* PRCM setup */
643
#define omap_writel(addr, val)        \
644
    buf = (val);                        \
645
    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
646

    
647
    omap_writel(0x48008060, 0x41);                /* PRCM_CLKSRC_CTRL */
648
    omap_writel(0x48008070, 1);                        /* PRCM_CLKOUT_CTRL */
649
    omap_writel(0x48008078, 0);                        /* PRCM_CLKEMUL_CTRL */
650
    omap_writel(0x48008090, 0);                        /* PRCM_VOLTSETUP */
651
    omap_writel(0x48008094, 0);                        /* PRCM_CLKSSETUP */
652
    omap_writel(0x48008098, 0);                        /* PRCM_POLCTRL */
653
    omap_writel(0x48008140, 2);                        /* CM_CLKSEL_MPU */
654
    omap_writel(0x48008148, 0);                        /* CM_CLKSTCTRL_MPU */
655
    omap_writel(0x48008158, 1);                        /* RM_RSTST_MPU */
656
    omap_writel(0x480081c8, 0x15);                /* PM_WKDEP_MPU */
657
    omap_writel(0x480081d4, 0x1d4);                /* PM_EVGENCTRL_MPU */
658
    omap_writel(0x480081d8, 0);                        /* PM_EVEGENONTIM_MPU */
659
    omap_writel(0x480081dc, 0);                        /* PM_EVEGENOFFTIM_MPU */
660
    omap_writel(0x480081e0, 0xc);                /* PM_PWSTCTRL_MPU */
661
    omap_writel(0x48008200, 0x047e7ff7);        /* CM_FCLKEN1_CORE */
662
    omap_writel(0x48008204, 0x00000004);        /* CM_FCLKEN2_CORE */
663
    omap_writel(0x48008210, 0x047e7ff1);        /* CM_ICLKEN1_CORE */
664
    omap_writel(0x48008214, 0x00000004);        /* CM_ICLKEN2_CORE */
665
    omap_writel(0x4800821c, 0x00000000);        /* CM_ICLKEN4_CORE */
666
    omap_writel(0x48008230, 0);                        /* CM_AUTOIDLE1_CORE */
667
    omap_writel(0x48008234, 0);                        /* CM_AUTOIDLE2_CORE */
668
    omap_writel(0x48008238, 7);                        /* CM_AUTOIDLE3_CORE */
669
    omap_writel(0x4800823c, 0);                        /* CM_AUTOIDLE4_CORE */
670
    omap_writel(0x48008240, 0x04360626);        /* CM_CLKSEL1_CORE */
671
    omap_writel(0x48008244, 0x00000014);        /* CM_CLKSEL2_CORE */
672
    omap_writel(0x48008248, 0);                        /* CM_CLKSTCTRL_CORE */
673
    omap_writel(0x48008300, 0x00000000);        /* CM_FCLKEN_GFX */
674
    omap_writel(0x48008310, 0x00000000);        /* CM_ICLKEN_GFX */
675
    omap_writel(0x48008340, 0x00000001);        /* CM_CLKSEL_GFX */
676
    omap_writel(0x48008400, 0x00000004);        /* CM_FCLKEN_WKUP */
677
    omap_writel(0x48008410, 0x00000004);        /* CM_ICLKEN_WKUP */
678
    omap_writel(0x48008440, 0x00000000);        /* CM_CLKSEL_WKUP */
679
    omap_writel(0x48008500, 0x000000cf);        /* CM_CLKEN_PLL */
680
    omap_writel(0x48008530, 0x0000000c);        /* CM_AUTOIDLE_PLL */
681
    omap_writel(0x48008540,                        /* CM_CLKSEL1_PLL */
682
                    (0x78 << 12) | (6 << 8));
683
    omap_writel(0x48008544, 2);                        /* CM_CLKSEL2_PLL */
684

    
685
    /* GPMC setup */
686
    n800_gpmc_init(s);
687

    
688
    /* Video setup */
689
    n800_dss_init(&s->blizzard);
690

    
691
    /* CPU setup */
692
    s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
693
    s->cpu->env->GE = 0x5;
694
}
695

    
696
#define OMAP_TAG_NOKIA_BT        0x4e01
697
#define OMAP_TAG_WLAN_CX3110X        0x4e02
698
#define OMAP_TAG_CBUS                0x4e03
699
#define OMAP_TAG_EM_ASIC_BB5        0x4e04
700

    
701
static struct omap_gpiosw_info_s {
702
    const char *name;
703
    int line;
704
    int type;
705
} n800_gpiosw_info[] = {
706
    {
707
        "bat_cover", N800_BAT_COVER_GPIO,
708
        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
709
    }, {
710
        "cam_act", N800_CAM_ACT_GPIO,
711
        OMAP_GPIOSW_TYPE_ACTIVITY,
712
    }, {
713
        "cam_turn", N800_CAM_TURN_GPIO,
714
        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
715
    }, {
716
        "headphone", N8X0_HEADPHONE_GPIO,
717
        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
718
    },
719
    { 0 }
720
}, n810_gpiosw_info[] = {
721
    {
722
        "gps_reset", N810_GPS_RESET_GPIO,
723
        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
724
    }, {
725
        "gps_wakeup", N810_GPS_WAKEUP_GPIO,
726
        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
727
    }, {
728
        "headphone", N8X0_HEADPHONE_GPIO,
729
        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
730
    }, {
731
        "kb_lock", N810_KB_LOCK_GPIO,
732
        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
733
    }, {
734
        "sleepx_led", N810_SLEEPX_LED_GPIO,
735
        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
736
    }, {
737
        "slide", N810_SLIDE_GPIO,
738
        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
739
    },
740
    { 0 }
741
};
742

    
743
static struct omap_partition_info_s {
744
    uint32_t offset;
745
    uint32_t size;
746
    int mask;
747
    const char *name;
748
} n800_part_info[] = {
749
    { 0x00000000, 0x00020000, 0x3, "bootloader" },
750
    { 0x00020000, 0x00060000, 0x0, "config" },
751
    { 0x00080000, 0x00200000, 0x0, "kernel" },
752
    { 0x00280000, 0x00200000, 0x3, "initfs" },
753
    { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
754

    
755
    { 0, 0, 0, 0 }
756
}, n810_part_info[] = {
757
    { 0x00000000, 0x00020000, 0x3, "bootloader" },
758
    { 0x00020000, 0x00060000, 0x0, "config" },
759
    { 0x00080000, 0x00220000, 0x0, "kernel" },
760
    { 0x002a0000, 0x00400000, 0x0, "initfs" },
761
    { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
762

    
763
    { 0, 0, 0, 0 }
764
};
765

    
766
static int n8x0_atag_setup(void *p, int model)
767
{
768
    uint8_t *b;
769
    uint16_t *w;
770
    uint32_t *l;
771
    struct omap_gpiosw_info_s *gpiosw;
772
    struct omap_partition_info_s *partition;
773
    const char *tag;
774

    
775
    w = p;
776

    
777
    stw_raw(w ++, OMAP_TAG_UART);                /* u16 tag */
778
    stw_raw(w ++, 4);                                /* u16 len */
779
    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
780
    w ++;
781

    
782
#if 0
783
    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);        /* u16 tag */
784
    stw_raw(w ++, 4);                                /* u16 len */
785
    stw_raw(w ++, XLDR_LL_UART);                /* u8 console_uart */
786
    stw_raw(w ++, 115200);                        /* u32 console_speed */
787
#endif
788

    
789
    stw_raw(w ++, OMAP_TAG_LCD);                /* u16 tag */
790
    stw_raw(w ++, 36);                                /* u16 len */
791
    strcpy((void *) w, "QEMU LCD panel");        /* char panel_name[16] */
792
    w += 8;
793
    strcpy((void *) w, "blizzard");                /* char ctrl_name[16] */
794
    w += 8;
795
    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);        /* TODO: n800 s16 nreset_gpio */
796
    stw_raw(w ++, 24);                                /* u8 data_lines */
797

    
798
    stw_raw(w ++, OMAP_TAG_CBUS);                /* u16 tag */
799
    stw_raw(w ++, 8);                                /* u16 len */
800
    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);                /* s16 clk_gpio */
801
    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);                /* s16 dat_gpio */
802
    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);                /* s16 sel_gpio */
803
    w ++;
804

    
805
    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);        /* u16 tag */
806
    stw_raw(w ++, 4);                                /* u16 len */
807
    stw_raw(w ++, N8X0_RETU_GPIO);                /* s16 retu_irq_gpio */
808
    stw_raw(w ++, N8X0_TAHVO_GPIO);                /* s16 tahvo_irq_gpio */
809

    
810
    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
811
    for (; gpiosw->name; gpiosw ++) {
812
        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);        /* u16 tag */
813
        stw_raw(w ++, 20);                        /* u16 len */
814
        strcpy((void *) w, gpiosw->name);        /* char name[12] */
815
        w += 6;
816
        stw_raw(w ++, gpiosw->line);                /* u16 gpio */
817
        stw_raw(w ++, gpiosw->type);
818
        stw_raw(w ++, 0);
819
        stw_raw(w ++, 0);
820
    }
821

    
822
    stw_raw(w ++, OMAP_TAG_NOKIA_BT);                /* u16 tag */
823
    stw_raw(w ++, 12);                                /* u16 len */
824
    b = (void *) w;
825
    stb_raw(b ++, 0x01);                        /* u8 chip_type        (CSR) */
826
    stb_raw(b ++, N8X0_BT_WKUP_GPIO);                /* u8 bt_wakeup_gpio */
827
    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);        /* u8 host_wakeup_gpio */
828
    stb_raw(b ++, N8X0_BT_RESET_GPIO);                /* u8 reset_gpio */
829
    stb_raw(b ++, 1);                                /* u8 bt_uart */
830
    memset(b, 0, 6);                                /* u8 bd_addr[6] */
831
    b += 6;
832
    stb_raw(b ++, 0x02);                        /* u8 bt_sysclk (38.4) */
833
    w = (void *) b;
834

    
835
    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);        /* u16 tag */
836
    stw_raw(w ++, 8);                                /* u16 len */
837
    stw_raw(w ++, 0x25);                        /* u8 chip_type */
838
    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);                /* s16 power_gpio */
839
    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);                /* s16 irq_gpio */
840
    stw_raw(w ++, -1);                                /* s16 spi_cs_gpio */
841

    
842
    stw_raw(w ++, OMAP_TAG_MMC);                /* u16 tag */
843
    stw_raw(w ++, 16);                                /* u16 len */
844
    if (model == 810) {
845
        stw_raw(w ++, 0x23f);                        /* unsigned flags */
846
        stw_raw(w ++, -1);                        /* s16 power_pin */
847
        stw_raw(w ++, -1);                        /* s16 switch_pin */
848
        stw_raw(w ++, -1);                        /* s16 wp_pin */
849
        stw_raw(w ++, 0x240);                        /* unsigned flags */
850
        stw_raw(w ++, 0xc000);                        /* s16 power_pin */
851
        stw_raw(w ++, 0x0248);                        /* s16 switch_pin */
852
        stw_raw(w ++, 0xc000);                        /* s16 wp_pin */
853
    } else {
854
        stw_raw(w ++, 0xf);                        /* unsigned flags */
855
        stw_raw(w ++, -1);                        /* s16 power_pin */
856
        stw_raw(w ++, -1);                        /* s16 switch_pin */
857
        stw_raw(w ++, -1);                        /* s16 wp_pin */
858
        stw_raw(w ++, 0);                        /* unsigned flags */
859
        stw_raw(w ++, 0);                        /* s16 power_pin */
860
        stw_raw(w ++, 0);                        /* s16 switch_pin */
861
        stw_raw(w ++, 0);                        /* s16 wp_pin */
862
    }
863

    
864
    stw_raw(w ++, OMAP_TAG_TEA5761);                /* u16 tag */
865
    stw_raw(w ++, 4);                                /* u16 len */
866
    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);        /* u16 enable_gpio */
867
    w ++;
868

    
869
    partition = (model == 810) ? n810_part_info : n800_part_info;
870
    for (; partition->name; partition ++) {
871
        stw_raw(w ++, OMAP_TAG_PARTITION);        /* u16 tag */
872
        stw_raw(w ++, 28);                        /* u16 len */
873
        strcpy((void *) w, partition->name);        /* char name[16] */
874
        l = (void *) (w + 8);
875
        stl_raw(l ++, partition->size);                /* unsigned int size */
876
        stl_raw(l ++, partition->offset);        /* unsigned int offset */
877
        stl_raw(l ++, partition->mask);                /* unsigned int mask_flags */
878
        w = (void *) l;
879
    }
880

    
881
    stw_raw(w ++, OMAP_TAG_BOOT_REASON);        /* u16 tag */
882
    stw_raw(w ++, 12);                                /* u16 len */
883
#if 0
884
    strcpy((void *) w, "por");                        /* char reason_str[12] */
885
    strcpy((void *) w, "charger");                /* char reason_str[12] */
886
    strcpy((void *) w, "32wd_to");                /* char reason_str[12] */
887
    strcpy((void *) w, "sw_rst");                /* char reason_str[12] */
888
    strcpy((void *) w, "mbus");                        /* char reason_str[12] */
889
    strcpy((void *) w, "unknown");                /* char reason_str[12] */
890
    strcpy((void *) w, "swdg_to");                /* char reason_str[12] */
891
    strcpy((void *) w, "sec_vio");                /* char reason_str[12] */
892
    strcpy((void *) w, "pwr_key");                /* char reason_str[12] */
893
    strcpy((void *) w, "rtc_alarm");                /* char reason_str[12] */
894
#else
895
    strcpy((void *) w, "pwr_key");                /* char reason_str[12] */
896
#endif
897
    w += 6;
898

    
899
    tag = (model == 810) ? "RX-44" : "RX-34";
900
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
901
    stw_raw(w ++, 24);                                /* u16 len */
902
    strcpy((void *) w, "product");                /* char component[12] */
903
    w += 6;
904
    strcpy((void *) w, tag);                        /* char version[12] */
905
    w += 6;
906

    
907
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
908
    stw_raw(w ++, 24);                                /* u16 len */
909
    strcpy((void *) w, "hw-build");                /* char component[12] */
910
    w += 6;
911
    strcpy((void *) w, "QEMU " QEMU_VERSION);        /* char version[12] */
912
    w += 6;
913

    
914
    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
915
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
916
    stw_raw(w ++, 24);                                /* u16 len */
917
    strcpy((void *) w, "nolo");                        /* char component[12] */
918
    w += 6;
919
    strcpy((void *) w, tag);                        /* char version[12] */
920
    w += 6;
921

    
922
    return (void *) w - p;
923
}
924

    
925
static int n800_atag_setup(struct arm_boot_info *info, void *p)
926
{
927
    return n8x0_atag_setup(p, 800);
928
}
929

    
930
static int n810_atag_setup(struct arm_boot_info *info, void *p)
931
{
932
    return n8x0_atag_setup(p, 810);
933
}
934

    
935
static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
936
                DisplayState *ds, const char *kernel_filename,
937
                const char *kernel_cmdline, const char *initrd_filename,
938
                const char *cpu_model, struct arm_boot_info *binfo, int model)
939
{
940
    struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s));
941
    int sdram_size = binfo->ram_size;
942
    int onenandram_size = 0x00010000;
943

    
944
    if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) {
945
        fprintf(stderr, "This architecture uses %i bytes of memory\n",
946
                        sdram_size + onenandram_size + OMAP242X_SRAM_SIZE);
947
        exit(1);
948
    }
949

    
950
    s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model);
951

    
952
    n8x0_gpio_setup(s);
953
    n8x0_nand_setup(s);
954
    n8x0_i2c_setup(s);
955
    if (model == 800)
956
        n800_tsc_kbd_setup(s);
957
    else if (model == 810)
958
        n810_tsc_setup(s);
959
    n8x0_spi_setup(s);
960
    n8x0_dss_setup(s, ds);
961
    n8x0_cbus_setup(s);
962
    if (usb_enabled)
963
        n8x0_usb_setup(s);
964

    
965
    /* Setup initial (reset) machine state */
966

    
967
    /* Start at the OneNAND bootloader.  */
968
    s->cpu->env->regs[15] = 0;
969

    
970
    if (kernel_filename) {
971
        /* Or at the linux loader.  */
972
        binfo->kernel_filename = kernel_filename;
973
        binfo->kernel_cmdline = kernel_cmdline;
974
        binfo->initrd_filename = initrd_filename;
975
        arm_load_kernel(s->cpu->env, binfo);
976

    
977
        qemu_register_reset(n8x0_boot_init, s);
978
        n8x0_boot_init(s);
979
    }
980

    
981
    dpy_resize(ds, 800, 480);
982
}
983

    
984
static struct arm_boot_info n800_binfo = {
985
    .loader_start = OMAP2_Q2_BASE,
986
    /* Actually two chips of 0x4000000 bytes each */
987
    .ram_size = 0x08000000,
988
    .board_id = 0x4f7,
989
    .atag_board = n800_atag_setup,
990
};
991

    
992
static struct arm_boot_info n810_binfo = {
993
    .loader_start = OMAP2_Q2_BASE,
994
    /* Actually two chips of 0x4000000 bytes each */
995
    .ram_size = 0x08000000,
996
    /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
997
     * used by some older versions of the bootloader and 5555 is used
998
     * instead (including versions that shipped with many devices).  */
999
    .board_id = 0x60c,
1000
    .atag_board = n810_atag_setup,
1001
};
1002

    
1003
static void n800_init(ram_addr_t ram_size, int vga_ram_size,
1004
                const char *boot_device, DisplayState *ds,
1005
                const char *kernel_filename, const char *kernel_cmdline,
1006
                const char *initrd_filename, const char *cpu_model)
1007
{
1008
    return n8x0_init(ram_size, boot_device, ds,
1009
                    kernel_filename, kernel_cmdline, initrd_filename,
1010
                    cpu_model, &n800_binfo, 800);
1011
}
1012

    
1013
static void n810_init(ram_addr_t ram_size, int vga_ram_size,
1014
                const char *boot_device, DisplayState *ds,
1015
                const char *kernel_filename, const char *kernel_cmdline,
1016
                const char *initrd_filename, const char *cpu_model)
1017
{
1018
    return n8x0_init(ram_size, boot_device, ds,
1019
                    kernel_filename, kernel_cmdline, initrd_filename,
1020
                    cpu_model, &n810_binfo, 810);
1021
}
1022

    
1023
QEMUMachine n800_machine = {
1024
    "n800",
1025
    "Nokia N800 tablet aka. RX-34 (OMAP2420)",
1026
    n800_init,
1027
    (0x08000000 + 0x00010000 + OMAP242X_SRAM_SIZE) | RAMSIZE_FIXED,
1028
};
1029

    
1030
QEMUMachine n810_machine = {
1031
    "n810",
1032
    "Nokia N810 tablet aka. RX-44 (OMAP2420)",
1033
    n810_init,
1034
    (0x08000000 + 0x00010000 + OMAP242X_SRAM_SIZE) | RAMSIZE_FIXED,
1035
};