Statistics
| Branch: | Revision:

root / hw / nseries.c @ 942ac052

History | View | Annotate | Download (28.7 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 uwire_slave_s *ts;
41
    i2c_bus *i2c;
42

    
43
    int keymap[0x80];
44

    
45
    struct tusb_s *usb;
46
    void *retu;
47
    void *tahvo;
48
};
49

    
50
/* GPIO pins */
51
#define N800_TUSB_ENABLE_GPIO                0
52
#define N800_MMC2_WP_GPIO                8
53
#define N800_UNKNOWN_GPIO0                9        /* out */
54
#define N800_UNKNOWN_GPIO1                10        /* out */
55
#define N800_CAM_TURN_GPIO                12
56
#define N800_BLIZZARD_POWERDOWN_GPIO        15
57
#define N800_MMC1_WP_GPIO                23
58
#define N8X0_ONENAND_GPIO                26
59
#define N800_UNKNOWN_GPIO2                53        /* out */
60
#define N8X0_TUSB_INT_GPIO                58
61
#define N800_BT_WKUP_GPIO                61
62
#define N800_STI_GPIO                        62
63
#define N8X0_CBUS_SEL_GPIO                64
64
#define N8X0_CBUS_CLK_GPIO                65        /* sure? */
65
#define N8X0_CBUS_DAT_GPIO                66
66
#define N800_WLAN_IRQ_GPIO                87
67
#define N800_BT_RESET_GPIO                92
68
#define N800_TEA5761_CS_GPIO                93
69
#define N800_UNKNOWN_GPIO                94
70
#define N800_CAM_ACT_GPIO                95
71
#define N800_MMC_CS_GPIO                96
72
#define N800_WLAN_PWR_GPIO                97
73
#define N8X0_BT_HOST_WKUP_GPIO                98
74
#define N800_UNKNOWN_GPIO3                101        /* out */
75
#define N810_KB_LOCK_GPIO                102
76
#define N800_TSC_TS_GPIO                103
77
#define N810_TSC2005_GPIO                106
78
#define N800_HEADPHONE_GPIO                107
79
#define N8X0_RETU_GPIO                        108
80
#define N800_TSC_KP_IRQ_GPIO                109
81
#define N810_KEYBOARD_GPIO                109
82
#define N800_BAT_COVER_GPIO                110
83
#define N810_SLIDE_GPIO                        110
84
#define N8X0_TAHVO_GPIO                        111
85
#define N800_UNKNOWN_GPIO4                112        /* out */
86
#define N810_TSC_RESET_GPIO                118
87
#define N800_TSC_RESET_GPIO                119        /* ? */
88
#define N8X0_TMP105_GPIO                125
89

    
90
/* Config */
91
#define XLDR_LL_UART                        1
92

    
93
/* Addresses on the I2C bus */
94
#define N8X0_TMP105_ADDR                0x48
95
#define N8X0_MENELAUS_ADDR                0x72
96

    
97
/* Chipselects on GPMC NOR interface */
98
#define N8X0_ONENAND_CS                        0
99
#define N8X0_USB_ASYNC_CS                1
100
#define N8X0_USB_SYNC_CS                4
101

    
102
static void n800_mmc_cs_cb(void *opaque, int line, int level)
103
{
104
    /* TODO: this seems to actually be connected to the menelaus, to
105
     * which also both MMC slots connect.  */
106
    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
107

    
108
    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
109
}
110

    
111
static void n800_gpio_setup(struct n800_s *s)
112
{
113
    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
114
    omap2_gpio_out_set(s->cpu->gpif, N800_MMC_CS_GPIO, mmc_cs[0]);
115

    
116
    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
117
}
118

    
119
static void n8x0_nand_setup(struct n800_s *s)
120
{
121
    /* Either ec40xx or ec48xx are OK for the ID */
122
    omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
123
                    onenand_base_unmap,
124
                    onenand_init(0xec4800, 1,
125
                            omap2_gpio_in_get(s->cpu->gpif,
126
                                    N8X0_ONENAND_GPIO)[0]));
127
}
128

    
129
static void n800_i2c_setup(struct n800_s *s)
130
{
131
    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0];
132

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

    
136
    /* Attach a menelaus PM chip */
137
    i2c_set_slave_address(
138
                    twl92230_init(s->i2c,
139
                            s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]),
140
                    N8X0_MENELAUS_ADDR);
141

    
142
    /* Attach a TMP105 PM chip (A0 wired to ground) */
143
    i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N8X0_TMP105_ADDR);
