]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/nseries.c
acpi: do not use TARGET_PAGE_SIZE
[mirror_qemu.git] / hw / arm / nseries.c
CommitLineData
7e7c5e4c
AZ
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 *
fad6cb1a 17 * You should have received a copy of the GNU General Public License along
8167ee88 18 * with this program; if not, see <http://www.gnu.org/licenses/>.
7e7c5e4c
AZ
19 */
20
12b16722 21#include "qemu/osdep.h"
da34e65c 22#include "qapi/error.h"
f348b6d1 23#include "qemu/cutils.h"
58369e22 24#include "qemu/bswap.h"
9c17d615 25#include "sysemu/sysemu.h"
0d09e41a 26#include "hw/arm/omap.h"
bd2be150 27#include "hw/arm/arm.h"
83c9f4ca 28#include "hw/irq.h"
28ecbaee 29#include "ui/console.h"
83c9f4ca 30#include "hw/boards.h"
0d09e41a 31#include "hw/i2c/i2c.h"
bd2be150 32#include "hw/devices.h"
0d09e41a 33#include "hw/block/flash.h"
83c9f4ca
PB
34#include "hw/hw.h"
35#include "hw/bt.h"
36#include "hw/loader.h"
fa1d36df 37#include "sysemu/block-backend.h"
83c9f4ca 38#include "hw/sysbus.h"
022c62cb 39#include "exec/address-spaces.h"
7e7c5e4c
AZ
40
41/* Nokia N8x0 support */
42struct n800_s {
518ec134 43 struct omap_mpu_state_s *mpu;
7e7c5e4c
AZ
44
45 struct rfbi_chip_s blizzard;
e927bb00
AZ
46 struct {
47 void *opaque;
48 uint32_t (*txrx)(void *opaque, uint32_t value, int len);
bc24a225 49 uWireSlave *chip;
e927bb00 50 } ts;
7e7c5e4c
AZ
51
52 int keymap[0x80];
c4f05c8c 53 DeviceState *kbd;
7e7c5e4c 54
bdc76462 55 DeviceState *usb;
7e7c5e4c
AZ
56 void *retu;
57 void *tahvo;
500954e3 58 DeviceState *nand;
7e7c5e4c
AZ
59};
60
61/* GPIO pins */
e927bb00 62#define N8X0_TUSB_ENABLE_GPIO 0
7e7c5e4c
AZ
63#define N800_MMC2_WP_GPIO 8
64#define N800_UNKNOWN_GPIO0 9 /* out */
0941041e 65#define N810_MMC2_VIOSD_GPIO 9
99570a40 66#define N810_HEADSET_AMP_GPIO 10
7e7c5e4c 67#define N800_CAM_TURN_GPIO 12
e927bb00 68#define N810_GPS_RESET_GPIO 12
7e7c5e4c
AZ
69#define N800_BLIZZARD_POWERDOWN_GPIO 15
70#define N800_MMC1_WP_GPIO 23
0941041e 71#define N810_MMC2_VSD_GPIO 23
7e7c5e4c 72#define N8X0_ONENAND_GPIO 26
e927bb00 73#define N810_BLIZZARD_RESET_GPIO 30
7e7c5e4c
AZ
74#define N800_UNKNOWN_GPIO2 53 /* out */
75#define N8X0_TUSB_INT_GPIO 58
e927bb00
AZ
76#define N8X0_BT_WKUP_GPIO 61
77#define N8X0_STI_GPIO 62
7e7c5e4c 78#define N8X0_CBUS_SEL_GPIO 64
e927bb00
AZ
79#define N8X0_CBUS_DAT_GPIO 65
80#define N8X0_CBUS_CLK_GPIO 66
81#define N8X0_WLAN_IRQ_GPIO 87
82#define N8X0_BT_RESET_GPIO 92
83#define N8X0_TEA5761_CS_GPIO 93
7e7c5e4c 84#define N800_UNKNOWN_GPIO 94
e927bb00 85#define N810_TSC_RESET_GPIO 94
7e7c5e4c 86#define N800_CAM_ACT_GPIO 95
e927bb00
AZ
87#define N810_GPS_WAKEUP_GPIO 95
88#define N8X0_MMC_CS_GPIO 96
89#define N8X0_WLAN_PWR_GPIO 97
7e7c5e4c 90#define N8X0_BT_HOST_WKUP_GPIO 98
99570a40 91#define N810_SPEAKER_AMP_GPIO 101
7e7c5e4c
AZ
92#define N810_KB_LOCK_GPIO 102
93#define N800_TSC_TS_GPIO 103
e927bb00
AZ
94#define N810_TSC_TS_GPIO 106
95#define N8X0_HEADPHONE_GPIO 107
7e7c5e4c
AZ
96#define N8X0_RETU_GPIO 108
97#define N800_TSC_KP_IRQ_GPIO 109
98#define N810_KEYBOARD_GPIO 109
99#define N800_BAT_COVER_GPIO 110
100#define N810_SLIDE_GPIO 110
101#define N8X0_TAHVO_GPIO 111
102#define N800_UNKNOWN_GPIO4 112 /* out */
e927bb00 103#define N810_SLEEPX_LED_GPIO 112
1d4e547b 104#define N800_TSC_RESET_GPIO 118 /* ? */
99570a40 105#define N810_AIC33_RESET_GPIO 118
1d4e547b 106#define N800_TSC_UNKNOWN_GPIO 119 /* out */
7e7c5e4c
AZ
107#define N8X0_TMP105_GPIO 125
108
109/* Config */
c580d92b 110#define BT_UART 0
7e7c5e4c
AZ
111#define XLDR_LL_UART 1
112
1d4e547b
AZ
113/* Addresses on the I2C bus 0 */
114#define N810_TLV320AIC33_ADDR 0x18 /* Audio CODEC */
115#define N8X0_TCM825x_ADDR 0x29 /* Camera */
116#define N810_LP5521_ADDR 0x32 /* LEDs */
117#define N810_TSL2563_ADDR 0x3d /* Light sensor */
118#define N810_LM8323_ADDR 0x45 /* Keyboard */
119/* Addresses on the I2C bus 1 */
120#define N8X0_TMP105_ADDR 0x48 /* Temperature sensor */
121#define N8X0_MENELAUS_ADDR 0x72 /* Power management */
7e7c5e4c
AZ
122
123/* Chipselects on GPMC NOR interface */
124#define N8X0_ONENAND_CS 0
125#define N8X0_USB_ASYNC_CS 1
126#define N8X0_USB_SYNC_CS 4
127
c580d92b
AZ
128#define N8X0_BD_ADDR 0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
129
7e7c5e4c
AZ
130static void n800_mmc_cs_cb(void *opaque, int line, int level)
131{
132 /* TODO: this seems to actually be connected to the menelaus, to
133 * which also both MMC slots connect. */
134 omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
7e7c5e4c
AZ
135}
136
e927bb00 137static void n8x0_gpio_setup(struct n800_s *s)
7e7c5e4c 138{
294972ce
SZ
139 qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO,
140 qemu_allocate_irq(n800_mmc_cs_cb, s->mpu->mmc, 0));
518ec134 141 qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
7e7c5e4c
AZ
142}
143
c580d92b
AZ
144#define MAEMO_CAL_HEADER(...) \
145 'C', 'o', 'n', 'F', 0x02, 0x00, 0x04, 0x00, \
146 __VA_ARGS__, \
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148
149static const uint8_t n8x0_cal_wlan_mac[] = {
150 MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
151 0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
152 0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
154 0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
155 0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
156};
157
158static const uint8_t n8x0_cal_bt_id[] = {
159 MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
160 0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
161 0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
162 N8X0_BD_ADDR,
163};
164
7e7c5e4c
AZ
165static void n8x0_nand_setup(struct n800_s *s)
166{
c580d92b 167 char *otp_region;
af5a75f4 168 DriveInfo *dinfo;
c580d92b 169
500954e3
JR
170 s->nand = qdev_create(NULL, "onenand");
171 qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
5923ba42 172 /* Either 0x40 or 0x48 are OK for the device ID */
500954e3
JR
173 qdev_prop_set_uint16(s->nand, "device_id", 0x48);
174 qdev_prop_set_uint16(s->nand, "version_id", 0);
175 qdev_prop_set_int32(s->nand, "shift", 1);
176 dinfo = drive_get(IF_MTD, 0, 0);
fa1d36df 177 if (dinfo) {
6231a6da
MA
178 qdev_prop_set_drive(s->nand, "drive", blk_by_legacy_dinfo(dinfo),
179 &error_fatal);
500954e3
JR
180 }
181 qdev_init_nofail(s->nand);
1356b98d 182 sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
518ec134
AF
183 qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
184 omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
1356b98d 185 sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
c580d92b
AZ
186 otp_region = onenand_raw_otp(s->nand);
187
188 memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
189 memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
190 /* XXX: in theory should also update the OOB for both pages */
7e7c5e4c
AZ
191}
192
c72ddb1e
IM
193static qemu_irq n8x0_system_powerdown;
194
195static void n8x0_powerdown_req(Notifier *n, void *opaque)
196{
197 qemu_irq_raise(n8x0_system_powerdown);
198}
199
200static Notifier n8x0_system_powerdown_notifier = {
201 .notify = n8x0_powerdown_req
202};
203
e927bb00 204static void n8x0_i2c_setup(struct n800_s *s)
7e7c5e4c 205{
697454eb 206 DeviceState *dev;
518ec134 207 qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
a5c82852 208 I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
7e7c5e4c
AZ
209
210 /* Attach a menelaus PM chip */
54e17933 211 dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
0919ac78 212 qdev_connect_gpio_out(dev, 3,
518ec134 213 qdev_get_gpio_in(s->mpu->ih[0],
0919ac78 214 OMAP_INT_24XX_SYS_NIRQ));
7e7c5e4c 215
c72ddb1e
IM
216 n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
217 qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
dd4427a6 218
7e7c5e4c 219 /* Attach a TMP105 PM chip (A0 wired to ground) */
54e17933 220 dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
697454eb 221 qdev_connect_gpio_out(dev, 0, tmp_irq);
7e7c5e4c
AZ
222}
223
224/* Touchscreen and keypad controller */
bc24a225 225static MouseTransformInfo n800_pointercal = {
e927bb00
AZ
226 .x = 800,
227 .y = 480,
228 .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
229};
230
bc24a225 231static MouseTransformInfo n810_pointercal = {
e927bb00
AZ
232 .x = 800,
233 .y = 480,
234 .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
235};
236
7e7c5e4c
AZ
237#define RETU_KEYCODE 61 /* F3 */
238
239static void n800_key_event(void *opaque, int keycode)
240{
241 struct n800_s *s = (struct n800_s *) opaque;
242 int code = s->keymap[keycode & 0x7f];
243
244 if (code == -1) {
fddbd80c 245 if ((keycode & 0x7f) == RETU_KEYCODE) {
7e7c5e4c 246 retu_key_event(s->retu, !(keycode & 0x80));
fddbd80c 247 }
7e7c5e4c
AZ
248 return;
249 }
250
e927bb00 251 tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
7e7c5e4c
AZ
252}
253
254static const int n800_keys[16] = {
255 -1,
256 72, /* Up */
257 63, /* Home (F5) */
258 -1,
259 75, /* Left */
260 28, /* Enter */
261 77, /* Right */
262 -1,
1d4e547b 263 1, /* Cycle (ESC) */
7e7c5e4c
AZ
264 80, /* Down */
265 62, /* Menu (F4) */
266 -1,
267 66, /* Zoom- (F8) */
1d4e547b 268 64, /* FullScreen (F6) */
7e7c5e4c
AZ
269 65, /* Zoom+ (F7) */
270 -1,
271};
272
e927bb00 273static void n800_tsc_kbd_setup(struct n800_s *s)
7e7c5e4c
AZ
274{
275 int i;
276
277 /* XXX: are the three pins inverted inside the chip between the
278 * tsc and the cpu (N4111)? */
b9d38e95 279 qemu_irq penirq = NULL; /* NC */
518ec134
AF
280 qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
281 qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
7e7c5e4c 282
22d83b14 283 s->ts.chip = tsc2301_init(penirq, kbirq, dav);
e927bb00
AZ
284 s->ts.opaque = s->ts.chip->opaque;
285 s->ts.txrx = tsc210x_txrx;
7e7c5e4c 286
fddbd80c 287 for (i = 0; i < 0x80; i++) {
7e7c5e4c 288 s->keymap[i] = -1;
fddbd80c
PB
289 }
290 for (i = 0; i < 0x10; i++) {
291 if (n800_keys[i] >= 0) {
7e7c5e4c 292 s->keymap[n800_keys[i]] = i;
fddbd80c
PB
293 }
294 }
7e7c5e4c
AZ
295
296 qemu_add_kbd_event_handler(n800_key_event, s);
297
e927bb00
AZ
298 tsc210x_set_transform(s->ts.chip, &n800_pointercal);
299}
300
301static void n810_tsc_setup(struct n800_s *s)
302{
518ec134 303 qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
e927bb00
AZ
304
305 s->ts.opaque = tsc2005_init(pintdav);
306 s->ts.txrx = tsc2005_txrx;
307
308 tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
7e7c5e4c
AZ
309}
310
1d4e547b
AZ
311/* N810 Keyboard controller */
312static void n810_key_event(void *opaque, int keycode)
313{
314 struct n800_s *s = (struct n800_s *) opaque;
315 int code = s->keymap[keycode & 0x7f];
316
317 if (code == -1) {
fddbd80c 318 if ((keycode & 0x7f) == RETU_KEYCODE) {
1d4e547b 319 retu_key_event(s->retu, !(keycode & 0x80));
fddbd80c 320 }
1d4e547b
AZ
321 return;
322 }
323
324 lm832x_key_event(s->kbd, code, !(keycode & 0x80));
325}
326
327#define M 0
328
329static int n810_keys[0x80] = {
330 [0x01] = 16, /* Q */
331 [0x02] = 37, /* K */
332 [0x03] = 24, /* O */
333 [0x04] = 25, /* P */
334 [0x05] = 14, /* Backspace */
335 [0x06] = 30, /* A */
336 [0x07] = 31, /* S */
337 [0x08] = 32, /* D */
338 [0x09] = 33, /* F */
339 [0x0a] = 34, /* G */
340 [0x0b] = 35, /* H */
341 [0x0c] = 36, /* J */
342
343 [0x11] = 17, /* W */
344 [0x12] = 62, /* Menu (F4) */
345 [0x13] = 38, /* L */
346 [0x14] = 40, /* ' (Apostrophe) */
347 [0x16] = 44, /* Z */
348 [0x17] = 45, /* X */
349 [0x18] = 46, /* C */
350 [0x19] = 47, /* V */
351 [0x1a] = 48, /* B */
352 [0x1b] = 49, /* N */
353 [0x1c] = 42, /* Shift (Left shift) */
354 [0x1f] = 65, /* Zoom+ (F7) */
355
356 [0x21] = 18, /* E */
357 [0x22] = 39, /* ; (Semicolon) */
358 [0x23] = 12, /* - (Minus) */
359 [0x24] = 13, /* = (Equal) */
360 [0x2b] = 56, /* Fn (Left Alt) */
361 [0x2c] = 50, /* M */
362 [0x2f] = 66, /* Zoom- (F8) */
363
364 [0x31] = 19, /* R */
365 [0x32] = 29 | M, /* Right Ctrl */
366 [0x34] = 57, /* Space */
367 [0x35] = 51, /* , (Comma) */
368 [0x37] = 72 | M, /* Up */
369 [0x3c] = 82 | M, /* Compose (Insert) */
370 [0x3f] = 64, /* FullScreen (F6) */
371
372 [0x41] = 20, /* T */
373 [0x44] = 52, /* . (Dot) */
374 [0x46] = 77 | M, /* Right */
375 [0x4f] = 63, /* Home (F5) */
376 [0x51] = 21, /* Y */
377 [0x53] = 80 | M, /* Down */
378 [0x55] = 28, /* Enter */
379 [0x5f] = 1, /* Cycle (ESC) */
380
381 [0x61] = 22, /* U */
382 [0x64] = 75 | M, /* Left */
383
384 [0x71] = 23, /* I */
385#if 0
386 [0x75] = 28 | M, /* KP Enter (KP Enter) */
387#else
388 [0x75] = 15, /* KP Enter (Tab) */
389#endif
390};
391
392#undef M
393
394static void n810_kbd_setup(struct n800_s *s)
395{
518ec134 396 qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
1d4e547b
AZ
397 int i;
398
fddbd80c 399 for (i = 0; i < 0x80; i++) {
1d4e547b 400 s->keymap[i] = -1;
fddbd80c
PB
401 }
402 for (i = 0; i < 0x80; i++) {
403 if (n810_keys[i] > 0) {
1d4e547b 404 s->keymap[n810_keys[i]] = i;
fddbd80c
PB
405 }
406 }
1d4e547b
AZ
407
408 qemu_add_kbd_event_handler(n810_key_event, s);
409
410 /* Attach the LM8322 keyboard to the I2C bus,
411 * should happen in n8x0_i2c_setup and s->kbd be initialised here. */
518ec134 412 s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
54e17933 413 "lm8323", N810_LM8323_ADDR);
c4f05c8c 414 qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
1d4e547b
AZ
415}
416
7e7c5e4c
AZ
417/* LCD MIPI DBI-C controller (URAL) */
418struct mipid_s {
419 int resp[4];
420 int param[4];
421 int p;
422 int pm;
423 int cmd;
424
425 int sleep;
426 int booster;
427 int te;
428 int selfcheck;
429 int partial;
430 int normal;
431 int vscr;
432 int invert;
433 int onoff;
434 int gamma;
435 uint32_t id;
436};
437
438static void mipid_reset(struct mipid_s *s)
439{
7e7c5e4c
AZ
440 s->pm = 0;
441 s->cmd = 0;
442
443 s->sleep = 1;
444 s->booster = 0;
445 s->selfcheck =
446 (1 << 7) | /* Register loading OK. */
447 (1 << 5) | /* The chip is attached. */
448 (1 << 4); /* Display glass still in one piece. */
449 s->te = 0;
450 s->partial = 0;
451 s->normal = 1;
452 s->vscr = 0;
453 s->invert = 0;
454 s->onoff = 1;
455 s->gamma = 0;
456}
457
e927bb00 458static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
7e7c5e4c
AZ
459{
460 struct mipid_s *s = (struct mipid_s *) opaque;
461 uint8_t ret;
462
fddbd80c 463 if (len > 9) {
2ac71179 464 hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
fddbd80c 465 }
e927bb00 466
fddbd80c 467 if (s->p >= ARRAY_SIZE(s->resp)) {
7e7c5e4c 468 ret = 0;
fddbd80c
PB
469 } else {
470 ret = s->resp[s->p++];
471 }
472 if (s->pm-- > 0) {
7e7c5e4c 473 s->param[s->pm] = cmd;
fddbd80c 474 } else {
7e7c5e4c 475 s->cmd = cmd;
fddbd80c 476 }
7e7c5e4c
AZ
477
478 switch (s->cmd) {
479 case 0x00: /* NOP */
480 break;
481
482 case 0x01: /* SWRESET */
483 mipid_reset(s);
484 break;
485
486 case 0x02: /* BSTROFF */
487 s->booster = 0;
488 break;
489 case 0x03: /* BSTRON */
490 s->booster = 1;
491 break;
492
493 case 0x04: /* RDDID */
494 s->p = 0;
495 s->resp[0] = (s->id >> 16) & 0xff;
496 s->resp[1] = (s->id >> 8) & 0xff;
497 s->resp[2] = (s->id >> 0) & 0xff;
498 break;
499
500 case 0x06: /* RD_RED */
501 case 0x07: /* RD_GREEN */
502 /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
503 * for the bootloader one needs to change this. */
504 case 0x08: /* RD_BLUE */
505 s->p = 0;
506 /* TODO: return first pixel components */
507 s->resp[0] = 0x01;
508 break;
509
510 case 0x09: /* RDDST */
511 s->p = 0;
512 s->resp[0] = s->booster << 7;
513 s->resp[1] = (5 << 4) | (s->partial << 2) |
514 (s->sleep << 1) | s->normal;
515 s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
516 (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
517 s->resp[3] = s->gamma << 6;
518 break;
519
520 case 0x0a: /* RDDPM */
521 s->p = 0;
522 s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
523 (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
524 break;
525 case 0x0b: /* RDDMADCTR */
526 s->p = 0;
527 s->resp[0] = 0;
528 break;
529 case 0x0c: /* RDDCOLMOD */
530 s->p = 0;
531 s->resp[0] = 5; /* 65K colours */
532 break;
533 case 0x0d: /* RDDIM */
534 s->p = 0;
535 s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
536 break;
537 case 0x0e: /* RDDSM */
538 s->p = 0;
539 s->resp[0] = s->te << 7;
540 break;
541 case 0x0f: /* RDDSDR */
542 s->p = 0;
543 s->resp[0] = s->selfcheck;
544 break;
545
546 case 0x10: /* SLPIN */
547 s->sleep = 1;
548 break;
549 case 0x11: /* SLPOUT */
550 s->sleep = 0;
551 s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */
552 break;
553
554 case 0x12: /* PTLON */
555 s->partial = 1;
556 s->normal = 0;
557 s->vscr = 0;
558 break;
559 case 0x13: /* NORON */
560 s->partial = 0;
561 s->normal = 1;
562 s->vscr = 0;
563 break;
564
565 case 0x20: /* INVOFF */
566 s->invert = 0;
567 break;
568 case 0x21: /* INVON */
569 s->invert = 1;
570 break;
571
572 case 0x22: /* APOFF */
573 case 0x23: /* APON */
574 goto bad_cmd;
575
576 case 0x25: /* WRCNTR */
fddbd80c 577 if (s->pm < 0) {
7e7c5e4c 578 s->pm = 1;
fddbd80c 579 }
7e7c5e4c
AZ
580 goto bad_cmd;
581
582 case 0x26: /* GAMSET */
fddbd80c 583 if (!s->pm) {
ad5f5fdc
SH
584 s->gamma = ctz32(s->param[0] & 0xf);
585 if (s->gamma == 32) {
586 s->gamma = -1; /* XXX: should this be 0? */
587 }
fddbd80c 588 } else if (s->pm < 0) {
7e7c5e4c 589 s->pm = 1;
fddbd80c 590 }
7e7c5e4c
AZ
591 break;
592
593 case 0x28: /* DISPOFF */
594 s->onoff = 0;
7e7c5e4c
AZ
595 break;
596 case 0x29: /* DISPON */
597 s->onoff = 1;
7e7c5e4c
AZ
598 break;
599
600 case 0x2a: /* CASET */
601 case 0x2b: /* RASET */
602 case 0x2c: /* RAMWR */
603 case 0x2d: /* RGBSET */
604 case 0x2e: /* RAMRD */
605 case 0x30: /* PTLAR */
606 case 0x33: /* SCRLAR */
607 goto bad_cmd;
608
609 case 0x34: /* TEOFF */
610 s->te = 0;
611 break;
612 case 0x35: /* TEON */
fddbd80c 613 if (!s->pm) {
7e7c5e4c 614 s->te = 1;
fddbd80c 615 } else if (s->pm < 0) {
7e7c5e4c 616 s->pm = 1;
fddbd80c 617 }
7e7c5e4c
AZ
618 break;
619
620 case 0x36: /* MADCTR */
621 goto bad_cmd;
622
623 case 0x37: /* VSCSAD */
624 s->partial = 0;
625 s->normal = 0;
626 s->vscr = 1;
627 break;
628
629 case 0x38: /* IDMOFF */
630 case 0x39: /* IDMON */
631 case 0x3a: /* COLMOD */
632 goto bad_cmd;
633
634 case 0xb0: /* CLKINT / DISCTL */
635 case 0xb1: /* CLKEXT */
fddbd80c 636 if (s->pm < 0) {
7e7c5e4c 637 s->pm = 2;
fddbd80c 638 }
7e7c5e4c
AZ
639 break;
640
641 case 0xb4: /* FRMSEL */
642 break;
643
644 case 0xb5: /* FRM8SEL */
645 case 0xb6: /* TMPRNG / INIESC */
646 case 0xb7: /* TMPHIS / NOP2 */
647 case 0xb8: /* TMPREAD / MADCTL */
648 case 0xba: /* DISTCTR */
649 case 0xbb: /* EPVOL */
650 goto bad_cmd;
651
652 case 0xbd: /* Unknown */
653 s->p = 0;
654 s->resp[0] = 0;
655 s->resp[1] = 1;
656 break;
657
658 case 0xc2: /* IFMOD */
fddbd80c 659 if (s->pm < 0) {
7e7c5e4c 660 s->pm = 2;
fddbd80c 661 }
7e7c5e4c
AZ
662 break;
663
664 case 0xc6: /* PWRCTL */
665 case 0xc7: /* PPWRCTL */
666 case 0xd0: /* EPWROUT */
667 case 0xd1: /* EPWRIN */
668 case 0xd4: /* RDEV */
669 case 0xd5: /* RDRR */
670 goto bad_cmd;
671
672 case 0xda: /* RDID1 */
673 s->p = 0;
674 s->resp[0] = (s->id >> 16) & 0xff;
675 break;
676 case 0xdb: /* RDID2 */
677 s->p = 0;
678 s->resp[0] = (s->id >> 8) & 0xff;
679 break;
680 case 0xdc: /* RDID3 */
681 s->p = 0;
682 s->resp[0] = (s->id >> 0) & 0xff;
683 break;
684
685 default:
686 bad_cmd:
591f73f6
PM
687 qemu_log_mask(LOG_GUEST_ERROR,
688 "%s: unknown command %02x\n", __func__, s->cmd);
7e7c5e4c
AZ
689 break;
690 }
691
692 return ret;
693}
694
695static void *mipid_init(void)
696{
7267c094 697 struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
7e7c5e4c
AZ
698
699 s->id = 0x838f03;
700 mipid_reset(s);
701
702 return s;
703}
704
e927bb00 705static void n8x0_spi_setup(struct n800_s *s)
7e7c5e4c 706{
e927bb00 707 void *tsc = s->ts.opaque;
7e7c5e4c
AZ
708 void *mipid = mipid_init();
709
518ec134
AF
710 omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
711 omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
7e7c5e4c
AZ
712}
713
714/* This task is normally performed by the bootloader. If we're loading
715 * a kernel directly, we need to enable the Blizzard ourselves. */
716static void n800_dss_init(struct rfbi_chip_s *chip)
717{
718 uint8_t *fb_blank;
719
720 chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */
721 chip->write(chip->opaque, 1, 0x64);
722 chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */
723 chip->write(chip->opaque, 1, 0x1e);
724 chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */
725 chip->write(chip->opaque, 1, 0xe0);
726 chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */
727 chip->write(chip->opaque, 1, 0x01);
728 chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */
729 chip->write(chip->opaque, 1, 0x06);
730 chip->write(chip->opaque, 0, 0x68); /* Display Mode register */
731 chip->write(chip->opaque, 1, 1); /* Enable bit */
732
733 chip->write(chip->opaque, 0, 0x6c);
734 chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */
735 chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */
736 chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */
737 chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */
738 chip->write(chip->opaque, 1, 0x1f); /* Input X End Position */
739 chip->write(chip->opaque, 1, 0x03); /* Input X End Position */
740 chip->write(chip->opaque, 1, 0xdf); /* Input Y End Position */
741 chip->write(chip->opaque, 1, 0x01); /* Input Y End Position */
742 chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */
743 chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */
744 chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */
745 chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */
746 chip->write(chip->opaque, 1, 0x1f); /* Output X End Position */
747 chip->write(chip->opaque, 1, 0x03); /* Output X End Position */
748 chip->write(chip->opaque, 1, 0xdf); /* Output Y End Position */
749 chip->write(chip->opaque, 1, 0x01); /* Output Y End Position */
750 chip->write(chip->opaque, 1, 0x01); /* Input Data Format */
751 chip->write(chip->opaque, 1, 0x01); /* Data Source Select */
752
7267c094 753 fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
7e7c5e4c
AZ
754 /* Display Memory Data Port */
755 chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
7267c094 756 g_free(fb_blank);
7e7c5e4c
AZ
757}
758
3023f332 759static void n8x0_dss_setup(struct n800_s *s)
7e7c5e4c 760{
b9d38e95 761 s->blizzard.opaque = s1d13745_init(NULL);
7e7c5e4c
AZ
762 s->blizzard.block = s1d13745_write_block;
763 s->blizzard.write = s1d13745_write;
764 s->blizzard.read = s1d13745_read;
765
518ec134 766 omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
7e7c5e4c
AZ
767}
768
e927bb00 769static void n8x0_cbus_setup(struct n800_s *s)
7e7c5e4c 770{
518ec134
AF
771 qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
772 qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
773 qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
7e7c5e4c 774
bc24a225 775 CBus *cbus = cbus_init(dat_out);
7e7c5e4c 776
518ec134
AF
777 qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
778 qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
779 qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
7e7c5e4c
AZ
780
781 cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
782 cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
783}
784
58a26b47
AZ
785static void n8x0_uart_setup(struct n800_s *s)
786{
787 CharDriverState *radio = uart_hci_init(
518ec134 788 qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
58a26b47 789
518ec134 790 qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
58a26b47 791 csrhci_pins_get(radio)[csrhci_pin_reset]);
518ec134 792 qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
58a26b47
AZ
793 csrhci_pins_get(radio)[csrhci_pin_wakeup]);
794
518ec134 795 omap_uart_attach(s->mpu->uart[BT_UART], radio);
58a26b47
AZ
796}
797
e927bb00 798static void n8x0_usb_setup(struct n800_s *s)
942ac052 799{
bdc76462
PM
800 SysBusDevice *dev;
801 s->usb = qdev_create(NULL, "tusb6010");
1356b98d 802 dev = SYS_BUS_DEVICE(s->usb);
bdc76462
PM
803 qdev_init_nofail(s->usb);
804 sysbus_connect_irq(dev, 0,
518ec134 805 qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
942ac052 806 /* Using the NOR interface */
518ec134 807 omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
bdc76462 808 sysbus_mmio_get_region(dev, 0));
518ec134 809 omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
bdc76462 810 sysbus_mmio_get_region(dev, 1));
518ec134 811 qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
bdc76462 812 qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
942ac052
AZ
813}
814
d238db7f
AZ
815/* Setup done before the main bootloader starts by some early setup code
816 * - used when we want to run the main bootloader in emulation. This
817 * isn't documented. */
818static uint32_t n800_pinout[104] = {
819 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
820 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
821 0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
822 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
823 0x01241800, 0x18181818, 0x000000f0, 0x01300000,
824 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
825 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
826 0x007c0000, 0x00000000, 0x00000088, 0x00840000,
827 0x00000000, 0x00000094, 0x00980300, 0x0f180003,
828 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
829 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
830 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
831 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
832 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
833 0x00000000, 0x00000038, 0x00340000, 0x00000000,
834 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
835 0x005c0808, 0x08080808, 0x08080058, 0x00540808,
836 0x08080808, 0x0808006c, 0x00680808, 0x08080808,
837 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
838 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
839 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
840 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
841 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
842 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
843 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
844 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
845};
846
847static void n800_setup_nolo_tags(void *sram_base)
848{
849 int i;
850 uint32_t *p = sram_base + 0x8000;
851 uint32_t *v = sram_base + 0xa000;
852
853 memset(p, 0, 0x3000);
854
855 strcpy((void *) (p + 0), "QEMU N800");
856
857 strcpy((void *) (p + 8), "F5");
858
0983979b 859 stl_p(p + 10, 0x04f70000);
d238db7f
AZ
860 strcpy((void *) (p + 9), "RX-34");
861
862 /* RAM size in MB? */
0983979b 863 stl_p(p + 12, 0x80);
d238db7f
AZ
864
865 /* Pointer to the list of tags */
0983979b 866 stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
d238db7f
AZ
867
868 /* The NOLO tags start here */
869 p = sram_base + 0x9000;
870#define ADD_TAG(tag, len) \
0983979b
PB
871 stw_p((uint16_t *) p + 0, tag); \
872 stw_p((uint16_t *) p + 1, len); p++; \
873 stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
d238db7f
AZ
874
875 /* OMAP STI console? Pin out settings? */
876 ADD_TAG(0x6e01, 414);
fddbd80c 877 for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
0983979b 878 stl_p(v++, n800_pinout[i]);
fddbd80c 879 }
d238db7f
AZ
880
881 /* Kernel memsize? */
882 ADD_TAG(0x6e05, 1);
0983979b 883 stl_p(v++, 2);
d238db7f
AZ
884
885 /* NOLO serial console */
886 ADD_TAG(0x6e02, 4);
0983979b 887 stl_p(v++, XLDR_LL_UART); /* UART number (1 - 3) */
d238db7f
AZ
888
889#if 0
890 /* CBUS settings (Retu/AVilma) */
891 ADD_TAG(0x6e03, 6);
0983979b
PB
892 stw_p((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
893 stw_p((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
894 stw_p((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
d238db7f
AZ
895 v += 2;
896#endif
897
898 /* Nokia ASIC BB5 (Retu/Tahvo) */
899 ADD_TAG(0x6e0a, 4);
0983979b
PB
900 stw_p((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
901 stw_p((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
fddbd80c 902 v++;
d238db7f
AZ
903
904 /* LCD console? */
905 ADD_TAG(0x6e04, 4);
0983979b
PB
906 stw_p((uint16_t *) v + 0, 30); /* ??? */
907 stw_p((uint16_t *) v + 1, 24); /* ??? */
fddbd80c 908 v++;
d238db7f
AZ
909
910#if 0
911 /* LCD settings */
912 ADD_TAG(0x6e06, 2);
0983979b 913 stw_p((uint16_t *) (v++), 15); /* ??? */
d238db7f
AZ
914#endif
915
916 /* I^2C (Menelaus) */
917 ADD_TAG(0x6e07, 4);
0983979b 918 stl_p(v++, 0x00720000); /* ??? */
d238db7f
AZ
919
920 /* Unknown */
921 ADD_TAG(0x6e0b, 6);
0983979b
PB
922 stw_p((uint16_t *) v + 0, 94); /* ??? */
923 stw_p((uint16_t *) v + 1, 23); /* ??? */
924 stw_p((uint16_t *) v + 2, 0); /* ??? */
d238db7f
AZ
925 v += 2;
926
927 /* OMAP gpio switch info */
928 ADD_TAG(0x6e0c, 80);
929 strcpy((void *) v, "bat_cover"); v += 3;
0983979b
PB
930 stw_p((uint16_t *) v + 0, 110); /* GPIO num ??? */
931 stw_p((uint16_t *) v + 1, 1); /* GPIO num ??? */
d238db7f
AZ
932 v += 2;
933 strcpy((void *) v, "cam_act"); v += 3;
0983979b
PB
934 stw_p((uint16_t *) v + 0, 95); /* GPIO num ??? */
935 stw_p((uint16_t *) v + 1, 32); /* GPIO num ??? */
d238db7f
AZ
936 v += 2;
937 strcpy((void *) v, "cam_turn"); v += 3;
0983979b
PB
938 stw_p((uint16_t *) v + 0, 12); /* GPIO num ??? */
939 stw_p((uint16_t *) v + 1, 33); /* GPIO num ??? */
d238db7f
AZ
940 v += 2;
941 strcpy((void *) v, "headphone"); v += 3;
0983979b
PB
942 stw_p((uint16_t *) v + 0, 107); /* GPIO num ??? */
943 stw_p((uint16_t *) v + 1, 17); /* GPIO num ??? */
d238db7f
AZ
944 v += 2;
945
946 /* Bluetooth */
947 ADD_TAG(0x6e0e, 12);
0983979b
PB
948 stl_p(v++, 0x5c623d01); /* ??? */
949 stl_p(v++, 0x00000201); /* ??? */
950 stl_p(v++, 0x00000000); /* ??? */
d238db7f
AZ
951
952 /* CX3110x WLAN settings */
953 ADD_TAG(0x6e0f, 8);
0983979b
PB
954 stl_p(v++, 0x00610025); /* ??? */
955 stl_p(v++, 0xffff0057); /* ??? */
d238db7f
AZ
956
957 /* MMC host settings */
958 ADD_TAG(0x6e10, 12);
0983979b
PB
959 stl_p(v++, 0xffff000f); /* ??? */
960 stl_p(v++, 0xffffffff); /* ??? */
961 stl_p(v++, 0x00000060); /* ??? */
d238db7f
AZ
962
963 /* OneNAND chip select */
964 ADD_TAG(0x6e11, 10);
0983979b
PB
965 stl_p(v++, 0x00000401); /* ??? */
966 stl_p(v++, 0x0002003a); /* ??? */
967 stl_p(v++, 0x00000002); /* ??? */
d238db7f
AZ
968
969 /* TEA5761 sensor settings */
970 ADD_TAG(0x6e12, 2);
0983979b 971 stl_p(v++, 93); /* GPIO num ??? */
d238db7f
AZ
972
973#if 0
974 /* Unknown tag */
975 ADD_TAG(6e09, 0);
976
977 /* Kernel UART / console */
978 ADD_TAG(6e12, 0);
979#endif
980
981 /* End of the list */
0983979b
PB
982 stl_p(p++, 0x00000000);
983 stl_p(p++, 0x00000000);
d238db7f
AZ
984}
985
7e7c5e4c
AZ
986/* This task is normally performed by the bootloader. If we're loading
987 * a kernel directly, we need to set up GPMC mappings ourselves. */
988static void n800_gpmc_init(struct n800_s *s)
989{
990 uint32_t config7 =
991 (0xf << 8) | /* MASKADDRESS */
992 (1 << 6) | /* CSVALID */
993 (4 << 0); /* BASEADDRESS */
994
995 cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */
e1fe50dc 996 &config7, sizeof(config7));
7e7c5e4c
AZ
997}
998
999/* Setup sequence done by the bootloader */
e927bb00 1000static void n8x0_boot_init(void *opaque)
7e7c5e4c
AZ
1001{
1002 struct n800_s *s = (struct n800_s *) opaque;
1003 uint32_t buf;
1004
1005 /* PRCM setup */
1006#define omap_writel(addr, val) \
1007 buf = (val); \
e1fe50dc 1008 cpu_physical_memory_write(addr, &buf, sizeof(buf))
7e7c5e4c
AZ
1009
1010 omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */
1011 omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */
1012 omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */
1013 omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */
1014 omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */
1015 omap_writel(0x48008098, 0); /* PRCM_POLCTRL */
1016 omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */
1017 omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */
1018 omap_writel(0x48008158, 1); /* RM_RSTST_MPU */
1019 omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */
1020 omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */
1021 omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */
1022 omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */
1023 omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */
1024 omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */
1025 omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */
1026 omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */
1027 omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */
1028 omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */
1029 omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */
1030 omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */
1031 omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */
1032 omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */
1033 omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */
1034 omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */
1035 omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */
1036 omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */
1037 omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */
1038 omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */
1039 omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */
1040 omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */
1041 omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */
1042 omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */
1043 omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */
1044 omap_writel(0x48008540, /* CM_CLKSEL1_PLL */
1045 (0x78 << 12) | (6 << 8));
1046 omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */
1047
1048 /* GPMC setup */
1049 n800_gpmc_init(s);
1050
1051 /* Video setup */
1052 n800_dss_init(&s->blizzard);
1053
1054 /* CPU setup */
518ec134 1055 s->mpu->cpu->env.GE = 0x5;
0941041e
AZ
1056
1057 /* If the machine has a slided keyboard, open it */
fddbd80c 1058 if (s->kbd) {
518ec134 1059 qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
fddbd80c 1060 }
7e7c5e4c
AZ
1061}
1062
1063#define OMAP_TAG_NOKIA_BT 0x4e01
1064#define OMAP_TAG_WLAN_CX3110X 0x4e02
1065#define OMAP_TAG_CBUS 0x4e03
1066#define OMAP_TAG_EM_ASIC_BB5 0x4e04
1067
e927bb00
AZ
1068static struct omap_gpiosw_info_s {
1069 const char *name;
1070 int line;
1071 int type;
1072} n800_gpiosw_info[] = {
1073 {
1074 "bat_cover", N800_BAT_COVER_GPIO,
1075 OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
1076 }, {
1077 "cam_act", N800_CAM_ACT_GPIO,
1078 OMAP_GPIOSW_TYPE_ACTIVITY,
1079 }, {
1080 "cam_turn", N800_CAM_TURN_GPIO,
1081 OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
1082 }, {
1083 "headphone", N8X0_HEADPHONE_GPIO,
1084 OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
1085 },
b9d38e95 1086 { NULL }
e927bb00
AZ
1087}, n810_gpiosw_info[] = {
1088 {
1089 "gps_reset", N810_GPS_RESET_GPIO,
1090 OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
1091 }, {
1092 "gps_wakeup", N810_GPS_WAKEUP_GPIO,
1093 OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
1094 }, {
1095 "headphone", N8X0_HEADPHONE_GPIO,
1096 OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
1097 }, {
1098 "kb_lock", N810_KB_LOCK_GPIO,
1099 OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
1100 }, {
1101 "sleepx_led", N810_SLEEPX_LED_GPIO,
1102 OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
1103 }, {
1104 "slide", N810_SLIDE_GPIO,
1105 OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
1106 },
b9d38e95 1107 { NULL }
e927bb00
AZ
1108};
1109
1110static struct omap_partition_info_s {
1111 uint32_t offset;
1112 uint32_t size;
1113 int mask;
1114 const char *name;
1115} n800_part_info[] = {
1116 { 0x00000000, 0x00020000, 0x3, "bootloader" },
1117 { 0x00020000, 0x00060000, 0x0, "config" },
1118 { 0x00080000, 0x00200000, 0x0, "kernel" },
1119 { 0x00280000, 0x00200000, 0x3, "initfs" },
1120 { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
1121
b9d38e95 1122 { 0, 0, 0, NULL }
e927bb00
AZ
1123}, n810_part_info[] = {
1124 { 0x00000000, 0x00020000, 0x3, "bootloader" },
1125 { 0x00020000, 0x00060000, 0x0, "config" },
1126 { 0x00080000, 0x00220000, 0x0, "kernel" },
1127 { 0x002a0000, 0x00400000, 0x0, "initfs" },
1128 { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
1129
b9d38e95 1130 { 0, 0, 0, NULL }
e927bb00
AZ
1131};
1132
c227f099 1133static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
c580d92b 1134
e927bb00 1135static int n8x0_atag_setup(void *p, int model)
7e7c5e4c
AZ
1136{
1137 uint8_t *b;
1138 uint16_t *w;
1139 uint32_t *l;
e927bb00
AZ
1140 struct omap_gpiosw_info_s *gpiosw;
1141 struct omap_partition_info_s *partition;
1142 const char *tag;
7e7c5e4c
AZ
1143
1144 w = p;
1145
0983979b
PB
1146 stw_p(w++, OMAP_TAG_UART); /* u16 tag */
1147 stw_p(w++, 4); /* u16 len */
1148 stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
fddbd80c 1149 w++;
7e7c5e4c 1150
e927bb00 1151#if 0
0983979b
PB
1152 stw_p(w++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
1153 stw_p(w++, 4); /* u16 len */
1154 stw_p(w++, XLDR_LL_UART + 1); /* u8 console_uart */
1155 stw_p(w++, 115200); /* u32 console_speed */
e927bb00
AZ
1156#endif
1157
0983979b
PB
1158 stw_p(w++, OMAP_TAG_LCD); /* u16 tag */
1159 stw_p(w++, 36); /* u16 len */
e927bb00
AZ
1160 strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */
1161 w += 8;
1162 strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */
1163 w += 8;
0983979b
PB
1164 stw_p(w++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
1165 stw_p(w++, 24); /* u8 data_lines */
1166
1167 stw_p(w++, OMAP_TAG_CBUS); /* u16 tag */
1168 stw_p(w++, 8); /* u16 len */
1169 stw_p(w++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
1170 stw_p(w++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
1171 stw_p(w++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
fddbd80c 1172 w++;
7e7c5e4c 1173
0983979b
PB
1174 stw_p(w++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
1175 stw_p(w++, 4); /* u16 len */
1176 stw_p(w++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
1177 stw_p(w++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
e927bb00
AZ
1178
1179 gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
fddbd80c 1180 for (; gpiosw->name; gpiosw++) {
0983979b
PB
1181 stw_p(w++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
1182 stw_p(w++, 20); /* u16 len */
e927bb00
AZ
1183 strcpy((void *) w, gpiosw->name); /* char name[12] */
1184 w += 6;
0983979b
PB
1185 stw_p(w++, gpiosw->line); /* u16 gpio */
1186 stw_p(w++, gpiosw->type);
1187 stw_p(w++, 0);
1188 stw_p(w++, 0);
e927bb00 1189 }
7e7c5e4c 1190
0983979b
PB
1191 stw_p(w++, OMAP_TAG_NOKIA_BT); /* u16 tag */
1192 stw_p(w++, 12); /* u16 len */
7e7c5e4c 1193 b = (void *) w;
0983979b
PB
1194 stb_p(b++, 0x01); /* u8 chip_type (CSR) */
1195 stb_p(b++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
1196 stb_p(b++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
1197 stb_p(b++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
1198 stb_p(b++, BT_UART + 1); /* u8 bt_uart */
c580d92b 1199 memcpy(b, &n8x0_bd_addr, 6); /* u8 bd_addr[6] */
7e7c5e4c 1200 b += 6;
0983979b 1201 stb_p(b++, 0x02); /* u8 bt_sysclk (38.4) */
7e7c5e4c
AZ
1202 w = (void *) b;
1203
0983979b
PB
1204 stw_p(w++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
1205 stw_p(w++, 8); /* u16 len */
1206 stw_p(w++, 0x25); /* u8 chip_type */
1207 stw_p(w++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
1208 stw_p(w++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
1209 stw_p(w++, -1); /* s16 spi_cs_gpio */
7e7c5e4c 1210
0983979b
PB
1211 stw_p(w++, OMAP_TAG_MMC); /* u16 tag */
1212 stw_p(w++, 16); /* u16 len */
e927bb00 1213 if (model == 810) {
0983979b
PB
1214 stw_p(w++, 0x23f); /* unsigned flags */
1215 stw_p(w++, -1); /* s16 power_pin */
1216 stw_p(w++, -1); /* s16 switch_pin */
1217 stw_p(w++, -1); /* s16 wp_pin */
1218 stw_p(w++, 0x240); /* unsigned flags */
1219 stw_p(w++, 0xc000); /* s16 power_pin */
1220 stw_p(w++, 0x0248); /* s16 switch_pin */
1221 stw_p(w++, 0xc000); /* s16 wp_pin */
e927bb00 1222 } else {
0983979b
PB
1223 stw_p(w++, 0xf); /* unsigned flags */
1224 stw_p(w++, -1); /* s16 power_pin */
1225 stw_p(w++, -1); /* s16 switch_pin */
1226 stw_p(w++, -1); /* s16 wp_pin */
1227 stw_p(w++, 0); /* unsigned flags */
1228 stw_p(w++, 0); /* s16 power_pin */
1229 stw_p(w++, 0); /* s16 switch_pin */
1230 stw_p(w++, 0); /* s16 wp_pin */
e927bb00 1231 }
7e7c5e4c 1232
0983979b
PB
1233 stw_p(w++, OMAP_TAG_TEA5761); /* u16 tag */
1234 stw_p(w++, 4); /* u16 len */
1235 stw_p(w++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
fddbd80c 1236 w++;
7e7c5e4c 1237
e927bb00 1238 partition = (model == 810) ? n810_part_info : n800_part_info;
fddbd80c 1239 for (; partition->name; partition++) {
0983979b
PB
1240 stw_p(w++, OMAP_TAG_PARTITION); /* u16 tag */
1241 stw_p(w++, 28); /* u16 len */
e927bb00
AZ
1242 strcpy((void *) w, partition->name); /* char name[16] */
1243 l = (void *) (w + 8);
0983979b
PB
1244 stl_p(l++, partition->size); /* unsigned int size */
1245 stl_p(l++, partition->offset); /* unsigned int offset */
1246 stl_p(l++, partition->mask); /* unsigned int mask_flags */
e927bb00
AZ
1247 w = (void *) l;
1248 }
7e7c5e4c 1249
0983979b
PB
1250 stw_p(w++, OMAP_TAG_BOOT_REASON); /* u16 tag */
1251 stw_p(w++, 12); /* u16 len */
7e7c5e4c
AZ
1252#if 0
1253 strcpy((void *) w, "por"); /* char reason_str[12] */
1254 strcpy((void *) w, "charger"); /* char reason_str[12] */
1255 strcpy((void *) w, "32wd_to"); /* char reason_str[12] */
1256 strcpy((void *) w, "sw_rst"); /* char reason_str[12] */
1257 strcpy((void *) w, "mbus"); /* char reason_str[12] */
1258 strcpy((void *) w, "unknown"); /* char reason_str[12] */
1259 strcpy((void *) w, "swdg_to"); /* char reason_str[12] */
1260 strcpy((void *) w, "sec_vio"); /* char reason_str[12] */
1261 strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
1262 strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */
1263#else
1264 strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
1265#endif
1266 w += 6;
1267
e927bb00 1268 tag = (model == 810) ? "RX-44" : "RX-34";
0983979b
PB
1269 stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
1270 stw_p(w++, 24); /* u16 len */
7e7c5e4c
AZ
1271 strcpy((void *) w, "product"); /* char component[12] */
1272 w += 6;
e927bb00 1273 strcpy((void *) w, tag); /* char version[12] */
7e7c5e4c
AZ
1274 w += 6;
1275
0983979b
PB
1276 stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
1277 stw_p(w++, 24); /* u16 len */
7e7c5e4c
AZ
1278 strcpy((void *) w, "hw-build"); /* char component[12] */
1279 w += 6;
93bfef4c 1280 strcpy((void *) w, "QEMU ");
35c2c8dc 1281 pstrcat((void *) w, 12, qemu_hw_version()); /* char version[12] */
7e7c5e4c
AZ
1282 w += 6;
1283
e927bb00 1284 tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
0983979b
PB
1285 stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
1286 stw_p(w++, 24); /* u16 len */
7e7c5e4c
AZ
1287 strcpy((void *) w, "nolo"); /* char component[12] */
1288 w += 6;
e927bb00 1289 strcpy((void *) w, tag); /* char version[12] */
7e7c5e4c 1290 w += 6;
7e7c5e4c
AZ
1291
1292 return (void *) w - p;
1293}
1294
462a8bc6 1295static int n800_atag_setup(const struct arm_boot_info *info, void *p)
e927bb00
AZ
1296{
1297 return n8x0_atag_setup(p, 800);
1298}
7e7c5e4c 1299
462a8bc6 1300static int n810_atag_setup(const struct arm_boot_info *info, void *p)
e927bb00
AZ
1301{
1302 return n8x0_atag_setup(p, 810);
1303}
1304
3ef96221 1305static void n8x0_init(MachineState *machine,
462b69bb 1306 struct arm_boot_info *binfo, int model)
7e7c5e4c 1307{
aee39503 1308 MemoryRegion *sysmem = get_system_memory();
7267c094 1309 struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
e927bb00 1310 int sdram_size = binfo->ram_size;
7e7c5e4c 1311
3ef96221 1312 s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_model);
7e7c5e4c 1313
0941041e
AZ
1314 /* Setup peripherals
1315 *
1316 * Believed external peripherals layout in the N810:
1317 * (spi bus 1)
1318 * tsc2005
1319 * lcd_mipid
1320 * (spi bus 2)
1321 * Conexant cx3110x (WLAN)
1322 * optional: pc2400m (WiMAX)
1323 * (i2c bus 0)
1324 * TLV320AIC33 (audio codec)
1325 * TCM825x (camera by Toshiba)
1326 * lp5521 (clever LEDs)
1327 * tsl2563 (light sensor, hwmon, model 7, rev. 0)
1328 * lm8323 (keypad, manf 00, rev 04)
1329 * (i2c bus 1)
1330 * tmp105 (temperature sensor, hwmon)
1331 * menelaus (pm)
d238db7f
AZ
1332 * (somewhere on i2c - maybe N800-only)
1333 * tea5761 (FM tuner)
1334 * (serial 0)
1335 * GPS
1336 * (some serial port)
1337 * csr41814 (Bluetooth)
0941041e 1338 */
e927bb00 1339 n8x0_gpio_setup(s);
7e7c5e4c 1340 n8x0_nand_setup(s);
e927bb00 1341 n8x0_i2c_setup(s);
fddbd80c 1342 if (model == 800) {
e927bb00 1343 n800_tsc_kbd_setup(s);
fddbd80c 1344 } else if (model == 810) {
e927bb00 1345 n810_tsc_setup(s);
1d4e547b
AZ
1346 n810_kbd_setup(s);
1347 }
e927bb00 1348 n8x0_spi_setup(s);
3023f332 1349 n8x0_dss_setup(s);
e927bb00 1350 n8x0_cbus_setup(s);
58a26b47 1351 n8x0_uart_setup(s);
de77a243 1352 if (usb_enabled()) {
e927bb00 1353 n8x0_usb_setup(s);
094b287f 1354 }
7e7c5e4c 1355
3ef96221 1356 if (machine->kernel_filename) {
7e7c5e4c 1357 /* Or at the linux loader. */
3ef96221
MA
1358 binfo->kernel_filename = machine->kernel_filename;
1359 binfo->kernel_cmdline = machine->kernel_cmdline;
1360 binfo->initrd_filename = machine->initrd_filename;
3aaa8dfa 1361 arm_load_kernel(s->mpu->cpu, binfo);
7e7c5e4c 1362
a08d4367 1363 qemu_register_reset(n8x0_boot_init, s);
7e7c5e4c
AZ
1364 }
1365
462b69bb 1366 if (option_rom[0].name &&
3ef96221 1367 (machine->boot_order[0] == 'n' || !machine->kernel_filename)) {
0b062eb0 1368 uint8_t *nolo_tags = g_new(uint8_t, 0x10000);
d238db7f 1369 /* No, wait, better start at the ROM. */
518ec134 1370 s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
d238db7f
AZ
1371
1372 /* This is intended for loading the `secondary.bin' program from
1373 * Nokia images (the NOLO bootloader). The entry point seems
1374 * to be at OMAP2_Q2_BASE + 0x400000.
1375 *
1376 * The `2nd.bin' files contain some kind of earlier boot code and
1377 * for them the entry point needs to be set to OMAP2_SRAM_BASE.
1378 *
1379 * The code above is for loading the `zImage' file from Nokia
1380 * images. */
591f73f6
PM
1381 load_image_targphys(option_rom[0].name,
1382 OMAP2_Q2_BASE + 0x400000,
1383 sdram_size - 0x400000);
d238db7f 1384
5c130f65
PB
1385 n800_setup_nolo_tags(nolo_tags);
1386 cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
0b062eb0 1387 g_free(nolo_tags);
d238db7f 1388 }
7e7c5e4c
AZ
1389}
1390
e927bb00
AZ
1391static struct arm_boot_info n800_binfo = {
1392 .loader_start = OMAP2_Q2_BASE,
1393 /* Actually two chips of 0x4000000 bytes each */
1394 .ram_size = 0x08000000,
1395 .board_id = 0x4f7,
1396 .atag_board = n800_atag_setup,
1397};
1398
1399static struct arm_boot_info n810_binfo = {
1400 .loader_start = OMAP2_Q2_BASE,
1401 /* Actually two chips of 0x4000000 bytes each */
1402 .ram_size = 0x08000000,
1403 /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
1404 * used by some older versions of the bootloader and 5555 is used
1405 * instead (including versions that shipped with many devices). */
1406 .board_id = 0x60c,
1407 .atag_board = n810_atag_setup,
1408};
1409
3ef96221 1410static void n800_init(MachineState *machine)
e927bb00 1411{
30d76f13 1412 n8x0_init(machine, &n800_binfo, 800);
e927bb00
AZ
1413}
1414
3ef96221 1415static void n810_init(MachineState *machine)
e927bb00 1416{
30d76f13 1417 n8x0_init(machine, &n810_binfo, 810);
e927bb00
AZ
1418}
1419
8a661aea 1420static void n800_class_init(ObjectClass *oc, void *data)
e264d29d 1421{
8a661aea
AF
1422 MachineClass *mc = MACHINE_CLASS(oc);
1423
e264d29d
EH
1424 mc->desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)";
1425 mc->init = n800_init;
1426 mc->default_boot_order = "";
1427}
e927bb00 1428
8a661aea
AF
1429static const TypeInfo n800_type = {
1430 .name = MACHINE_TYPE_NAME("n800"),
1431 .parent = TYPE_MACHINE,
1432 .class_init = n800_class_init,
1433};
f80f9ec9 1434
8a661aea 1435static void n810_class_init(ObjectClass *oc, void *data)
f80f9ec9 1436{
8a661aea
AF
1437 MachineClass *mc = MACHINE_CLASS(oc);
1438
e264d29d
EH
1439 mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)";
1440 mc->init = n810_init;
1441 mc->default_boot_order = "";
f80f9ec9
AL
1442}
1443
8a661aea
AF
1444static const TypeInfo n810_type = {
1445 .name = MACHINE_TYPE_NAME("n810"),
1446 .parent = TYPE_MACHINE,
1447 .class_init = n810_class_init,
1448};
1449
1450static void nseries_machine_init(void)
1451{
1452 type_register_static(&n800_type);
1453 type_register_static(&n810_type);
1454}
1455
0e6aac87 1456type_init(nseries_machine_init)