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
2112b16722SPeter Maydell #include "qemu/osdep.h"
22da34e65cSMarkus Armbruster #include "qapi/error.h"
2333c11879SPaolo Bonzini #include "cpu.h"
246da68df7SThomas Huth #include "chardev/char.h"
25f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
2658369e22SPaolo Bonzini #include "qemu/bswap.h"
2715e09912SPeter Maydell #include "qemu/hw-version.h"
2871e8a915SMarkus Armbruster #include "sysemu/reset.h"
2954d31236SMarkus Armbruster #include "sysemu/runstate.h"
3053018216SPaolo Bonzini #include "sysemu/sysemu.h"
310d09e41aSPaolo Bonzini #include "hw/arm/omap.h"
3212ec8bd5SPeter Maydell #include "hw/arm/boot.h"
3353018216SPaolo Bonzini #include "hw/irq.h"
3453018216SPaolo Bonzini #include "ui/console.h"
3553018216SPaolo Bonzini #include "hw/boards.h"
360d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h"
378a08cc71SPhilippe Mathieu-Daudé #include "hw/display/blizzard.h"
38410bbee1SPhilippe Mathieu-Daudé #include "hw/input/lm832x.h"
39a331dd02SPhilippe Mathieu-Daudé #include "hw/input/tsc2xxx.h"
40e8fa3958SPhilippe Mathieu-Daudé #include "hw/misc/cbus.h"
415e9ae4b1SCorey Minyard #include "hw/sensor/tmp105.h"
42a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
430d09e41aSPaolo Bonzini #include "hw/block/flash.h"
4453018216SPaolo Bonzini #include "hw/hw.h"
4553018216SPaolo Bonzini #include "hw/loader.h"
4653018216SPaolo Bonzini #include "hw/sysbus.h"
4703dd024fSPaolo Bonzini #include "qemu/log.h"
48cc37d98bSRichard Henderson #include "qemu/error-report.h"
49cc37d98bSRichard Henderson
5053018216SPaolo Bonzini
5153018216SPaolo Bonzini /* Nokia N8x0 support */
5253018216SPaolo Bonzini struct n800_s {
5353018216SPaolo Bonzini struct omap_mpu_state_s *mpu;
5453018216SPaolo Bonzini
5553018216SPaolo Bonzini struct rfbi_chip_s blizzard;
5653018216SPaolo Bonzini struct {
5753018216SPaolo Bonzini void *opaque;
5853018216SPaolo Bonzini uint32_t (*txrx)(void *opaque, uint32_t value, int len);
5953018216SPaolo Bonzini uWireSlave *chip;
6053018216SPaolo Bonzini } ts;
6153018216SPaolo Bonzini
6253018216SPaolo Bonzini int keymap[0x80];
6353018216SPaolo Bonzini DeviceState *kbd;
6453018216SPaolo Bonzini
6553018216SPaolo Bonzini DeviceState *usb;
6653018216SPaolo Bonzini void *retu;
6753018216SPaolo Bonzini void *tahvo;
6853018216SPaolo Bonzini DeviceState *nand;
6953018216SPaolo Bonzini };
7053018216SPaolo Bonzini
7153018216SPaolo Bonzini /* GPIO pins */
7253018216SPaolo Bonzini #define N8X0_TUSB_ENABLE_GPIO 0
7353018216SPaolo Bonzini #define N800_MMC2_WP_GPIO 8
7453018216SPaolo Bonzini #define N800_UNKNOWN_GPIO0 9 /* out */
7553018216SPaolo Bonzini #define N810_MMC2_VIOSD_GPIO 9
7653018216SPaolo Bonzini #define N810_HEADSET_AMP_GPIO 10
7753018216SPaolo Bonzini #define N800_CAM_TURN_GPIO 12
7853018216SPaolo Bonzini #define N810_GPS_RESET_GPIO 12
7953018216SPaolo Bonzini #define N800_BLIZZARD_POWERDOWN_GPIO 15
8053018216SPaolo Bonzini #define N800_MMC1_WP_GPIO 23
8153018216SPaolo Bonzini #define N810_MMC2_VSD_GPIO 23
8253018216SPaolo Bonzini #define N8X0_ONENAND_GPIO 26
8353018216SPaolo Bonzini #define N810_BLIZZARD_RESET_GPIO 30
8453018216SPaolo Bonzini #define N800_UNKNOWN_GPIO2 53 /* out */
8553018216SPaolo Bonzini #define N8X0_TUSB_INT_GPIO 58
8653018216SPaolo Bonzini #define N8X0_BT_WKUP_GPIO 61
8753018216SPaolo Bonzini #define N8X0_STI_GPIO 62
8853018216SPaolo Bonzini #define N8X0_CBUS_SEL_GPIO 64
8953018216SPaolo Bonzini #define N8X0_CBUS_DAT_GPIO 65
9053018216SPaolo Bonzini #define N8X0_CBUS_CLK_GPIO 66
9153018216SPaolo Bonzini #define N8X0_WLAN_IRQ_GPIO 87
9253018216SPaolo Bonzini #define N8X0_BT_RESET_GPIO 92
9353018216SPaolo Bonzini #define N8X0_TEA5761_CS_GPIO 93
9453018216SPaolo Bonzini #define N800_UNKNOWN_GPIO 94
9553018216SPaolo Bonzini #define N810_TSC_RESET_GPIO 94
9653018216SPaolo Bonzini #define N800_CAM_ACT_GPIO 95
9753018216SPaolo Bonzini #define N810_GPS_WAKEUP_GPIO 95
9853018216SPaolo Bonzini #define N8X0_MMC_CS_GPIO 96
9953018216SPaolo Bonzini #define N8X0_WLAN_PWR_GPIO 97
10053018216SPaolo Bonzini #define N8X0_BT_HOST_WKUP_GPIO 98
10153018216SPaolo Bonzini #define N810_SPEAKER_AMP_GPIO 101
10253018216SPaolo Bonzini #define N810_KB_LOCK_GPIO 102
10353018216SPaolo Bonzini #define N800_TSC_TS_GPIO 103
10453018216SPaolo Bonzini #define N810_TSC_TS_GPIO 106
10553018216SPaolo Bonzini #define N8X0_HEADPHONE_GPIO 107
10653018216SPaolo Bonzini #define N8X0_RETU_GPIO 108
10753018216SPaolo Bonzini #define N800_TSC_KP_IRQ_GPIO 109
10853018216SPaolo Bonzini #define N810_KEYBOARD_GPIO 109
10953018216SPaolo Bonzini #define N800_BAT_COVER_GPIO 110
11053018216SPaolo Bonzini #define N810_SLIDE_GPIO 110
11153018216SPaolo Bonzini #define N8X0_TAHVO_GPIO 111
11253018216SPaolo Bonzini #define N800_UNKNOWN_GPIO4 112 /* out */
11353018216SPaolo Bonzini #define N810_SLEEPX_LED_GPIO 112
11453018216SPaolo Bonzini #define N800_TSC_RESET_GPIO 118 /* ? */
11553018216SPaolo Bonzini #define N810_AIC33_RESET_GPIO 118
11653018216SPaolo Bonzini #define N800_TSC_UNKNOWN_GPIO 119 /* out */
11753018216SPaolo Bonzini #define N8X0_TMP105_GPIO 125
11853018216SPaolo Bonzini
11953018216SPaolo Bonzini /* Config */
12053018216SPaolo Bonzini #define BT_UART 0
12153018216SPaolo Bonzini #define XLDR_LL_UART 1
12253018216SPaolo Bonzini
12353018216SPaolo Bonzini /* Addresses on the I2C bus 0 */
12453018216SPaolo Bonzini #define N810_TLV320AIC33_ADDR 0x18 /* Audio CODEC */
12553018216SPaolo Bonzini #define N8X0_TCM825x_ADDR 0x29 /* Camera */
12653018216SPaolo Bonzini #define N810_LP5521_ADDR 0x32 /* LEDs */
12753018216SPaolo Bonzini #define N810_TSL2563_ADDR 0x3d /* Light sensor */
12853018216SPaolo Bonzini #define N810_LM8323_ADDR 0x45 /* Keyboard */
12953018216SPaolo Bonzini /* Addresses on the I2C bus 1 */
13053018216SPaolo Bonzini #define N8X0_TMP105_ADDR 0x48 /* Temperature sensor */
13153018216SPaolo Bonzini #define N8X0_MENELAUS_ADDR 0x72 /* Power management */
13253018216SPaolo Bonzini
13353018216SPaolo Bonzini /* Chipselects on GPMC NOR interface */
13453018216SPaolo Bonzini #define N8X0_ONENAND_CS 0
13553018216SPaolo Bonzini #define N8X0_USB_ASYNC_CS 1
13653018216SPaolo Bonzini #define N8X0_USB_SYNC_CS 4
13753018216SPaolo Bonzini
13853018216SPaolo Bonzini #define N8X0_BD_ADDR 0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
13953018216SPaolo Bonzini
n800_mmc_cs_cb(void * opaque,int line,int level)14053018216SPaolo Bonzini static void n800_mmc_cs_cb(void *opaque, int line, int level)
14153018216SPaolo Bonzini {
14253018216SPaolo Bonzini /* TODO: this seems to actually be connected to the menelaus, to
14353018216SPaolo Bonzini * which also both MMC slots connect. */
14453018216SPaolo Bonzini omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
14553018216SPaolo Bonzini }
14653018216SPaolo Bonzini
n8x0_gpio_setup(struct n800_s * s)14753018216SPaolo Bonzini static void n8x0_gpio_setup(struct n800_s *s)
14853018216SPaolo Bonzini {
149294972ceSShannon Zhao qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO,
150294972ceSShannon Zhao qemu_allocate_irq(n800_mmc_cs_cb, s->mpu->mmc, 0));
15153018216SPaolo Bonzini qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
15253018216SPaolo Bonzini }
15353018216SPaolo Bonzini
15453018216SPaolo Bonzini #define MAEMO_CAL_HEADER(...) \
15553018216SPaolo Bonzini 'C', 'o', 'n', 'F', 0x02, 0x00, 0x04, 0x00, \
15653018216SPaolo Bonzini __VA_ARGS__, \
15753018216SPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15853018216SPaolo Bonzini
15953018216SPaolo Bonzini static const uint8_t n8x0_cal_wlan_mac[] = {
16053018216SPaolo Bonzini MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
16153018216SPaolo Bonzini 0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
16253018216SPaolo Bonzini 0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
16353018216SPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
16453018216SPaolo Bonzini 0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
16553018216SPaolo Bonzini 0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
16653018216SPaolo Bonzini };
16753018216SPaolo Bonzini
16853018216SPaolo Bonzini static const uint8_t n8x0_cal_bt_id[] = {
16953018216SPaolo Bonzini MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
17053018216SPaolo Bonzini 0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
17153018216SPaolo Bonzini 0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
17253018216SPaolo Bonzini N8X0_BD_ADDR,
17353018216SPaolo Bonzini };
17453018216SPaolo Bonzini
n8x0_nand_setup(struct n800_s * s)17553018216SPaolo Bonzini static void n8x0_nand_setup(struct n800_s *s)
17653018216SPaolo Bonzini {
17753018216SPaolo Bonzini char *otp_region;
17853018216SPaolo Bonzini DriveInfo *dinfo;
17953018216SPaolo Bonzini
1803e80f690SMarkus Armbruster s->nand = qdev_new("onenand");
18153018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
18253018216SPaolo Bonzini /* Either 0x40 or 0x48 are OK for the device ID */
18353018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "device_id", 0x48);
18453018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "version_id", 0);
18553018216SPaolo Bonzini qdev_prop_set_int32(s->nand, "shift", 1);
18653018216SPaolo Bonzini dinfo = drive_get(IF_MTD, 0, 0);
187fa1d36dfSMarkus Armbruster if (dinfo) {
188934df912SMarkus Armbruster qdev_prop_set_drive_err(s->nand, "drive", blk_by_legacy_dinfo(dinfo),
1896231a6daSMarkus Armbruster &error_fatal);
19053018216SPaolo Bonzini }
1913c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(s->nand), &error_fatal);
19253018216SPaolo Bonzini sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
19353018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
19453018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
19553018216SPaolo Bonzini sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
19653018216SPaolo Bonzini otp_region = onenand_raw_otp(s->nand);
19753018216SPaolo Bonzini
19853018216SPaolo Bonzini memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
19953018216SPaolo Bonzini memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
20053018216SPaolo Bonzini /* XXX: in theory should also update the OOB for both pages */
20153018216SPaolo Bonzini }
20253018216SPaolo Bonzini
20353018216SPaolo Bonzini static qemu_irq n8x0_system_powerdown;
20453018216SPaolo Bonzini
n8x0_powerdown_req(Notifier * n,void * opaque)20553018216SPaolo Bonzini static void n8x0_powerdown_req(Notifier *n, void *opaque)
20653018216SPaolo Bonzini {
20753018216SPaolo Bonzini qemu_irq_raise(n8x0_system_powerdown);
20853018216SPaolo Bonzini }
20953018216SPaolo Bonzini
21053018216SPaolo Bonzini static Notifier n8x0_system_powerdown_notifier = {
21153018216SPaolo Bonzini .notify = n8x0_powerdown_req
21253018216SPaolo Bonzini };
21353018216SPaolo Bonzini
n8x0_i2c_setup(struct n800_s * s)21453018216SPaolo Bonzini static void n8x0_i2c_setup(struct n800_s *s)
21553018216SPaolo Bonzini {
21653018216SPaolo Bonzini DeviceState *dev;
21753018216SPaolo Bonzini qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
218a5c82852SAndreas Färber I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
21953018216SPaolo Bonzini
22053018216SPaolo Bonzini /* Attach a menelaus PM chip */
2211373b15bSPhilippe Mathieu-Daudé dev = DEVICE(i2c_slave_create_simple(i2c, "twl92230", N8X0_MENELAUS_ADDR));
22253018216SPaolo Bonzini qdev_connect_gpio_out(dev, 3,
22353018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->ih[0],
22453018216SPaolo Bonzini OMAP_INT_24XX_SYS_NIRQ));
22553018216SPaolo Bonzini
22653018216SPaolo Bonzini n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
22753018216SPaolo Bonzini qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
22853018216SPaolo Bonzini
22953018216SPaolo Bonzini /* Attach a TMP105 PM chip (A0 wired to ground) */
2301373b15bSPhilippe Mathieu-Daudé dev = DEVICE(i2c_slave_create_simple(i2c, TYPE_TMP105, N8X0_TMP105_ADDR));
23153018216SPaolo Bonzini qdev_connect_gpio_out(dev, 0, tmp_irq);
23253018216SPaolo Bonzini }
23353018216SPaolo Bonzini
23453018216SPaolo Bonzini /* Touchscreen and keypad controller */
235bd8d01bfSPhilippe Mathieu-Daudé static const MouseTransformInfo n800_pointercal = {
23653018216SPaolo Bonzini .x = 800,
23753018216SPaolo Bonzini .y = 480,
23853018216SPaolo Bonzini .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
23953018216SPaolo Bonzini };
24053018216SPaolo Bonzini
241bd8d01bfSPhilippe Mathieu-Daudé static const MouseTransformInfo n810_pointercal = {
24253018216SPaolo Bonzini .x = 800,
24353018216SPaolo Bonzini .y = 480,
24453018216SPaolo Bonzini .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
24553018216SPaolo Bonzini };
24653018216SPaolo Bonzini
24753018216SPaolo Bonzini #define RETU_KEYCODE 61 /* F3 */
24853018216SPaolo Bonzini
n800_key_event(void * opaque,int keycode)24953018216SPaolo Bonzini static void n800_key_event(void *opaque, int keycode)
25053018216SPaolo Bonzini {
25153018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque;
25253018216SPaolo Bonzini int code = s->keymap[keycode & 0x7f];
25353018216SPaolo Bonzini
25453018216SPaolo Bonzini if (code == -1) {
255fddbd80cSPaolo Bonzini if ((keycode & 0x7f) == RETU_KEYCODE) {
25653018216SPaolo Bonzini retu_key_event(s->retu, !(keycode & 0x80));
257fddbd80cSPaolo Bonzini }
25853018216SPaolo Bonzini return;
25953018216SPaolo Bonzini }
26053018216SPaolo Bonzini
26153018216SPaolo Bonzini tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
26253018216SPaolo Bonzini }
26353018216SPaolo Bonzini
26453018216SPaolo Bonzini static const int n800_keys[16] = {
26553018216SPaolo Bonzini -1,
26653018216SPaolo Bonzini 72, /* Up */
26753018216SPaolo Bonzini 63, /* Home (F5) */
26853018216SPaolo Bonzini -1,
26953018216SPaolo Bonzini 75, /* Left */
27053018216SPaolo Bonzini 28, /* Enter */
27153018216SPaolo Bonzini 77, /* Right */
27253018216SPaolo Bonzini -1,
27353018216SPaolo Bonzini 1, /* Cycle (ESC) */
27453018216SPaolo Bonzini 80, /* Down */
27553018216SPaolo Bonzini 62, /* Menu (F4) */
27653018216SPaolo Bonzini -1,
27753018216SPaolo Bonzini 66, /* Zoom- (F8) */
27853018216SPaolo Bonzini 64, /* FullScreen (F6) */
27953018216SPaolo Bonzini 65, /* Zoom+ (F7) */
28053018216SPaolo Bonzini -1,
28153018216SPaolo Bonzini };
28253018216SPaolo Bonzini
n800_tsc_kbd_setup(struct n800_s * s)28353018216SPaolo Bonzini static void n800_tsc_kbd_setup(struct n800_s *s)
28453018216SPaolo Bonzini {
28553018216SPaolo Bonzini int i;
28653018216SPaolo Bonzini
28753018216SPaolo Bonzini /* XXX: are the three pins inverted inside the chip between the
28853018216SPaolo Bonzini * tsc and the cpu (N4111)? */
28953018216SPaolo Bonzini qemu_irq penirq = NULL; /* NC */
29053018216SPaolo Bonzini qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
29153018216SPaolo Bonzini qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
29253018216SPaolo Bonzini
29353018216SPaolo Bonzini s->ts.chip = tsc2301_init(penirq, kbirq, dav);
29453018216SPaolo Bonzini s->ts.opaque = s->ts.chip->opaque;
29553018216SPaolo Bonzini s->ts.txrx = tsc210x_txrx;
29653018216SPaolo Bonzini
297fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) {
29853018216SPaolo Bonzini s->keymap[i] = -1;
299fddbd80cSPaolo Bonzini }
300fddbd80cSPaolo Bonzini for (i = 0; i < 0x10; i++) {
301fddbd80cSPaolo Bonzini if (n800_keys[i] >= 0) {
30253018216SPaolo Bonzini s->keymap[n800_keys[i]] = i;
303fddbd80cSPaolo Bonzini }
304fddbd80cSPaolo Bonzini }
30553018216SPaolo Bonzini
30653018216SPaolo Bonzini qemu_add_kbd_event_handler(n800_key_event, s);
30753018216SPaolo Bonzini
30853018216SPaolo Bonzini tsc210x_set_transform(s->ts.chip, &n800_pointercal);
30953018216SPaolo Bonzini }
31053018216SPaolo Bonzini
n810_tsc_setup(struct n800_s * s)31153018216SPaolo Bonzini static void n810_tsc_setup(struct n800_s *s)
31253018216SPaolo Bonzini {
31353018216SPaolo Bonzini qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
31453018216SPaolo Bonzini
31553018216SPaolo Bonzini s->ts.opaque = tsc2005_init(pintdav);
31653018216SPaolo Bonzini s->ts.txrx = tsc2005_txrx;
31753018216SPaolo Bonzini
31853018216SPaolo Bonzini tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
31953018216SPaolo Bonzini }
32053018216SPaolo Bonzini
32153018216SPaolo Bonzini /* N810 Keyboard controller */
n810_key_event(void * opaque,int keycode)32253018216SPaolo Bonzini static void n810_key_event(void *opaque, int keycode)
32353018216SPaolo Bonzini {
32453018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque;
32553018216SPaolo Bonzini int code = s->keymap[keycode & 0x7f];
32653018216SPaolo Bonzini
32753018216SPaolo Bonzini if (code == -1) {
328fddbd80cSPaolo Bonzini if ((keycode & 0x7f) == RETU_KEYCODE) {
32953018216SPaolo Bonzini retu_key_event(s->retu, !(keycode & 0x80));
330fddbd80cSPaolo Bonzini }
33153018216SPaolo Bonzini return;
33253018216SPaolo Bonzini }
33353018216SPaolo Bonzini
33453018216SPaolo Bonzini lm832x_key_event(s->kbd, code, !(keycode & 0x80));
33553018216SPaolo Bonzini }
33653018216SPaolo Bonzini
33753018216SPaolo Bonzini #define M 0
33853018216SPaolo Bonzini
339bd8d01bfSPhilippe Mathieu-Daudé static const int n810_keys[0x80] = {
34053018216SPaolo Bonzini [0x01] = 16, /* Q */
34153018216SPaolo Bonzini [0x02] = 37, /* K */
34253018216SPaolo Bonzini [0x03] = 24, /* O */
34353018216SPaolo Bonzini [0x04] = 25, /* P */
34453018216SPaolo Bonzini [0x05] = 14, /* Backspace */
34553018216SPaolo Bonzini [0x06] = 30, /* A */
34653018216SPaolo Bonzini [0x07] = 31, /* S */
34753018216SPaolo Bonzini [0x08] = 32, /* D */
34853018216SPaolo Bonzini [0x09] = 33, /* F */
34953018216SPaolo Bonzini [0x0a] = 34, /* G */
35053018216SPaolo Bonzini [0x0b] = 35, /* H */
35153018216SPaolo Bonzini [0x0c] = 36, /* J */
35253018216SPaolo Bonzini
35353018216SPaolo Bonzini [0x11] = 17, /* W */
35453018216SPaolo Bonzini [0x12] = 62, /* Menu (F4) */
35553018216SPaolo Bonzini [0x13] = 38, /* L */
35653018216SPaolo Bonzini [0x14] = 40, /* ' (Apostrophe) */
35753018216SPaolo Bonzini [0x16] = 44, /* Z */
35853018216SPaolo Bonzini [0x17] = 45, /* X */
35953018216SPaolo Bonzini [0x18] = 46, /* C */
36053018216SPaolo Bonzini [0x19] = 47, /* V */
36153018216SPaolo Bonzini [0x1a] = 48, /* B */
36253018216SPaolo Bonzini [0x1b] = 49, /* N */
36353018216SPaolo Bonzini [0x1c] = 42, /* Shift (Left shift) */
36453018216SPaolo Bonzini [0x1f] = 65, /* Zoom+ (F7) */
36553018216SPaolo Bonzini
36653018216SPaolo Bonzini [0x21] = 18, /* E */
36753018216SPaolo Bonzini [0x22] = 39, /* ; (Semicolon) */
36853018216SPaolo Bonzini [0x23] = 12, /* - (Minus) */
36953018216SPaolo Bonzini [0x24] = 13, /* = (Equal) */
37053018216SPaolo Bonzini [0x2b] = 56, /* Fn (Left Alt) */
37153018216SPaolo Bonzini [0x2c] = 50, /* M */
37253018216SPaolo Bonzini [0x2f] = 66, /* Zoom- (F8) */
37353018216SPaolo Bonzini
37453018216SPaolo Bonzini [0x31] = 19, /* R */
37553018216SPaolo Bonzini [0x32] = 29 | M, /* Right Ctrl */
37653018216SPaolo Bonzini [0x34] = 57, /* Space */
37753018216SPaolo Bonzini [0x35] = 51, /* , (Comma) */
37853018216SPaolo Bonzini [0x37] = 72 | M, /* Up */
37953018216SPaolo Bonzini [0x3c] = 82 | M, /* Compose (Insert) */
38053018216SPaolo Bonzini [0x3f] = 64, /* FullScreen (F6) */
38153018216SPaolo Bonzini
38253018216SPaolo Bonzini [0x41] = 20, /* T */
38353018216SPaolo Bonzini [0x44] = 52, /* . (Dot) */
38453018216SPaolo Bonzini [0x46] = 77 | M, /* Right */
38553018216SPaolo Bonzini [0x4f] = 63, /* Home (F5) */
38653018216SPaolo Bonzini [0x51] = 21, /* Y */
38753018216SPaolo Bonzini [0x53] = 80 | M, /* Down */
38853018216SPaolo Bonzini [0x55] = 28, /* Enter */
38953018216SPaolo Bonzini [0x5f] = 1, /* Cycle (ESC) */
39053018216SPaolo Bonzini
39153018216SPaolo Bonzini [0x61] = 22, /* U */
39253018216SPaolo Bonzini [0x64] = 75 | M, /* Left */
39353018216SPaolo Bonzini
39453018216SPaolo Bonzini [0x71] = 23, /* I */
39553018216SPaolo Bonzini #if 0
39653018216SPaolo Bonzini [0x75] = 28 | M, /* KP Enter (KP Enter) */
39753018216SPaolo Bonzini #else
39853018216SPaolo Bonzini [0x75] = 15, /* KP Enter (Tab) */
39953018216SPaolo Bonzini #endif
40053018216SPaolo Bonzini };
40153018216SPaolo Bonzini
40253018216SPaolo Bonzini #undef M
40353018216SPaolo Bonzini
n810_kbd_setup(struct n800_s * s)40453018216SPaolo Bonzini static void n810_kbd_setup(struct n800_s *s)
40553018216SPaolo Bonzini {
40653018216SPaolo Bonzini qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
40753018216SPaolo Bonzini int i;
40853018216SPaolo Bonzini
409fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) {
41053018216SPaolo Bonzini s->keymap[i] = -1;
411fddbd80cSPaolo Bonzini }
412fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) {
413fddbd80cSPaolo Bonzini if (n810_keys[i] > 0) {
41453018216SPaolo Bonzini s->keymap[n810_keys[i]] = i;
415fddbd80cSPaolo Bonzini }
416fddbd80cSPaolo Bonzini }
41753018216SPaolo Bonzini
41853018216SPaolo Bonzini qemu_add_kbd_event_handler(n810_key_event, s);
41953018216SPaolo Bonzini
42053018216SPaolo Bonzini /* Attach the LM8322 keyboard to the I2C bus,
42153018216SPaolo Bonzini * should happen in n8x0_i2c_setup and s->kbd be initialised here. */
4221373b15bSPhilippe Mathieu-Daudé s->kbd = DEVICE(i2c_slave_create_simple(omap_i2c_bus(s->mpu->i2c[0]),
423426f53deSPhilippe Mathieu-Daudé TYPE_LM8323, N810_LM8323_ADDR));
42453018216SPaolo Bonzini qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
42553018216SPaolo Bonzini }
42653018216SPaolo Bonzini
42753018216SPaolo Bonzini /* LCD MIPI DBI-C controller (URAL) */
42853018216SPaolo Bonzini struct mipid_s {
42953018216SPaolo Bonzini int resp[4];
43053018216SPaolo Bonzini int param[4];
43153018216SPaolo Bonzini int p;
43253018216SPaolo Bonzini int pm;
43353018216SPaolo Bonzini int cmd;
43453018216SPaolo Bonzini
43553018216SPaolo Bonzini int sleep;
43653018216SPaolo Bonzini int booster;
43753018216SPaolo Bonzini int te;
43853018216SPaolo Bonzini int selfcheck;
43953018216SPaolo Bonzini int partial;
44053018216SPaolo Bonzini int normal;
44153018216SPaolo Bonzini int vscr;
44253018216SPaolo Bonzini int invert;
44353018216SPaolo Bonzini int onoff;
44453018216SPaolo Bonzini int gamma;
44553018216SPaolo Bonzini uint32_t id;
44653018216SPaolo Bonzini };
44753018216SPaolo Bonzini
mipid_reset(struct mipid_s * s)44853018216SPaolo Bonzini static void mipid_reset(struct mipid_s *s)
44953018216SPaolo Bonzini {
45053018216SPaolo Bonzini s->pm = 0;
45153018216SPaolo Bonzini s->cmd = 0;
45253018216SPaolo Bonzini
45353018216SPaolo Bonzini s->sleep = 1;
45453018216SPaolo Bonzini s->booster = 0;
45553018216SPaolo Bonzini s->selfcheck =
45653018216SPaolo Bonzini (1 << 7) | /* Register loading OK. */
45753018216SPaolo Bonzini (1 << 5) | /* The chip is attached. */
45853018216SPaolo Bonzini (1 << 4); /* Display glass still in one piece. */
45953018216SPaolo Bonzini s->te = 0;
46053018216SPaolo Bonzini s->partial = 0;
46153018216SPaolo Bonzini s->normal = 1;
46253018216SPaolo Bonzini s->vscr = 0;
46353018216SPaolo Bonzini s->invert = 0;
46453018216SPaolo Bonzini s->onoff = 1;
46553018216SPaolo Bonzini s->gamma = 0;
46653018216SPaolo Bonzini }
46753018216SPaolo Bonzini
mipid_txrx(void * opaque,uint32_t cmd,int len)46853018216SPaolo Bonzini static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
46953018216SPaolo Bonzini {
47053018216SPaolo Bonzini struct mipid_s *s = (struct mipid_s *) opaque;
47153018216SPaolo Bonzini uint8_t ret;
47253018216SPaolo Bonzini
473fddbd80cSPaolo Bonzini if (len > 9) {
474a89f364aSAlistair Francis hw_error("%s: FIXME: bad SPI word width %i\n", __func__, len);
475fddbd80cSPaolo Bonzini }
47653018216SPaolo Bonzini
477fddbd80cSPaolo Bonzini if (s->p >= ARRAY_SIZE(s->resp)) {
47853018216SPaolo Bonzini ret = 0;
479fddbd80cSPaolo Bonzini } else {
48053018216SPaolo Bonzini ret = s->resp[s->p++];
481fddbd80cSPaolo Bonzini }
482fddbd80cSPaolo Bonzini if (s->pm-- > 0) {
48353018216SPaolo Bonzini s->param[s->pm] = cmd;
484fddbd80cSPaolo Bonzini } else {
48553018216SPaolo Bonzini s->cmd = cmd;
486fddbd80cSPaolo Bonzini }
48753018216SPaolo Bonzini
48853018216SPaolo Bonzini switch (s->cmd) {
48953018216SPaolo Bonzini case 0x00: /* NOP */
49053018216SPaolo Bonzini break;
49153018216SPaolo Bonzini
49253018216SPaolo Bonzini case 0x01: /* SWRESET */
49353018216SPaolo Bonzini mipid_reset(s);
49453018216SPaolo Bonzini break;
49553018216SPaolo Bonzini
49653018216SPaolo Bonzini case 0x02: /* BSTROFF */
49753018216SPaolo Bonzini s->booster = 0;
49853018216SPaolo Bonzini break;
49953018216SPaolo Bonzini case 0x03: /* BSTRON */
50053018216SPaolo Bonzini s->booster = 1;
50153018216SPaolo Bonzini break;
50253018216SPaolo Bonzini
50353018216SPaolo Bonzini case 0x04: /* RDDID */
50453018216SPaolo Bonzini s->p = 0;
50553018216SPaolo Bonzini s->resp[0] = (s->id >> 16) & 0xff;
50653018216SPaolo Bonzini s->resp[1] = (s->id >> 8) & 0xff;
50753018216SPaolo Bonzini s->resp[2] = (s->id >> 0) & 0xff;
50853018216SPaolo Bonzini break;
50953018216SPaolo Bonzini
51053018216SPaolo Bonzini case 0x06: /* RD_RED */
51153018216SPaolo Bonzini case 0x07: /* RD_GREEN */
51253018216SPaolo Bonzini /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
51353018216SPaolo Bonzini * for the bootloader one needs to change this. */
51453018216SPaolo Bonzini case 0x08: /* RD_BLUE */
51553018216SPaolo Bonzini s->p = 0;
51653018216SPaolo Bonzini /* TODO: return first pixel components */
51753018216SPaolo Bonzini s->resp[0] = 0x01;
51853018216SPaolo Bonzini break;
51953018216SPaolo Bonzini
52053018216SPaolo Bonzini case 0x09: /* RDDST */
52153018216SPaolo Bonzini s->p = 0;
52253018216SPaolo Bonzini s->resp[0] = s->booster << 7;
52353018216SPaolo Bonzini s->resp[1] = (5 << 4) | (s->partial << 2) |
52453018216SPaolo Bonzini (s->sleep << 1) | s->normal;
52553018216SPaolo Bonzini s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
52653018216SPaolo Bonzini (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
52753018216SPaolo Bonzini s->resp[3] = s->gamma << 6;
52853018216SPaolo Bonzini break;
52953018216SPaolo Bonzini
53053018216SPaolo Bonzini case 0x0a: /* RDDPM */
53153018216SPaolo Bonzini s->p = 0;
53253018216SPaolo Bonzini s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
53353018216SPaolo Bonzini (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
53453018216SPaolo Bonzini break;
53553018216SPaolo Bonzini case 0x0b: /* RDDMADCTR */
53653018216SPaolo Bonzini s->p = 0;
53753018216SPaolo Bonzini s->resp[0] = 0;
53853018216SPaolo Bonzini break;
53953018216SPaolo Bonzini case 0x0c: /* RDDCOLMOD */
54053018216SPaolo Bonzini s->p = 0;
54153018216SPaolo Bonzini s->resp[0] = 5; /* 65K colours */
54253018216SPaolo Bonzini break;
54353018216SPaolo Bonzini case 0x0d: /* RDDIM */
54453018216SPaolo Bonzini s->p = 0;
54553018216SPaolo Bonzini s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
54653018216SPaolo Bonzini break;
54753018216SPaolo Bonzini case 0x0e: /* RDDSM */
54853018216SPaolo Bonzini s->p = 0;
54953018216SPaolo Bonzini s->resp[0] = s->te << 7;
55053018216SPaolo Bonzini break;
55153018216SPaolo Bonzini case 0x0f: /* RDDSDR */
55253018216SPaolo Bonzini s->p = 0;
55353018216SPaolo Bonzini s->resp[0] = s->selfcheck;
55453018216SPaolo Bonzini break;
55553018216SPaolo Bonzini
55653018216SPaolo Bonzini case 0x10: /* SLPIN */
55753018216SPaolo Bonzini s->sleep = 1;
55853018216SPaolo Bonzini break;
55953018216SPaolo Bonzini case 0x11: /* SLPOUT */
56053018216SPaolo Bonzini s->sleep = 0;
56153018216SPaolo Bonzini s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */
56253018216SPaolo Bonzini break;
56353018216SPaolo Bonzini
56453018216SPaolo Bonzini case 0x12: /* PTLON */
56553018216SPaolo Bonzini s->partial = 1;
56653018216SPaolo Bonzini s->normal = 0;
56753018216SPaolo Bonzini s->vscr = 0;
56853018216SPaolo Bonzini break;
56953018216SPaolo Bonzini case 0x13: /* NORON */
57053018216SPaolo Bonzini s->partial = 0;
57153018216SPaolo Bonzini s->normal = 1;
57253018216SPaolo Bonzini s->vscr = 0;
57353018216SPaolo Bonzini break;
57453018216SPaolo Bonzini
57553018216SPaolo Bonzini case 0x20: /* INVOFF */
57653018216SPaolo Bonzini s->invert = 0;
57753018216SPaolo Bonzini break;
57853018216SPaolo Bonzini case 0x21: /* INVON */
57953018216SPaolo Bonzini s->invert = 1;
58053018216SPaolo Bonzini break;
58153018216SPaolo Bonzini
58253018216SPaolo Bonzini case 0x22: /* APOFF */
58353018216SPaolo Bonzini case 0x23: /* APON */
58453018216SPaolo Bonzini goto bad_cmd;
58553018216SPaolo Bonzini
58653018216SPaolo Bonzini case 0x25: /* WRCNTR */
587fddbd80cSPaolo Bonzini if (s->pm < 0) {
58853018216SPaolo Bonzini s->pm = 1;
589fddbd80cSPaolo Bonzini }
59053018216SPaolo Bonzini goto bad_cmd;
59153018216SPaolo Bonzini
59253018216SPaolo Bonzini case 0x26: /* GAMSET */
593fddbd80cSPaolo Bonzini if (!s->pm) {
594ad5f5fdcSStefan Hajnoczi s->gamma = ctz32(s->param[0] & 0xf);
595ad5f5fdcSStefan Hajnoczi if (s->gamma == 32) {
596ad5f5fdcSStefan Hajnoczi s->gamma = -1; /* XXX: should this be 0? */
597ad5f5fdcSStefan Hajnoczi }
598fddbd80cSPaolo Bonzini } else if (s->pm < 0) {
59953018216SPaolo Bonzini s->pm = 1;
600fddbd80cSPaolo Bonzini }
60153018216SPaolo Bonzini break;
60253018216SPaolo Bonzini
60353018216SPaolo Bonzini case 0x28: /* DISPOFF */
60453018216SPaolo Bonzini s->onoff = 0;
60553018216SPaolo Bonzini break;
60653018216SPaolo Bonzini case 0x29: /* DISPON */
60753018216SPaolo Bonzini s->onoff = 1;
60853018216SPaolo Bonzini break;
60953018216SPaolo Bonzini
61053018216SPaolo Bonzini case 0x2a: /* CASET */
61153018216SPaolo Bonzini case 0x2b: /* RASET */
61253018216SPaolo Bonzini case 0x2c: /* RAMWR */
61353018216SPaolo Bonzini case 0x2d: /* RGBSET */
61453018216SPaolo Bonzini case 0x2e: /* RAMRD */
61553018216SPaolo Bonzini case 0x30: /* PTLAR */
61653018216SPaolo Bonzini case 0x33: /* SCRLAR */
61753018216SPaolo Bonzini goto bad_cmd;
61853018216SPaolo Bonzini
61953018216SPaolo Bonzini case 0x34: /* TEOFF */
62053018216SPaolo Bonzini s->te = 0;
62153018216SPaolo Bonzini break;
62253018216SPaolo Bonzini case 0x35: /* TEON */
623fddbd80cSPaolo Bonzini if (!s->pm) {
62453018216SPaolo Bonzini s->te = 1;
625fddbd80cSPaolo Bonzini } else if (s->pm < 0) {
62653018216SPaolo Bonzini s->pm = 1;
627fddbd80cSPaolo Bonzini }
62853018216SPaolo Bonzini break;
62953018216SPaolo Bonzini
63053018216SPaolo Bonzini case 0x36: /* MADCTR */
63153018216SPaolo Bonzini goto bad_cmd;
63253018216SPaolo Bonzini
63353018216SPaolo Bonzini case 0x37: /* VSCSAD */
63453018216SPaolo Bonzini s->partial = 0;
63553018216SPaolo Bonzini s->normal = 0;
63653018216SPaolo Bonzini s->vscr = 1;
63753018216SPaolo Bonzini break;
63853018216SPaolo Bonzini
63953018216SPaolo Bonzini case 0x38: /* IDMOFF */
64053018216SPaolo Bonzini case 0x39: /* IDMON */
64153018216SPaolo Bonzini case 0x3a: /* COLMOD */
64253018216SPaolo Bonzini goto bad_cmd;
64353018216SPaolo Bonzini
64453018216SPaolo Bonzini case 0xb0: /* CLKINT / DISCTL */
64553018216SPaolo Bonzini case 0xb1: /* CLKEXT */
646fddbd80cSPaolo Bonzini if (s->pm < 0) {
64753018216SPaolo Bonzini s->pm = 2;
648fddbd80cSPaolo Bonzini }
64953018216SPaolo Bonzini break;
65053018216SPaolo Bonzini
65153018216SPaolo Bonzini case 0xb4: /* FRMSEL */
65253018216SPaolo Bonzini break;
65353018216SPaolo Bonzini
65453018216SPaolo Bonzini case 0xb5: /* FRM8SEL */
65553018216SPaolo Bonzini case 0xb6: /* TMPRNG / INIESC */
65653018216SPaolo Bonzini case 0xb7: /* TMPHIS / NOP2 */
65753018216SPaolo Bonzini case 0xb8: /* TMPREAD / MADCTL */
65853018216SPaolo Bonzini case 0xba: /* DISTCTR */
65953018216SPaolo Bonzini case 0xbb: /* EPVOL */
66053018216SPaolo Bonzini goto bad_cmd;
66153018216SPaolo Bonzini
66253018216SPaolo Bonzini case 0xbd: /* Unknown */
66353018216SPaolo Bonzini s->p = 0;
66453018216SPaolo Bonzini s->resp[0] = 0;
66553018216SPaolo Bonzini s->resp[1] = 1;
66653018216SPaolo Bonzini break;
66753018216SPaolo Bonzini
66853018216SPaolo Bonzini case 0xc2: /* IFMOD */
669fddbd80cSPaolo Bonzini if (s->pm < 0) {
67053018216SPaolo Bonzini s->pm = 2;
671fddbd80cSPaolo Bonzini }
67253018216SPaolo Bonzini break;
67353018216SPaolo Bonzini
67453018216SPaolo Bonzini case 0xc6: /* PWRCTL */
67553018216SPaolo Bonzini case 0xc7: /* PPWRCTL */
67653018216SPaolo Bonzini case 0xd0: /* EPWROUT */
67753018216SPaolo Bonzini case 0xd1: /* EPWRIN */
67853018216SPaolo Bonzini case 0xd4: /* RDEV */
67953018216SPaolo Bonzini case 0xd5: /* RDRR */
68053018216SPaolo Bonzini goto bad_cmd;
68153018216SPaolo Bonzini
68253018216SPaolo Bonzini case 0xda: /* RDID1 */
68353018216SPaolo Bonzini s->p = 0;
68453018216SPaolo Bonzini s->resp[0] = (s->id >> 16) & 0xff;
68553018216SPaolo Bonzini break;
68653018216SPaolo Bonzini case 0xdb: /* RDID2 */
68753018216SPaolo Bonzini s->p = 0;
68853018216SPaolo Bonzini s->resp[0] = (s->id >> 8) & 0xff;
68953018216SPaolo Bonzini break;
69053018216SPaolo Bonzini case 0xdc: /* RDID3 */
69153018216SPaolo Bonzini s->p = 0;
69253018216SPaolo Bonzini s->resp[0] = (s->id >> 0) & 0xff;
69353018216SPaolo Bonzini break;
69453018216SPaolo Bonzini
69553018216SPaolo Bonzini default:
69653018216SPaolo Bonzini bad_cmd:
697591f73f6SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR,
698b1c2a6bdSPhilippe Mathieu-Daudé "%s: unknown command 0x%02x\n", __func__, s->cmd);
69953018216SPaolo Bonzini break;
70053018216SPaolo Bonzini }
70153018216SPaolo Bonzini
70253018216SPaolo Bonzini return ret;
70353018216SPaolo Bonzini }
70453018216SPaolo Bonzini
mipid_init(void)70553018216SPaolo Bonzini static void *mipid_init(void)
70653018216SPaolo Bonzini {
7070a553c12SMarkus Armbruster struct mipid_s *s = g_malloc0(sizeof(*s));
70853018216SPaolo Bonzini
70953018216SPaolo Bonzini s->id = 0x838f03;
71053018216SPaolo Bonzini mipid_reset(s);
71153018216SPaolo Bonzini
71253018216SPaolo Bonzini return s;
71353018216SPaolo Bonzini }
71453018216SPaolo Bonzini
n8x0_spi_setup(struct n800_s * s)71553018216SPaolo Bonzini static void n8x0_spi_setup(struct n800_s *s)
71653018216SPaolo Bonzini {
71753018216SPaolo Bonzini void *tsc = s->ts.opaque;
71853018216SPaolo Bonzini void *mipid = mipid_init();
71953018216SPaolo Bonzini
72053018216SPaolo Bonzini omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
72153018216SPaolo Bonzini omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
72253018216SPaolo Bonzini }
72353018216SPaolo Bonzini
72453018216SPaolo Bonzini /* This task is normally performed by the bootloader. If we're loading
72553018216SPaolo Bonzini * a kernel directly, we need to enable the Blizzard ourselves. */
n800_dss_init(struct rfbi_chip_s * chip)72653018216SPaolo Bonzini static void n800_dss_init(struct rfbi_chip_s *chip)
72753018216SPaolo Bonzini {
72853018216SPaolo Bonzini uint8_t *fb_blank;
72953018216SPaolo Bonzini
73053018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */
73153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x64);
73253018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */
73353018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1e);
73453018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */
73553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xe0);
73653018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */
73753018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01);
73853018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */
73953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x06);
74053018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x68); /* Display Mode register */
74153018216SPaolo Bonzini chip->write(chip->opaque, 1, 1); /* Enable bit */
74253018216SPaolo Bonzini
74353018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x6c);
74453018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */
74553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */
74653018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */
74753018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */
74853018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1f); /* Input X End Position */
74953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x03); /* Input X End Position */
75053018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xdf); /* Input Y End Position */
75153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Input Y End Position */
75253018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */
75353018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */
75453018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */
75553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */
75653018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1f); /* Output X End Position */
75753018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x03); /* Output X End Position */
75853018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xdf); /* Output Y End Position */
75953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Output Y End Position */
76053018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Input Data Format */
76153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Data Source Select */
76253018216SPaolo Bonzini
76353018216SPaolo Bonzini fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
76453018216SPaolo Bonzini /* Display Memory Data Port */
76553018216SPaolo Bonzini chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
76653018216SPaolo Bonzini g_free(fb_blank);
76753018216SPaolo Bonzini }
76853018216SPaolo Bonzini
n8x0_dss_setup(struct n800_s * s)76953018216SPaolo Bonzini static void n8x0_dss_setup(struct n800_s *s)
77053018216SPaolo Bonzini {
77153018216SPaolo Bonzini s->blizzard.opaque = s1d13745_init(NULL);
77253018216SPaolo Bonzini s->blizzard.block = s1d13745_write_block;
77353018216SPaolo Bonzini s->blizzard.write = s1d13745_write;
77453018216SPaolo Bonzini s->blizzard.read = s1d13745_read;
77553018216SPaolo Bonzini
77653018216SPaolo Bonzini omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
77753018216SPaolo Bonzini }
77853018216SPaolo Bonzini
n8x0_cbus_setup(struct n800_s * s)77953018216SPaolo Bonzini static void n8x0_cbus_setup(struct n800_s *s)
78053018216SPaolo Bonzini {
78153018216SPaolo Bonzini qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
78253018216SPaolo Bonzini qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
78353018216SPaolo Bonzini qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
78453018216SPaolo Bonzini
78553018216SPaolo Bonzini CBus *cbus = cbus_init(dat_out);
78653018216SPaolo Bonzini
78753018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
78853018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
78953018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
79053018216SPaolo Bonzini
79153018216SPaolo Bonzini cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
79253018216SPaolo Bonzini cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
79353018216SPaolo Bonzini }
79453018216SPaolo Bonzini
n8x0_usb_setup(struct n800_s * s)79553018216SPaolo Bonzini static void n8x0_usb_setup(struct n800_s *s)
79653018216SPaolo Bonzini {
79753018216SPaolo Bonzini SysBusDevice *dev;
7983e80f690SMarkus Armbruster s->usb = qdev_new("tusb6010");
79953018216SPaolo Bonzini dev = SYS_BUS_DEVICE(s->usb);
8003c6ef471SMarkus Armbruster sysbus_realize_and_unref(dev, &error_fatal);
80153018216SPaolo Bonzini sysbus_connect_irq(dev, 0,
80253018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
80353018216SPaolo Bonzini /* Using the NOR interface */
80453018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
80553018216SPaolo Bonzini sysbus_mmio_get_region(dev, 0));
80653018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
80753018216SPaolo Bonzini sysbus_mmio_get_region(dev, 1));
80853018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
80953018216SPaolo Bonzini qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
81053018216SPaolo Bonzini }
81153018216SPaolo Bonzini
81253018216SPaolo Bonzini /* Setup done before the main bootloader starts by some early setup code
81353018216SPaolo Bonzini * - used when we want to run the main bootloader in emulation. This
81453018216SPaolo Bonzini * isn't documented. */
815bd8d01bfSPhilippe Mathieu-Daudé static const uint32_t n800_pinout[104] = {
81653018216SPaolo Bonzini 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
81753018216SPaolo Bonzini 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
81853018216SPaolo Bonzini 0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
81953018216SPaolo Bonzini 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
82053018216SPaolo Bonzini 0x01241800, 0x18181818, 0x000000f0, 0x01300000,
82153018216SPaolo Bonzini 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
82253018216SPaolo Bonzini 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
82353018216SPaolo Bonzini 0x007c0000, 0x00000000, 0x00000088, 0x00840000,
82453018216SPaolo Bonzini 0x00000000, 0x00000094, 0x00980300, 0x0f180003,
82553018216SPaolo Bonzini 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
82653018216SPaolo Bonzini 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
82753018216SPaolo Bonzini 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
82853018216SPaolo Bonzini 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
82953018216SPaolo Bonzini 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
83053018216SPaolo Bonzini 0x00000000, 0x00000038, 0x00340000, 0x00000000,
83153018216SPaolo Bonzini 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
83253018216SPaolo Bonzini 0x005c0808, 0x08080808, 0x08080058, 0x00540808,
83353018216SPaolo Bonzini 0x08080808, 0x0808006c, 0x00680808, 0x08080808,
83453018216SPaolo Bonzini 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
83553018216SPaolo Bonzini 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
83653018216SPaolo Bonzini 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
83753018216SPaolo Bonzini 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
83853018216SPaolo Bonzini 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
83953018216SPaolo Bonzini 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
84053018216SPaolo Bonzini 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
84153018216SPaolo Bonzini 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
84253018216SPaolo Bonzini };
84353018216SPaolo Bonzini
n800_setup_nolo_tags(void * sram_base)84453018216SPaolo Bonzini static void n800_setup_nolo_tags(void *sram_base)
84553018216SPaolo Bonzini {
84653018216SPaolo Bonzini int i;
84753018216SPaolo Bonzini uint32_t *p = sram_base + 0x8000;
84853018216SPaolo Bonzini uint32_t *v = sram_base + 0xa000;
84953018216SPaolo Bonzini
85053018216SPaolo Bonzini memset(p, 0, 0x3000);
85153018216SPaolo Bonzini
85253018216SPaolo Bonzini strcpy((void *) (p + 0), "QEMU N800");
85353018216SPaolo Bonzini
85453018216SPaolo Bonzini strcpy((void *) (p + 8), "F5");
85553018216SPaolo Bonzini
8560983979bSPaolo Bonzini stl_p(p + 10, 0x04f70000);
85753018216SPaolo Bonzini strcpy((void *) (p + 9), "RX-34");
85853018216SPaolo Bonzini
85953018216SPaolo Bonzini /* RAM size in MB? */
8600983979bSPaolo Bonzini stl_p(p + 12, 0x80);
86153018216SPaolo Bonzini
86253018216SPaolo Bonzini /* Pointer to the list of tags */
8630983979bSPaolo Bonzini stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
86453018216SPaolo Bonzini
86553018216SPaolo Bonzini /* The NOLO tags start here */
86653018216SPaolo Bonzini p = sram_base + 0x9000;
86753018216SPaolo Bonzini #define ADD_TAG(tag, len) \
8680983979bSPaolo Bonzini stw_p((uint16_t *) p + 0, tag); \
8690983979bSPaolo Bonzini stw_p((uint16_t *) p + 1, len); p++; \
8700983979bSPaolo Bonzini stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
87153018216SPaolo Bonzini
87253018216SPaolo Bonzini /* OMAP STI console? Pin out settings? */
87353018216SPaolo Bonzini ADD_TAG(0x6e01, 414);
874fddbd80cSPaolo Bonzini for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
8750983979bSPaolo Bonzini stl_p(v++, n800_pinout[i]);
876fddbd80cSPaolo Bonzini }
87753018216SPaolo Bonzini
87853018216SPaolo Bonzini /* Kernel memsize? */
87953018216SPaolo Bonzini ADD_TAG(0x6e05, 1);
8800983979bSPaolo Bonzini stl_p(v++, 2);
88153018216SPaolo Bonzini
88253018216SPaolo Bonzini /* NOLO serial console */
88353018216SPaolo Bonzini ADD_TAG(0x6e02, 4);
8840983979bSPaolo Bonzini stl_p(v++, XLDR_LL_UART); /* UART number (1 - 3) */
88553018216SPaolo Bonzini
88653018216SPaolo Bonzini #if 0
88753018216SPaolo Bonzini /* CBUS settings (Retu/AVilma) */
88853018216SPaolo Bonzini ADD_TAG(0x6e03, 6);
8890983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
8900983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
8910983979bSPaolo Bonzini stw_p((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
89253018216SPaolo Bonzini v += 2;
89353018216SPaolo Bonzini #endif
89453018216SPaolo Bonzini
89553018216SPaolo Bonzini /* Nokia ASIC BB5 (Retu/Tahvo) */
89653018216SPaolo Bonzini ADD_TAG(0x6e0a, 4);
8970983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
8980983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
89953018216SPaolo Bonzini v++;
90053018216SPaolo Bonzini
90153018216SPaolo Bonzini /* LCD console? */
90253018216SPaolo Bonzini ADD_TAG(0x6e04, 4);
9030983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 30); /* ??? */
9040983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 24); /* ??? */
90553018216SPaolo Bonzini v++;
90653018216SPaolo Bonzini
90753018216SPaolo Bonzini #if 0
90853018216SPaolo Bonzini /* LCD settings */
90953018216SPaolo Bonzini ADD_TAG(0x6e06, 2);
9100983979bSPaolo Bonzini stw_p((uint16_t *) (v++), 15); /* ??? */
91153018216SPaolo Bonzini #endif
91253018216SPaolo Bonzini
91353018216SPaolo Bonzini /* I^2C (Menelaus) */
91453018216SPaolo Bonzini ADD_TAG(0x6e07, 4);
9150983979bSPaolo Bonzini stl_p(v++, 0x00720000); /* ??? */
91653018216SPaolo Bonzini
91753018216SPaolo Bonzini /* Unknown */
91853018216SPaolo Bonzini ADD_TAG(0x6e0b, 6);
9190983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 94); /* ??? */
9200983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 23); /* ??? */
9210983979bSPaolo Bonzini stw_p((uint16_t *) v + 2, 0); /* ??? */
92253018216SPaolo Bonzini v += 2;
92353018216SPaolo Bonzini
92453018216SPaolo Bonzini /* OMAP gpio switch info */
92553018216SPaolo Bonzini ADD_TAG(0x6e0c, 80);
92653018216SPaolo Bonzini strcpy((void *) v, "bat_cover"); v += 3;
9270983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 110); /* GPIO num ??? */
9280983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 1); /* GPIO num ??? */
92953018216SPaolo Bonzini v += 2;
93053018216SPaolo Bonzini strcpy((void *) v, "cam_act"); v += 3;
9310983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 95); /* GPIO num ??? */
9320983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 32); /* GPIO num ??? */
93353018216SPaolo Bonzini v += 2;
93453018216SPaolo Bonzini strcpy((void *) v, "cam_turn"); v += 3;
9350983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 12); /* GPIO num ??? */
9360983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 33); /* GPIO num ??? */
93753018216SPaolo Bonzini v += 2;
93853018216SPaolo Bonzini strcpy((void *) v, "headphone"); v += 3;
9390983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 107); /* GPIO num ??? */
9400983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 17); /* GPIO num ??? */
94153018216SPaolo Bonzini v += 2;
94253018216SPaolo Bonzini
94353018216SPaolo Bonzini /* Bluetooth */
94453018216SPaolo Bonzini ADD_TAG(0x6e0e, 12);
9450983979bSPaolo Bonzini stl_p(v++, 0x5c623d01); /* ??? */
9460983979bSPaolo Bonzini stl_p(v++, 0x00000201); /* ??? */
9470983979bSPaolo Bonzini stl_p(v++, 0x00000000); /* ??? */
94853018216SPaolo Bonzini
94953018216SPaolo Bonzini /* CX3110x WLAN settings */
95053018216SPaolo Bonzini ADD_TAG(0x6e0f, 8);
9510983979bSPaolo Bonzini stl_p(v++, 0x00610025); /* ??? */
9520983979bSPaolo Bonzini stl_p(v++, 0xffff0057); /* ??? */
95353018216SPaolo Bonzini
95453018216SPaolo Bonzini /* MMC host settings */
95553018216SPaolo Bonzini ADD_TAG(0x6e10, 12);
9560983979bSPaolo Bonzini stl_p(v++, 0xffff000f); /* ??? */
9570983979bSPaolo Bonzini stl_p(v++, 0xffffffff); /* ??? */
9580983979bSPaolo Bonzini stl_p(v++, 0x00000060); /* ??? */
95953018216SPaolo Bonzini
96053018216SPaolo Bonzini /* OneNAND chip select */
96153018216SPaolo Bonzini ADD_TAG(0x6e11, 10);
9620983979bSPaolo Bonzini stl_p(v++, 0x00000401); /* ??? */
9630983979bSPaolo Bonzini stl_p(v++, 0x0002003a); /* ??? */
9640983979bSPaolo Bonzini stl_p(v++, 0x00000002); /* ??? */
96553018216SPaolo Bonzini
96653018216SPaolo Bonzini /* TEA5761 sensor settings */
96753018216SPaolo Bonzini ADD_TAG(0x6e12, 2);
9680983979bSPaolo Bonzini stl_p(v++, 93); /* GPIO num ??? */
96953018216SPaolo Bonzini
97053018216SPaolo Bonzini #if 0
97153018216SPaolo Bonzini /* Unknown tag */
97253018216SPaolo Bonzini ADD_TAG(6e09, 0);
97353018216SPaolo Bonzini
97453018216SPaolo Bonzini /* Kernel UART / console */
97553018216SPaolo Bonzini ADD_TAG(6e12, 0);
97653018216SPaolo Bonzini #endif
97753018216SPaolo Bonzini
97853018216SPaolo Bonzini /* End of the list */
9790983979bSPaolo Bonzini stl_p(p++, 0x00000000);
9800983979bSPaolo Bonzini stl_p(p++, 0x00000000);
98153018216SPaolo Bonzini }
98253018216SPaolo Bonzini
98353018216SPaolo Bonzini /* This task is normally performed by the bootloader. If we're loading
98453018216SPaolo Bonzini * a kernel directly, we need to set up GPMC mappings ourselves. */
n800_gpmc_init(struct n800_s * s)98553018216SPaolo Bonzini static void n800_gpmc_init(struct n800_s *s)
98653018216SPaolo Bonzini {
98753018216SPaolo Bonzini uint32_t config7 =
98853018216SPaolo Bonzini (0xf << 8) | /* MASKADDRESS */
98953018216SPaolo Bonzini (1 << 6) | /* CSVALID */
99053018216SPaolo Bonzini (4 << 0); /* BASEADDRESS */
99153018216SPaolo Bonzini
99253018216SPaolo Bonzini cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */
993e1fe50dcSStefan Weil &config7, sizeof(config7));
99453018216SPaolo Bonzini }
99553018216SPaolo Bonzini
99653018216SPaolo Bonzini /* Setup sequence done by the bootloader */
n8x0_boot_init(void * opaque)99753018216SPaolo Bonzini static void n8x0_boot_init(void *opaque)
99853018216SPaolo Bonzini {
99953018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque;
100053018216SPaolo Bonzini uint32_t buf;
100153018216SPaolo Bonzini
100253018216SPaolo Bonzini /* PRCM setup */
100353018216SPaolo Bonzini #define omap_writel(addr, val) \
100453018216SPaolo Bonzini buf = (val); \
1005e1fe50dcSStefan Weil cpu_physical_memory_write(addr, &buf, sizeof(buf))
100653018216SPaolo Bonzini
100753018216SPaolo Bonzini omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */
100853018216SPaolo Bonzini omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */
100953018216SPaolo Bonzini omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */
101053018216SPaolo Bonzini omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */
101153018216SPaolo Bonzini omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */
101253018216SPaolo Bonzini omap_writel(0x48008098, 0); /* PRCM_POLCTRL */
101353018216SPaolo Bonzini omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */
101453018216SPaolo Bonzini omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */
101553018216SPaolo Bonzini omap_writel(0x48008158, 1); /* RM_RSTST_MPU */
101653018216SPaolo Bonzini omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */
101753018216SPaolo Bonzini omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */
101853018216SPaolo Bonzini omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */
101953018216SPaolo Bonzini omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */
102053018216SPaolo Bonzini omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */
102153018216SPaolo Bonzini omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */
102253018216SPaolo Bonzini omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */
102353018216SPaolo Bonzini omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */
102453018216SPaolo Bonzini omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */
102553018216SPaolo Bonzini omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */
102653018216SPaolo Bonzini omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */
102753018216SPaolo Bonzini omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */
102853018216SPaolo Bonzini omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */
102953018216SPaolo Bonzini omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */
103053018216SPaolo Bonzini omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */
103153018216SPaolo Bonzini omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */
103253018216SPaolo Bonzini omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */
103353018216SPaolo Bonzini omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */
103453018216SPaolo Bonzini omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */
103553018216SPaolo Bonzini omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */
103653018216SPaolo Bonzini omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */
103753018216SPaolo Bonzini omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */
103853018216SPaolo Bonzini omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */
103953018216SPaolo Bonzini omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */
104053018216SPaolo Bonzini omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */
104153018216SPaolo Bonzini omap_writel(0x48008540, /* CM_CLKSEL1_PLL */
104253018216SPaolo Bonzini (0x78 << 12) | (6 << 8));
104353018216SPaolo Bonzini omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */
104453018216SPaolo Bonzini
104553018216SPaolo Bonzini /* GPMC setup */
104653018216SPaolo Bonzini n800_gpmc_init(s);
104753018216SPaolo Bonzini
104853018216SPaolo Bonzini /* Video setup */
104953018216SPaolo Bonzini n800_dss_init(&s->blizzard);
105053018216SPaolo Bonzini
105153018216SPaolo Bonzini /* CPU setup */
105253018216SPaolo Bonzini s->mpu->cpu->env.GE = 0x5;
105353018216SPaolo Bonzini
105453018216SPaolo Bonzini /* If the machine has a slided keyboard, open it */
1055fddbd80cSPaolo Bonzini if (s->kbd) {
105653018216SPaolo Bonzini qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
105753018216SPaolo Bonzini }
1058fddbd80cSPaolo Bonzini }
105953018216SPaolo Bonzini
106053018216SPaolo Bonzini #define OMAP_TAG_NOKIA_BT 0x4e01
106153018216SPaolo Bonzini #define OMAP_TAG_WLAN_CX3110X 0x4e02
106253018216SPaolo Bonzini #define OMAP_TAG_CBUS 0x4e03
106353018216SPaolo Bonzini #define OMAP_TAG_EM_ASIC_BB5 0x4e04
106453018216SPaolo Bonzini
1065bd8d01bfSPhilippe Mathieu-Daudé static const struct omap_gpiosw_info_s {
106653018216SPaolo Bonzini const char *name;
106753018216SPaolo Bonzini int line;
106853018216SPaolo Bonzini int type;
106953018216SPaolo Bonzini } n800_gpiosw_info[] = {
107053018216SPaolo Bonzini {
107153018216SPaolo Bonzini "bat_cover", N800_BAT_COVER_GPIO,
107253018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
107353018216SPaolo Bonzini }, {
107453018216SPaolo Bonzini "cam_act", N800_CAM_ACT_GPIO,
107553018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY,
107653018216SPaolo Bonzini }, {
107753018216SPaolo Bonzini "cam_turn", N800_CAM_TURN_GPIO,
107853018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
107953018216SPaolo Bonzini }, {
108053018216SPaolo Bonzini "headphone", N8X0_HEADPHONE_GPIO,
108153018216SPaolo Bonzini OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
108253018216SPaolo Bonzini },
10836aee3400SPhilippe Mathieu-Daudé { /* end of list */ }
108453018216SPaolo Bonzini }, n810_gpiosw_info[] = {
108553018216SPaolo Bonzini {
108653018216SPaolo Bonzini "gps_reset", N810_GPS_RESET_GPIO,
108753018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
108853018216SPaolo Bonzini }, {
108953018216SPaolo Bonzini "gps_wakeup", N810_GPS_WAKEUP_GPIO,
109053018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
109153018216SPaolo Bonzini }, {
109253018216SPaolo Bonzini "headphone", N8X0_HEADPHONE_GPIO,
109353018216SPaolo Bonzini OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
109453018216SPaolo Bonzini }, {
109553018216SPaolo Bonzini "kb_lock", N810_KB_LOCK_GPIO,
109653018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
109753018216SPaolo Bonzini }, {
109853018216SPaolo Bonzini "sleepx_led", N810_SLEEPX_LED_GPIO,
109953018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
110053018216SPaolo Bonzini }, {
110153018216SPaolo Bonzini "slide", N810_SLIDE_GPIO,
110253018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
110353018216SPaolo Bonzini },
11046aee3400SPhilippe Mathieu-Daudé { /* end of list */ }
110553018216SPaolo Bonzini };
110653018216SPaolo Bonzini
1107bd8d01bfSPhilippe Mathieu-Daudé static const struct omap_partition_info_s {
110853018216SPaolo Bonzini uint32_t offset;
110953018216SPaolo Bonzini uint32_t size;
111053018216SPaolo Bonzini int mask;
111153018216SPaolo Bonzini const char *name;
111253018216SPaolo Bonzini } n800_part_info[] = {
111353018216SPaolo Bonzini { 0x00000000, 0x00020000, 0x3, "bootloader" },
111453018216SPaolo Bonzini { 0x00020000, 0x00060000, 0x0, "config" },
111553018216SPaolo Bonzini { 0x00080000, 0x00200000, 0x0, "kernel" },
111653018216SPaolo Bonzini { 0x00280000, 0x00200000, 0x3, "initfs" },
111753018216SPaolo Bonzini { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
11186aee3400SPhilippe Mathieu-Daudé { /* end of list */ }
111953018216SPaolo Bonzini }, n810_part_info[] = {
112053018216SPaolo Bonzini { 0x00000000, 0x00020000, 0x3, "bootloader" },
112153018216SPaolo Bonzini { 0x00020000, 0x00060000, 0x0, "config" },
112253018216SPaolo Bonzini { 0x00080000, 0x00220000, 0x0, "kernel" },
112353018216SPaolo Bonzini { 0x002a0000, 0x00400000, 0x0, "initfs" },
112453018216SPaolo Bonzini { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
11256aee3400SPhilippe Mathieu-Daudé { /* end of list */ }
112653018216SPaolo Bonzini };
112753018216SPaolo Bonzini
1128bd8d01bfSPhilippe Mathieu-Daudé static const uint8_t n8x0_bd_addr[6] = { N8X0_BD_ADDR };
112953018216SPaolo Bonzini
n8x0_atag_setup(void * p,int model)113053018216SPaolo Bonzini static int n8x0_atag_setup(void *p, int model)
113153018216SPaolo Bonzini {
113253018216SPaolo Bonzini uint8_t *b;
113353018216SPaolo Bonzini uint16_t *w;
113453018216SPaolo Bonzini uint32_t *l;
1135bd8d01bfSPhilippe Mathieu-Daudé const struct omap_gpiosw_info_s *gpiosw;
1136bd8d01bfSPhilippe Mathieu-Daudé const struct omap_partition_info_s *partition;
113753018216SPaolo Bonzini const char *tag;
113853018216SPaolo Bonzini
113953018216SPaolo Bonzini w = p;
114053018216SPaolo Bonzini
11410983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_UART); /* u16 tag */
11420983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */
11430983979bSPaolo Bonzini stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
114453018216SPaolo Bonzini w++;
114553018216SPaolo Bonzini
114653018216SPaolo Bonzini #if 0
11470983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
11480983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */
11490983979bSPaolo Bonzini stw_p(w++, XLDR_LL_UART + 1); /* u8 console_uart */
11500983979bSPaolo Bonzini stw_p(w++, 115200); /* u32 console_speed */
115153018216SPaolo Bonzini #endif
115253018216SPaolo Bonzini
11530983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_LCD); /* u16 tag */
11540983979bSPaolo Bonzini stw_p(w++, 36); /* u16 len */
115553018216SPaolo Bonzini strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */
115653018216SPaolo Bonzini w += 8;
115753018216SPaolo Bonzini strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */
115853018216SPaolo Bonzini w += 8;
11590983979bSPaolo Bonzini stw_p(w++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
11600983979bSPaolo Bonzini stw_p(w++, 24); /* u8 data_lines */
116153018216SPaolo Bonzini
11620983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_CBUS); /* u16 tag */
11630983979bSPaolo Bonzini stw_p(w++, 8); /* u16 len */
11640983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
11650983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
11660983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
116753018216SPaolo Bonzini w++;
116853018216SPaolo Bonzini
11690983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
11700983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */
11710983979bSPaolo Bonzini stw_p(w++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
11720983979bSPaolo Bonzini stw_p(w++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
117353018216SPaolo Bonzini
117453018216SPaolo Bonzini gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
117553018216SPaolo Bonzini for (; gpiosw->name; gpiosw++) {
11760983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
11770983979bSPaolo Bonzini stw_p(w++, 20); /* u16 len */
117853018216SPaolo Bonzini strcpy((void *) w, gpiosw->name); /* char name[12] */
117953018216SPaolo Bonzini w += 6;
11800983979bSPaolo Bonzini stw_p(w++, gpiosw->line); /* u16 gpio */
11810983979bSPaolo Bonzini stw_p(w++, gpiosw->type);
11820983979bSPaolo Bonzini stw_p(w++, 0);
11830983979bSPaolo Bonzini stw_p(w++, 0);
118453018216SPaolo Bonzini }
118553018216SPaolo Bonzini
11860983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_NOKIA_BT); /* u16 tag */
11870983979bSPaolo Bonzini stw_p(w++, 12); /* u16 len */
118853018216SPaolo Bonzini b = (void *) w;
11890983979bSPaolo Bonzini stb_p(b++, 0x01); /* u8 chip_type (CSR) */
11900983979bSPaolo Bonzini stb_p(b++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
11910983979bSPaolo Bonzini stb_p(b++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
11920983979bSPaolo Bonzini stb_p(b++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
11930983979bSPaolo Bonzini stb_p(b++, BT_UART + 1); /* u8 bt_uart */
119453018216SPaolo Bonzini memcpy(b, &n8x0_bd_addr, 6); /* u8 bd_addr[6] */
119553018216SPaolo Bonzini b += 6;
11960983979bSPaolo Bonzini stb_p(b++, 0x02); /* u8 bt_sysclk (38.4) */
119753018216SPaolo Bonzini w = (void *) b;
119853018216SPaolo Bonzini
11990983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
12000983979bSPaolo Bonzini stw_p(w++, 8); /* u16 len */
12010983979bSPaolo Bonzini stw_p(w++, 0x25); /* u8 chip_type */
12020983979bSPaolo Bonzini stw_p(w++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
12030983979bSPaolo Bonzini stw_p(w++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
12040983979bSPaolo Bonzini stw_p(w++, -1); /* s16 spi_cs_gpio */
120553018216SPaolo Bonzini
12060983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_MMC); /* u16 tag */
12070983979bSPaolo Bonzini stw_p(w++, 16); /* u16 len */
120853018216SPaolo Bonzini if (model == 810) {
12090983979bSPaolo Bonzini stw_p(w++, 0x23f); /* unsigned flags */
12100983979bSPaolo Bonzini stw_p(w++, -1); /* s16 power_pin */
12110983979bSPaolo Bonzini stw_p(w++, -1); /* s16 switch_pin */
12120983979bSPaolo Bonzini stw_p(w++, -1); /* s16 wp_pin */
12130983979bSPaolo Bonzini stw_p(w++, 0x240); /* unsigned flags */
12140983979bSPaolo Bonzini stw_p(w++, 0xc000); /* s16 power_pin */
12150983979bSPaolo Bonzini stw_p(w++, 0x0248); /* s16 switch_pin */
12160983979bSPaolo Bonzini stw_p(w++, 0xc000); /* s16 wp_pin */
121753018216SPaolo Bonzini } else {
12180983979bSPaolo Bonzini stw_p(w++, 0xf); /* unsigned flags */
12190983979bSPaolo Bonzini stw_p(w++, -1); /* s16 power_pin */
12200983979bSPaolo Bonzini stw_p(w++, -1); /* s16 switch_pin */
12210983979bSPaolo Bonzini stw_p(w++, -1); /* s16 wp_pin */
12220983979bSPaolo Bonzini stw_p(w++, 0); /* unsigned flags */
12230983979bSPaolo Bonzini stw_p(w++, 0); /* s16 power_pin */
12240983979bSPaolo Bonzini stw_p(w++, 0); /* s16 switch_pin */
12250983979bSPaolo Bonzini stw_p(w++, 0); /* s16 wp_pin */
122653018216SPaolo Bonzini }
122753018216SPaolo Bonzini
12280983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_TEA5761); /* u16 tag */
12290983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */
12300983979bSPaolo Bonzini stw_p(w++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
123153018216SPaolo Bonzini w++;
123253018216SPaolo Bonzini
123353018216SPaolo Bonzini partition = (model == 810) ? n810_part_info : n800_part_info;
123453018216SPaolo Bonzini for (; partition->name; partition++) {
12350983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_PARTITION); /* u16 tag */
12360983979bSPaolo Bonzini stw_p(w++, 28); /* u16 len */
123753018216SPaolo Bonzini strcpy((void *) w, partition->name); /* char name[16] */
123853018216SPaolo Bonzini l = (void *) (w + 8);
12390983979bSPaolo Bonzini stl_p(l++, partition->size); /* unsigned int size */
12400983979bSPaolo Bonzini stl_p(l++, partition->offset); /* unsigned int offset */
12410983979bSPaolo Bonzini stl_p(l++, partition->mask); /* unsigned int mask_flags */
124253018216SPaolo Bonzini w = (void *) l;
124353018216SPaolo Bonzini }
124453018216SPaolo Bonzini
12450983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_BOOT_REASON); /* u16 tag */
12460983979bSPaolo Bonzini stw_p(w++, 12); /* u16 len */
124753018216SPaolo Bonzini #if 0
124853018216SPaolo Bonzini strcpy((void *) w, "por"); /* char reason_str[12] */
124953018216SPaolo Bonzini strcpy((void *) w, "charger"); /* char reason_str[12] */
125053018216SPaolo Bonzini strcpy((void *) w, "32wd_to"); /* char reason_str[12] */
125153018216SPaolo Bonzini strcpy((void *) w, "sw_rst"); /* char reason_str[12] */
125253018216SPaolo Bonzini strcpy((void *) w, "mbus"); /* char reason_str[12] */
125353018216SPaolo Bonzini strcpy((void *) w, "unknown"); /* char reason_str[12] */
125453018216SPaolo Bonzini strcpy((void *) w, "swdg_to"); /* char reason_str[12] */
125553018216SPaolo Bonzini strcpy((void *) w, "sec_vio"); /* char reason_str[12] */
125653018216SPaolo Bonzini strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
125753018216SPaolo Bonzini strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */
125853018216SPaolo Bonzini #else
125953018216SPaolo Bonzini strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
126053018216SPaolo Bonzini #endif
126153018216SPaolo Bonzini w += 6;
126253018216SPaolo Bonzini
126353018216SPaolo Bonzini tag = (model == 810) ? "RX-44" : "RX-34";
12640983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
12650983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */
126653018216SPaolo Bonzini strcpy((void *) w, "product"); /* char component[12] */
126753018216SPaolo Bonzini w += 6;
126853018216SPaolo Bonzini strcpy((void *) w, tag); /* char version[12] */
126953018216SPaolo Bonzini w += 6;
127053018216SPaolo Bonzini
12710983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
12720983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */
127353018216SPaolo Bonzini strcpy((void *) w, "hw-build"); /* char component[12] */
127453018216SPaolo Bonzini w += 6;
127553018216SPaolo Bonzini strcpy((void *) w, "QEMU ");
127635c2c8dcSEduardo Habkost pstrcat((void *) w, 12, qemu_hw_version()); /* char version[12] */
127753018216SPaolo Bonzini w += 6;
127853018216SPaolo Bonzini
127953018216SPaolo Bonzini tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
12800983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
12810983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */
128253018216SPaolo Bonzini strcpy((void *) w, "nolo"); /* char component[12] */
128353018216SPaolo Bonzini w += 6;
128453018216SPaolo Bonzini strcpy((void *) w, tag); /* char version[12] */
128553018216SPaolo Bonzini w += 6;
128653018216SPaolo Bonzini
128753018216SPaolo Bonzini return (void *) w - p;
128853018216SPaolo Bonzini }
128953018216SPaolo Bonzini
n800_atag_setup(const struct arm_boot_info * info,void * p)129053018216SPaolo Bonzini static int n800_atag_setup(const struct arm_boot_info *info, void *p)
129153018216SPaolo Bonzini {
129253018216SPaolo Bonzini return n8x0_atag_setup(p, 800);
129353018216SPaolo Bonzini }
129453018216SPaolo Bonzini
n810_atag_setup(const struct arm_boot_info * info,void * p)129553018216SPaolo Bonzini static int n810_atag_setup(const struct arm_boot_info *info, void *p)
129653018216SPaolo Bonzini {
129753018216SPaolo Bonzini return n8x0_atag_setup(p, 810);
129853018216SPaolo Bonzini }
129953018216SPaolo Bonzini
n8x0_init(MachineState * machine,struct arm_boot_info * binfo,int model)13003ef96221SMarcel Apfelbaum static void n8x0_init(MachineState *machine,
130153018216SPaolo Bonzini struct arm_boot_info *binfo, int model)
130253018216SPaolo Bonzini {
13030a553c12SMarkus Armbruster struct n800_s *s = g_malloc0(sizeof(*s));
13047998beb9SIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine);
130553018216SPaolo Bonzini
13067998beb9SIgor Mammedov if (machine->ram_size != mc->default_ram_size) {
13077998beb9SIgor Mammedov char *sz = size_to_str(mc->default_ram_size);
13087998beb9SIgor Mammedov error_report("Invalid RAM size, should be %s", sz);
13097998beb9SIgor Mammedov g_free(sz);
13107998beb9SIgor Mammedov exit(EXIT_FAILURE);
13117998beb9SIgor Mammedov }
1312b3267ff6SPhilippe Mathieu-Daudé binfo->ram_size = machine->ram_size;
1313e285e867SPhilippe Mathieu-Daudé
13147998beb9SIgor Mammedov memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
13157998beb9SIgor Mammedov machine->ram);
13167998beb9SIgor Mammedov
13177998beb9SIgor Mammedov s->mpu = omap2420_mpu_init(machine->ram, machine->cpu_type);
131853018216SPaolo Bonzini
131953018216SPaolo Bonzini /* Setup peripherals
132053018216SPaolo Bonzini *
132153018216SPaolo Bonzini * Believed external peripherals layout in the N810:
132253018216SPaolo Bonzini * (spi bus 1)
132353018216SPaolo Bonzini * tsc2005
132453018216SPaolo Bonzini * lcd_mipid
132553018216SPaolo Bonzini * (spi bus 2)
132653018216SPaolo Bonzini * Conexant cx3110x (WLAN)
132753018216SPaolo Bonzini * optional: pc2400m (WiMAX)
132853018216SPaolo Bonzini * (i2c bus 0)
132953018216SPaolo Bonzini * TLV320AIC33 (audio codec)
133053018216SPaolo Bonzini * TCM825x (camera by Toshiba)
133153018216SPaolo Bonzini * lp5521 (clever LEDs)
133253018216SPaolo Bonzini * tsl2563 (light sensor, hwmon, model 7, rev. 0)
133353018216SPaolo Bonzini * lm8323 (keypad, manf 00, rev 04)
133453018216SPaolo Bonzini * (i2c bus 1)
133553018216SPaolo Bonzini * tmp105 (temperature sensor, hwmon)
133653018216SPaolo Bonzini * menelaus (pm)
133753018216SPaolo Bonzini * (somewhere on i2c - maybe N800-only)
133853018216SPaolo Bonzini * tea5761 (FM tuner)
133953018216SPaolo Bonzini * (serial 0)
134053018216SPaolo Bonzini * GPS
134153018216SPaolo Bonzini * (some serial port)
134253018216SPaolo Bonzini * csr41814 (Bluetooth)
134353018216SPaolo Bonzini */
134453018216SPaolo Bonzini n8x0_gpio_setup(s);
134553018216SPaolo Bonzini n8x0_nand_setup(s);
134653018216SPaolo Bonzini n8x0_i2c_setup(s);
1347fddbd80cSPaolo Bonzini if (model == 800) {
134853018216SPaolo Bonzini n800_tsc_kbd_setup(s);
1349fddbd80cSPaolo Bonzini } else if (model == 810) {
135053018216SPaolo Bonzini n810_tsc_setup(s);
135153018216SPaolo Bonzini n810_kbd_setup(s);
135253018216SPaolo Bonzini }
135353018216SPaolo Bonzini n8x0_spi_setup(s);
135453018216SPaolo Bonzini n8x0_dss_setup(s);
135553018216SPaolo Bonzini n8x0_cbus_setup(s);
13564bcbe0b6SEduardo Habkost if (machine_usb(machine)) {
135753018216SPaolo Bonzini n8x0_usb_setup(s);
135853018216SPaolo Bonzini }
135953018216SPaolo Bonzini
13603ef96221SMarcel Apfelbaum if (machine->kernel_filename) {
136153018216SPaolo Bonzini /* Or at the linux loader. */
13622744ece8STao Xu arm_load_kernel(s->mpu->cpu, machine, binfo);
136353018216SPaolo Bonzini
136453018216SPaolo Bonzini qemu_register_reset(n8x0_boot_init, s);
136553018216SPaolo Bonzini }
136653018216SPaolo Bonzini
136753018216SPaolo Bonzini if (option_rom[0].name &&
136897ec4d21SPaolo Bonzini (machine->boot_config.order[0] == 'n' || !machine->kernel_filename)) {
13690b062eb0SZhou Jie uint8_t *nolo_tags = g_new(uint8_t, 0x10000);
137053018216SPaolo Bonzini /* No, wait, better start at the ROM. */
137153018216SPaolo Bonzini s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
137253018216SPaolo Bonzini
13730e5dc775SPeter Maydell /*
13740e5dc775SPeter Maydell * This is intended for loading the `secondary.bin' program from
137553018216SPaolo Bonzini * Nokia images (the NOLO bootloader). The entry point seems
137653018216SPaolo Bonzini * to be at OMAP2_Q2_BASE + 0x400000.
137753018216SPaolo Bonzini *
137853018216SPaolo Bonzini * The `2nd.bin' files contain some kind of earlier boot code and
137953018216SPaolo Bonzini * for them the entry point needs to be set to OMAP2_SRAM_BASE.
138053018216SPaolo Bonzini *
138153018216SPaolo Bonzini * The code above is for loading the `zImage' file from Nokia
13820e5dc775SPeter Maydell * images.
13830e5dc775SPeter Maydell */
13840e5dc775SPeter Maydell if (load_image_targphys(option_rom[0].name,
13850e5dc775SPeter Maydell OMAP2_Q2_BASE + 0x400000,
13860e5dc775SPeter Maydell machine->ram_size - 0x400000) < 0) {
13870e5dc775SPeter Maydell error_report("Failed to load secondary bootloader %s",
13880e5dc775SPeter Maydell option_rom[0].name);
13890e5dc775SPeter Maydell exit(EXIT_FAILURE);
13900e5dc775SPeter Maydell }
139153018216SPaolo Bonzini
139253018216SPaolo Bonzini n800_setup_nolo_tags(nolo_tags);
139353018216SPaolo Bonzini cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
13940b062eb0SZhou Jie g_free(nolo_tags);
139553018216SPaolo Bonzini }
139653018216SPaolo Bonzini }
139753018216SPaolo Bonzini
139853018216SPaolo Bonzini static struct arm_boot_info n800_binfo = {
139953018216SPaolo Bonzini .loader_start = OMAP2_Q2_BASE,
140053018216SPaolo Bonzini .board_id = 0x4f7,
140153018216SPaolo Bonzini .atag_board = n800_atag_setup,
140253018216SPaolo Bonzini };
140353018216SPaolo Bonzini
140453018216SPaolo Bonzini static struct arm_boot_info n810_binfo = {
140553018216SPaolo Bonzini .loader_start = OMAP2_Q2_BASE,
140653018216SPaolo Bonzini /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
140753018216SPaolo Bonzini * used by some older versions of the bootloader and 5555 is used
140853018216SPaolo Bonzini * instead (including versions that shipped with many devices). */
140953018216SPaolo Bonzini .board_id = 0x60c,
141053018216SPaolo Bonzini .atag_board = n810_atag_setup,
141153018216SPaolo Bonzini };
141253018216SPaolo Bonzini
n800_init(MachineState * machine)14133ef96221SMarcel Apfelbaum static void n800_init(MachineState *machine)
141453018216SPaolo Bonzini {
141530d76f13SStefan Weil n8x0_init(machine, &n800_binfo, 800);
141653018216SPaolo Bonzini }
141753018216SPaolo Bonzini
n810_init(MachineState * machine)14183ef96221SMarcel Apfelbaum static void n810_init(MachineState *machine)
141953018216SPaolo Bonzini {
142030d76f13SStefan Weil n8x0_init(machine, &n810_binfo, 810);
142153018216SPaolo Bonzini }
142253018216SPaolo Bonzini
n800_class_init(ObjectClass * oc,void * data)14238a661aeaSAndreas Färber static void n800_class_init(ObjectClass *oc, void *data)
142453018216SPaolo Bonzini {
14258a661aeaSAndreas Färber MachineClass *mc = MACHINE_CLASS(oc);
14268a661aeaSAndreas Färber
1427e264d29dSEduardo Habkost mc->desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)";
1428e264d29dSEduardo Habkost mc->init = n800_init;
1429e264d29dSEduardo Habkost mc->default_boot_order = "";
14304672cbd7SPeter Maydell mc->ignore_memory_transaction_failures = true;
1431ba1ba5ccSIgor Mammedov mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm1136-r2");
14327998beb9SIgor Mammedov /* Actually two chips of 0x4000000 bytes each */
14337998beb9SIgor Mammedov mc->default_ram_size = 0x08000000;
14347998beb9SIgor Mammedov mc->default_ram_id = "omap2.dram";
1435*b8ab0303SMartin Kletzander
1436*b8ab0303SMartin Kletzander machine_add_audiodev_property(mc);
143753018216SPaolo Bonzini }
143853018216SPaolo Bonzini
14398a661aeaSAndreas Färber static const TypeInfo n800_type = {
14408a661aeaSAndreas Färber .name = MACHINE_TYPE_NAME("n800"),
14418a661aeaSAndreas Färber .parent = TYPE_MACHINE,
14428a661aeaSAndreas Färber .class_init = n800_class_init,
14438a661aeaSAndreas Färber };
1444e264d29dSEduardo Habkost
n810_class_init(ObjectClass * oc,void * data)14458a661aeaSAndreas Färber static void n810_class_init(ObjectClass *oc, void *data)
1446e264d29dSEduardo Habkost {
14478a661aeaSAndreas Färber MachineClass *mc = MACHINE_CLASS(oc);
14488a661aeaSAndreas Färber
1449e264d29dSEduardo Habkost mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)";
1450e264d29dSEduardo Habkost mc->init = n810_init;
1451e264d29dSEduardo Habkost mc->default_boot_order = "";
14524672cbd7SPeter Maydell mc->ignore_memory_transaction_failures = true;
1453ba1ba5ccSIgor Mammedov mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm1136-r2");
14547998beb9SIgor Mammedov /* Actually two chips of 0x4000000 bytes each */
14557998beb9SIgor Mammedov mc->default_ram_size = 0x08000000;
14567998beb9SIgor Mammedov mc->default_ram_id = "omap2.dram";
1457*b8ab0303SMartin Kletzander
1458*b8ab0303SMartin Kletzander machine_add_audiodev_property(mc);
1459e264d29dSEduardo Habkost }
1460e264d29dSEduardo Habkost
14618a661aeaSAndreas Färber static const TypeInfo n810_type = {
14628a661aeaSAndreas Färber .name = MACHINE_TYPE_NAME("n810"),
14638a661aeaSAndreas Färber .parent = TYPE_MACHINE,
14648a661aeaSAndreas Färber .class_init = n810_class_init,
14658a661aeaSAndreas Färber };
14668a661aeaSAndreas Färber
nseries_machine_init(void)14678a661aeaSAndreas Färber static void nseries_machine_init(void)
14688a661aeaSAndreas Färber {
14698a661aeaSAndreas Färber type_register_static(&n800_type);
14708a661aeaSAndreas Färber type_register_static(&n810_type);
14718a661aeaSAndreas Färber }
14728a661aeaSAndreas Färber
14730e6aac87SEduardo Habkost type_init(nseries_machine_init)
1474