144
}
145

    
146
/* Touchscreen and keypad controller */
147
#define RETU_KEYCODE        61        /* F3 */
148

    
149
static void n800_key_event(void *opaque, int keycode)
150
{
151
    struct n800_s *s = (struct n800_s *) opaque;
152
    int code = s->keymap[keycode & 0x7f];
153

    
154
    if (code == -1) {
155
        if ((keycode & 0x7f) == RETU_KEYCODE)
156
            retu_key_event(s->retu, !(keycode & 0x80));
157
        return;
158
    }
159

    
160
    tsc210x_key_event(s->ts, code, !(keycode & 0x80));
161
}
162

    
163
static const int n800_keys[16] = {
164
    -1,
165
    72,        /* Up */
166
    63,        /* Home (F5) */
167
    -1,
168
    75,        /* Left */
169
    28,        /* Enter */
170
    77,        /* Right */
171
    -1,
172
    1,        /* Cycle (ESC) */
173
    80,        /* Down */
174
    62,        /* Menu (F4) */
175
    -1,
176
    66,        /* Zoom- (F8) */
177
    64,        /* FS (F6) */
178
    65,        /* Zoom+ (F7) */
179
    -1,
180
};
181

    
182
static struct mouse_transform_info_s n800_pointercal = {
183
    .x = 800,
184
    .y = 480,
185
    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
186
};
187

    
188
static void n800_tsc_setup(struct n800_s *s)
189
{
190
    int i;
191

    
192
    /* XXX: are the three pins inverted inside the chip between the
193
     * tsc and the cpu (N4111)?  */
194
    qemu_irq penirq = 0;        /* NC */
195
    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
196
    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
197

    
198
    s->ts = tsc2301_init(penirq, kbirq, dav, 0);
199

    
200
    for (i = 0; i < 0x80; i ++)
201
        s->keymap[i] = -1;
202
    for (i = 0; i < 0x10; i ++)
203
        if (n800_keys[i] >= 0)
204
            s->keymap[n800_keys[i]] = i;
205

    
206
    qemu_add_kbd_event_handler(n800_key_event, s);
207

    
208
    tsc210x_set_transform(s->ts, &n800_pointercal);
209
}
210

    
211
/* LCD MIPI DBI-C controller (URAL) */
212
struct mipid_s {
213
    int resp[4];
214
    int param[4];
215
    int p;
216
    int pm;
217
    int cmd;
218

    
219
    int sleep;
220
    int booster;
221
    int te;
222
    int selfcheck;
223
    int partial;
224
    int normal;
225
    int vscr;
226
    int invert;
227
    int onoff;
228
    int gamma;
229
    uint32_t id;
230
};
231

    
232
static void mipid_reset(struct mipid_s *s)
233
{
234
    if (!s->sleep)
235
        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
236

    
237
    s->pm = 0;
238
    s->cmd = 0;
239

    
240
    s->sleep = 1;
241
    s->booster = 0;
242
    s->selfcheck =
243
            (1 << 7) |        /* Register loading OK.  */
244
            (1 << 5) |        /* The chip is attached.  */
245
            (1 << 4);        /* Display glass still in one piece.  */
246
    s->te = 0;
247
    s->partial = 0;
248
    s->normal = 1;
249
    s->vscr = 0;
250
    s->invert = 0;
251
    s->onoff = 1;
252
    s->gamma = 0;
253
}
254

    
255
static uint32_t mipid_txrx(void *opaque, uint32_t cmd)
256
{
257
    struct mipid_s *s = (struct mipid_s *) opaque;
258
    uint8_t ret;
259

    
260
    if (s->p >= sizeof(s->resp) / sizeof(*s->resp))
261
        ret = 0;
262
    else
263
        ret = s->resp[s->p ++];
264
    if (s->pm --> 0)
265
        s->param[s->pm] = cmd;
266
    else
267
        s->cmd = cmd;
268

    
269
    switch (s->cmd) {
270
    case 0x00:        /* NOP */
271
        break;
272

    
273
    case 0x01:        /* SWRESET */
274
        mipid_reset(s);
275
        break;
276

    
277
    case 0x02:        /* BSTROFF */
278
        s->booster = 0;
279
        break;
280
    case 0x03:        /* BSTRON */
281
        s->booster = 1;
282
        break;
283

    
284
    case 0x04:        /* RDDID */
285
        s->p = 0;
286
        s->resp[0] = (s->id >> 16) & 0xff;
287
        s->resp[1] = (s->id >>  8) & 0xff;
288
        s->resp[2] = (s->id >>  0) & 0xff;
289
        break;
290

    
291
    case 0x06:        /* RD_RED */
292
    case 0x07:        /* RD_GREEN */
293
        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
294
         * for the bootloader one needs to change this.  */
295
    case 0x08:        /* RD_BLUE */
296
        s->p = 0;
297
        /* TODO: return first pixel components */
298
        s->resp[0] = 0x01;
299
        break;
300

    
301
    case 0x09:        /* RDDST */
302
        s->p = 0;
303
        s->resp[0] = s->booster << 7;
304
        s->resp[1] = (5 << 4) | (s->partial << 2) |
305
                (s->sleep << 1) | s->normal;
306
        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
307
                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
308
        s->resp[3] = s->gamma << 6;
309
        break;
310

    
311
    case 0x0a:        /* RDDPM */
312
        s->p = 0;
313
        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
314
                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
315
        break;
316
    case 0x0b:        /* RDDMADCTR */
317
        s->p = 0;
318
        s->resp[0] = 0;
319
        break;
320
    case 0x0c:        /* RDDCOLMOD */
321
        s->p = 0;
322
        s->resp[0] = 5;        /* 65K colours */
323
        break;
324
    case 0x0d:        /* RDDIM */
325
        s->p = 0;
326
        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
327
        break;
328
    case 0x0e:        /* RDDSM */
329
        s->p = 0;
330
        s->resp[0] = s->te << 7;
331
        break;
332
    case 0x0f:        /* RDDSDR */
333
        s->p = 0;
334
        s->resp[0] = s->selfcheck;
335
        break;
336

    
337
    case 0x10:        /* SLPIN */
338
        s->sleep = 1;
339
        break;
340
    case 0x11:        /* SLPOUT */
341
        s->sleep = 0;
342
        s->selfcheck ^= 1 << 6;        /* POFF self-diagnosis Ok */
343
        break;
344

    
345
    case 0x12:        /* PTLON */
346
        s->partial = 1;
347
        s->normal = 0;
348
        s->vscr = 0;
349
        break;
350
    case 0x13:        /* NORON */
351
        s->partial = 0;
352
        s->normal = 1;
353
        s->vscr = 0;
354
        break;
355

    
356
    case 0x20:        /* INVOFF */
357
        s->invert = 0;
358
        break;
359
    case 0x21:        /* INVON */
360
        s->invert = 1;
361
        break;
362

    
363
    case 0x22:        /* APOFF */
364
    case 0x23:        /* APON */
365
        goto bad_cmd;
366

    
367
    case 0x25:        /* WRCNTR */
368
        if (s->pm < 0)
369
            s->pm = 1;
370
        goto bad_cmd;
371

    
372
    case 0x26:        /* GAMSET */
373
        if (!s->pm)
374
            s->gamma = ffs(s->param[0] & 0xf) - 1;
375
        else if (s->pm < 0)
376
            s->pm = 1;
377
        break;
378

    
379
    case 0x28:        /* DISPOFF */
380
        s->onoff = 0;
381
        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
382
        break;
383
    case 0x29:        /* DISPON */
384
        s->onoff = 1;
385
        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
386
        break;
387

    
388
    case 0x2a:        /* CASET */
389
    case 0x2b:        /* RASET */
390
    case 0x2c:        /* RAMWR */
391
    case 0x2d:        /* RGBSET */
392
    case 0x2e:        /* RAMRD */
393
    case 0x30:        /* PTLAR */
394
    case 0x33:        /* SCRLAR */
395
        goto bad_cmd;
396

    
397
    case 0x34:        /* TEOFF */
398
        s->te = 0;
399
        break;
400
    case 0x35:        /* TEON */
401
        if (!s->pm)
402
            s->te = 1;
403
        else if (s->pm < 0)
404
            s->pm = 1;
405
        break;
406

    
407
    case 0x36:        /* MADCTR */
408
        goto bad_cmd;
409

    
410
    case 0x37:        /* VSCSAD */
411
        s->partial = 0;
412
        s->normal = 0;
413
        s->vscr = 1;
414
        break;
415

    
416
    case 0x38:        /* IDMOFF */
417
    case 0x39:        /* IDMON */
418
    case 0x3a:        /* COLMOD */
419
        goto bad_cmd;
420

    
421
    case 0xb0:        /* CLKINT / DISCTL */
422
    case 0xb1:        /* CLKEXT */
423
        if (s->pm < 0)
424
            s->pm = 2;
425
        break;
426

    
427
    case 0xb4:        /* FRMSEL */
428
        break;
429

    
430
    case 0xb5:        /* FRM8SEL */
431
    case 0xb6:        /* TMPRNG / INIESC */
432
    case 0xb7:        /* TMPHIS / NOP2 */
433
    case 0xb8:        /* TMPREAD / MADCTL */
434
    case 0xba:        /* DISTCTR */
435
    case 0xbb:        /* EPVOL */
436
        goto bad_cmd;
437

    
438
    case 0xbd:        /* Unknown */
439
        s->p = 0;
440
        s->resp[0] = 0;
441
        s->resp[1] = 1;
442
        break;
443

    
444
    case 0xc2:        /* IFMOD */
445
        if (s->pm < 0)
446
            s->pm = 2;
447
        break;
448

    
449
    case 0xc6:        /* PWRCTL */
450
    case 0xc7:        /* PPWRCTL */
451
    case 0xd0:        /* EPWROUT */
452
    case 0xd1:        /* EPWRIN */
453
    case 0xd4:        /* RDEV */
454
    case 0xd5:        /* RDRR */
455
        goto bad_cmd;
456

    
457
    case 0xda:        /* RDID1 */
458
        s->p = 0;
459
        s->resp[0] = (s->id >> 16) & 0xff;
460
        break;
461
    case 0xdb:        /* RDID2 */
462
        s->p = 0;
463
        s->resp[0] = (s->id >>  8) & 0xff;
464
        break;
465
    case 0xdc:        /* RDID3 */
466
        s->p = 0;
467
        s->resp[0] = (s->id >>  0) & 0xff;
468
        break;
469

    
470
    default:
471
    bad_cmd:
472
        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
473
        break;
474
    }
475

    
476
    return ret;
477
}
478

    
479
static void *mipid_init(void)
480
{
481
    struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s));
