xref: /openbmc/qemu/hw/arm/nseries.c (revision 3ef96221)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * Nokia N-series internet tablets.
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (C) 2007 Nokia Corporation
553018216SPaolo Bonzini  * Written by Andrzej Zaborowski <andrew@openedhand.com>
653018216SPaolo Bonzini  *
753018216SPaolo Bonzini  * This program is free software; you can redistribute it and/or
853018216SPaolo Bonzini  * modify it under the terms of the GNU General Public License as
953018216SPaolo Bonzini  * published by the Free Software Foundation; either version 2 or
1053018216SPaolo Bonzini  * (at your option) version 3 of the License.
1153018216SPaolo Bonzini  *
1253018216SPaolo Bonzini  * This program is distributed in the hope that it will be useful,
1353018216SPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1453018216SPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1553018216SPaolo Bonzini  * GNU General Public License for more details.
1653018216SPaolo Bonzini  *
1753018216SPaolo Bonzini  * You should have received a copy of the GNU General Public License along
1853018216SPaolo Bonzini  * with this program; if not, see <http://www.gnu.org/licenses/>.
1953018216SPaolo Bonzini  */
2053018216SPaolo Bonzini 
2153018216SPaolo Bonzini #include "qemu-common.h"
2253018216SPaolo Bonzini #include "sysemu/sysemu.h"
230d09e41aSPaolo Bonzini #include "hw/arm/omap.h"
24bd2be150SPeter Maydell #include "hw/arm/arm.h"
2553018216SPaolo Bonzini #include "hw/irq.h"
2653018216SPaolo Bonzini #include "ui/console.h"
2753018216SPaolo Bonzini #include "hw/boards.h"
280d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h"
29bd2be150SPeter Maydell #include "hw/devices.h"
300d09e41aSPaolo Bonzini #include "hw/block/flash.h"
3153018216SPaolo Bonzini #include "hw/hw.h"
3253018216SPaolo Bonzini #include "hw/bt.h"
3353018216SPaolo Bonzini #include "hw/loader.h"
3453018216SPaolo Bonzini #include "sysemu/blockdev.h"
3553018216SPaolo Bonzini #include "hw/sysbus.h"
3653018216SPaolo Bonzini #include "exec/address-spaces.h"
3753018216SPaolo Bonzini 
3853018216SPaolo Bonzini /* Nokia N8x0 support */
3953018216SPaolo Bonzini struct n800_s {
4053018216SPaolo Bonzini     struct omap_mpu_state_s *mpu;
4153018216SPaolo Bonzini 
4253018216SPaolo Bonzini     struct rfbi_chip_s blizzard;
4353018216SPaolo Bonzini     struct {
4453018216SPaolo Bonzini         void *opaque;
4553018216SPaolo Bonzini         uint32_t (*txrx)(void *opaque, uint32_t value, int len);
4653018216SPaolo Bonzini         uWireSlave *chip;
4753018216SPaolo Bonzini     } ts;
4853018216SPaolo Bonzini 
4953018216SPaolo Bonzini     int keymap[0x80];
5053018216SPaolo Bonzini     DeviceState *kbd;
5153018216SPaolo Bonzini 
5253018216SPaolo Bonzini     DeviceState *usb;
5353018216SPaolo Bonzini     void *retu;
5453018216SPaolo Bonzini     void *tahvo;
5553018216SPaolo Bonzini     DeviceState *nand;
5653018216SPaolo Bonzini };
5753018216SPaolo Bonzini 
5853018216SPaolo Bonzini /* GPIO pins */
5953018216SPaolo Bonzini #define N8X0_TUSB_ENABLE_GPIO		0
6053018216SPaolo Bonzini #define N800_MMC2_WP_GPIO		8
6153018216SPaolo Bonzini #define N800_UNKNOWN_GPIO0		9	/* out */
6253018216SPaolo Bonzini #define N810_MMC2_VIOSD_GPIO		9
6353018216SPaolo Bonzini #define N810_HEADSET_AMP_GPIO		10
6453018216SPaolo Bonzini #define N800_CAM_TURN_GPIO		12
6553018216SPaolo Bonzini #define N810_GPS_RESET_GPIO		12
6653018216SPaolo Bonzini #define N800_BLIZZARD_POWERDOWN_GPIO	15
6753018216SPaolo Bonzini #define N800_MMC1_WP_GPIO		23
6853018216SPaolo Bonzini #define N810_MMC2_VSD_GPIO		23
6953018216SPaolo Bonzini #define N8X0_ONENAND_GPIO		26
7053018216SPaolo Bonzini #define N810_BLIZZARD_RESET_GPIO	30
7153018216SPaolo Bonzini #define N800_UNKNOWN_GPIO2		53	/* out */
7253018216SPaolo Bonzini #define N8X0_TUSB_INT_GPIO		58
7353018216SPaolo Bonzini #define N8X0_BT_WKUP_GPIO		61
7453018216SPaolo Bonzini #define N8X0_STI_GPIO			62
7553018216SPaolo Bonzini #define N8X0_CBUS_SEL_GPIO		64
7653018216SPaolo Bonzini #define N8X0_CBUS_DAT_GPIO		65
7753018216SPaolo Bonzini #define N8X0_CBUS_CLK_GPIO		66
7853018216SPaolo Bonzini #define N8X0_WLAN_IRQ_GPIO		87
7953018216SPaolo Bonzini #define N8X0_BT_RESET_GPIO		92
8053018216SPaolo Bonzini #define N8X0_TEA5761_CS_GPIO		93
8153018216SPaolo Bonzini #define N800_UNKNOWN_GPIO		94
8253018216SPaolo Bonzini #define N810_TSC_RESET_GPIO		94
8353018216SPaolo Bonzini #define N800_CAM_ACT_GPIO		95
8453018216SPaolo Bonzini #define N810_GPS_WAKEUP_GPIO		95
8553018216SPaolo Bonzini #define N8X0_MMC_CS_GPIO		96
8653018216SPaolo Bonzini #define N8X0_WLAN_PWR_GPIO		97
8753018216SPaolo Bonzini #define N8X0_BT_HOST_WKUP_GPIO		98
8853018216SPaolo Bonzini #define N810_SPEAKER_AMP_GPIO		101
8953018216SPaolo Bonzini #define N810_KB_LOCK_GPIO		102
9053018216SPaolo Bonzini #define N800_TSC_TS_GPIO		103
9153018216SPaolo Bonzini #define N810_TSC_TS_GPIO		106
9253018216SPaolo Bonzini #define N8X0_HEADPHONE_GPIO		107
9353018216SPaolo Bonzini #define N8X0_RETU_GPIO			108
9453018216SPaolo Bonzini #define N800_TSC_KP_IRQ_GPIO		109
9553018216SPaolo Bonzini #define N810_KEYBOARD_GPIO		109
9653018216SPaolo Bonzini #define N800_BAT_COVER_GPIO		110
9753018216SPaolo Bonzini #define N810_SLIDE_GPIO			110
9853018216SPaolo Bonzini #define N8X0_TAHVO_GPIO			111
9953018216SPaolo Bonzini #define N800_UNKNOWN_GPIO4		112	/* out */
10053018216SPaolo Bonzini #define N810_SLEEPX_LED_GPIO		112
10153018216SPaolo Bonzini #define N800_TSC_RESET_GPIO		118	/* ? */
10253018216SPaolo Bonzini #define N810_AIC33_RESET_GPIO		118
10353018216SPaolo Bonzini #define N800_TSC_UNKNOWN_GPIO		119	/* out */
10453018216SPaolo Bonzini #define N8X0_TMP105_GPIO		125
10553018216SPaolo Bonzini 
10653018216SPaolo Bonzini /* Config */
10753018216SPaolo Bonzini #define BT_UART				0
10853018216SPaolo Bonzini #define XLDR_LL_UART			1
10953018216SPaolo Bonzini 
11053018216SPaolo Bonzini /* Addresses on the I2C bus 0 */
11153018216SPaolo Bonzini #define N810_TLV320AIC33_ADDR		0x18	/* Audio CODEC */
11253018216SPaolo Bonzini #define N8X0_TCM825x_ADDR		0x29	/* Camera */
11353018216SPaolo Bonzini #define N810_LP5521_ADDR		0x32	/* LEDs */
11453018216SPaolo Bonzini #define N810_TSL2563_ADDR		0x3d	/* Light sensor */
11553018216SPaolo Bonzini #define N810_LM8323_ADDR		0x45	/* Keyboard */
11653018216SPaolo Bonzini /* Addresses on the I2C bus 1 */
11753018216SPaolo Bonzini #define N8X0_TMP105_ADDR		0x48	/* Temperature sensor */
11853018216SPaolo Bonzini #define N8X0_MENELAUS_ADDR		0x72	/* Power management */
11953018216SPaolo Bonzini 
12053018216SPaolo Bonzini /* Chipselects on GPMC NOR interface */
12153018216SPaolo Bonzini #define N8X0_ONENAND_CS			0
12253018216SPaolo Bonzini #define N8X0_USB_ASYNC_CS		1
12353018216SPaolo Bonzini #define N8X0_USB_SYNC_CS		4
12453018216SPaolo Bonzini 
12553018216SPaolo Bonzini #define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
12653018216SPaolo Bonzini 
12753018216SPaolo Bonzini static void n800_mmc_cs_cb(void *opaque, int line, int level)
12853018216SPaolo Bonzini {
12953018216SPaolo Bonzini     /* TODO: this seems to actually be connected to the menelaus, to
13053018216SPaolo Bonzini      * which also both MMC slots connect.  */
13153018216SPaolo Bonzini     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
13253018216SPaolo Bonzini }
13353018216SPaolo Bonzini 
13453018216SPaolo Bonzini static void n8x0_gpio_setup(struct n800_s *s)
13553018216SPaolo Bonzini {
13653018216SPaolo Bonzini     qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
13753018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
13853018216SPaolo Bonzini 
13953018216SPaolo Bonzini     qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
14053018216SPaolo Bonzini }
14153018216SPaolo Bonzini 
14253018216SPaolo Bonzini #define MAEMO_CAL_HEADER(...)				\
14353018216SPaolo Bonzini     'C',  'o',  'n',  'F',  0x02, 0x00, 0x04, 0x00,	\
14453018216SPaolo Bonzini     __VA_ARGS__,					\
14553018216SPaolo Bonzini     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14653018216SPaolo Bonzini 
14753018216SPaolo Bonzini static const uint8_t n8x0_cal_wlan_mac[] = {
14853018216SPaolo Bonzini     MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
14953018216SPaolo Bonzini     0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
15053018216SPaolo Bonzini     0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
15153018216SPaolo Bonzini     0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
15253018216SPaolo Bonzini     0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
15353018216SPaolo Bonzini     0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
15453018216SPaolo Bonzini };
15553018216SPaolo Bonzini 
15653018216SPaolo Bonzini static const uint8_t n8x0_cal_bt_id[] = {
15753018216SPaolo Bonzini     MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
15853018216SPaolo Bonzini     0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
15953018216SPaolo Bonzini     0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
16053018216SPaolo Bonzini     N8X0_BD_ADDR,
16153018216SPaolo Bonzini };
16253018216SPaolo Bonzini 
16353018216SPaolo Bonzini static void n8x0_nand_setup(struct n800_s *s)
16453018216SPaolo Bonzini {
16553018216SPaolo Bonzini     char *otp_region;
16653018216SPaolo Bonzini     DriveInfo *dinfo;
16753018216SPaolo Bonzini 
16853018216SPaolo Bonzini     s->nand = qdev_create(NULL, "onenand");
16953018216SPaolo Bonzini     qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
17053018216SPaolo Bonzini     /* Either 0x40 or 0x48 are OK for the device ID */
17153018216SPaolo Bonzini     qdev_prop_set_uint16(s->nand, "device_id", 0x48);
17253018216SPaolo Bonzini     qdev_prop_set_uint16(s->nand, "version_id", 0);
17353018216SPaolo Bonzini     qdev_prop_set_int32(s->nand, "shift", 1);
17453018216SPaolo Bonzini     dinfo = drive_get(IF_MTD, 0, 0);
17553018216SPaolo Bonzini     if (dinfo && dinfo->bdrv) {
17653018216SPaolo Bonzini         qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
17753018216SPaolo Bonzini     }
17853018216SPaolo Bonzini     qdev_init_nofail(s->nand);
17953018216SPaolo Bonzini     sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
18053018216SPaolo Bonzini                        qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
18153018216SPaolo Bonzini     omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
18253018216SPaolo Bonzini                      sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
18353018216SPaolo Bonzini     otp_region = onenand_raw_otp(s->nand);
18453018216SPaolo Bonzini 
18553018216SPaolo Bonzini     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
18653018216SPaolo Bonzini     memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
18753018216SPaolo Bonzini     /* XXX: in theory should also update the OOB for both pages */
18853018216SPaolo Bonzini }
18953018216SPaolo Bonzini 
19053018216SPaolo Bonzini static qemu_irq n8x0_system_powerdown;
19153018216SPaolo Bonzini 
19253018216SPaolo Bonzini static void n8x0_powerdown_req(Notifier *n, void *opaque)
19353018216SPaolo Bonzini {
19453018216SPaolo Bonzini     qemu_irq_raise(n8x0_system_powerdown);
19553018216SPaolo Bonzini }
19653018216SPaolo Bonzini 
19753018216SPaolo Bonzini static Notifier n8x0_system_powerdown_notifier = {
19853018216SPaolo Bonzini     .notify = n8x0_powerdown_req
19953018216SPaolo Bonzini };
20053018216SPaolo Bonzini 
20153018216SPaolo Bonzini static void n8x0_i2c_setup(struct n800_s *s)
20253018216SPaolo Bonzini {
20353018216SPaolo Bonzini     DeviceState *dev;
20453018216SPaolo Bonzini     qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
205a5c82852SAndreas Färber     I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
20653018216SPaolo Bonzini 
20753018216SPaolo Bonzini     /* Attach a menelaus PM chip */
20853018216SPaolo Bonzini     dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
20953018216SPaolo Bonzini     qdev_connect_gpio_out(dev, 3,
21053018216SPaolo Bonzini                           qdev_get_gpio_in(s->mpu->ih[0],
21153018216SPaolo Bonzini                                            OMAP_INT_24XX_SYS_NIRQ));
21253018216SPaolo Bonzini 
21353018216SPaolo Bonzini     n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
21453018216SPaolo Bonzini     qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
21553018216SPaolo Bonzini 
21653018216SPaolo Bonzini     /* Attach a TMP105 PM chip (A0 wired to ground) */
21753018216SPaolo Bonzini     dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
21853018216SPaolo Bonzini     qdev_connect_gpio_out(dev, 0, tmp_irq);
21953018216SPaolo Bonzini }
22053018216SPaolo Bonzini 
22153018216SPaolo Bonzini /* Touchscreen and keypad controller */
22253018216SPaolo Bonzini static MouseTransformInfo n800_pointercal = {
22353018216SPaolo Bonzini     .x = 800,
22453018216SPaolo Bonzini     .y = 480,
22553018216SPaolo Bonzini     .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
22653018216SPaolo Bonzini };
22753018216SPaolo Bonzini 
22853018216SPaolo Bonzini static MouseTransformInfo n810_pointercal = {
22953018216SPaolo Bonzini     .x = 800,
23053018216SPaolo Bonzini     .y = 480,
23153018216SPaolo Bonzini     .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
23253018216SPaolo Bonzini };
23353018216SPaolo Bonzini 
23453018216SPaolo Bonzini #define RETU_KEYCODE	61	/* F3 */
23553018216SPaolo Bonzini 
23653018216SPaolo Bonzini static void n800_key_event(void *opaque, int keycode)
23753018216SPaolo Bonzini {
23853018216SPaolo Bonzini     struct n800_s *s = (struct n800_s *) opaque;
23953018216SPaolo Bonzini     int code = s->keymap[keycode & 0x7f];
24053018216SPaolo Bonzini 
24153018216SPaolo Bonzini     if (code == -1) {
24253018216SPaolo Bonzini         if ((keycode & 0x7f) == RETU_KEYCODE)
24353018216SPaolo Bonzini             retu_key_event(s->retu, !(keycode & 0x80));
24453018216SPaolo Bonzini         return;
24553018216SPaolo Bonzini     }
24653018216SPaolo Bonzini 
24753018216SPaolo Bonzini     tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
24853018216SPaolo Bonzini }
24953018216SPaolo Bonzini 
25053018216SPaolo Bonzini static const int n800_keys[16] = {
25153018216SPaolo Bonzini     -1,
25253018216SPaolo Bonzini     72,	/* Up */
25353018216SPaolo Bonzini     63,	/* Home (F5) */
25453018216SPaolo Bonzini     -1,
25553018216SPaolo Bonzini     75,	/* Left */
25653018216SPaolo Bonzini     28,	/* Enter */
25753018216SPaolo Bonzini     77,	/* Right */
25853018216SPaolo Bonzini     -1,
25953018216SPaolo Bonzini      1,	/* Cycle (ESC) */
26053018216SPaolo Bonzini     80,	/* Down */
26153018216SPaolo Bonzini     62,	/* Menu (F4) */
26253018216SPaolo Bonzini     -1,
26353018216SPaolo Bonzini     66,	/* Zoom- (F8) */
26453018216SPaolo Bonzini     64,	/* FullScreen (F6) */
26553018216SPaolo Bonzini     65,	/* Zoom+ (F7) */
26653018216SPaolo Bonzini     -1,
26753018216SPaolo Bonzini };
26853018216SPaolo Bonzini 
26953018216SPaolo Bonzini static void n800_tsc_kbd_setup(struct n800_s *s)
27053018216SPaolo Bonzini {
27153018216SPaolo Bonzini     int i;
27253018216SPaolo Bonzini 
27353018216SPaolo Bonzini     /* XXX: are the three pins inverted inside the chip between the
27453018216SPaolo Bonzini      * tsc and the cpu (N4111)?  */
27553018216SPaolo Bonzini     qemu_irq penirq = NULL;	/* NC */
27653018216SPaolo Bonzini     qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
27753018216SPaolo Bonzini     qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
27853018216SPaolo Bonzini 
27953018216SPaolo Bonzini     s->ts.chip = tsc2301_init(penirq, kbirq, dav);
28053018216SPaolo Bonzini     s->ts.opaque = s->ts.chip->opaque;
28153018216SPaolo Bonzini     s->ts.txrx = tsc210x_txrx;
28253018216SPaolo Bonzini 
28353018216SPaolo Bonzini     for (i = 0; i < 0x80; i ++)
28453018216SPaolo Bonzini         s->keymap[i] = -1;
28553018216SPaolo Bonzini     for (i = 0; i < 0x10; i ++)
28653018216SPaolo Bonzini         if (n800_keys[i] >= 0)
28753018216SPaolo Bonzini             s->keymap[n800_keys[i]] = i;
28853018216SPaolo Bonzini 
28953018216SPaolo Bonzini     qemu_add_kbd_event_handler(n800_key_event, s);
29053018216SPaolo Bonzini 
29153018216SPaolo Bonzini     tsc210x_set_transform(s->ts.chip, &n800_pointercal);
29253018216SPaolo Bonzini }
29353018216SPaolo Bonzini 
29453018216SPaolo Bonzini static void n810_tsc_setup(struct n800_s *s)
29553018216SPaolo Bonzini {
29653018216SPaolo Bonzini     qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
29753018216SPaolo Bonzini 
29853018216SPaolo Bonzini     s->ts.opaque = tsc2005_init(pintdav);
29953018216SPaolo Bonzini     s->ts.txrx = tsc2005_txrx;
30053018216SPaolo Bonzini 
30153018216SPaolo Bonzini     tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
30253018216SPaolo Bonzini }
30353018216SPaolo Bonzini 
30453018216SPaolo Bonzini /* N810 Keyboard controller */
30553018216SPaolo Bonzini static void n810_key_event(void *opaque, int keycode)
30653018216SPaolo Bonzini {
30753018216SPaolo Bonzini     struct n800_s *s = (struct n800_s *) opaque;
30853018216SPaolo Bonzini     int code = s->keymap[keycode & 0x7f];
30953018216SPaolo Bonzini 
31053018216SPaolo Bonzini     if (code == -1) {
31153018216SPaolo Bonzini         if ((keycode & 0x7f) == RETU_KEYCODE)
31253018216SPaolo Bonzini             retu_key_event(s->retu, !(keycode & 0x80));
31353018216SPaolo Bonzini         return;
31453018216SPaolo Bonzini     }
31553018216SPaolo Bonzini 
31653018216SPaolo Bonzini     lm832x_key_event(s->kbd, code, !(keycode & 0x80));
31753018216SPaolo Bonzini }
31853018216SPaolo Bonzini 
31953018216SPaolo Bonzini #define M	0
32053018216SPaolo Bonzini 
32153018216SPaolo Bonzini static int n810_keys[0x80] = {
32253018216SPaolo Bonzini     [0x01] = 16,	/* Q */
32353018216SPaolo Bonzini     [0x02] = 37,	/* K */
32453018216SPaolo Bonzini     [0x03] = 24,	/* O */
32553018216SPaolo Bonzini     [0x04] = 25,	/* P */
32653018216SPaolo Bonzini     [0x05] = 14,	/* Backspace */
32753018216SPaolo Bonzini     [0x06] = 30,	/* A */
32853018216SPaolo Bonzini     [0x07] = 31,	/* S */
32953018216SPaolo Bonzini     [0x08] = 32,	/* D */
33053018216SPaolo Bonzini     [0x09] = 33,	/* F */
33153018216SPaolo Bonzini     [0x0a] = 34,	/* G */
33253018216SPaolo Bonzini     [0x0b] = 35,	/* H */
33353018216SPaolo Bonzini     [0x0c] = 36,	/* J */
33453018216SPaolo Bonzini 
33553018216SPaolo Bonzini     [0x11] = 17,	/* W */
33653018216SPaolo Bonzini     [0x12] = 62,	/* Menu (F4) */
33753018216SPaolo Bonzini     [0x13] = 38,	/* L */
33853018216SPaolo Bonzini     [0x14] = 40,	/* ' (Apostrophe) */
33953018216SPaolo Bonzini     [0x16] = 44,	/* Z */
34053018216SPaolo Bonzini     [0x17] = 45,	/* X */
34153018216SPaolo Bonzini     [0x18] = 46,	/* C */
34253018216SPaolo Bonzini     [0x19] = 47,	/* V */
34353018216SPaolo Bonzini     [0x1a] = 48,	/* B */
34453018216SPaolo Bonzini     [0x1b] = 49,	/* N */
34553018216SPaolo Bonzini     [0x1c] = 42,	/* Shift (Left shift) */
34653018216SPaolo Bonzini     [0x1f] = 65,	/* Zoom+ (F7) */
34753018216SPaolo Bonzini 
34853018216SPaolo Bonzini     [0x21] = 18,	/* E */
34953018216SPaolo Bonzini     [0x22] = 39,	/* ; (Semicolon) */
35053018216SPaolo Bonzini     [0x23] = 12,	/* - (Minus) */
35153018216SPaolo Bonzini     [0x24] = 13,	/* = (Equal) */
35253018216SPaolo Bonzini     [0x2b] = 56,	/* Fn (Left Alt) */
35353018216SPaolo Bonzini     [0x2c] = 50,	/* M */
35453018216SPaolo Bonzini     [0x2f] = 66,	/* Zoom- (F8) */
35553018216SPaolo Bonzini 
35653018216SPaolo Bonzini     [0x31] = 19,	/* R */
35753018216SPaolo Bonzini     [0x32] = 29 | M,	/* Right Ctrl */
35853018216SPaolo Bonzini     [0x34] = 57,	/* Space */
35953018216SPaolo Bonzini     [0x35] = 51,	/* , (Comma) */
36053018216SPaolo Bonzini     [0x37] = 72 | M,	/* Up */
36153018216SPaolo Bonzini     [0x3c] = 82 | M,	/* Compose (Insert) */
36253018216SPaolo Bonzini     [0x3f] = 64,	/* FullScreen (F6) */
36353018216SPaolo Bonzini 
36453018216SPaolo Bonzini     [0x41] = 20,	/* T */
36553018216SPaolo Bonzini     [0x44] = 52,	/* . (Dot) */
36653018216SPaolo Bonzini     [0x46] = 77 | M,	/* Right */
36753018216SPaolo Bonzini     [0x4f] = 63,	/* Home (F5) */
36853018216SPaolo Bonzini     [0x51] = 21,	/* Y */
36953018216SPaolo Bonzini     [0x53] = 80 | M,	/* Down */
37053018216SPaolo Bonzini     [0x55] = 28,	/* Enter */
37153018216SPaolo Bonzini     [0x5f] =  1,	/* Cycle (ESC) */
37253018216SPaolo Bonzini 
37353018216SPaolo Bonzini     [0x61] = 22,	/* U */
37453018216SPaolo Bonzini     [0x64] = 75 | M,	/* Left */
37553018216SPaolo Bonzini 
37653018216SPaolo Bonzini     [0x71] = 23,	/* I */
37753018216SPaolo Bonzini #if 0
37853018216SPaolo Bonzini     [0x75] = 28 | M,	/* KP Enter (KP Enter) */
37953018216SPaolo Bonzini #else
38053018216SPaolo Bonzini     [0x75] = 15,	/* KP Enter (Tab) */
38153018216SPaolo Bonzini #endif
38253018216SPaolo Bonzini };
38353018216SPaolo Bonzini 
38453018216SPaolo Bonzini #undef M
38553018216SPaolo Bonzini 
38653018216SPaolo Bonzini static void n810_kbd_setup(struct n800_s *s)
38753018216SPaolo Bonzini {
38853018216SPaolo Bonzini     qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
38953018216SPaolo Bonzini     int i;
39053018216SPaolo Bonzini 
39153018216SPaolo Bonzini     for (i = 0; i < 0x80; i ++)
39253018216SPaolo Bonzini         s->keymap[i] = -1;
39353018216SPaolo Bonzini     for (i = 0; i < 0x80; i ++)
39453018216SPaolo Bonzini         if (n810_keys[i] > 0)
39553018216SPaolo Bonzini             s->keymap[n810_keys[i]] = i;
39653018216SPaolo Bonzini 
39753018216SPaolo Bonzini     qemu_add_kbd_event_handler(n810_key_event, s);
39853018216SPaolo Bonzini 
39953018216SPaolo Bonzini     /* Attach the LM8322 keyboard to the I2C bus,
40053018216SPaolo Bonzini      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
40153018216SPaolo Bonzini     s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
40253018216SPaolo Bonzini                            "lm8323", N810_LM8323_ADDR);
40353018216SPaolo Bonzini     qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
40453018216SPaolo Bonzini }
40553018216SPaolo Bonzini 
40653018216SPaolo Bonzini /* LCD MIPI DBI-C controller (URAL) */
40753018216SPaolo Bonzini struct mipid_s {
40853018216SPaolo Bonzini     int resp[4];
40953018216SPaolo Bonzini     int param[4];
41053018216SPaolo Bonzini     int p;
41153018216SPaolo Bonzini     int pm;
41253018216SPaolo Bonzini     int cmd;
41353018216SPaolo Bonzini 
41453018216SPaolo Bonzini     int sleep;
41553018216SPaolo Bonzini     int booster;
41653018216SPaolo Bonzini     int te;
41753018216SPaolo Bonzini     int selfcheck;
41853018216SPaolo Bonzini     int partial;
41953018216SPaolo Bonzini     int normal;
42053018216SPaolo Bonzini     int vscr;
42153018216SPaolo Bonzini     int invert;
42253018216SPaolo Bonzini     int onoff;
42353018216SPaolo Bonzini     int gamma;
42453018216SPaolo Bonzini     uint32_t id;
42553018216SPaolo Bonzini };
42653018216SPaolo Bonzini 
42753018216SPaolo Bonzini static void mipid_reset(struct mipid_s *s)
42853018216SPaolo Bonzini {
42953018216SPaolo Bonzini     s->pm = 0;
43053018216SPaolo Bonzini     s->cmd = 0;
43153018216SPaolo Bonzini 
43253018216SPaolo Bonzini     s->sleep = 1;
43353018216SPaolo Bonzini     s->booster = 0;
43453018216SPaolo Bonzini     s->selfcheck =
43553018216SPaolo Bonzini             (1 << 7) |	/* Register loading OK.  */
43653018216SPaolo Bonzini             (1 << 5) |	/* The chip is attached.  */
43753018216SPaolo Bonzini             (1 << 4);	/* Display glass still in one piece.  */
43853018216SPaolo Bonzini     s->te = 0;
43953018216SPaolo Bonzini     s->partial = 0;
44053018216SPaolo Bonzini     s->normal = 1;
44153018216SPaolo Bonzini     s->vscr = 0;
44253018216SPaolo Bonzini     s->invert = 0;
44353018216SPaolo Bonzini     s->onoff = 1;
44453018216SPaolo Bonzini     s->gamma = 0;
44553018216SPaolo Bonzini }
44653018216SPaolo Bonzini 
44753018216SPaolo Bonzini static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
44853018216SPaolo Bonzini {
44953018216SPaolo Bonzini     struct mipid_s *s = (struct mipid_s *) opaque;
45053018216SPaolo Bonzini     uint8_t ret;
45153018216SPaolo Bonzini 
45253018216SPaolo Bonzini     if (len > 9)
45353018216SPaolo Bonzini         hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
45453018216SPaolo Bonzini 
45553018216SPaolo Bonzini     if (s->p >= ARRAY_SIZE(s->resp))
45653018216SPaolo Bonzini         ret = 0;
45753018216SPaolo Bonzini     else
45853018216SPaolo Bonzini         ret = s->resp[s->p ++];
45953018216SPaolo Bonzini     if (s->pm --> 0)
46053018216SPaolo Bonzini         s->param[s->pm] = cmd;
46153018216SPaolo Bonzini     else
46253018216SPaolo Bonzini         s->cmd = cmd;
46353018216SPaolo Bonzini 
46453018216SPaolo Bonzini     switch (s->cmd) {
46553018216SPaolo Bonzini     case 0x00:	/* NOP */
46653018216SPaolo Bonzini         break;
46753018216SPaolo Bonzini 
46853018216SPaolo Bonzini     case 0x01:	/* SWRESET */
46953018216SPaolo Bonzini         mipid_reset(s);
47053018216SPaolo Bonzini         break;
47153018216SPaolo Bonzini 
47253018216SPaolo Bonzini     case 0x02:	/* BSTROFF */
47353018216SPaolo Bonzini         s->booster = 0;
47453018216SPaolo Bonzini         break;
47553018216SPaolo Bonzini     case 0x03:	/* BSTRON */
47653018216SPaolo Bonzini         s->booster = 1;
47753018216SPaolo Bonzini         break;
47853018216SPaolo Bonzini 
47953018216SPaolo Bonzini     case 0x04:	/* RDDID */
48053018216SPaolo Bonzini         s->p = 0;
48153018216SPaolo Bonzini         s->resp[0] = (s->id >> 16) & 0xff;
48253018216SPaolo Bonzini         s->resp[1] = (s->id >>  8) & 0xff;
48353018216SPaolo Bonzini         s->resp[2] = (s->id >>  0) & 0xff;
48453018216SPaolo Bonzini         break;
48553018216SPaolo Bonzini 
48653018216SPaolo Bonzini     case 0x06:	/* RD_RED */
48753018216SPaolo Bonzini     case 0x07:	/* RD_GREEN */
48853018216SPaolo Bonzini         /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
48953018216SPaolo Bonzini          * for the bootloader one needs to change this.  */
49053018216SPaolo Bonzini     case 0x08:	/* RD_BLUE */
49153018216SPaolo Bonzini         s->p = 0;
49253018216SPaolo Bonzini         /* TODO: return first pixel components */
49353018216SPaolo Bonzini         s->resp[0] = 0x01;
49453018216SPaolo Bonzini         break;
49553018216SPaolo Bonzini 
49653018216SPaolo Bonzini     case 0x09:	/* RDDST */
49753018216SPaolo Bonzini         s->p = 0;
49853018216SPaolo Bonzini         s->resp[0] = s->booster << 7;
49953018216SPaolo Bonzini         s->resp[1] = (5 << 4) | (s->partial << 2) |
50053018216SPaolo Bonzini                 (s->sleep << 1) | s->normal;
50153018216SPaolo Bonzini         s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
50253018216SPaolo Bonzini                 (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
50353018216SPaolo Bonzini         s->resp[3] = s->gamma << 6;
50453018216SPaolo Bonzini         break;
50553018216SPaolo Bonzini 
50653018216SPaolo Bonzini     case 0x0a:	/* RDDPM */
50753018216SPaolo Bonzini         s->p = 0;
50853018216SPaolo Bonzini         s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
50953018216SPaolo Bonzini                 (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
51053018216SPaolo Bonzini         break;
51153018216SPaolo Bonzini     case 0x0b:	/* RDDMADCTR */
51253018216SPaolo Bonzini         s->p = 0;
51353018216SPaolo Bonzini         s->resp[0] = 0;
51453018216SPaolo Bonzini         break;
51553018216SPaolo Bonzini     case 0x0c:	/* RDDCOLMOD */
51653018216SPaolo Bonzini         s->p = 0;
51753018216SPaolo Bonzini         s->resp[0] = 5;	/* 65K colours */
51853018216SPaolo Bonzini         break;
51953018216SPaolo Bonzini     case 0x0d:	/* RDDIM */
52053018216SPaolo Bonzini         s->p = 0;
52153018216SPaolo Bonzini         s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
52253018216SPaolo Bonzini         break;
52353018216SPaolo Bonzini     case 0x0e:	/* RDDSM */
52453018216SPaolo Bonzini         s->p = 0;
52553018216SPaolo Bonzini         s->resp[0] = s->te << 7;
52653018216SPaolo Bonzini         break;
52753018216SPaolo Bonzini     case 0x0f:	/* RDDSDR */
52853018216SPaolo Bonzini         s->p = 0;
52953018216SPaolo Bonzini         s->resp[0] = s->selfcheck;
53053018216SPaolo Bonzini         break;
53153018216SPaolo Bonzini 
53253018216SPaolo Bonzini     case 0x10:	/* SLPIN */
53353018216SPaolo Bonzini         s->sleep = 1;
53453018216SPaolo Bonzini         break;
53553018216SPaolo Bonzini     case 0x11:	/* SLPOUT */
53653018216SPaolo Bonzini         s->sleep = 0;
53753018216SPaolo Bonzini         s->selfcheck ^= 1 << 6;	/* POFF self-diagnosis Ok */
53853018216SPaolo Bonzini         break;
53953018216SPaolo Bonzini 
54053018216SPaolo Bonzini     case 0x12:	/* PTLON */
54153018216SPaolo Bonzini         s->partial = 1;
54253018216SPaolo Bonzini         s->normal = 0;
54353018216SPaolo Bonzini         s->vscr = 0;
54453018216SPaolo Bonzini         break;
54553018216SPaolo Bonzini     case 0x13:	/* NORON */
54653018216SPaolo Bonzini         s->partial = 0;
54753018216SPaolo Bonzini         s->normal = 1;
54853018216SPaolo Bonzini         s->vscr = 0;
54953018216SPaolo Bonzini         break;
55053018216SPaolo Bonzini 
55153018216SPaolo Bonzini     case 0x20:	/* INVOFF */
55253018216SPaolo Bonzini         s->invert = 0;
55353018216SPaolo Bonzini         break;
55453018216SPaolo Bonzini     case 0x21:	/* INVON */
55553018216SPaolo Bonzini         s->invert = 1;
55653018216SPaolo Bonzini         break;
55753018216SPaolo Bonzini 
55853018216SPaolo Bonzini     case 0x22:	/* APOFF */
55953018216SPaolo Bonzini     case 0x23:	/* APON */
56053018216SPaolo Bonzini         goto bad_cmd;
56153018216SPaolo Bonzini 
56253018216SPaolo Bonzini     case 0x25:	/* WRCNTR */
56353018216SPaolo Bonzini         if (s->pm < 0)
56453018216SPaolo Bonzini             s->pm = 1;
56553018216SPaolo Bonzini         goto bad_cmd;
56653018216SPaolo Bonzini 
56753018216SPaolo Bonzini     case 0x26:	/* GAMSET */
56853018216SPaolo Bonzini         if (!s->pm)
56953018216SPaolo Bonzini             s->gamma = ffs(s->param[0] & 0xf) - 1;
57053018216SPaolo Bonzini         else if (s->pm < 0)
57153018216SPaolo Bonzini             s->pm = 1;
57253018216SPaolo Bonzini         break;
57353018216SPaolo Bonzini 
57453018216SPaolo Bonzini     case 0x28:	/* DISPOFF */
57553018216SPaolo Bonzini         s->onoff = 0;
57653018216SPaolo Bonzini         break;
57753018216SPaolo Bonzini     case 0x29:	/* DISPON */
57853018216SPaolo Bonzini         s->onoff = 1;
57953018216SPaolo Bonzini         break;
58053018216SPaolo Bonzini 
58153018216SPaolo Bonzini     case 0x2a:	/* CASET */
58253018216SPaolo Bonzini     case 0x2b:	/* RASET */
58353018216SPaolo Bonzini     case 0x2c:	/* RAMWR */
58453018216SPaolo Bonzini     case 0x2d:	/* RGBSET */
58553018216SPaolo Bonzini     case 0x2e:	/* RAMRD */
58653018216SPaolo Bonzini     case 0x30:	/* PTLAR */
58753018216SPaolo Bonzini     case 0x33:	/* SCRLAR */
58853018216SPaolo Bonzini         goto bad_cmd;
58953018216SPaolo Bonzini 
59053018216SPaolo Bonzini     case 0x34:	/* TEOFF */
59153018216SPaolo Bonzini         s->te = 0;
59253018216SPaolo Bonzini         break;
59353018216SPaolo Bonzini     case 0x35:	/* TEON */
59453018216SPaolo Bonzini         if (!s->pm)
59553018216SPaolo Bonzini             s->te = 1;
59653018216SPaolo Bonzini         else if (s->pm < 0)
59753018216SPaolo Bonzini             s->pm = 1;
59853018216SPaolo Bonzini         break;
59953018216SPaolo Bonzini 
60053018216SPaolo Bonzini     case 0x36:	/* MADCTR */
60153018216SPaolo Bonzini         goto bad_cmd;
60253018216SPaolo Bonzini 
60353018216SPaolo Bonzini     case 0x37:	/* VSCSAD */
60453018216SPaolo Bonzini         s->partial = 0;
60553018216SPaolo Bonzini         s->normal = 0;
60653018216SPaolo Bonzini         s->vscr = 1;
60753018216SPaolo Bonzini         break;
60853018216SPaolo Bonzini 
60953018216SPaolo Bonzini     case 0x38:	/* IDMOFF */
61053018216SPaolo Bonzini     case 0x39:	/* IDMON */
61153018216SPaolo Bonzini     case 0x3a:	/* COLMOD */
61253018216SPaolo Bonzini         goto bad_cmd;
61353018216SPaolo Bonzini 
61453018216SPaolo Bonzini     case 0xb0:	/* CLKINT / DISCTL */
61553018216SPaolo Bonzini     case 0xb1:	/* CLKEXT */
61653018216SPaolo Bonzini         if (s->pm < 0)
61753018216SPaolo Bonzini             s->pm = 2;
61853018216SPaolo Bonzini         break;
61953018216SPaolo Bonzini 
62053018216SPaolo Bonzini     case 0xb4:	/* FRMSEL */
62153018216SPaolo Bonzini         break;
62253018216SPaolo Bonzini 
62353018216SPaolo Bonzini     case 0xb5:	/* FRM8SEL */
62453018216SPaolo Bonzini     case 0xb6:	/* TMPRNG / INIESC */
62553018216SPaolo Bonzini     case 0xb7:	/* TMPHIS / NOP2 */
62653018216SPaolo Bonzini     case 0xb8:	/* TMPREAD / MADCTL */
62753018216SPaolo Bonzini     case 0xba:	/* DISTCTR */
62853018216SPaolo Bonzini     case 0xbb:	/* EPVOL */
62953018216SPaolo Bonzini         goto bad_cmd;
63053018216SPaolo Bonzini 
63153018216SPaolo Bonzini     case 0xbd:	/* Unknown */
63253018216SPaolo Bonzini         s->p = 0;
63353018216SPaolo Bonzini         s->resp[0] = 0;
63453018216SPaolo Bonzini         s->resp[1] = 1;
63553018216SPaolo Bonzini         break;
63653018216SPaolo Bonzini 
63753018216SPaolo Bonzini     case 0xc2:	/* IFMOD */
63853018216SPaolo Bonzini         if (s->pm < 0)
63953018216SPaolo Bonzini             s->pm = 2;
64053018216SPaolo Bonzini         break;
64153018216SPaolo Bonzini 
64253018216SPaolo Bonzini     case 0xc6:	/* PWRCTL */
64353018216SPaolo Bonzini     case 0xc7:	/* PPWRCTL */
64453018216SPaolo Bonzini     case 0xd0:	/* EPWROUT */
64553018216SPaolo Bonzini     case 0xd1:	/* EPWRIN */
64653018216SPaolo Bonzini     case 0xd4:	/* RDEV */
64753018216SPaolo Bonzini     case 0xd5:	/* RDRR */
64853018216SPaolo Bonzini         goto bad_cmd;
64953018216SPaolo Bonzini 
65053018216SPaolo Bonzini     case 0xda:	/* RDID1 */
65153018216SPaolo Bonzini         s->p = 0;
65253018216SPaolo Bonzini         s->resp[0] = (s->id >> 16) & 0xff;
65353018216SPaolo Bonzini         break;
65453018216SPaolo Bonzini     case 0xdb:	/* RDID2 */
65553018216SPaolo Bonzini         s->p = 0;
65653018216SPaolo Bonzini         s->resp[0] = (s->id >>  8) & 0xff;
65753018216SPaolo Bonzini         break;
65853018216SPaolo Bonzini     case 0xdc:	/* RDID3 */
65953018216SPaolo Bonzini         s->p = 0;
66053018216SPaolo Bonzini         s->resp[0] = (s->id >>  0) & 0xff;
66153018216SPaolo Bonzini         break;
66253018216SPaolo Bonzini 
66353018216SPaolo Bonzini     default:
66453018216SPaolo Bonzini     bad_cmd:
665591f73f6SPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
666591f73f6SPeter Maydell                       "%s: unknown command %02x\n", __func__, s->cmd);
66753018216SPaolo Bonzini         break;
66853018216SPaolo Bonzini     }
66953018216SPaolo Bonzini 
67053018216SPaolo Bonzini     return ret;
67153018216SPaolo Bonzini }
67253018216SPaolo Bonzini 
67353018216SPaolo Bonzini static void *mipid_init(void)
67453018216SPaolo Bonzini {
67553018216SPaolo Bonzini     struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
67653018216SPaolo Bonzini 
67753018216SPaolo Bonzini     s->id = 0x838f03;
67853018216SPaolo Bonzini     mipid_reset(s);
67953018216SPaolo Bonzini 
68053018216SPaolo Bonzini     return s;
68153018216SPaolo Bonzini }
68253018216SPaolo Bonzini 
68353018216SPaolo Bonzini static void n8x0_spi_setup(struct n800_s *s)
68453018216SPaolo Bonzini {
68553018216SPaolo Bonzini     void *tsc = s->ts.opaque;
68653018216SPaolo Bonzini     void *mipid = mipid_init();
68753018216SPaolo Bonzini 
68853018216SPaolo Bonzini     omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
68953018216SPaolo Bonzini     omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
69053018216SPaolo Bonzini }
69153018216SPaolo Bonzini 
69253018216SPaolo Bonzini /* This task is normally performed by the bootloader.  If we're loading
69353018216SPaolo Bonzini  * a kernel directly, we need to enable the Blizzard ourselves.  */
69453018216SPaolo Bonzini static void n800_dss_init(struct rfbi_chip_s *chip)
69553018216SPaolo Bonzini {
69653018216SPaolo Bonzini     uint8_t *fb_blank;
69753018216SPaolo Bonzini 
69853018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x2a);		/* LCD Width register */
69953018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x64);
70053018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x2c);		/* LCD HNDP register */
70153018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x1e);
70253018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x2e);		/* LCD Height 0 register */
70353018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0xe0);
70453018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x30);		/* LCD Height 1 register */
70553018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x01);
70653018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x32);		/* LCD VNDP register */
70753018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x06);
70853018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x68);		/* Display Mode register */
70953018216SPaolo Bonzini     chip->write(chip->opaque, 1, 1);		/* Enable bit */
71053018216SPaolo Bonzini 
71153018216SPaolo Bonzini     chip->write(chip->opaque, 0, 0x6c);
71253018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
71353018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
71453018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
71553018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
71653018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x1f);		/* Input X End Position */
71753018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x03);		/* Input X End Position */
71853018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0xdf);		/* Input Y End Position */
71953018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x01);		/* Input Y End Position */
72053018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
72153018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
72253018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
72353018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
72453018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x1f);		/* Output X End Position */
72553018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x03);		/* Output X End Position */
72653018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0xdf);		/* Output Y End Position */
72753018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x01);		/* Output Y End Position */
72853018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x01);		/* Input Data Format */
72953018216SPaolo Bonzini     chip->write(chip->opaque, 1, 0x01);		/* Data Source Select */
73053018216SPaolo Bonzini 
73153018216SPaolo Bonzini     fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
73253018216SPaolo Bonzini     /* Display Memory Data Port */
73353018216SPaolo Bonzini     chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
73453018216SPaolo Bonzini     g_free(fb_blank);
73553018216SPaolo Bonzini }
73653018216SPaolo Bonzini 
73753018216SPaolo Bonzini static void n8x0_dss_setup(struct n800_s *s)
73853018216SPaolo Bonzini {
73953018216SPaolo Bonzini     s->blizzard.opaque = s1d13745_init(NULL);
74053018216SPaolo Bonzini     s->blizzard.block = s1d13745_write_block;
74153018216SPaolo Bonzini     s->blizzard.write = s1d13745_write;
74253018216SPaolo Bonzini     s->blizzard.read = s1d13745_read;
74353018216SPaolo Bonzini 
74453018216SPaolo Bonzini     omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
74553018216SPaolo Bonzini }
74653018216SPaolo Bonzini 
74753018216SPaolo Bonzini static void n8x0_cbus_setup(struct n800_s *s)
74853018216SPaolo Bonzini {
74953018216SPaolo Bonzini     qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
75053018216SPaolo Bonzini     qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
75153018216SPaolo Bonzini     qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
75253018216SPaolo Bonzini 
75353018216SPaolo Bonzini     CBus *cbus = cbus_init(dat_out);
75453018216SPaolo Bonzini 
75553018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
75653018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
75753018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
75853018216SPaolo Bonzini 
75953018216SPaolo Bonzini     cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
76053018216SPaolo Bonzini     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
76153018216SPaolo Bonzini }
76253018216SPaolo Bonzini 
76353018216SPaolo Bonzini static void n8x0_uart_setup(struct n800_s *s)
76453018216SPaolo Bonzini {
76553018216SPaolo Bonzini     CharDriverState *radio = uart_hci_init(
76653018216SPaolo Bonzini                     qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
76753018216SPaolo Bonzini 
76853018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
76953018216SPaolo Bonzini                     csrhci_pins_get(radio)[csrhci_pin_reset]);
77053018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
77153018216SPaolo Bonzini                     csrhci_pins_get(radio)[csrhci_pin_wakeup]);
77253018216SPaolo Bonzini 
77353018216SPaolo Bonzini     omap_uart_attach(s->mpu->uart[BT_UART], radio);
77453018216SPaolo Bonzini }
77553018216SPaolo Bonzini 
77653018216SPaolo Bonzini static void n8x0_usb_setup(struct n800_s *s)
77753018216SPaolo Bonzini {
77853018216SPaolo Bonzini     SysBusDevice *dev;
77953018216SPaolo Bonzini     s->usb = qdev_create(NULL, "tusb6010");
78053018216SPaolo Bonzini     dev = SYS_BUS_DEVICE(s->usb);
78153018216SPaolo Bonzini     qdev_init_nofail(s->usb);
78253018216SPaolo Bonzini     sysbus_connect_irq(dev, 0,
78353018216SPaolo Bonzini                        qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
78453018216SPaolo Bonzini     /* Using the NOR interface */
78553018216SPaolo Bonzini     omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
78653018216SPaolo Bonzini                      sysbus_mmio_get_region(dev, 0));
78753018216SPaolo Bonzini     omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
78853018216SPaolo Bonzini                      sysbus_mmio_get_region(dev, 1));
78953018216SPaolo Bonzini     qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
79053018216SPaolo Bonzini                           qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
79153018216SPaolo Bonzini }
79253018216SPaolo Bonzini 
79353018216SPaolo Bonzini /* Setup done before the main bootloader starts by some early setup code
79453018216SPaolo Bonzini  * - used when we want to run the main bootloader in emulation.  This
79553018216SPaolo Bonzini  * isn't documented.  */
79653018216SPaolo Bonzini static uint32_t n800_pinout[104] = {
79753018216SPaolo Bonzini     0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
79853018216SPaolo Bonzini     0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
79953018216SPaolo Bonzini     0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
80053018216SPaolo Bonzini     0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
80153018216SPaolo Bonzini     0x01241800, 0x18181818, 0x000000f0, 0x01300000,
80253018216SPaolo Bonzini     0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
80353018216SPaolo Bonzini     0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
80453018216SPaolo Bonzini     0x007c0000, 0x00000000, 0x00000088, 0x00840000,
80553018216SPaolo Bonzini     0x00000000, 0x00000094, 0x00980300, 0x0f180003,
80653018216SPaolo Bonzini     0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
80753018216SPaolo Bonzini     0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
80853018216SPaolo Bonzini     0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
80953018216SPaolo Bonzini     0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
81053018216SPaolo Bonzini     0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
81153018216SPaolo Bonzini     0x00000000, 0x00000038, 0x00340000, 0x00000000,
81253018216SPaolo Bonzini     0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
81353018216SPaolo Bonzini     0x005c0808, 0x08080808, 0x08080058, 0x00540808,
81453018216SPaolo Bonzini     0x08080808, 0x0808006c, 0x00680808, 0x08080808,
81553018216SPaolo Bonzini     0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
81653018216SPaolo Bonzini     0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
81753018216SPaolo Bonzini     0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
81853018216SPaolo Bonzini     0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
81953018216SPaolo Bonzini     0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
82053018216SPaolo Bonzini     0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
82153018216SPaolo Bonzini     0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
82253018216SPaolo Bonzini     0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
82353018216SPaolo Bonzini };
82453018216SPaolo Bonzini 
82553018216SPaolo Bonzini static void n800_setup_nolo_tags(void *sram_base)
82653018216SPaolo Bonzini {
82753018216SPaolo Bonzini     int i;
82853018216SPaolo Bonzini     uint32_t *p = sram_base + 0x8000;
82953018216SPaolo Bonzini     uint32_t *v = sram_base + 0xa000;
83053018216SPaolo Bonzini 
83153018216SPaolo Bonzini     memset(p, 0, 0x3000);
83253018216SPaolo Bonzini 
83353018216SPaolo Bonzini     strcpy((void *) (p + 0), "QEMU N800");
83453018216SPaolo Bonzini 
83553018216SPaolo Bonzini     strcpy((void *) (p + 8), "F5");
83653018216SPaolo Bonzini 
83753018216SPaolo Bonzini     stl_raw(p + 10, 0x04f70000);
83853018216SPaolo Bonzini     strcpy((void *) (p + 9), "RX-34");
83953018216SPaolo Bonzini 
84053018216SPaolo Bonzini     /* RAM size in MB? */
84153018216SPaolo Bonzini     stl_raw(p + 12, 0x80);
84253018216SPaolo Bonzini 
84353018216SPaolo Bonzini     /* Pointer to the list of tags */
84453018216SPaolo Bonzini     stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
84553018216SPaolo Bonzini 
84653018216SPaolo Bonzini     /* The NOLO tags start here */
84753018216SPaolo Bonzini     p = sram_base + 0x9000;
84853018216SPaolo Bonzini #define ADD_TAG(tag, len)				\
84953018216SPaolo Bonzini     stw_raw((uint16_t *) p + 0, tag);			\
85053018216SPaolo Bonzini     stw_raw((uint16_t *) p + 1, len); p ++;		\
85153018216SPaolo Bonzini     stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
85253018216SPaolo Bonzini 
85353018216SPaolo Bonzini     /* OMAP STI console? Pin out settings? */
85453018216SPaolo Bonzini     ADD_TAG(0x6e01, 414);
85553018216SPaolo Bonzini     for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
85653018216SPaolo Bonzini         stl_raw(v ++, n800_pinout[i]);
85753018216SPaolo Bonzini 
85853018216SPaolo Bonzini     /* Kernel memsize? */
85953018216SPaolo Bonzini     ADD_TAG(0x6e05, 1);
86053018216SPaolo Bonzini     stl_raw(v ++, 2);
86153018216SPaolo Bonzini 
86253018216SPaolo Bonzini     /* NOLO serial console */
86353018216SPaolo Bonzini     ADD_TAG(0x6e02, 4);
86453018216SPaolo Bonzini     stl_raw(v ++, XLDR_LL_UART);	/* UART number (1 - 3) */
86553018216SPaolo Bonzini 
86653018216SPaolo Bonzini #if 0
86753018216SPaolo Bonzini     /* CBUS settings (Retu/AVilma) */
86853018216SPaolo Bonzini     ADD_TAG(0x6e03, 6);
86953018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 65);	/* CBUS GPIO0 */
87053018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 66);	/* CBUS GPIO1 */
87153018216SPaolo Bonzini     stw_raw((uint16_t *) v + 2, 64);	/* CBUS GPIO2 */
87253018216SPaolo Bonzini     v += 2;
87353018216SPaolo Bonzini #endif
87453018216SPaolo Bonzini 
87553018216SPaolo Bonzini     /* Nokia ASIC BB5 (Retu/Tahvo) */
87653018216SPaolo Bonzini     ADD_TAG(0x6e0a, 4);
87753018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 111);	/* "Retu" interrupt GPIO */
87853018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 108);	/* "Tahvo" interrupt GPIO */
87953018216SPaolo Bonzini     v ++;
88053018216SPaolo Bonzini 
88153018216SPaolo Bonzini     /* LCD console? */
88253018216SPaolo Bonzini     ADD_TAG(0x6e04, 4);
88353018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 30);	/* ??? */
88453018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 24);	/* ??? */
88553018216SPaolo Bonzini     v ++;
88653018216SPaolo Bonzini 
88753018216SPaolo Bonzini #if 0
88853018216SPaolo Bonzini     /* LCD settings */
88953018216SPaolo Bonzini     ADD_TAG(0x6e06, 2);
89053018216SPaolo Bonzini     stw_raw((uint16_t *) (v ++), 15);	/* ??? */
89153018216SPaolo Bonzini #endif
89253018216SPaolo Bonzini 
89353018216SPaolo Bonzini     /* I^2C (Menelaus) */
89453018216SPaolo Bonzini     ADD_TAG(0x6e07, 4);
89553018216SPaolo Bonzini     stl_raw(v ++, 0x00720000);		/* ??? */
89653018216SPaolo Bonzini 
89753018216SPaolo Bonzini     /* Unknown */
89853018216SPaolo Bonzini     ADD_TAG(0x6e0b, 6);
89953018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 94);	/* ??? */
90053018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 23);	/* ??? */
90153018216SPaolo Bonzini     stw_raw((uint16_t *) v + 2, 0);	/* ??? */
90253018216SPaolo Bonzini     v += 2;
90353018216SPaolo Bonzini 
90453018216SPaolo Bonzini     /* OMAP gpio switch info */
90553018216SPaolo Bonzini     ADD_TAG(0x6e0c, 80);
90653018216SPaolo Bonzini     strcpy((void *) v, "bat_cover");	v += 3;
90753018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 110);	/* GPIO num ??? */
90853018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 1);	/* GPIO num ??? */
90953018216SPaolo Bonzini     v += 2;
91053018216SPaolo Bonzini     strcpy((void *) v, "cam_act");	v += 3;
91153018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 95);	/* GPIO num ??? */
91253018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 32);	/* GPIO num ??? */
91353018216SPaolo Bonzini     v += 2;
91453018216SPaolo Bonzini     strcpy((void *) v, "cam_turn");	v += 3;
91553018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 12);	/* GPIO num ??? */
91653018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 33);	/* GPIO num ??? */
91753018216SPaolo Bonzini     v += 2;
91853018216SPaolo Bonzini     strcpy((void *) v, "headphone");	v += 3;
91953018216SPaolo Bonzini     stw_raw((uint16_t *) v + 0, 107);	/* GPIO num ??? */
92053018216SPaolo Bonzini     stw_raw((uint16_t *) v + 1, 17);	/* GPIO num ??? */
92153018216SPaolo Bonzini     v += 2;
92253018216SPaolo Bonzini 
92353018216SPaolo Bonzini     /* Bluetooth */
92453018216SPaolo Bonzini     ADD_TAG(0x6e0e, 12);
92553018216SPaolo Bonzini     stl_raw(v ++, 0x5c623d01);		/* ??? */
92653018216SPaolo Bonzini     stl_raw(v ++, 0x00000201);		/* ??? */
92753018216SPaolo Bonzini     stl_raw(v ++, 0x00000000);		/* ??? */
92853018216SPaolo Bonzini 
92953018216SPaolo Bonzini     /* CX3110x WLAN settings */
93053018216SPaolo Bonzini     ADD_TAG(0x6e0f, 8);
93153018216SPaolo Bonzini     stl_raw(v ++, 0x00610025);		/* ??? */
93253018216SPaolo Bonzini     stl_raw(v ++, 0xffff0057);		/* ??? */
93353018216SPaolo Bonzini 
93453018216SPaolo Bonzini     /* MMC host settings */
93553018216SPaolo Bonzini     ADD_TAG(0x6e10, 12);
93653018216SPaolo Bonzini     stl_raw(v ++, 0xffff000f);		/* ??? */
93753018216SPaolo Bonzini     stl_raw(v ++, 0xffffffff);		/* ??? */
93853018216SPaolo Bonzini     stl_raw(v ++, 0x00000060);		/* ??? */
93953018216SPaolo Bonzini 
94053018216SPaolo Bonzini     /* OneNAND chip select */
94153018216SPaolo Bonzini     ADD_TAG(0x6e11, 10);
94253018216SPaolo Bonzini     stl_raw(v ++, 0x00000401);		/* ??? */
94353018216SPaolo Bonzini     stl_raw(v ++, 0x0002003a);		/* ??? */
94453018216SPaolo Bonzini     stl_raw(v ++, 0x00000002);		/* ??? */
94553018216SPaolo Bonzini 
94653018216SPaolo Bonzini     /* TEA5761 sensor settings */
94753018216SPaolo Bonzini     ADD_TAG(0x6e12, 2);
94853018216SPaolo Bonzini     stl_raw(v ++, 93);			/* GPIO num ??? */
94953018216SPaolo Bonzini 
95053018216SPaolo Bonzini #if 0
95153018216SPaolo Bonzini     /* Unknown tag */
95253018216SPaolo Bonzini     ADD_TAG(6e09, 0);
95353018216SPaolo Bonzini 
95453018216SPaolo Bonzini     /* Kernel UART / console */
95553018216SPaolo Bonzini     ADD_TAG(6e12, 0);
95653018216SPaolo Bonzini #endif
95753018216SPaolo Bonzini 
95853018216SPaolo Bonzini     /* End of the list */
95953018216SPaolo Bonzini     stl_raw(p ++, 0x00000000);
96053018216SPaolo Bonzini     stl_raw(p ++, 0x00000000);
96153018216SPaolo Bonzini }
96253018216SPaolo Bonzini 
96353018216SPaolo Bonzini /* This task is normally performed by the bootloader.  If we're loading
96453018216SPaolo Bonzini  * a kernel directly, we need to set up GPMC mappings ourselves.  */
96553018216SPaolo Bonzini static void n800_gpmc_init(struct n800_s *s)
96653018216SPaolo Bonzini {
96753018216SPaolo Bonzini     uint32_t config7 =
96853018216SPaolo Bonzini             (0xf << 8) |	/* MASKADDRESS */
96953018216SPaolo Bonzini             (1 << 6) |		/* CSVALID */
97053018216SPaolo Bonzini             (4 << 0);		/* BASEADDRESS */
97153018216SPaolo Bonzini 
97253018216SPaolo Bonzini     cpu_physical_memory_write(0x6800a078,		/* GPMC_CONFIG7_0 */
973e1fe50dcSStefan Weil                               &config7, sizeof(config7));
97453018216SPaolo Bonzini }
97553018216SPaolo Bonzini 
97653018216SPaolo Bonzini /* Setup sequence done by the bootloader */
97753018216SPaolo Bonzini static void n8x0_boot_init(void *opaque)
97853018216SPaolo Bonzini {
97953018216SPaolo Bonzini     struct n800_s *s = (struct n800_s *) opaque;
98053018216SPaolo Bonzini     uint32_t buf;
98153018216SPaolo Bonzini 
98253018216SPaolo Bonzini     /* PRCM setup */
98353018216SPaolo Bonzini #define omap_writel(addr, val)	\
98453018216SPaolo Bonzini     buf = (val);			\
985e1fe50dcSStefan Weil     cpu_physical_memory_write(addr, &buf, sizeof(buf))
98653018216SPaolo Bonzini 
98753018216SPaolo Bonzini     omap_writel(0x48008060, 0x41);		/* PRCM_CLKSRC_CTRL */
98853018216SPaolo Bonzini     omap_writel(0x48008070, 1);			/* PRCM_CLKOUT_CTRL */
98953018216SPaolo Bonzini     omap_writel(0x48008078, 0);			/* PRCM_CLKEMUL_CTRL */
99053018216SPaolo Bonzini     omap_writel(0x48008090, 0);			/* PRCM_VOLTSETUP */
99153018216SPaolo Bonzini     omap_writel(0x48008094, 0);			/* PRCM_CLKSSETUP */
99253018216SPaolo Bonzini     omap_writel(0x48008098, 0);			/* PRCM_POLCTRL */
99353018216SPaolo Bonzini     omap_writel(0x48008140, 2);			/* CM_CLKSEL_MPU */
99453018216SPaolo Bonzini     omap_writel(0x48008148, 0);			/* CM_CLKSTCTRL_MPU */
99553018216SPaolo Bonzini     omap_writel(0x48008158, 1);			/* RM_RSTST_MPU */
99653018216SPaolo Bonzini     omap_writel(0x480081c8, 0x15);		/* PM_WKDEP_MPU */
99753018216SPaolo Bonzini     omap_writel(0x480081d4, 0x1d4);		/* PM_EVGENCTRL_MPU */
99853018216SPaolo Bonzini     omap_writel(0x480081d8, 0);			/* PM_EVEGENONTIM_MPU */
99953018216SPaolo Bonzini     omap_writel(0x480081dc, 0);			/* PM_EVEGENOFFTIM_MPU */
100053018216SPaolo Bonzini     omap_writel(0x480081e0, 0xc);		/* PM_PWSTCTRL_MPU */
100153018216SPaolo Bonzini     omap_writel(0x48008200, 0x047e7ff7);	/* CM_FCLKEN1_CORE */
100253018216SPaolo Bonzini     omap_writel(0x48008204, 0x00000004);	/* CM_FCLKEN2_CORE */
100353018216SPaolo Bonzini     omap_writel(0x48008210, 0x047e7ff1);	/* CM_ICLKEN1_CORE */
100453018216SPaolo Bonzini     omap_writel(0x48008214, 0x00000004);	/* CM_ICLKEN2_CORE */
100553018216SPaolo Bonzini     omap_writel(0x4800821c, 0x00000000);	/* CM_ICLKEN4_CORE */
100653018216SPaolo Bonzini     omap_writel(0x48008230, 0);			/* CM_AUTOIDLE1_CORE */
100753018216SPaolo Bonzini     omap_writel(0x48008234, 0);			/* CM_AUTOIDLE2_CORE */
100853018216SPaolo Bonzini     omap_writel(0x48008238, 7);			/* CM_AUTOIDLE3_CORE */
100953018216SPaolo Bonzini     omap_writel(0x4800823c, 0);			/* CM_AUTOIDLE4_CORE */
101053018216SPaolo Bonzini     omap_writel(0x48008240, 0x04360626);	/* CM_CLKSEL1_CORE */
101153018216SPaolo Bonzini     omap_writel(0x48008244, 0x00000014);	/* CM_CLKSEL2_CORE */
101253018216SPaolo Bonzini     omap_writel(0x48008248, 0);			/* CM_CLKSTCTRL_CORE */
101353018216SPaolo Bonzini     omap_writel(0x48008300, 0x00000000);	/* CM_FCLKEN_GFX */
101453018216SPaolo Bonzini     omap_writel(0x48008310, 0x00000000);	/* CM_ICLKEN_GFX */
101553018216SPaolo Bonzini     omap_writel(0x48008340, 0x00000001);	/* CM_CLKSEL_GFX */
101653018216SPaolo Bonzini     omap_writel(0x48008400, 0x00000004);	/* CM_FCLKEN_WKUP */
101753018216SPaolo Bonzini     omap_writel(0x48008410, 0x00000004);	/* CM_ICLKEN_WKUP */
101853018216SPaolo Bonzini     omap_writel(0x48008440, 0x00000000);	/* CM_CLKSEL_WKUP */
101953018216SPaolo Bonzini     omap_writel(0x48008500, 0x000000cf);	/* CM_CLKEN_PLL */
102053018216SPaolo Bonzini     omap_writel(0x48008530, 0x0000000c);	/* CM_AUTOIDLE_PLL */
102153018216SPaolo Bonzini     omap_writel(0x48008540,			/* CM_CLKSEL1_PLL */
102253018216SPaolo Bonzini                     (0x78 << 12) | (6 << 8));
102353018216SPaolo Bonzini     omap_writel(0x48008544, 2);			/* CM_CLKSEL2_PLL */
102453018216SPaolo Bonzini 
102553018216SPaolo Bonzini     /* GPMC setup */
102653018216SPaolo Bonzini     n800_gpmc_init(s);
102753018216SPaolo Bonzini 
102853018216SPaolo Bonzini     /* Video setup */
102953018216SPaolo Bonzini     n800_dss_init(&s->blizzard);
103053018216SPaolo Bonzini 
103153018216SPaolo Bonzini     /* CPU setup */
103253018216SPaolo Bonzini     s->mpu->cpu->env.GE = 0x5;
103353018216SPaolo Bonzini 
103453018216SPaolo Bonzini     /* If the machine has a slided keyboard, open it */
103553018216SPaolo Bonzini     if (s->kbd)
103653018216SPaolo Bonzini         qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
103753018216SPaolo Bonzini }
103853018216SPaolo Bonzini 
103953018216SPaolo Bonzini #define OMAP_TAG_NOKIA_BT	0x4e01
104053018216SPaolo Bonzini #define OMAP_TAG_WLAN_CX3110X	0x4e02
104153018216SPaolo Bonzini #define OMAP_TAG_CBUS		0x4e03
104253018216SPaolo Bonzini #define OMAP_TAG_EM_ASIC_BB5	0x4e04
104353018216SPaolo Bonzini 
104453018216SPaolo Bonzini static struct omap_gpiosw_info_s {
104553018216SPaolo Bonzini     const char *name;
104653018216SPaolo Bonzini     int line;
104753018216SPaolo Bonzini     int type;
104853018216SPaolo Bonzini } n800_gpiosw_info[] = {
104953018216SPaolo Bonzini     {
105053018216SPaolo Bonzini         "bat_cover", N800_BAT_COVER_GPIO,
105153018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
105253018216SPaolo Bonzini     }, {
105353018216SPaolo Bonzini         "cam_act", N800_CAM_ACT_GPIO,
105453018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_ACTIVITY,
105553018216SPaolo Bonzini     }, {
105653018216SPaolo Bonzini         "cam_turn", N800_CAM_TURN_GPIO,
105753018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
105853018216SPaolo Bonzini     }, {
105953018216SPaolo Bonzini         "headphone", N8X0_HEADPHONE_GPIO,
106053018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
106153018216SPaolo Bonzini     },
106253018216SPaolo Bonzini     { NULL }
106353018216SPaolo Bonzini }, n810_gpiosw_info[] = {
106453018216SPaolo Bonzini     {
106553018216SPaolo Bonzini         "gps_reset", N810_GPS_RESET_GPIO,
106653018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
106753018216SPaolo Bonzini     }, {
106853018216SPaolo Bonzini         "gps_wakeup", N810_GPS_WAKEUP_GPIO,
106953018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
107053018216SPaolo Bonzini     }, {
107153018216SPaolo Bonzini         "headphone", N8X0_HEADPHONE_GPIO,
107253018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
107353018216SPaolo Bonzini     }, {
107453018216SPaolo Bonzini         "kb_lock", N810_KB_LOCK_GPIO,
107553018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
107653018216SPaolo Bonzini     }, {
107753018216SPaolo Bonzini         "sleepx_led", N810_SLEEPX_LED_GPIO,
107853018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
107953018216SPaolo Bonzini     }, {
108053018216SPaolo Bonzini         "slide", N810_SLIDE_GPIO,
108153018216SPaolo Bonzini         OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
108253018216SPaolo Bonzini     },
108353018216SPaolo Bonzini     { NULL }
108453018216SPaolo Bonzini };
108553018216SPaolo Bonzini 
108653018216SPaolo Bonzini static struct omap_partition_info_s {
108753018216SPaolo Bonzini     uint32_t offset;
108853018216SPaolo Bonzini     uint32_t size;
108953018216SPaolo Bonzini     int mask;
109053018216SPaolo Bonzini     const char *name;
109153018216SPaolo Bonzini } n800_part_info[] = {
109253018216SPaolo Bonzini     { 0x00000000, 0x00020000, 0x3, "bootloader" },
109353018216SPaolo Bonzini     { 0x00020000, 0x00060000, 0x0, "config" },
109453018216SPaolo Bonzini     { 0x00080000, 0x00200000, 0x0, "kernel" },
109553018216SPaolo Bonzini     { 0x00280000, 0x00200000, 0x3, "initfs" },
109653018216SPaolo Bonzini     { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
109753018216SPaolo Bonzini 
109853018216SPaolo Bonzini     { 0, 0, 0, NULL }
109953018216SPaolo Bonzini }, n810_part_info[] = {
110053018216SPaolo Bonzini     { 0x00000000, 0x00020000, 0x3, "bootloader" },
110153018216SPaolo Bonzini     { 0x00020000, 0x00060000, 0x0, "config" },
110253018216SPaolo Bonzini     { 0x00080000, 0x00220000, 0x0, "kernel" },
110353018216SPaolo Bonzini     { 0x002a0000, 0x00400000, 0x0, "initfs" },
110453018216SPaolo Bonzini     { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
110553018216SPaolo Bonzini 
110653018216SPaolo Bonzini     { 0, 0, 0, NULL }
110753018216SPaolo Bonzini };
110853018216SPaolo Bonzini 
110953018216SPaolo Bonzini static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
111053018216SPaolo Bonzini 
111153018216SPaolo Bonzini static int n8x0_atag_setup(void *p, int model)
111253018216SPaolo Bonzini {
111353018216SPaolo Bonzini     uint8_t *b;
111453018216SPaolo Bonzini     uint16_t *w;
111553018216SPaolo Bonzini     uint32_t *l;
111653018216SPaolo Bonzini     struct omap_gpiosw_info_s *gpiosw;
111753018216SPaolo Bonzini     struct omap_partition_info_s *partition;
111853018216SPaolo Bonzini     const char *tag;
111953018216SPaolo Bonzini 
112053018216SPaolo Bonzini     w = p;
112153018216SPaolo Bonzini 
112253018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_UART);		/* u16 tag */
112353018216SPaolo Bonzini     stw_raw(w ++, 4);				/* u16 len */
112453018216SPaolo Bonzini     stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
112553018216SPaolo Bonzini     w ++;
112653018216SPaolo Bonzini 
112753018216SPaolo Bonzini #if 0
112853018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);	/* u16 tag */
112953018216SPaolo Bonzini     stw_raw(w ++, 4);				/* u16 len */
113053018216SPaolo Bonzini     stw_raw(w ++, XLDR_LL_UART + 1);		/* u8 console_uart */
113153018216SPaolo Bonzini     stw_raw(w ++, 115200);			/* u32 console_speed */
113253018216SPaolo Bonzini #endif
113353018216SPaolo Bonzini 
113453018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_LCD);		/* u16 tag */
113553018216SPaolo Bonzini     stw_raw(w ++, 36);				/* u16 len */
113653018216SPaolo Bonzini     strcpy((void *) w, "QEMU LCD panel");	/* char panel_name[16] */
113753018216SPaolo Bonzini     w += 8;
113853018216SPaolo Bonzini     strcpy((void *) w, "blizzard");		/* char ctrl_name[16] */
113953018216SPaolo Bonzini     w += 8;
114053018216SPaolo Bonzini     stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);	/* TODO: n800 s16 nreset_gpio */
114153018216SPaolo Bonzini     stw_raw(w ++, 24);				/* u8 data_lines */
114253018216SPaolo Bonzini 
114353018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_CBUS);		/* u16 tag */
114453018216SPaolo Bonzini     stw_raw(w ++, 8);				/* u16 len */
114553018216SPaolo Bonzini     stw_raw(w ++, N8X0_CBUS_CLK_GPIO);		/* s16 clk_gpio */
114653018216SPaolo Bonzini     stw_raw(w ++, N8X0_CBUS_DAT_GPIO);		/* s16 dat_gpio */
114753018216SPaolo Bonzini     stw_raw(w ++, N8X0_CBUS_SEL_GPIO);		/* s16 sel_gpio */
114853018216SPaolo Bonzini     w ++;
114953018216SPaolo Bonzini 
115053018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);	/* u16 tag */
115153018216SPaolo Bonzini     stw_raw(w ++, 4);				/* u16 len */
115253018216SPaolo Bonzini     stw_raw(w ++, N8X0_RETU_GPIO);		/* s16 retu_irq_gpio */
115353018216SPaolo Bonzini     stw_raw(w ++, N8X0_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
115453018216SPaolo Bonzini 
115553018216SPaolo Bonzini     gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
115653018216SPaolo Bonzini     for (; gpiosw->name; gpiosw ++) {
115753018216SPaolo Bonzini         stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
115853018216SPaolo Bonzini         stw_raw(w ++, 20);			/* u16 len */
115953018216SPaolo Bonzini         strcpy((void *) w, gpiosw->name);	/* char name[12] */
116053018216SPaolo Bonzini         w += 6;
116153018216SPaolo Bonzini         stw_raw(w ++, gpiosw->line);		/* u16 gpio */
116253018216SPaolo Bonzini         stw_raw(w ++, gpiosw->type);
116353018216SPaolo Bonzini         stw_raw(w ++, 0);
116453018216SPaolo Bonzini         stw_raw(w ++, 0);
116553018216SPaolo Bonzini     }
116653018216SPaolo Bonzini 
116753018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
116853018216SPaolo Bonzini     stw_raw(w ++, 12);				/* u16 len */
116953018216SPaolo Bonzini     b = (void *) w;
117053018216SPaolo Bonzini     stb_raw(b ++, 0x01);			/* u8 chip_type	(CSR) */
117153018216SPaolo Bonzini     stb_raw(b ++, N8X0_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
117253018216SPaolo Bonzini     stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);	/* u8 host_wakeup_gpio */
117353018216SPaolo Bonzini     stb_raw(b ++, N8X0_BT_RESET_GPIO);		/* u8 reset_gpio */
117453018216SPaolo Bonzini     stb_raw(b ++, BT_UART + 1);			/* u8 bt_uart */
117553018216SPaolo Bonzini     memcpy(b, &n8x0_bd_addr, 6);		/* u8 bd_addr[6] */
117653018216SPaolo Bonzini     b += 6;
117753018216SPaolo Bonzini     stb_raw(b ++, 0x02);			/* u8 bt_sysclk (38.4) */
117853018216SPaolo Bonzini     w = (void *) b;
117953018216SPaolo Bonzini 
118053018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);	/* u16 tag */
118153018216SPaolo Bonzini     stw_raw(w ++, 8);				/* u16 len */
118253018216SPaolo Bonzini     stw_raw(w ++, 0x25);			/* u8 chip_type */
118353018216SPaolo Bonzini     stw_raw(w ++, N8X0_WLAN_PWR_GPIO);		/* s16 power_gpio */
118453018216SPaolo Bonzini     stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
118553018216SPaolo Bonzini     stw_raw(w ++, -1);				/* s16 spi_cs_gpio */
118653018216SPaolo Bonzini 
118753018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_MMC);		/* u16 tag */
118853018216SPaolo Bonzini     stw_raw(w ++, 16);				/* u16 len */
118953018216SPaolo Bonzini     if (model == 810) {
119053018216SPaolo Bonzini         stw_raw(w ++, 0x23f);			/* unsigned flags */
119153018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 power_pin */
119253018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 switch_pin */
119353018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 wp_pin */
119453018216SPaolo Bonzini         stw_raw(w ++, 0x240);			/* unsigned flags */
119553018216SPaolo Bonzini         stw_raw(w ++, 0xc000);			/* s16 power_pin */
119653018216SPaolo Bonzini         stw_raw(w ++, 0x0248);			/* s16 switch_pin */
119753018216SPaolo Bonzini         stw_raw(w ++, 0xc000);			/* s16 wp_pin */
119853018216SPaolo Bonzini     } else {
119953018216SPaolo Bonzini         stw_raw(w ++, 0xf);			/* unsigned flags */
120053018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 power_pin */
120153018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 switch_pin */
120253018216SPaolo Bonzini         stw_raw(w ++, -1);			/* s16 wp_pin */
120353018216SPaolo Bonzini         stw_raw(w ++, 0);			/* unsigned flags */
120453018216SPaolo Bonzini         stw_raw(w ++, 0);			/* s16 power_pin */
120553018216SPaolo Bonzini         stw_raw(w ++, 0);			/* s16 switch_pin */
120653018216SPaolo Bonzini         stw_raw(w ++, 0);			/* s16 wp_pin */
120753018216SPaolo Bonzini     }
120853018216SPaolo Bonzini 
120953018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_TEA5761);		/* u16 tag */
121053018216SPaolo Bonzini     stw_raw(w ++, 4);				/* u16 len */
121153018216SPaolo Bonzini     stw_raw(w ++, N8X0_TEA5761_CS_GPIO);	/* u16 enable_gpio */
121253018216SPaolo Bonzini     w ++;
121353018216SPaolo Bonzini 
121453018216SPaolo Bonzini     partition = (model == 810) ? n810_part_info : n800_part_info;
121553018216SPaolo Bonzini     for (; partition->name; partition ++) {
121653018216SPaolo Bonzini         stw_raw(w ++, OMAP_TAG_PARTITION);	/* u16 tag */
121753018216SPaolo Bonzini         stw_raw(w ++, 28);			/* u16 len */
121853018216SPaolo Bonzini         strcpy((void *) w, partition->name);	/* char name[16] */
121953018216SPaolo Bonzini         l = (void *) (w + 8);
122053018216SPaolo Bonzini         stl_raw(l ++, partition->size);		/* unsigned int size */
122153018216SPaolo Bonzini         stl_raw(l ++, partition->offset);	/* unsigned int offset */
122253018216SPaolo Bonzini         stl_raw(l ++, partition->mask);		/* unsigned int mask_flags */
122353018216SPaolo Bonzini         w = (void *) l;
122453018216SPaolo Bonzini     }
122553018216SPaolo Bonzini 
122653018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_BOOT_REASON);	/* u16 tag */
122753018216SPaolo Bonzini     stw_raw(w ++, 12);				/* u16 len */
122853018216SPaolo Bonzini #if 0
122953018216SPaolo Bonzini     strcpy((void *) w, "por");			/* char reason_str[12] */
123053018216SPaolo Bonzini     strcpy((void *) w, "charger");		/* char reason_str[12] */
123153018216SPaolo Bonzini     strcpy((void *) w, "32wd_to");		/* char reason_str[12] */
123253018216SPaolo Bonzini     strcpy((void *) w, "sw_rst");		/* char reason_str[12] */
123353018216SPaolo Bonzini     strcpy((void *) w, "mbus");			/* char reason_str[12] */
123453018216SPaolo Bonzini     strcpy((void *) w, "unknown");		/* char reason_str[12] */
123553018216SPaolo Bonzini     strcpy((void *) w, "swdg_to");		/* char reason_str[12] */
123653018216SPaolo Bonzini     strcpy((void *) w, "sec_vio");		/* char reason_str[12] */
123753018216SPaolo Bonzini     strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
123853018216SPaolo Bonzini     strcpy((void *) w, "rtc_alarm");		/* char reason_str[12] */
123953018216SPaolo Bonzini #else
124053018216SPaolo Bonzini     strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
124153018216SPaolo Bonzini #endif
124253018216SPaolo Bonzini     w += 6;
124353018216SPaolo Bonzini 
124453018216SPaolo Bonzini     tag = (model == 810) ? "RX-44" : "RX-34";
124553018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
124653018216SPaolo Bonzini     stw_raw(w ++, 24);				/* u16 len */
124753018216SPaolo Bonzini     strcpy((void *) w, "product");		/* char component[12] */
124853018216SPaolo Bonzini     w += 6;
124953018216SPaolo Bonzini     strcpy((void *) w, tag);			/* char version[12] */
125053018216SPaolo Bonzini     w += 6;
125153018216SPaolo Bonzini 
125253018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
125353018216SPaolo Bonzini     stw_raw(w ++, 24);				/* u16 len */
125453018216SPaolo Bonzini     strcpy((void *) w, "hw-build");		/* char component[12] */
125553018216SPaolo Bonzini     w += 6;
125653018216SPaolo Bonzini     strcpy((void *) w, "QEMU ");
125753018216SPaolo Bonzini     pstrcat((void *) w, 12, qemu_get_version()); /* char version[12] */
125853018216SPaolo Bonzini     w += 6;
125953018216SPaolo Bonzini 
126053018216SPaolo Bonzini     tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
126153018216SPaolo Bonzini     stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
126253018216SPaolo Bonzini     stw_raw(w ++, 24);				/* u16 len */
126353018216SPaolo Bonzini     strcpy((void *) w, "nolo");			/* char component[12] */
126453018216SPaolo Bonzini     w += 6;
126553018216SPaolo Bonzini     strcpy((void *) w, tag);			/* char version[12] */
126653018216SPaolo Bonzini     w += 6;
126753018216SPaolo Bonzini 
126853018216SPaolo Bonzini     return (void *) w - p;
126953018216SPaolo Bonzini }
127053018216SPaolo Bonzini 
127153018216SPaolo Bonzini static int n800_atag_setup(const struct arm_boot_info *info, void *p)
127253018216SPaolo Bonzini {
127353018216SPaolo Bonzini     return n8x0_atag_setup(p, 800);
127453018216SPaolo Bonzini }
127553018216SPaolo Bonzini 
127653018216SPaolo Bonzini static int n810_atag_setup(const struct arm_boot_info *info, void *p)
127753018216SPaolo Bonzini {
127853018216SPaolo Bonzini     return n8x0_atag_setup(p, 810);
127953018216SPaolo Bonzini }
128053018216SPaolo Bonzini 
1281*3ef96221SMarcel Apfelbaum static void n8x0_init(MachineState *machine,
128253018216SPaolo Bonzini                       struct arm_boot_info *binfo, int model)
128353018216SPaolo Bonzini {
128453018216SPaolo Bonzini     MemoryRegion *sysmem = get_system_memory();
128553018216SPaolo Bonzini     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
128653018216SPaolo Bonzini     int sdram_size = binfo->ram_size;
128753018216SPaolo Bonzini 
1288*3ef96221SMarcel Apfelbaum     s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_model);
128953018216SPaolo Bonzini 
129053018216SPaolo Bonzini     /* Setup peripherals
129153018216SPaolo Bonzini      *
129253018216SPaolo Bonzini      * Believed external peripherals layout in the N810:
129353018216SPaolo Bonzini      * (spi bus 1)
129453018216SPaolo Bonzini      *   tsc2005
129553018216SPaolo Bonzini      *   lcd_mipid
129653018216SPaolo Bonzini      * (spi bus 2)
129753018216SPaolo Bonzini      *   Conexant cx3110x (WLAN)
129853018216SPaolo Bonzini      *   optional: pc2400m (WiMAX)
129953018216SPaolo Bonzini      * (i2c bus 0)
130053018216SPaolo Bonzini      *   TLV320AIC33 (audio codec)
130153018216SPaolo Bonzini      *   TCM825x (camera by Toshiba)
130253018216SPaolo Bonzini      *   lp5521 (clever LEDs)
130353018216SPaolo Bonzini      *   tsl2563 (light sensor, hwmon, model 7, rev. 0)
130453018216SPaolo Bonzini      *   lm8323 (keypad, manf 00, rev 04)
130553018216SPaolo Bonzini      * (i2c bus 1)
130653018216SPaolo Bonzini      *   tmp105 (temperature sensor, hwmon)
130753018216SPaolo Bonzini      *   menelaus (pm)
130853018216SPaolo Bonzini      * (somewhere on i2c - maybe N800-only)
130953018216SPaolo Bonzini      *   tea5761 (FM tuner)
131053018216SPaolo Bonzini      * (serial 0)
131153018216SPaolo Bonzini      *   GPS
131253018216SPaolo Bonzini      * (some serial port)
131353018216SPaolo Bonzini      *   csr41814 (Bluetooth)
131453018216SPaolo Bonzini      */
131553018216SPaolo Bonzini     n8x0_gpio_setup(s);
131653018216SPaolo Bonzini     n8x0_nand_setup(s);
131753018216SPaolo Bonzini     n8x0_i2c_setup(s);
131853018216SPaolo Bonzini     if (model == 800)
131953018216SPaolo Bonzini         n800_tsc_kbd_setup(s);
132053018216SPaolo Bonzini     else if (model == 810) {
132153018216SPaolo Bonzini         n810_tsc_setup(s);
132253018216SPaolo Bonzini         n810_kbd_setup(s);
132353018216SPaolo Bonzini     }
132453018216SPaolo Bonzini     n8x0_spi_setup(s);
132553018216SPaolo Bonzini     n8x0_dss_setup(s);
132653018216SPaolo Bonzini     n8x0_cbus_setup(s);
132753018216SPaolo Bonzini     n8x0_uart_setup(s);
132853018216SPaolo Bonzini     if (usb_enabled(false)) {
132953018216SPaolo Bonzini         n8x0_usb_setup(s);
133053018216SPaolo Bonzini     }
133153018216SPaolo Bonzini 
1332*3ef96221SMarcel Apfelbaum     if (machine->kernel_filename) {
133353018216SPaolo Bonzini         /* Or at the linux loader.  */
1334*3ef96221SMarcel Apfelbaum         binfo->kernel_filename = machine->kernel_filename;
1335*3ef96221SMarcel Apfelbaum         binfo->kernel_cmdline = machine->kernel_cmdline;
1336*3ef96221SMarcel Apfelbaum         binfo->initrd_filename = machine->initrd_filename;
133753018216SPaolo Bonzini         arm_load_kernel(s->mpu->cpu, binfo);
133853018216SPaolo Bonzini 
133953018216SPaolo Bonzini         qemu_register_reset(n8x0_boot_init, s);
134053018216SPaolo Bonzini     }
134153018216SPaolo Bonzini 
134253018216SPaolo Bonzini     if (option_rom[0].name &&
1343*3ef96221SMarcel Apfelbaum         (machine->boot_order[0] == 'n' || !machine->kernel_filename)) {
134453018216SPaolo Bonzini         uint8_t nolo_tags[0x10000];
134553018216SPaolo Bonzini         /* No, wait, better start at the ROM.  */
134653018216SPaolo Bonzini         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
134753018216SPaolo Bonzini 
134853018216SPaolo Bonzini         /* This is intended for loading the `secondary.bin' program from
134953018216SPaolo Bonzini          * Nokia images (the NOLO bootloader).  The entry point seems
135053018216SPaolo Bonzini          * to be at OMAP2_Q2_BASE + 0x400000.
135153018216SPaolo Bonzini          *
135253018216SPaolo Bonzini          * The `2nd.bin' files contain some kind of earlier boot code and
135353018216SPaolo Bonzini          * for them the entry point needs to be set to OMAP2_SRAM_BASE.
135453018216SPaolo Bonzini          *
135553018216SPaolo Bonzini          * The code above is for loading the `zImage' file from Nokia
135653018216SPaolo Bonzini          * images.  */
1357591f73f6SPeter Maydell         load_image_targphys(option_rom[0].name,
135853018216SPaolo Bonzini                             OMAP2_Q2_BASE + 0x400000,
135953018216SPaolo Bonzini                             sdram_size - 0x400000);
136053018216SPaolo Bonzini 
136153018216SPaolo Bonzini         n800_setup_nolo_tags(nolo_tags);
136253018216SPaolo Bonzini         cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
136353018216SPaolo Bonzini     }
136453018216SPaolo Bonzini }
136553018216SPaolo Bonzini 
136653018216SPaolo Bonzini static struct arm_boot_info n800_binfo = {
136753018216SPaolo Bonzini     .loader_start = OMAP2_Q2_BASE,
136853018216SPaolo Bonzini     /* Actually two chips of 0x4000000 bytes each */
136953018216SPaolo Bonzini     .ram_size = 0x08000000,
137053018216SPaolo Bonzini     .board_id = 0x4f7,
137153018216SPaolo Bonzini     .atag_board = n800_atag_setup,
137253018216SPaolo Bonzini };
137353018216SPaolo Bonzini 
137453018216SPaolo Bonzini static struct arm_boot_info n810_binfo = {
137553018216SPaolo Bonzini     .loader_start = OMAP2_Q2_BASE,
137653018216SPaolo Bonzini     /* Actually two chips of 0x4000000 bytes each */
137753018216SPaolo Bonzini     .ram_size = 0x08000000,
137853018216SPaolo Bonzini     /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
137953018216SPaolo Bonzini      * used by some older versions of the bootloader and 5555 is used
138053018216SPaolo Bonzini      * instead (including versions that shipped with many devices).  */
138153018216SPaolo Bonzini     .board_id = 0x60c,
138253018216SPaolo Bonzini     .atag_board = n810_atag_setup,
138353018216SPaolo Bonzini };
138453018216SPaolo Bonzini 
1385*3ef96221SMarcel Apfelbaum static void n800_init(MachineState *machine)
138653018216SPaolo Bonzini {
1387*3ef96221SMarcel Apfelbaum     return n8x0_init(machine, &n800_binfo, 800);
138853018216SPaolo Bonzini }
138953018216SPaolo Bonzini 
1390*3ef96221SMarcel Apfelbaum static void n810_init(MachineState *machine)
139153018216SPaolo Bonzini {
1392*3ef96221SMarcel Apfelbaum     return n8x0_init(machine, &n810_binfo, 810);
139353018216SPaolo Bonzini }
139453018216SPaolo Bonzini 
139553018216SPaolo Bonzini static QEMUMachine n800_machine = {
139653018216SPaolo Bonzini     .name = "n800",
139753018216SPaolo Bonzini     .desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)",
139853018216SPaolo Bonzini     .init = n800_init,
1399c1654732SMarkus Armbruster     .default_boot_order = "",
140053018216SPaolo Bonzini };
140153018216SPaolo Bonzini 
140253018216SPaolo Bonzini static QEMUMachine n810_machine = {
140353018216SPaolo Bonzini     .name = "n810",
140453018216SPaolo Bonzini     .desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)",
140553018216SPaolo Bonzini     .init = n810_init,
1406c1654732SMarkus Armbruster     .default_boot_order = "",
140753018216SPaolo Bonzini };
140853018216SPaolo Bonzini 
140953018216SPaolo Bonzini static void nseries_machine_init(void)
141053018216SPaolo Bonzini {
141153018216SPaolo Bonzini     qemu_register_machine(&n800_machine);
141253018216SPaolo Bonzini     qemu_register_machine(&n810_machine);
141353018216SPaolo Bonzini }
141453018216SPaolo Bonzini 
141553018216SPaolo Bonzini machine_init(nseries_machine_init);
1416