482

    
483
    s->id = 0x838f03;
484
    mipid_reset(s);
485

    
486
    return s;
487
}
488

    
489
static void n800_spi_setup(struct n800_s *s)
490
{
491
    void *tsc2301 = s->ts->opaque;
492
    void *mipid = mipid_init();
493

    
494
    omap_mcspi_attach(s->cpu->mcspi[0], tsc210x_txrx, tsc2301, 0);
495
    omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
496
}
497

    
498
/* This task is normally performed by the bootloader.  If we're loading
499
 * a kernel directly, we need to enable the Blizzard ourselves.  */
500
static void n800_dss_init(struct rfbi_chip_s *chip)
501
{
502
    uint8_t *fb_blank;
503

    
504
    chip->write(chip->opaque, 0, 0x2a);                /* LCD Width register */
505
    chip->write(chip->opaque, 1, 0x64);
506
    chip->write(chip->opaque, 0, 0x2c);                /* LCD HNDP register */
507
    chip->write(chip->opaque, 1, 0x1e);
508
    chip->write(chip->opaque, 0, 0x2e);                /* LCD Height 0 register */
509
    chip->write(chip->opaque, 1, 0xe0);
510
    chip->write(chip->opaque, 0, 0x30);                /* LCD Height 1 register */
511
    chip->write(chip->opaque, 1, 0x01);
512
    chip->write(chip->opaque, 0, 0x32);                /* LCD VNDP register */
513
    chip->write(chip->opaque, 1, 0x06);
514
    chip->write(chip->opaque, 0, 0x68);                /* Display Mode register */
515
    chip->write(chip->opaque, 1, 1);                /* Enable bit */
516

    
517
    chip->write(chip->opaque, 0, 0x6c);        
518
    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
519
    chip->write(chip->opaque, 1, 0x00);                /* Input X Start Position */
520
    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
521
    chip->write(chip->opaque, 1, 0x00);                /* Input Y Start Position */
522
    chip->write(chip->opaque, 1, 0x1f);                /* Input X End Position */
523
    chip->write(chip->opaque, 1, 0x03);                /* Input X End Position */
524
    chip->write(chip->opaque, 1, 0xdf);                /* Input Y End Position */
525
    chip->write(chip->opaque, 1, 0x01);                /* Input Y End Position */
526
    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
527
    chip->write(chip->opaque, 1, 0x00);                /* Output X Start Position */
528
    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
529
    chip->write(chip->opaque, 1, 0x00);                /* Output Y Start Position */
530
    chip->write(chip->opaque, 1, 0x1f);                /* Output X End Position */
531
    chip->write(chip->opaque, 1, 0x03);                /* Output X End Position */
532
    chip->write(chip->opaque, 1, 0xdf);                /* Output Y End Position */
533
    chip->write(chip->opaque, 1, 0x01);                /* Output Y End Position */
534
    chip->write(chip->opaque, 1, 0x01);                /* Input Data Format */
535
    chip->write(chip->opaque, 1, 0x01);                /* Data Source Select */
536

    
537
    fb_blank = memset(qemu_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
538
    /* Display Memory Data Port */
539
    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
540
    free(fb_blank);
541
}
542

    
543
static void n800_dss_setup(struct n800_s *s, DisplayState *ds)
544
{
545
    s->blizzard.opaque = s1d13745_init(0, ds);
546
    s->blizzard.block = s1d13745_write_block;
547
    s->blizzard.write = s1d13745_write;
548
    s->blizzard.read = s1d13745_read;
549

    
550
    omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
551
}
552

    
553
static void n800_cbus_setup(struct n800_s *s)
554
{
555
    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0];
556
    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0];
557
    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0];
558

    
559
    struct cbus_s *cbus = cbus_init(dat_out);
560

    
561
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk);
562
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat);
563
    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel);
564

    
565
    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
566
    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
567
}
568

    
569
static void n800_usb_power_cb(void *opaque, int line, int level)
570
{
571
    struct n800_s *s = opaque;
572

    
573
    tusb6010_power(s->usb, level);
574
}
575

    
576
static void n800_usb_setup(struct n800_s *s)
577
{
578
    qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0];
579
    qemu_irq tusb_pwr = qemu_allocate_irqs(n800_usb_power_cb, s, 1)[0];
580
    struct tusb_s *tusb = tusb6010_init(tusb_irq);
581

    
582
    /* Using the NOR interface */
583
    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS,
584
                    tusb6010_async_io(tusb), 0, 0, tusb);
585
    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS,
586
                    tusb6010_sync_io(tusb), 0, 0, tusb);
587

    
588
    s->usb = tusb;
589
    omap2_gpio_out_set(s->cpu->gpif, N800_TUSB_ENABLE_GPIO, tusb_pwr);
590
}
591

    
592
/* This task is normally performed by the bootloader.  If we're loading
593
 * a kernel directly, we need to set up GPMC mappings ourselves.  */
594
static void n800_gpmc_init(struct n800_s *s)
595
{
596
    uint32_t config7 =
597
            (0xf << 8) |        /* MASKADDRESS */
598
            (1 << 6) |                /* CSVALID */
599
            (4 << 0);                /* BASEADDRESS */
600

    
601
    cpu_physical_memory_write(0x6800a078,                /* GPMC_CONFIG7_0 */
602
                    (void *) &config7, sizeof(config7));
603
}
604

    
605
/* Setup sequence done by the bootloader */
606
static void n800_boot_init(void *opaque)
607
{
608
    struct n800_s *s = (struct n800_s *) opaque;
609
    uint32_t buf;
610

    
611
    /* PRCM setup */
612
#define omap_writel(addr, val)        \
613
    buf = (val);                        \
614
    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
615

    
616
    omap_writel(0x48008060, 0x41);                /* PRCM_CLKSRC_CTRL */
617
    omap_writel(0x48008070, 1);                        /* PRCM_CLKOUT_CTRL */
618
    omap_writel(0x48008078, 0);                        /* PRCM_CLKEMUL_CTRL */
619
    omap_writel(0x48008090, 0);                        /* PRCM_VOLTSETUP */
620
    omap_writel(0x48008094, 0);                        /* PRCM_CLKSSETUP */
621
    omap_writel(0x48008098, 0);                        /* PRCM_POLCTRL */
622
    omap_writel(0x48008140, 2);                        /* CM_CLKSEL_MPU */
623
    omap_writel(0x48008148, 0);                        /* CM_CLKSTCTRL_MPU */
624
    omap_writel(0x48008158, 1);                        /* RM_RSTST_MPU */
625
    omap_writel(0x480081c8, 0x15);                /* PM_WKDEP_MPU */
626
    omap_writel(0x480081d4, 0x1d4);                /* PM_EVGENCTRL_MPU */
627
    omap_writel(0x480081d8, 0);                        /* PM_EVEGENONTIM_MPU */
628
    omap_writel(0x480081dc, 0);                        /* PM_EVEGENOFFTIM_MPU */
629
    omap_writel(0x480081e0, 0xc);                /* PM_PWSTCTRL_MPU */
630
    omap_writel(0x48008200, 0x047e7ff7);        /* CM_FCLKEN1_CORE */
631
    omap_writel(0x48008204, 0x00000004);        /* CM_FCLKEN2_CORE */
632
    omap_writel(0x48008210, 0x047e7ff1);        /* CM_ICLKEN1_CORE */
633
    omap_writel(0x48008214, 0x00000004);        /* CM_ICLKEN2_CORE */
634
    omap_writel(0x4800821c, 0x00000000);        /* CM_ICLKEN4_CORE */
635
    omap_writel(0x48008230, 0);                        /* CM_AUTOIDLE1_CORE */
636
    omap_writel(0x48008234, 0);                        /* CM_AUTOIDLE2_CORE */
637
    omap_writel(0x48008238, 7);                        /* CM_AUTOIDLE3_CORE */
638
    omap_writel(0x4800823c, 0);                        /* CM_AUTOIDLE4_CORE */
639
    omap_writel(0x48008240, 0x04360626);        /* CM_CLKSEL1_CORE */
640
    omap_writel(0x48008244, 0x00000014);        /* CM_CLKSEL2_CORE */
641
    omap_writel(0x48008248, 0);                        /* CM_CLKSTCTRL_CORE */
642
    omap_writel(0x48008300, 0x00000000);        /* CM_FCLKEN_GFX */
643
    omap_writel(0x48008310, 0x00000000);        /* CM_ICLKEN_GFX */
644
    omap_writel(0x48008340, 0x00000001);        /* CM_CLKSEL_GFX */
645
    omap_writel(0x48008400, 0x00000004);        /* CM_FCLKEN_WKUP */
646
    omap_writel(0x48008410, 0x00000004);        /* CM_ICLKEN_WKUP */
647
    omap_writel(0x48008440, 0x00000000);        /* CM_CLKSEL_WKUP */
648
    omap_writel(0x48008500, 0x000000cf);        /* CM_CLKEN_PLL */
649
    omap_writel(0x48008530, 0x0000000c);        /* CM_AUTOIDLE_PLL */
650
    omap_writel(0x48008540,                        /* CM_CLKSEL1_PLL */
651
                    (0x78 << 12) | (6 << 8));
652
    omap_writel(0x48008544, 2);                        /* CM_CLKSEL2_PLL */
653

    
654
    /* GPMC setup */
655
    n800_gpmc_init(s);
656

    
657
    /* Video setup */
658
    n800_dss_init(&s->blizzard);
659

    
660
    /* CPU setup */
661
    s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
662
    s->cpu->env->GE = 0x5;
663
}
664

    
665
#define OMAP_TAG_NOKIA_BT        0x4e01
666
#define OMAP_TAG_WLAN_CX3110X        0x4e02
667
#define OMAP_TAG_CBUS                0x4e03
668
#define OMAP_TAG_EM_ASIC_BB5        0x4e04
669

    
670
static int n800_atag_setup(struct arm_boot_info *info, void *p)
671
{
672
    uint8_t *b;
673
    uint16_t *w;
674
    uint32_t *l;
675

    
676
    w = p;
677

    
678
    stw_raw(w ++, OMAP_TAG_UART);                /* u16 tag */
679
    stw_raw(w ++, 4);                                /* u16 len */
680
    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
681
    w ++;
682

    
683
    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);        /* u16 tag */
684
    stw_raw(w ++, 4);                                /* u16 len */
685
    stw_raw(w ++, N8X0_RETU_GPIO);                /* s16 retu_irq_gpio */
686
    stw_raw(w ++, N8X0_TAHVO_GPIO);                /* s16 tahvo_irq_gpio */
687

    
688
    stw_raw(w ++, OMAP_TAG_CBUS);                /* u16 tag */
689
    stw_raw(w ++, 8);                                /* u16 len */
690
    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);                /* s16 clk_gpio */
691
    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);                /* s16 dat_gpio */
692
    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);                /* s16 sel_gpio */
693
    w ++;
694

    
695
    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);        /* u16 tag */
696
    stw_raw(w ++, 20);                                /* u16 len */
697
    strcpy((void *) w, "bat_cover");                /* char name[12] */
698
    w += 6;
699
    stw_raw(w ++, N800_BAT_COVER_GPIO);                /* u16 gpio */
700
    stw_raw(w ++, 0x01);
701
    stw_raw(w ++, 0);
702
    stw_raw(w ++, 0);
703

    
704
    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);        /* u16 tag */
705
    stw_raw(w ++, 20);                                /* u16 len */
706
    strcpy((void *) w, "cam_act");                /* char name[12] */
707
    w += 6;
708
    stw_raw(w ++, N800_CAM_ACT_GPIO);                /* u16 gpio */
709
    stw_raw(w ++, 0x20);
710
    stw_raw(w ++, 0);
711
    stw_raw(w ++, 0);
712

    
713
    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);        /* u16 tag */
714
    stw_raw(w ++, 20);                                /* u16 len */
715
    strcpy((void *) w, "cam_turn");                /* char name[12] */
716
    w += 6;
717
    stw_raw(w ++, N800_CAM_TURN_GPIO);                /* u16 gpio */
718
    stw_raw(w ++, 0x21);
719
    stw_raw(w ++, 0);
720
    stw_raw(w ++, 0);
721

    
722
    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);        /* u16 tag */
723
    stw_raw(w ++, 20);                                /* u16 len */
724
    strcpy((void *) w, "headphone");                /* char name[12] */
725
    w += 6;
726
    stw_raw(w ++, N800_HEADPHONE_GPIO);                /* u16 gpio */
727
    stw_raw(w ++, 0x11);
728
    stw_raw(w ++, 0);
729
    stw_raw(w ++, 0);
730

    
731
    stw_raw(w ++, OMAP_TAG_NOKIA_BT);                /* u16 tag */
732
    stw_raw(w ++, 12);                                /* u16 len */
733
    b = (void *) w;
734
    stb_raw(b ++, 0x01);                        /* u8 chip_type        (CSR) */
735
    stb_raw(b ++, N800_BT_WKUP_GPIO);                /* u8 bt_wakeup_gpio */
736
    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);        /* u8 host_wakeup_gpio */
737
    stb_raw(b ++, N800_BT_RESET_GPIO);                /* u8 reset_gpio */
738
    stb_raw(b ++, 1);                                /* u8 bt_uart */
739
    memset(b, 0, 6);                                /* u8 bd_addr[6] */
740
    b += 6;
741
    stb_raw(b ++, 0x02);                        /* u8 bt_sysclk (38.4) */
742
    w = (void *) b;
743

    
744
    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);        /* u16 tag */
745
    stw_raw(w ++, 8);                                /* u16 len */
746
    stw_raw(w ++, 0x25);                        /* u8 chip_type */
747
    stw_raw(w ++, N800_WLAN_PWR_GPIO);                /* s16 power_gpio */
748
    stw_raw(w ++, N800_WLAN_IRQ_GPIO);                /* s16 irq_gpio */
749
    stw_raw(w ++, -1);                                /* s16 spi_cs_gpio */
750

    
751
    stw_raw(w ++, OMAP_TAG_MMC);                /* u16 tag */
752
    stw_raw(w ++, 16);                                /* u16 len */
753
    stw_raw(w ++, 0xf);                                /* unsigned flags */
754
    stw_raw(w ++, -1);                                /* s16 power_pin */
755
    stw_raw(w ++, -1);                                /* s16 switch_pin */
756
    stw_raw(w ++, -1);                                /* s16 wp_pin */
757
    stw_raw(w ++, 0);                                /* unsigned flags */
758
    stw_raw(w ++, 0);                                /* s16 power_pin */
759
    stw_raw(w ++, 0);                                /* s16 switch_pin */
760
    stw_raw(w ++, 0);                                /* s16 wp_pin */
761

    
762
    stw_raw(w ++, OMAP_TAG_TEA5761);                /* u16 tag */
763
    stw_raw(w ++, 4);                                /* u16 len */
764
    stw_raw(w ++, N800_TEA5761_CS_GPIO);        /* u16 enable_gpio */
765
    w ++;
766

    
767
    stw_raw(w ++, OMAP_TAG_PARTITION);                /* u16 tag */
768
    stw_raw(w ++, 28);                                /* u16 len */
769
    strcpy((void *) w, "bootloader");                /* char name[16] */
770
    l = (void *) (w + 8);
771
    stl_raw(l ++, 0x00020000);                        /* unsigned int size */
772
    stl_raw(l ++, 0x00000000);                        /* unsigned int offset */
773
    stl_raw(l ++, 0x3);                                /* unsigned int mask_flags */
774
    w = (void *) l;
775

    
776
    stw_raw(w ++, OMAP_TAG_PARTITION);                /* u16 tag */
777
    stw_raw(w ++, 28);                                /* u16 len */
778
    strcpy((void *) w, "config");                /* char name[16] */
779
    l = (void *) (w + 8);
780
    stl_raw(l ++, 0x00060000);                        /* unsigned int size */
781
    stl_raw(l ++, 0x00020000);                        /* unsigned int offset */
782
    stl_raw(l ++, 0x0);                                /* unsigned int mask_flags */
783
    w = (void *) l;
784

    
785
    stw_raw(w ++, OMAP_TAG_PARTITION);                /* u16 tag */
786
    stw_raw(w ++, 28);                                /* u16 len */
787
    strcpy((void *) w, "kernel");                /* char name[16] */
788
    l = (void *) (w + 8);
789
    stl_raw(l ++, 0x00200000);                        /* unsigned int size */
790
    stl_raw(l ++, 0x00080000);                        /* unsigned int offset */
791
    stl_raw(l ++, 0x0);                                /* unsigned int mask_flags */
792
    w = (void *) l;
793

    
794
    stw_raw(w ++, OMAP_TAG_PARTITION);                /* u16 tag */
795
    stw_raw(w ++, 28);                                /* u16 len */
796
    strcpy((void *) w, "initfs");                /* char name[16] */
797
    l = (void *) (w + 8);
798
    stl_raw(l ++, 0x00200000);                        /* unsigned int size */
799
    stl_raw(l ++, 0x00280000);                        /* unsigned int offset */
800
    stl_raw(l ++, 0x3);                                /* unsigned int mask_flags */
801
    w = (void *) l;
802

    
803
    stw_raw(w ++, OMAP_TAG_PARTITION);                /* u16 tag */
804
    stw_raw(w ++, 28);                                /* u16 len */
805
    strcpy((void *) w, "rootfs");                /* char name[16] */
806
    l = (void *) (w + 8);
807
    stl_raw(l ++, 0x0fb80000);                        /* unsigned int size */
808
    stl_raw(l ++, 0x00480000);                        /* unsigned int offset */
809
    stl_raw(l ++, 0x3);                                /* unsigned int mask_flags */
810
    w = (void *) l;
811

    
812
    stw_raw(w ++, OMAP_TAG_BOOT_REASON);        /* u16 tag */
813
    stw_raw(w ++, 12);                                /* u16 len */
814
#if 0
815
    strcpy((void *) w, "por");                        /* char reason_str[12] */
816
    strcpy((void *) w, "charger");                /* char reason_str[12] */
817
    strcpy((void *) w, "32wd_to");                /* char reason_str[12] */
818
    strcpy((void *) w, "sw_rst");                /* char reason_str[12] */
819
    strcpy((void *) w, "mbus");                        /* char reason_str[12] */
820
    strcpy((void *) w, "unknown");                /* char reason_str[12] */
821
    strcpy((void *) w, "swdg_to");                /* char reason_str[12] */
822
    strcpy((void *) w, "sec_vio");                /* char reason_str[12] */
823
    strcpy((void *) w, "pwr_key");                /* char reason_str[12] */
824
    strcpy((void *) w, "rtc_alarm");                /* char reason_str[12] */
825
#else
826
    strcpy((void *) w, "pwr_key");                /* char reason_str[12] */
827
#endif
828
    w += 6;
829

    
830
#if 0        /* N810 */
831
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
832
    stw_raw(w ++, 24);                                /* u16 len */
833
    strcpy((void *) w, "product");                /* char component[12] */
834
    w += 6;
835
    strcpy((void *) w, "RX-44");                /* char version[12] */
836
    w += 6;
837

838
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
839
    stw_raw(w ++, 24);                                /* u16 len */
840
    strcpy((void *) w, "hw-build");                /* char component[12] */
841
    w += 6;
842
    strcpy((void *) w, "QEMU");                        /* char version[12] */
843
    w += 6;
844

845
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
846
    stw_raw(w ++, 24);                                /* u16 len */
847
    strcpy((void *) w, "nolo");                        /* char component[12] */
848
    w += 6;
849
    strcpy((void *) w, "1.1.10-qemu");                /* char version[12] */
850
    w += 6;
851
#else
852
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
853
    stw_raw(w ++, 24);                                /* u16 len */
854
    strcpy((void *) w, "product");                /* char component[12] */
855
    w += 6;
856
    strcpy((void *) w, "RX-34");                /* char version[12] */
857
    w += 6;
858

    
859
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
860
    stw_raw(w ++, 24);                                /* u16 len */
861
    strcpy((void *) w, "hw-build");                /* char component[12] */
862
    w += 6;
863
    strcpy((void *) w, "QEMU");                        /* char version[12] */
864
    w += 6;
865

    
866
    stw_raw(w ++, OMAP_TAG_VERSION_STR);        /* u16 tag */
867
    stw_raw(w ++, 24);                                /* u16 len */
868
    strcpy((void *) w, "nolo");                        /* char component[12] */
869
    w += 6;
870
    strcpy((void *) w, "1.1.6-qemu");                /* char version[12] */
871
    w += 6;
872
#endif
873

    
874
    stw_raw(w ++, OMAP_TAG_LCD);                /* u16 tag */
875
    stw_raw(w ++, 36);                                /* u16 len */
876
    strcpy((void *) w, "QEMU LCD panel");        /* char panel_name[16] */
877
    w += 8;
878
    strcpy((void *) w, "blizzard");                /* char ctrl_name[16] */
879
    w += 8;
880
    stw_raw(w ++, 5);                                /* TODO s16 nreset_gpio */
881
    stw_raw(w ++, 16);                                /* u8 data_lines */
882

    
883
    return (void *) w - p;
884
}
885

    
886
static struct arm_boot_info n800_binfo = {
887
    .loader_start = OMAP2_Q2_BASE,
888
    /* Actually two chips of 0x4000000 bytes each */
889
    .ram_size = 0x08000000,
890
    .board_id = 0x4f7,
891
    .atag_board = n800_atag_setup,
892
};
893

    
894
static void n800_init(int ram_size, int vga_ram_size,
895
                const char *boot_device, DisplayState *ds,
896
                const char *kernel_filename, const char *kernel_cmdline,
897
                const char *initrd_filename, const char *cpu_model)
898
{
899
    struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s));
900
    int sdram_size = n800_binfo.ram_size;
901
    int onenandram_size = 0x00010000;
902

    
903
    if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) {
904
        fprintf(stderr, "This architecture uses %i bytes of memory\n",
905
                        sdram_size + onenandram_size + OMAP242X_SRAM_SIZE);
906
        exit(1);
907
    }
908

    
909
    s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model);
910

    
911
    n800_gpio_setup(s);
912
    n8x0_nand_setup(s);
913
    n800_i2c_setup(s);
914
    n800_tsc_setup(s);
915
    n800_spi_setup(s);
916
    n800_dss_setup(s, ds);
917
    n800_cbus_setup(s);
918
    if (usb_enabled)
919
        n800_usb_setup(s);
920

    
921
    /* Setup initial (reset) machine state */
922

    
923
    /* Start at the OneNAND bootloader.  */
924
    s->cpu->env->regs[15] = 0;
925

    
926
    if (kernel_filename) {
927
        /* Or at the linux loader.  */
928
        n800_binfo.kernel_filename = kernel_filename;
929
        n800_binfo.kernel_cmdline = kernel_cmdline;
930
        n800_binfo.initrd_filename = initrd_filename;
931
        arm_load_kernel(s->cpu->env, &n800_binfo);
932

    
933
        qemu_register_reset(n800_boot_init, s);
934
        n800_boot_init(s);
935
    }
936

    
937
    dpy_resize(ds, 800, 480);
938
}
939

    
940
QEMUMachine n800_machine = {
941
    "n800",
942
    "Nokia N800 aka. RX-34 tablet (OMAP2420)",
943
    n800_init,
944
};