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" 24f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 2558369e22SPaolo Bonzini #include "qemu/bswap.h" 2653018216SPaolo Bonzini #include "sysemu/sysemu.h" 270d09e41aSPaolo Bonzini #include "hw/arm/omap.h" 28*12ec8bd5SPeter Maydell #include "hw/arm/boot.h" 2953018216SPaolo Bonzini #include "hw/irq.h" 3053018216SPaolo Bonzini #include "ui/console.h" 3153018216SPaolo Bonzini #include "hw/boards.h" 320d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h" 338a08cc71SPhilippe Mathieu-Daudé #include "hw/display/blizzard.h" 34a331dd02SPhilippe Mathieu-Daudé #include "hw/input/tsc2xxx.h" 35e8fa3958SPhilippe Mathieu-Daudé #include "hw/misc/cbus.h" 365f299c55SPhilippe Mathieu-Daudé #include "hw/misc/tmp105.h" 370d09e41aSPaolo Bonzini #include "hw/block/flash.h" 3853018216SPaolo Bonzini #include "hw/hw.h" 3953018216SPaolo Bonzini #include "hw/bt.h" 4053018216SPaolo Bonzini #include "hw/loader.h" 4153018216SPaolo Bonzini #include "hw/sysbus.h" 4203dd024fSPaolo Bonzini #include "qemu/log.h" 4353018216SPaolo Bonzini #include "exec/address-spaces.h" 4453018216SPaolo Bonzini 4553018216SPaolo Bonzini /* Nokia N8x0 support */ 4653018216SPaolo Bonzini struct n800_s { 4753018216SPaolo Bonzini struct omap_mpu_state_s *mpu; 4853018216SPaolo Bonzini 4953018216SPaolo Bonzini struct rfbi_chip_s blizzard; 5053018216SPaolo Bonzini struct { 5153018216SPaolo Bonzini void *opaque; 5253018216SPaolo Bonzini uint32_t (*txrx)(void *opaque, uint32_t value, int len); 5353018216SPaolo Bonzini uWireSlave *chip; 5453018216SPaolo Bonzini } ts; 5553018216SPaolo Bonzini 5653018216SPaolo Bonzini int keymap[0x80]; 5753018216SPaolo Bonzini DeviceState *kbd; 5853018216SPaolo Bonzini 5953018216SPaolo Bonzini DeviceState *usb; 6053018216SPaolo Bonzini void *retu; 6153018216SPaolo Bonzini void *tahvo; 6253018216SPaolo Bonzini DeviceState *nand; 6353018216SPaolo Bonzini }; 6453018216SPaolo Bonzini 6553018216SPaolo Bonzini /* GPIO pins */ 6653018216SPaolo Bonzini #define N8X0_TUSB_ENABLE_GPIO 0 6753018216SPaolo Bonzini #define N800_MMC2_WP_GPIO 8 6853018216SPaolo Bonzini #define N800_UNKNOWN_GPIO0 9 /* out */ 6953018216SPaolo Bonzini #define N810_MMC2_VIOSD_GPIO 9 7053018216SPaolo Bonzini #define N810_HEADSET_AMP_GPIO 10 7153018216SPaolo Bonzini #define N800_CAM_TURN_GPIO 12 7253018216SPaolo Bonzini #define N810_GPS_RESET_GPIO 12 7353018216SPaolo Bonzini #define N800_BLIZZARD_POWERDOWN_GPIO 15 7453018216SPaolo Bonzini #define N800_MMC1_WP_GPIO 23 7553018216SPaolo Bonzini #define N810_MMC2_VSD_GPIO 23 7653018216SPaolo Bonzini #define N8X0_ONENAND_GPIO 26 7753018216SPaolo Bonzini #define N810_BLIZZARD_RESET_GPIO 30 7853018216SPaolo Bonzini #define N800_UNKNOWN_GPIO2 53 /* out */ 7953018216SPaolo Bonzini #define N8X0_TUSB_INT_GPIO 58 8053018216SPaolo Bonzini #define N8X0_BT_WKUP_GPIO 61 8153018216SPaolo Bonzini #define N8X0_STI_GPIO 62 8253018216SPaolo Bonzini #define N8X0_CBUS_SEL_GPIO 64 8353018216SPaolo Bonzini #define N8X0_CBUS_DAT_GPIO 65 8453018216SPaolo Bonzini #define N8X0_CBUS_CLK_GPIO 66 8553018216SPaolo Bonzini #define N8X0_WLAN_IRQ_GPIO 87 8653018216SPaolo Bonzini #define N8X0_BT_RESET_GPIO 92 8753018216SPaolo Bonzini #define N8X0_TEA5761_CS_GPIO 93 8853018216SPaolo Bonzini #define N800_UNKNOWN_GPIO 94 8953018216SPaolo Bonzini #define N810_TSC_RESET_GPIO 94 9053018216SPaolo Bonzini #define N800_CAM_ACT_GPIO 95 9153018216SPaolo Bonzini #define N810_GPS_WAKEUP_GPIO 95 9253018216SPaolo Bonzini #define N8X0_MMC_CS_GPIO 96 9353018216SPaolo Bonzini #define N8X0_WLAN_PWR_GPIO 97 9453018216SPaolo Bonzini #define N8X0_BT_HOST_WKUP_GPIO 98 9553018216SPaolo Bonzini #define N810_SPEAKER_AMP_GPIO 101 9653018216SPaolo Bonzini #define N810_KB_LOCK_GPIO 102 9753018216SPaolo Bonzini #define N800_TSC_TS_GPIO 103 9853018216SPaolo Bonzini #define N810_TSC_TS_GPIO 106 9953018216SPaolo Bonzini #define N8X0_HEADPHONE_GPIO 107 10053018216SPaolo Bonzini #define N8X0_RETU_GPIO 108 10153018216SPaolo Bonzini #define N800_TSC_KP_IRQ_GPIO 109 10253018216SPaolo Bonzini #define N810_KEYBOARD_GPIO 109 10353018216SPaolo Bonzini #define N800_BAT_COVER_GPIO 110 10453018216SPaolo Bonzini #define N810_SLIDE_GPIO 110 10553018216SPaolo Bonzini #define N8X0_TAHVO_GPIO 111 10653018216SPaolo Bonzini #define N800_UNKNOWN_GPIO4 112 /* out */ 10753018216SPaolo Bonzini #define N810_SLEEPX_LED_GPIO 112 10853018216SPaolo Bonzini #define N800_TSC_RESET_GPIO 118 /* ? */ 10953018216SPaolo Bonzini #define N810_AIC33_RESET_GPIO 118 11053018216SPaolo Bonzini #define N800_TSC_UNKNOWN_GPIO 119 /* out */ 11153018216SPaolo Bonzini #define N8X0_TMP105_GPIO 125 11253018216SPaolo Bonzini 11353018216SPaolo Bonzini /* Config */ 11453018216SPaolo Bonzini #define BT_UART 0 11553018216SPaolo Bonzini #define XLDR_LL_UART 1 11653018216SPaolo Bonzini 11753018216SPaolo Bonzini /* Addresses on the I2C bus 0 */ 11853018216SPaolo Bonzini #define N810_TLV320AIC33_ADDR 0x18 /* Audio CODEC */ 11953018216SPaolo Bonzini #define N8X0_TCM825x_ADDR 0x29 /* Camera */ 12053018216SPaolo Bonzini #define N810_LP5521_ADDR 0x32 /* LEDs */ 12153018216SPaolo Bonzini #define N810_TSL2563_ADDR 0x3d /* Light sensor */ 12253018216SPaolo Bonzini #define N810_LM8323_ADDR 0x45 /* Keyboard */ 12353018216SPaolo Bonzini /* Addresses on the I2C bus 1 */ 12453018216SPaolo Bonzini #define N8X0_TMP105_ADDR 0x48 /* Temperature sensor */ 12553018216SPaolo Bonzini #define N8X0_MENELAUS_ADDR 0x72 /* Power management */ 12653018216SPaolo Bonzini 12753018216SPaolo Bonzini /* Chipselects on GPMC NOR interface */ 12853018216SPaolo Bonzini #define N8X0_ONENAND_CS 0 12953018216SPaolo Bonzini #define N8X0_USB_ASYNC_CS 1 13053018216SPaolo Bonzini #define N8X0_USB_SYNC_CS 4 13153018216SPaolo Bonzini 13253018216SPaolo Bonzini #define N8X0_BD_ADDR 0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81 13353018216SPaolo Bonzini 13453018216SPaolo Bonzini static void n800_mmc_cs_cb(void *opaque, int line, int level) 13553018216SPaolo Bonzini { 13653018216SPaolo Bonzini /* TODO: this seems to actually be connected to the menelaus, to 13753018216SPaolo Bonzini * which also both MMC slots connect. */ 13853018216SPaolo Bonzini omap_mmc_enable((struct omap_mmc_s *) opaque, !level); 13953018216SPaolo Bonzini } 14053018216SPaolo Bonzini 14153018216SPaolo Bonzini static void n8x0_gpio_setup(struct n800_s *s) 14253018216SPaolo Bonzini { 143294972ceSShannon Zhao qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, 144294972ceSShannon Zhao qemu_allocate_irq(n800_mmc_cs_cb, s->mpu->mmc, 0)); 14553018216SPaolo Bonzini qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO)); 14653018216SPaolo Bonzini } 14753018216SPaolo Bonzini 14853018216SPaolo Bonzini #define MAEMO_CAL_HEADER(...) \ 14953018216SPaolo Bonzini 'C', 'o', 'n', 'F', 0x02, 0x00, 0x04, 0x00, \ 15053018216SPaolo Bonzini __VA_ARGS__, \ 15153018216SPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15253018216SPaolo Bonzini 15353018216SPaolo Bonzini static const uint8_t n8x0_cal_wlan_mac[] = { 15453018216SPaolo Bonzini MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c') 15553018216SPaolo Bonzini 0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3, 15653018216SPaolo Bonzini 0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00, 15753018216SPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 15853018216SPaolo Bonzini 0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 15953018216SPaolo Bonzini 0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 16053018216SPaolo Bonzini }; 16153018216SPaolo Bonzini 16253018216SPaolo Bonzini static const uint8_t n8x0_cal_bt_id[] = { 16353018216SPaolo Bonzini MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0) 16453018216SPaolo Bonzini 0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96, 16553018216SPaolo Bonzini 0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00, 16653018216SPaolo Bonzini N8X0_BD_ADDR, 16753018216SPaolo Bonzini }; 16853018216SPaolo Bonzini 16953018216SPaolo Bonzini static void n8x0_nand_setup(struct n800_s *s) 17053018216SPaolo Bonzini { 17153018216SPaolo Bonzini char *otp_region; 17253018216SPaolo Bonzini DriveInfo *dinfo; 17353018216SPaolo Bonzini 17453018216SPaolo Bonzini s->nand = qdev_create(NULL, "onenand"); 17553018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG); 17653018216SPaolo Bonzini /* Either 0x40 or 0x48 are OK for the device ID */ 17753018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "device_id", 0x48); 17853018216SPaolo Bonzini qdev_prop_set_uint16(s->nand, "version_id", 0); 17953018216SPaolo Bonzini qdev_prop_set_int32(s->nand, "shift", 1); 18053018216SPaolo Bonzini dinfo = drive_get(IF_MTD, 0, 0); 181fa1d36dfSMarkus Armbruster if (dinfo) { 1826231a6daSMarkus Armbruster qdev_prop_set_drive(s->nand, "drive", blk_by_legacy_dinfo(dinfo), 1836231a6daSMarkus Armbruster &error_fatal); 18453018216SPaolo Bonzini } 18553018216SPaolo Bonzini qdev_init_nofail(s->nand); 18653018216SPaolo Bonzini sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0, 18753018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO)); 18853018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS, 18953018216SPaolo Bonzini sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0)); 19053018216SPaolo Bonzini otp_region = onenand_raw_otp(s->nand); 19153018216SPaolo Bonzini 19253018216SPaolo Bonzini memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac)); 19353018216SPaolo Bonzini memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id)); 19453018216SPaolo Bonzini /* XXX: in theory should also update the OOB for both pages */ 19553018216SPaolo Bonzini } 19653018216SPaolo Bonzini 19753018216SPaolo Bonzini static qemu_irq n8x0_system_powerdown; 19853018216SPaolo Bonzini 19953018216SPaolo Bonzini static void n8x0_powerdown_req(Notifier *n, void *opaque) 20053018216SPaolo Bonzini { 20153018216SPaolo Bonzini qemu_irq_raise(n8x0_system_powerdown); 20253018216SPaolo Bonzini } 20353018216SPaolo Bonzini 20453018216SPaolo Bonzini static Notifier n8x0_system_powerdown_notifier = { 20553018216SPaolo Bonzini .notify = n8x0_powerdown_req 20653018216SPaolo Bonzini }; 20753018216SPaolo Bonzini 20853018216SPaolo Bonzini static void n8x0_i2c_setup(struct n800_s *s) 20953018216SPaolo Bonzini { 21053018216SPaolo Bonzini DeviceState *dev; 21153018216SPaolo Bonzini qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO); 212a5c82852SAndreas Färber I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]); 21353018216SPaolo Bonzini 21453018216SPaolo Bonzini /* Attach a menelaus PM chip */ 21553018216SPaolo Bonzini dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR); 21653018216SPaolo Bonzini qdev_connect_gpio_out(dev, 3, 21753018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->ih[0], 21853018216SPaolo Bonzini OMAP_INT_24XX_SYS_NIRQ)); 21953018216SPaolo Bonzini 22053018216SPaolo Bonzini n8x0_system_powerdown = qdev_get_gpio_in(dev, 3); 22153018216SPaolo Bonzini qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier); 22253018216SPaolo Bonzini 22353018216SPaolo Bonzini /* Attach a TMP105 PM chip (A0 wired to ground) */ 2245f299c55SPhilippe Mathieu-Daudé dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR); 22553018216SPaolo Bonzini qdev_connect_gpio_out(dev, 0, tmp_irq); 22653018216SPaolo Bonzini } 22753018216SPaolo Bonzini 22853018216SPaolo Bonzini /* Touchscreen and keypad controller */ 22953018216SPaolo Bonzini static MouseTransformInfo n800_pointercal = { 23053018216SPaolo Bonzini .x = 800, 23153018216SPaolo Bonzini .y = 480, 23253018216SPaolo Bonzini .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 }, 23353018216SPaolo Bonzini }; 23453018216SPaolo Bonzini 23553018216SPaolo Bonzini static MouseTransformInfo n810_pointercal = { 23653018216SPaolo Bonzini .x = 800, 23753018216SPaolo Bonzini .y = 480, 23853018216SPaolo Bonzini .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 }, 23953018216SPaolo Bonzini }; 24053018216SPaolo Bonzini 24153018216SPaolo Bonzini #define RETU_KEYCODE 61 /* F3 */ 24253018216SPaolo Bonzini 24353018216SPaolo Bonzini static void n800_key_event(void *opaque, int keycode) 24453018216SPaolo Bonzini { 24553018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque; 24653018216SPaolo Bonzini int code = s->keymap[keycode & 0x7f]; 24753018216SPaolo Bonzini 24853018216SPaolo Bonzini if (code == -1) { 249fddbd80cSPaolo Bonzini if ((keycode & 0x7f) == RETU_KEYCODE) { 25053018216SPaolo Bonzini retu_key_event(s->retu, !(keycode & 0x80)); 251fddbd80cSPaolo Bonzini } 25253018216SPaolo Bonzini return; 25353018216SPaolo Bonzini } 25453018216SPaolo Bonzini 25553018216SPaolo Bonzini tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80)); 25653018216SPaolo Bonzini } 25753018216SPaolo Bonzini 25853018216SPaolo Bonzini static const int n800_keys[16] = { 25953018216SPaolo Bonzini -1, 26053018216SPaolo Bonzini 72, /* Up */ 26153018216SPaolo Bonzini 63, /* Home (F5) */ 26253018216SPaolo Bonzini -1, 26353018216SPaolo Bonzini 75, /* Left */ 26453018216SPaolo Bonzini 28, /* Enter */ 26553018216SPaolo Bonzini 77, /* Right */ 26653018216SPaolo Bonzini -1, 26753018216SPaolo Bonzini 1, /* Cycle (ESC) */ 26853018216SPaolo Bonzini 80, /* Down */ 26953018216SPaolo Bonzini 62, /* Menu (F4) */ 27053018216SPaolo Bonzini -1, 27153018216SPaolo Bonzini 66, /* Zoom- (F8) */ 27253018216SPaolo Bonzini 64, /* FullScreen (F6) */ 27353018216SPaolo Bonzini 65, /* Zoom+ (F7) */ 27453018216SPaolo Bonzini -1, 27553018216SPaolo Bonzini }; 27653018216SPaolo Bonzini 27753018216SPaolo Bonzini static void n800_tsc_kbd_setup(struct n800_s *s) 27853018216SPaolo Bonzini { 27953018216SPaolo Bonzini int i; 28053018216SPaolo Bonzini 28153018216SPaolo Bonzini /* XXX: are the three pins inverted inside the chip between the 28253018216SPaolo Bonzini * tsc and the cpu (N4111)? */ 28353018216SPaolo Bonzini qemu_irq penirq = NULL; /* NC */ 28453018216SPaolo Bonzini qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO); 28553018216SPaolo Bonzini qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO); 28653018216SPaolo Bonzini 28753018216SPaolo Bonzini s->ts.chip = tsc2301_init(penirq, kbirq, dav); 28853018216SPaolo Bonzini s->ts.opaque = s->ts.chip->opaque; 28953018216SPaolo Bonzini s->ts.txrx = tsc210x_txrx; 29053018216SPaolo Bonzini 291fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) { 29253018216SPaolo Bonzini s->keymap[i] = -1; 293fddbd80cSPaolo Bonzini } 294fddbd80cSPaolo Bonzini for (i = 0; i < 0x10; i++) { 295fddbd80cSPaolo Bonzini if (n800_keys[i] >= 0) { 29653018216SPaolo Bonzini s->keymap[n800_keys[i]] = i; 297fddbd80cSPaolo Bonzini } 298fddbd80cSPaolo Bonzini } 29953018216SPaolo Bonzini 30053018216SPaolo Bonzini qemu_add_kbd_event_handler(n800_key_event, s); 30153018216SPaolo Bonzini 30253018216SPaolo Bonzini tsc210x_set_transform(s->ts.chip, &n800_pointercal); 30353018216SPaolo Bonzini } 30453018216SPaolo Bonzini 30553018216SPaolo Bonzini static void n810_tsc_setup(struct n800_s *s) 30653018216SPaolo Bonzini { 30753018216SPaolo Bonzini qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO); 30853018216SPaolo Bonzini 30953018216SPaolo Bonzini s->ts.opaque = tsc2005_init(pintdav); 31053018216SPaolo Bonzini s->ts.txrx = tsc2005_txrx; 31153018216SPaolo Bonzini 31253018216SPaolo Bonzini tsc2005_set_transform(s->ts.opaque, &n810_pointercal); 31353018216SPaolo Bonzini } 31453018216SPaolo Bonzini 31553018216SPaolo Bonzini /* N810 Keyboard controller */ 31653018216SPaolo Bonzini static void n810_key_event(void *opaque, int keycode) 31753018216SPaolo Bonzini { 31853018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque; 31953018216SPaolo Bonzini int code = s->keymap[keycode & 0x7f]; 32053018216SPaolo Bonzini 32153018216SPaolo Bonzini if (code == -1) { 322fddbd80cSPaolo Bonzini if ((keycode & 0x7f) == RETU_KEYCODE) { 32353018216SPaolo Bonzini retu_key_event(s->retu, !(keycode & 0x80)); 324fddbd80cSPaolo Bonzini } 32553018216SPaolo Bonzini return; 32653018216SPaolo Bonzini } 32753018216SPaolo Bonzini 32853018216SPaolo Bonzini lm832x_key_event(s->kbd, code, !(keycode & 0x80)); 32953018216SPaolo Bonzini } 33053018216SPaolo Bonzini 33153018216SPaolo Bonzini #define M 0 33253018216SPaolo Bonzini 33353018216SPaolo Bonzini static int n810_keys[0x80] = { 33453018216SPaolo Bonzini [0x01] = 16, /* Q */ 33553018216SPaolo Bonzini [0x02] = 37, /* K */ 33653018216SPaolo Bonzini [0x03] = 24, /* O */ 33753018216SPaolo Bonzini [0x04] = 25, /* P */ 33853018216SPaolo Bonzini [0x05] = 14, /* Backspace */ 33953018216SPaolo Bonzini [0x06] = 30, /* A */ 34053018216SPaolo Bonzini [0x07] = 31, /* S */ 34153018216SPaolo Bonzini [0x08] = 32, /* D */ 34253018216SPaolo Bonzini [0x09] = 33, /* F */ 34353018216SPaolo Bonzini [0x0a] = 34, /* G */ 34453018216SPaolo Bonzini [0x0b] = 35, /* H */ 34553018216SPaolo Bonzini [0x0c] = 36, /* J */ 34653018216SPaolo Bonzini 34753018216SPaolo Bonzini [0x11] = 17, /* W */ 34853018216SPaolo Bonzini [0x12] = 62, /* Menu (F4) */ 34953018216SPaolo Bonzini [0x13] = 38, /* L */ 35053018216SPaolo Bonzini [0x14] = 40, /* ' (Apostrophe) */ 35153018216SPaolo Bonzini [0x16] = 44, /* Z */ 35253018216SPaolo Bonzini [0x17] = 45, /* X */ 35353018216SPaolo Bonzini [0x18] = 46, /* C */ 35453018216SPaolo Bonzini [0x19] = 47, /* V */ 35553018216SPaolo Bonzini [0x1a] = 48, /* B */ 35653018216SPaolo Bonzini [0x1b] = 49, /* N */ 35753018216SPaolo Bonzini [0x1c] = 42, /* Shift (Left shift) */ 35853018216SPaolo Bonzini [0x1f] = 65, /* Zoom+ (F7) */ 35953018216SPaolo Bonzini 36053018216SPaolo Bonzini [0x21] = 18, /* E */ 36153018216SPaolo Bonzini [0x22] = 39, /* ; (Semicolon) */ 36253018216SPaolo Bonzini [0x23] = 12, /* - (Minus) */ 36353018216SPaolo Bonzini [0x24] = 13, /* = (Equal) */ 36453018216SPaolo Bonzini [0x2b] = 56, /* Fn (Left Alt) */ 36553018216SPaolo Bonzini [0x2c] = 50, /* M */ 36653018216SPaolo Bonzini [0x2f] = 66, /* Zoom- (F8) */ 36753018216SPaolo Bonzini 36853018216SPaolo Bonzini [0x31] = 19, /* R */ 36953018216SPaolo Bonzini [0x32] = 29 | M, /* Right Ctrl */ 37053018216SPaolo Bonzini [0x34] = 57, /* Space */ 37153018216SPaolo Bonzini [0x35] = 51, /* , (Comma) */ 37253018216SPaolo Bonzini [0x37] = 72 | M, /* Up */ 37353018216SPaolo Bonzini [0x3c] = 82 | M, /* Compose (Insert) */ 37453018216SPaolo Bonzini [0x3f] = 64, /* FullScreen (F6) */ 37553018216SPaolo Bonzini 37653018216SPaolo Bonzini [0x41] = 20, /* T */ 37753018216SPaolo Bonzini [0x44] = 52, /* . (Dot) */ 37853018216SPaolo Bonzini [0x46] = 77 | M, /* Right */ 37953018216SPaolo Bonzini [0x4f] = 63, /* Home (F5) */ 38053018216SPaolo Bonzini [0x51] = 21, /* Y */ 38153018216SPaolo Bonzini [0x53] = 80 | M, /* Down */ 38253018216SPaolo Bonzini [0x55] = 28, /* Enter */ 38353018216SPaolo Bonzini [0x5f] = 1, /* Cycle (ESC) */ 38453018216SPaolo Bonzini 38553018216SPaolo Bonzini [0x61] = 22, /* U */ 38653018216SPaolo Bonzini [0x64] = 75 | M, /* Left */ 38753018216SPaolo Bonzini 38853018216SPaolo Bonzini [0x71] = 23, /* I */ 38953018216SPaolo Bonzini #if 0 39053018216SPaolo Bonzini [0x75] = 28 | M, /* KP Enter (KP Enter) */ 39153018216SPaolo Bonzini #else 39253018216SPaolo Bonzini [0x75] = 15, /* KP Enter (Tab) */ 39353018216SPaolo Bonzini #endif 39453018216SPaolo Bonzini }; 39553018216SPaolo Bonzini 39653018216SPaolo Bonzini #undef M 39753018216SPaolo Bonzini 39853018216SPaolo Bonzini static void n810_kbd_setup(struct n800_s *s) 39953018216SPaolo Bonzini { 40053018216SPaolo Bonzini qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO); 40153018216SPaolo Bonzini int i; 40253018216SPaolo Bonzini 403fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) { 40453018216SPaolo Bonzini s->keymap[i] = -1; 405fddbd80cSPaolo Bonzini } 406fddbd80cSPaolo Bonzini for (i = 0; i < 0x80; i++) { 407fddbd80cSPaolo Bonzini if (n810_keys[i] > 0) { 40853018216SPaolo Bonzini s->keymap[n810_keys[i]] = i; 409fddbd80cSPaolo Bonzini } 410fddbd80cSPaolo Bonzini } 41153018216SPaolo Bonzini 41253018216SPaolo Bonzini qemu_add_kbd_event_handler(n810_key_event, s); 41353018216SPaolo Bonzini 41453018216SPaolo Bonzini /* Attach the LM8322 keyboard to the I2C bus, 41553018216SPaolo Bonzini * should happen in n8x0_i2c_setup and s->kbd be initialised here. */ 41653018216SPaolo Bonzini s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]), 41753018216SPaolo Bonzini "lm8323", N810_LM8323_ADDR); 41853018216SPaolo Bonzini qdev_connect_gpio_out(s->kbd, 0, kbd_irq); 41953018216SPaolo Bonzini } 42053018216SPaolo Bonzini 42153018216SPaolo Bonzini /* LCD MIPI DBI-C controller (URAL) */ 42253018216SPaolo Bonzini struct mipid_s { 42353018216SPaolo Bonzini int resp[4]; 42453018216SPaolo Bonzini int param[4]; 42553018216SPaolo Bonzini int p; 42653018216SPaolo Bonzini int pm; 42753018216SPaolo Bonzini int cmd; 42853018216SPaolo Bonzini 42953018216SPaolo Bonzini int sleep; 43053018216SPaolo Bonzini int booster; 43153018216SPaolo Bonzini int te; 43253018216SPaolo Bonzini int selfcheck; 43353018216SPaolo Bonzini int partial; 43453018216SPaolo Bonzini int normal; 43553018216SPaolo Bonzini int vscr; 43653018216SPaolo Bonzini int invert; 43753018216SPaolo Bonzini int onoff; 43853018216SPaolo Bonzini int gamma; 43953018216SPaolo Bonzini uint32_t id; 44053018216SPaolo Bonzini }; 44153018216SPaolo Bonzini 44253018216SPaolo Bonzini static void mipid_reset(struct mipid_s *s) 44353018216SPaolo Bonzini { 44453018216SPaolo Bonzini s->pm = 0; 44553018216SPaolo Bonzini s->cmd = 0; 44653018216SPaolo Bonzini 44753018216SPaolo Bonzini s->sleep = 1; 44853018216SPaolo Bonzini s->booster = 0; 44953018216SPaolo Bonzini s->selfcheck = 45053018216SPaolo Bonzini (1 << 7) | /* Register loading OK. */ 45153018216SPaolo Bonzini (1 << 5) | /* The chip is attached. */ 45253018216SPaolo Bonzini (1 << 4); /* Display glass still in one piece. */ 45353018216SPaolo Bonzini s->te = 0; 45453018216SPaolo Bonzini s->partial = 0; 45553018216SPaolo Bonzini s->normal = 1; 45653018216SPaolo Bonzini s->vscr = 0; 45753018216SPaolo Bonzini s->invert = 0; 45853018216SPaolo Bonzini s->onoff = 1; 45953018216SPaolo Bonzini s->gamma = 0; 46053018216SPaolo Bonzini } 46153018216SPaolo Bonzini 46253018216SPaolo Bonzini static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len) 46353018216SPaolo Bonzini { 46453018216SPaolo Bonzini struct mipid_s *s = (struct mipid_s *) opaque; 46553018216SPaolo Bonzini uint8_t ret; 46653018216SPaolo Bonzini 467fddbd80cSPaolo Bonzini if (len > 9) { 468a89f364aSAlistair Francis hw_error("%s: FIXME: bad SPI word width %i\n", __func__, len); 469fddbd80cSPaolo Bonzini } 47053018216SPaolo Bonzini 471fddbd80cSPaolo Bonzini if (s->p >= ARRAY_SIZE(s->resp)) { 47253018216SPaolo Bonzini ret = 0; 473fddbd80cSPaolo Bonzini } else { 47453018216SPaolo Bonzini ret = s->resp[s->p++]; 475fddbd80cSPaolo Bonzini } 476fddbd80cSPaolo Bonzini if (s->pm-- > 0) { 47753018216SPaolo Bonzini s->param[s->pm] = cmd; 478fddbd80cSPaolo Bonzini } else { 47953018216SPaolo Bonzini s->cmd = cmd; 480fddbd80cSPaolo Bonzini } 48153018216SPaolo Bonzini 48253018216SPaolo Bonzini switch (s->cmd) { 48353018216SPaolo Bonzini case 0x00: /* NOP */ 48453018216SPaolo Bonzini break; 48553018216SPaolo Bonzini 48653018216SPaolo Bonzini case 0x01: /* SWRESET */ 48753018216SPaolo Bonzini mipid_reset(s); 48853018216SPaolo Bonzini break; 48953018216SPaolo Bonzini 49053018216SPaolo Bonzini case 0x02: /* BSTROFF */ 49153018216SPaolo Bonzini s->booster = 0; 49253018216SPaolo Bonzini break; 49353018216SPaolo Bonzini case 0x03: /* BSTRON */ 49453018216SPaolo Bonzini s->booster = 1; 49553018216SPaolo Bonzini break; 49653018216SPaolo Bonzini 49753018216SPaolo Bonzini case 0x04: /* RDDID */ 49853018216SPaolo Bonzini s->p = 0; 49953018216SPaolo Bonzini s->resp[0] = (s->id >> 16) & 0xff; 50053018216SPaolo Bonzini s->resp[1] = (s->id >> 8) & 0xff; 50153018216SPaolo Bonzini s->resp[2] = (s->id >> 0) & 0xff; 50253018216SPaolo Bonzini break; 50353018216SPaolo Bonzini 50453018216SPaolo Bonzini case 0x06: /* RD_RED */ 50553018216SPaolo Bonzini case 0x07: /* RD_GREEN */ 50653018216SPaolo Bonzini /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so 50753018216SPaolo Bonzini * for the bootloader one needs to change this. */ 50853018216SPaolo Bonzini case 0x08: /* RD_BLUE */ 50953018216SPaolo Bonzini s->p = 0; 51053018216SPaolo Bonzini /* TODO: return first pixel components */ 51153018216SPaolo Bonzini s->resp[0] = 0x01; 51253018216SPaolo Bonzini break; 51353018216SPaolo Bonzini 51453018216SPaolo Bonzini case 0x09: /* RDDST */ 51553018216SPaolo Bonzini s->p = 0; 51653018216SPaolo Bonzini s->resp[0] = s->booster << 7; 51753018216SPaolo Bonzini s->resp[1] = (5 << 4) | (s->partial << 2) | 51853018216SPaolo Bonzini (s->sleep << 1) | s->normal; 51953018216SPaolo Bonzini s->resp[2] = (s->vscr << 7) | (s->invert << 5) | 52053018216SPaolo Bonzini (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2); 52153018216SPaolo Bonzini s->resp[3] = s->gamma << 6; 52253018216SPaolo Bonzini break; 52353018216SPaolo Bonzini 52453018216SPaolo Bonzini case 0x0a: /* RDDPM */ 52553018216SPaolo Bonzini s->p = 0; 52653018216SPaolo Bonzini s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) | 52753018216SPaolo Bonzini (s->partial << 5) | (s->sleep << 6) | (s->booster << 7); 52853018216SPaolo Bonzini break; 52953018216SPaolo Bonzini case 0x0b: /* RDDMADCTR */ 53053018216SPaolo Bonzini s->p = 0; 53153018216SPaolo Bonzini s->resp[0] = 0; 53253018216SPaolo Bonzini break; 53353018216SPaolo Bonzini case 0x0c: /* RDDCOLMOD */ 53453018216SPaolo Bonzini s->p = 0; 53553018216SPaolo Bonzini s->resp[0] = 5; /* 65K colours */ 53653018216SPaolo Bonzini break; 53753018216SPaolo Bonzini case 0x0d: /* RDDIM */ 53853018216SPaolo Bonzini s->p = 0; 53953018216SPaolo Bonzini s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma; 54053018216SPaolo Bonzini break; 54153018216SPaolo Bonzini case 0x0e: /* RDDSM */ 54253018216SPaolo Bonzini s->p = 0; 54353018216SPaolo Bonzini s->resp[0] = s->te << 7; 54453018216SPaolo Bonzini break; 54553018216SPaolo Bonzini case 0x0f: /* RDDSDR */ 54653018216SPaolo Bonzini s->p = 0; 54753018216SPaolo Bonzini s->resp[0] = s->selfcheck; 54853018216SPaolo Bonzini break; 54953018216SPaolo Bonzini 55053018216SPaolo Bonzini case 0x10: /* SLPIN */ 55153018216SPaolo Bonzini s->sleep = 1; 55253018216SPaolo Bonzini break; 55353018216SPaolo Bonzini case 0x11: /* SLPOUT */ 55453018216SPaolo Bonzini s->sleep = 0; 55553018216SPaolo Bonzini s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */ 55653018216SPaolo Bonzini break; 55753018216SPaolo Bonzini 55853018216SPaolo Bonzini case 0x12: /* PTLON */ 55953018216SPaolo Bonzini s->partial = 1; 56053018216SPaolo Bonzini s->normal = 0; 56153018216SPaolo Bonzini s->vscr = 0; 56253018216SPaolo Bonzini break; 56353018216SPaolo Bonzini case 0x13: /* NORON */ 56453018216SPaolo Bonzini s->partial = 0; 56553018216SPaolo Bonzini s->normal = 1; 56653018216SPaolo Bonzini s->vscr = 0; 56753018216SPaolo Bonzini break; 56853018216SPaolo Bonzini 56953018216SPaolo Bonzini case 0x20: /* INVOFF */ 57053018216SPaolo Bonzini s->invert = 0; 57153018216SPaolo Bonzini break; 57253018216SPaolo Bonzini case 0x21: /* INVON */ 57353018216SPaolo Bonzini s->invert = 1; 57453018216SPaolo Bonzini break; 57553018216SPaolo Bonzini 57653018216SPaolo Bonzini case 0x22: /* APOFF */ 57753018216SPaolo Bonzini case 0x23: /* APON */ 57853018216SPaolo Bonzini goto bad_cmd; 57953018216SPaolo Bonzini 58053018216SPaolo Bonzini case 0x25: /* WRCNTR */ 581fddbd80cSPaolo Bonzini if (s->pm < 0) { 58253018216SPaolo Bonzini s->pm = 1; 583fddbd80cSPaolo Bonzini } 58453018216SPaolo Bonzini goto bad_cmd; 58553018216SPaolo Bonzini 58653018216SPaolo Bonzini case 0x26: /* GAMSET */ 587fddbd80cSPaolo Bonzini if (!s->pm) { 588ad5f5fdcSStefan Hajnoczi s->gamma = ctz32(s->param[0] & 0xf); 589ad5f5fdcSStefan Hajnoczi if (s->gamma == 32) { 590ad5f5fdcSStefan Hajnoczi s->gamma = -1; /* XXX: should this be 0? */ 591ad5f5fdcSStefan Hajnoczi } 592fddbd80cSPaolo Bonzini } else if (s->pm < 0) { 59353018216SPaolo Bonzini s->pm = 1; 594fddbd80cSPaolo Bonzini } 59553018216SPaolo Bonzini break; 59653018216SPaolo Bonzini 59753018216SPaolo Bonzini case 0x28: /* DISPOFF */ 59853018216SPaolo Bonzini s->onoff = 0; 59953018216SPaolo Bonzini break; 60053018216SPaolo Bonzini case 0x29: /* DISPON */ 60153018216SPaolo Bonzini s->onoff = 1; 60253018216SPaolo Bonzini break; 60353018216SPaolo Bonzini 60453018216SPaolo Bonzini case 0x2a: /* CASET */ 60553018216SPaolo Bonzini case 0x2b: /* RASET */ 60653018216SPaolo Bonzini case 0x2c: /* RAMWR */ 60753018216SPaolo Bonzini case 0x2d: /* RGBSET */ 60853018216SPaolo Bonzini case 0x2e: /* RAMRD */ 60953018216SPaolo Bonzini case 0x30: /* PTLAR */ 61053018216SPaolo Bonzini case 0x33: /* SCRLAR */ 61153018216SPaolo Bonzini goto bad_cmd; 61253018216SPaolo Bonzini 61353018216SPaolo Bonzini case 0x34: /* TEOFF */ 61453018216SPaolo Bonzini s->te = 0; 61553018216SPaolo Bonzini break; 61653018216SPaolo Bonzini case 0x35: /* TEON */ 617fddbd80cSPaolo Bonzini if (!s->pm) { 61853018216SPaolo Bonzini s->te = 1; 619fddbd80cSPaolo Bonzini } else if (s->pm < 0) { 62053018216SPaolo Bonzini s->pm = 1; 621fddbd80cSPaolo Bonzini } 62253018216SPaolo Bonzini break; 62353018216SPaolo Bonzini 62453018216SPaolo Bonzini case 0x36: /* MADCTR */ 62553018216SPaolo Bonzini goto bad_cmd; 62653018216SPaolo Bonzini 62753018216SPaolo Bonzini case 0x37: /* VSCSAD */ 62853018216SPaolo Bonzini s->partial = 0; 62953018216SPaolo Bonzini s->normal = 0; 63053018216SPaolo Bonzini s->vscr = 1; 63153018216SPaolo Bonzini break; 63253018216SPaolo Bonzini 63353018216SPaolo Bonzini case 0x38: /* IDMOFF */ 63453018216SPaolo Bonzini case 0x39: /* IDMON */ 63553018216SPaolo Bonzini case 0x3a: /* COLMOD */ 63653018216SPaolo Bonzini goto bad_cmd; 63753018216SPaolo Bonzini 63853018216SPaolo Bonzini case 0xb0: /* CLKINT / DISCTL */ 63953018216SPaolo Bonzini case 0xb1: /* CLKEXT */ 640fddbd80cSPaolo Bonzini if (s->pm < 0) { 64153018216SPaolo Bonzini s->pm = 2; 642fddbd80cSPaolo Bonzini } 64353018216SPaolo Bonzini break; 64453018216SPaolo Bonzini 64553018216SPaolo Bonzini case 0xb4: /* FRMSEL */ 64653018216SPaolo Bonzini break; 64753018216SPaolo Bonzini 64853018216SPaolo Bonzini case 0xb5: /* FRM8SEL */ 64953018216SPaolo Bonzini case 0xb6: /* TMPRNG / INIESC */ 65053018216SPaolo Bonzini case 0xb7: /* TMPHIS / NOP2 */ 65153018216SPaolo Bonzini case 0xb8: /* TMPREAD / MADCTL */ 65253018216SPaolo Bonzini case 0xba: /* DISTCTR */ 65353018216SPaolo Bonzini case 0xbb: /* EPVOL */ 65453018216SPaolo Bonzini goto bad_cmd; 65553018216SPaolo Bonzini 65653018216SPaolo Bonzini case 0xbd: /* Unknown */ 65753018216SPaolo Bonzini s->p = 0; 65853018216SPaolo Bonzini s->resp[0] = 0; 65953018216SPaolo Bonzini s->resp[1] = 1; 66053018216SPaolo Bonzini break; 66153018216SPaolo Bonzini 66253018216SPaolo Bonzini case 0xc2: /* IFMOD */ 663fddbd80cSPaolo Bonzini if (s->pm < 0) { 66453018216SPaolo Bonzini s->pm = 2; 665fddbd80cSPaolo Bonzini } 66653018216SPaolo Bonzini break; 66753018216SPaolo Bonzini 66853018216SPaolo Bonzini case 0xc6: /* PWRCTL */ 66953018216SPaolo Bonzini case 0xc7: /* PPWRCTL */ 67053018216SPaolo Bonzini case 0xd0: /* EPWROUT */ 67153018216SPaolo Bonzini case 0xd1: /* EPWRIN */ 67253018216SPaolo Bonzini case 0xd4: /* RDEV */ 67353018216SPaolo Bonzini case 0xd5: /* RDRR */ 67453018216SPaolo Bonzini goto bad_cmd; 67553018216SPaolo Bonzini 67653018216SPaolo Bonzini case 0xda: /* RDID1 */ 67753018216SPaolo Bonzini s->p = 0; 67853018216SPaolo Bonzini s->resp[0] = (s->id >> 16) & 0xff; 67953018216SPaolo Bonzini break; 68053018216SPaolo Bonzini case 0xdb: /* RDID2 */ 68153018216SPaolo Bonzini s->p = 0; 68253018216SPaolo Bonzini s->resp[0] = (s->id >> 8) & 0xff; 68353018216SPaolo Bonzini break; 68453018216SPaolo Bonzini case 0xdc: /* RDID3 */ 68553018216SPaolo Bonzini s->p = 0; 68653018216SPaolo Bonzini s->resp[0] = (s->id >> 0) & 0xff; 68753018216SPaolo Bonzini break; 68853018216SPaolo Bonzini 68953018216SPaolo Bonzini default: 69053018216SPaolo Bonzini bad_cmd: 691591f73f6SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 692591f73f6SPeter Maydell "%s: unknown command %02x\n", __func__, s->cmd); 69353018216SPaolo Bonzini break; 69453018216SPaolo Bonzini } 69553018216SPaolo Bonzini 69653018216SPaolo Bonzini return ret; 69753018216SPaolo Bonzini } 69853018216SPaolo Bonzini 69953018216SPaolo Bonzini static void *mipid_init(void) 70053018216SPaolo Bonzini { 70153018216SPaolo Bonzini struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s)); 70253018216SPaolo Bonzini 70353018216SPaolo Bonzini s->id = 0x838f03; 70453018216SPaolo Bonzini mipid_reset(s); 70553018216SPaolo Bonzini 70653018216SPaolo Bonzini return s; 70753018216SPaolo Bonzini } 70853018216SPaolo Bonzini 70953018216SPaolo Bonzini static void n8x0_spi_setup(struct n800_s *s) 71053018216SPaolo Bonzini { 71153018216SPaolo Bonzini void *tsc = s->ts.opaque; 71253018216SPaolo Bonzini void *mipid = mipid_init(); 71353018216SPaolo Bonzini 71453018216SPaolo Bonzini omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0); 71553018216SPaolo Bonzini omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1); 71653018216SPaolo Bonzini } 71753018216SPaolo Bonzini 71853018216SPaolo Bonzini /* This task is normally performed by the bootloader. If we're loading 71953018216SPaolo Bonzini * a kernel directly, we need to enable the Blizzard ourselves. */ 72053018216SPaolo Bonzini static void n800_dss_init(struct rfbi_chip_s *chip) 72153018216SPaolo Bonzini { 72253018216SPaolo Bonzini uint8_t *fb_blank; 72353018216SPaolo Bonzini 72453018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */ 72553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x64); 72653018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */ 72753018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1e); 72853018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */ 72953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xe0); 73053018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */ 73153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); 73253018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */ 73353018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x06); 73453018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x68); /* Display Mode register */ 73553018216SPaolo Bonzini chip->write(chip->opaque, 1, 1); /* Enable bit */ 73653018216SPaolo Bonzini 73753018216SPaolo Bonzini chip->write(chip->opaque, 0, 0x6c); 73853018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */ 73953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input X Start Position */ 74053018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */ 74153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Input Y Start Position */ 74253018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1f); /* Input X End Position */ 74353018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x03); /* Input X End Position */ 74453018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xdf); /* Input Y End Position */ 74553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Input Y End Position */ 74653018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */ 74753018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output X Start Position */ 74853018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */ 74953018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x00); /* Output Y Start Position */ 75053018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x1f); /* Output X End Position */ 75153018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x03); /* Output X End Position */ 75253018216SPaolo Bonzini chip->write(chip->opaque, 1, 0xdf); /* Output Y End Position */ 75353018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Output Y End Position */ 75453018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Input Data Format */ 75553018216SPaolo Bonzini chip->write(chip->opaque, 1, 0x01); /* Data Source Select */ 75653018216SPaolo Bonzini 75753018216SPaolo Bonzini fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2); 75853018216SPaolo Bonzini /* Display Memory Data Port */ 75953018216SPaolo Bonzini chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800); 76053018216SPaolo Bonzini g_free(fb_blank); 76153018216SPaolo Bonzini } 76253018216SPaolo Bonzini 76353018216SPaolo Bonzini static void n8x0_dss_setup(struct n800_s *s) 76453018216SPaolo Bonzini { 76553018216SPaolo Bonzini s->blizzard.opaque = s1d13745_init(NULL); 76653018216SPaolo Bonzini s->blizzard.block = s1d13745_write_block; 76753018216SPaolo Bonzini s->blizzard.write = s1d13745_write; 76853018216SPaolo Bonzini s->blizzard.read = s1d13745_read; 76953018216SPaolo Bonzini 77053018216SPaolo Bonzini omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard); 77153018216SPaolo Bonzini } 77253018216SPaolo Bonzini 77353018216SPaolo Bonzini static void n8x0_cbus_setup(struct n800_s *s) 77453018216SPaolo Bonzini { 77553018216SPaolo Bonzini qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO); 77653018216SPaolo Bonzini qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO); 77753018216SPaolo Bonzini qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO); 77853018216SPaolo Bonzini 77953018216SPaolo Bonzini CBus *cbus = cbus_init(dat_out); 78053018216SPaolo Bonzini 78153018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk); 78253018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat); 78353018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel); 78453018216SPaolo Bonzini 78553018216SPaolo Bonzini cbus_attach(cbus, s->retu = retu_init(retu_irq, 1)); 78653018216SPaolo Bonzini cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1)); 78753018216SPaolo Bonzini } 78853018216SPaolo Bonzini 78953018216SPaolo Bonzini static void n8x0_uart_setup(struct n800_s *s) 79053018216SPaolo Bonzini { 7910ec7b3e7SMarc-André Lureau Chardev *radio = uart_hci_init(); 79253018216SPaolo Bonzini 79353018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO, 79453018216SPaolo Bonzini csrhci_pins_get(radio)[csrhci_pin_reset]); 79553018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO, 79653018216SPaolo Bonzini csrhci_pins_get(radio)[csrhci_pin_wakeup]); 79753018216SPaolo Bonzini 79853018216SPaolo Bonzini omap_uart_attach(s->mpu->uart[BT_UART], radio); 79953018216SPaolo Bonzini } 80053018216SPaolo Bonzini 80153018216SPaolo Bonzini static void n8x0_usb_setup(struct n800_s *s) 80253018216SPaolo Bonzini { 80353018216SPaolo Bonzini SysBusDevice *dev; 80453018216SPaolo Bonzini s->usb = qdev_create(NULL, "tusb6010"); 80553018216SPaolo Bonzini dev = SYS_BUS_DEVICE(s->usb); 80653018216SPaolo Bonzini qdev_init_nofail(s->usb); 80753018216SPaolo Bonzini sysbus_connect_irq(dev, 0, 80853018216SPaolo Bonzini qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO)); 80953018216SPaolo Bonzini /* Using the NOR interface */ 81053018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS, 81153018216SPaolo Bonzini sysbus_mmio_get_region(dev, 0)); 81253018216SPaolo Bonzini omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS, 81353018216SPaolo Bonzini sysbus_mmio_get_region(dev, 1)); 81453018216SPaolo Bonzini qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO, 81553018216SPaolo Bonzini qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */ 81653018216SPaolo Bonzini } 81753018216SPaolo Bonzini 81853018216SPaolo Bonzini /* Setup done before the main bootloader starts by some early setup code 81953018216SPaolo Bonzini * - used when we want to run the main bootloader in emulation. This 82053018216SPaolo Bonzini * isn't documented. */ 82153018216SPaolo Bonzini static uint32_t n800_pinout[104] = { 82253018216SPaolo Bonzini 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0, 82353018216SPaolo Bonzini 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808, 82453018216SPaolo Bonzini 0x08080808, 0x180800c4, 0x00b80000, 0x08080808, 82553018216SPaolo Bonzini 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128, 82653018216SPaolo Bonzini 0x01241800, 0x18181818, 0x000000f0, 0x01300000, 82753018216SPaolo Bonzini 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b, 82853018216SPaolo Bonzini 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080, 82953018216SPaolo Bonzini 0x007c0000, 0x00000000, 0x00000088, 0x00840000, 83053018216SPaolo Bonzini 0x00000000, 0x00000094, 0x00980300, 0x0f180003, 83153018216SPaolo Bonzini 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c, 83253018216SPaolo Bonzini 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008, 83353018216SPaolo Bonzini 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f, 83453018216SPaolo Bonzini 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc, 83553018216SPaolo Bonzini 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008, 83653018216SPaolo Bonzini 0x00000000, 0x00000038, 0x00340000, 0x00000000, 83753018216SPaolo Bonzini 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060, 83853018216SPaolo Bonzini 0x005c0808, 0x08080808, 0x08080058, 0x00540808, 83953018216SPaolo Bonzini 0x08080808, 0x0808006c, 0x00680808, 0x08080808, 84053018216SPaolo Bonzini 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0, 84153018216SPaolo Bonzini 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808, 84253018216SPaolo Bonzini 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff, 84353018216SPaolo Bonzini 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100, 84453018216SPaolo Bonzini 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a, 84553018216SPaolo Bonzini 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00, 84653018216SPaolo Bonzini 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118, 84753018216SPaolo Bonzini 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b, 84853018216SPaolo Bonzini }; 84953018216SPaolo Bonzini 85053018216SPaolo Bonzini static void n800_setup_nolo_tags(void *sram_base) 85153018216SPaolo Bonzini { 85253018216SPaolo Bonzini int i; 85353018216SPaolo Bonzini uint32_t *p = sram_base + 0x8000; 85453018216SPaolo Bonzini uint32_t *v = sram_base + 0xa000; 85553018216SPaolo Bonzini 85653018216SPaolo Bonzini memset(p, 0, 0x3000); 85753018216SPaolo Bonzini 85853018216SPaolo Bonzini strcpy((void *) (p + 0), "QEMU N800"); 85953018216SPaolo Bonzini 86053018216SPaolo Bonzini strcpy((void *) (p + 8), "F5"); 86153018216SPaolo Bonzini 8620983979bSPaolo Bonzini stl_p(p + 10, 0x04f70000); 86353018216SPaolo Bonzini strcpy((void *) (p + 9), "RX-34"); 86453018216SPaolo Bonzini 86553018216SPaolo Bonzini /* RAM size in MB? */ 8660983979bSPaolo Bonzini stl_p(p + 12, 0x80); 86753018216SPaolo Bonzini 86853018216SPaolo Bonzini /* Pointer to the list of tags */ 8690983979bSPaolo Bonzini stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000); 87053018216SPaolo Bonzini 87153018216SPaolo Bonzini /* The NOLO tags start here */ 87253018216SPaolo Bonzini p = sram_base + 0x9000; 87353018216SPaolo Bonzini #define ADD_TAG(tag, len) \ 8740983979bSPaolo Bonzini stw_p((uint16_t *) p + 0, tag); \ 8750983979bSPaolo Bonzini stw_p((uint16_t *) p + 1, len); p++; \ 8760983979bSPaolo Bonzini stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff)); 87753018216SPaolo Bonzini 87853018216SPaolo Bonzini /* OMAP STI console? Pin out settings? */ 87953018216SPaolo Bonzini ADD_TAG(0x6e01, 414); 880fddbd80cSPaolo Bonzini for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) { 8810983979bSPaolo Bonzini stl_p(v++, n800_pinout[i]); 882fddbd80cSPaolo Bonzini } 88353018216SPaolo Bonzini 88453018216SPaolo Bonzini /* Kernel memsize? */ 88553018216SPaolo Bonzini ADD_TAG(0x6e05, 1); 8860983979bSPaolo Bonzini stl_p(v++, 2); 88753018216SPaolo Bonzini 88853018216SPaolo Bonzini /* NOLO serial console */ 88953018216SPaolo Bonzini ADD_TAG(0x6e02, 4); 8900983979bSPaolo Bonzini stl_p(v++, XLDR_LL_UART); /* UART number (1 - 3) */ 89153018216SPaolo Bonzini 89253018216SPaolo Bonzini #if 0 89353018216SPaolo Bonzini /* CBUS settings (Retu/AVilma) */ 89453018216SPaolo Bonzini ADD_TAG(0x6e03, 6); 8950983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 65); /* CBUS GPIO0 */ 8960983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 66); /* CBUS GPIO1 */ 8970983979bSPaolo Bonzini stw_p((uint16_t *) v + 2, 64); /* CBUS GPIO2 */ 89853018216SPaolo Bonzini v += 2; 89953018216SPaolo Bonzini #endif 90053018216SPaolo Bonzini 90153018216SPaolo Bonzini /* Nokia ASIC BB5 (Retu/Tahvo) */ 90253018216SPaolo Bonzini ADD_TAG(0x6e0a, 4); 9030983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */ 9040983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */ 90553018216SPaolo Bonzini v++; 90653018216SPaolo Bonzini 90753018216SPaolo Bonzini /* LCD console? */ 90853018216SPaolo Bonzini ADD_TAG(0x6e04, 4); 9090983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 30); /* ??? */ 9100983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 24); /* ??? */ 91153018216SPaolo Bonzini v++; 91253018216SPaolo Bonzini 91353018216SPaolo Bonzini #if 0 91453018216SPaolo Bonzini /* LCD settings */ 91553018216SPaolo Bonzini ADD_TAG(0x6e06, 2); 9160983979bSPaolo Bonzini stw_p((uint16_t *) (v++), 15); /* ??? */ 91753018216SPaolo Bonzini #endif 91853018216SPaolo Bonzini 91953018216SPaolo Bonzini /* I^2C (Menelaus) */ 92053018216SPaolo Bonzini ADD_TAG(0x6e07, 4); 9210983979bSPaolo Bonzini stl_p(v++, 0x00720000); /* ??? */ 92253018216SPaolo Bonzini 92353018216SPaolo Bonzini /* Unknown */ 92453018216SPaolo Bonzini ADD_TAG(0x6e0b, 6); 9250983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 94); /* ??? */ 9260983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 23); /* ??? */ 9270983979bSPaolo Bonzini stw_p((uint16_t *) v + 2, 0); /* ??? */ 92853018216SPaolo Bonzini v += 2; 92953018216SPaolo Bonzini 93053018216SPaolo Bonzini /* OMAP gpio switch info */ 93153018216SPaolo Bonzini ADD_TAG(0x6e0c, 80); 93253018216SPaolo Bonzini strcpy((void *) v, "bat_cover"); v += 3; 9330983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 110); /* GPIO num ??? */ 9340983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 1); /* GPIO num ??? */ 93553018216SPaolo Bonzini v += 2; 93653018216SPaolo Bonzini strcpy((void *) v, "cam_act"); v += 3; 9370983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 95); /* GPIO num ??? */ 9380983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 32); /* GPIO num ??? */ 93953018216SPaolo Bonzini v += 2; 94053018216SPaolo Bonzini strcpy((void *) v, "cam_turn"); v += 3; 9410983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 12); /* GPIO num ??? */ 9420983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 33); /* GPIO num ??? */ 94353018216SPaolo Bonzini v += 2; 94453018216SPaolo Bonzini strcpy((void *) v, "headphone"); v += 3; 9450983979bSPaolo Bonzini stw_p((uint16_t *) v + 0, 107); /* GPIO num ??? */ 9460983979bSPaolo Bonzini stw_p((uint16_t *) v + 1, 17); /* GPIO num ??? */ 94753018216SPaolo Bonzini v += 2; 94853018216SPaolo Bonzini 94953018216SPaolo Bonzini /* Bluetooth */ 95053018216SPaolo Bonzini ADD_TAG(0x6e0e, 12); 9510983979bSPaolo Bonzini stl_p(v++, 0x5c623d01); /* ??? */ 9520983979bSPaolo Bonzini stl_p(v++, 0x00000201); /* ??? */ 9530983979bSPaolo Bonzini stl_p(v++, 0x00000000); /* ??? */ 95453018216SPaolo Bonzini 95553018216SPaolo Bonzini /* CX3110x WLAN settings */ 95653018216SPaolo Bonzini ADD_TAG(0x6e0f, 8); 9570983979bSPaolo Bonzini stl_p(v++, 0x00610025); /* ??? */ 9580983979bSPaolo Bonzini stl_p(v++, 0xffff0057); /* ??? */ 95953018216SPaolo Bonzini 96053018216SPaolo Bonzini /* MMC host settings */ 96153018216SPaolo Bonzini ADD_TAG(0x6e10, 12); 9620983979bSPaolo Bonzini stl_p(v++, 0xffff000f); /* ??? */ 9630983979bSPaolo Bonzini stl_p(v++, 0xffffffff); /* ??? */ 9640983979bSPaolo Bonzini stl_p(v++, 0x00000060); /* ??? */ 96553018216SPaolo Bonzini 96653018216SPaolo Bonzini /* OneNAND chip select */ 96753018216SPaolo Bonzini ADD_TAG(0x6e11, 10); 9680983979bSPaolo Bonzini stl_p(v++, 0x00000401); /* ??? */ 9690983979bSPaolo Bonzini stl_p(v++, 0x0002003a); /* ??? */ 9700983979bSPaolo Bonzini stl_p(v++, 0x00000002); /* ??? */ 97153018216SPaolo Bonzini 97253018216SPaolo Bonzini /* TEA5761 sensor settings */ 97353018216SPaolo Bonzini ADD_TAG(0x6e12, 2); 9740983979bSPaolo Bonzini stl_p(v++, 93); /* GPIO num ??? */ 97553018216SPaolo Bonzini 97653018216SPaolo Bonzini #if 0 97753018216SPaolo Bonzini /* Unknown tag */ 97853018216SPaolo Bonzini ADD_TAG(6e09, 0); 97953018216SPaolo Bonzini 98053018216SPaolo Bonzini /* Kernel UART / console */ 98153018216SPaolo Bonzini ADD_TAG(6e12, 0); 98253018216SPaolo Bonzini #endif 98353018216SPaolo Bonzini 98453018216SPaolo Bonzini /* End of the list */ 9850983979bSPaolo Bonzini stl_p(p++, 0x00000000); 9860983979bSPaolo Bonzini stl_p(p++, 0x00000000); 98753018216SPaolo Bonzini } 98853018216SPaolo Bonzini 98953018216SPaolo Bonzini /* This task is normally performed by the bootloader. If we're loading 99053018216SPaolo Bonzini * a kernel directly, we need to set up GPMC mappings ourselves. */ 99153018216SPaolo Bonzini static void n800_gpmc_init(struct n800_s *s) 99253018216SPaolo Bonzini { 99353018216SPaolo Bonzini uint32_t config7 = 99453018216SPaolo Bonzini (0xf << 8) | /* MASKADDRESS */ 99553018216SPaolo Bonzini (1 << 6) | /* CSVALID */ 99653018216SPaolo Bonzini (4 << 0); /* BASEADDRESS */ 99753018216SPaolo Bonzini 99853018216SPaolo Bonzini cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */ 999e1fe50dcSStefan Weil &config7, sizeof(config7)); 100053018216SPaolo Bonzini } 100153018216SPaolo Bonzini 100253018216SPaolo Bonzini /* Setup sequence done by the bootloader */ 100353018216SPaolo Bonzini static void n8x0_boot_init(void *opaque) 100453018216SPaolo Bonzini { 100553018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) opaque; 100653018216SPaolo Bonzini uint32_t buf; 100753018216SPaolo Bonzini 100853018216SPaolo Bonzini /* PRCM setup */ 100953018216SPaolo Bonzini #define omap_writel(addr, val) \ 101053018216SPaolo Bonzini buf = (val); \ 1011e1fe50dcSStefan Weil cpu_physical_memory_write(addr, &buf, sizeof(buf)) 101253018216SPaolo Bonzini 101353018216SPaolo Bonzini omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */ 101453018216SPaolo Bonzini omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */ 101553018216SPaolo Bonzini omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */ 101653018216SPaolo Bonzini omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */ 101753018216SPaolo Bonzini omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */ 101853018216SPaolo Bonzini omap_writel(0x48008098, 0); /* PRCM_POLCTRL */ 101953018216SPaolo Bonzini omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */ 102053018216SPaolo Bonzini omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */ 102153018216SPaolo Bonzini omap_writel(0x48008158, 1); /* RM_RSTST_MPU */ 102253018216SPaolo Bonzini omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */ 102353018216SPaolo Bonzini omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */ 102453018216SPaolo Bonzini omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */ 102553018216SPaolo Bonzini omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */ 102653018216SPaolo Bonzini omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */ 102753018216SPaolo Bonzini omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */ 102853018216SPaolo Bonzini omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */ 102953018216SPaolo Bonzini omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */ 103053018216SPaolo Bonzini omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */ 103153018216SPaolo Bonzini omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */ 103253018216SPaolo Bonzini omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */ 103353018216SPaolo Bonzini omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */ 103453018216SPaolo Bonzini omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */ 103553018216SPaolo Bonzini omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */ 103653018216SPaolo Bonzini omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */ 103753018216SPaolo Bonzini omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */ 103853018216SPaolo Bonzini omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */ 103953018216SPaolo Bonzini omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */ 104053018216SPaolo Bonzini omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */ 104153018216SPaolo Bonzini omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */ 104253018216SPaolo Bonzini omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */ 104353018216SPaolo Bonzini omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */ 104453018216SPaolo Bonzini omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */ 104553018216SPaolo Bonzini omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */ 104653018216SPaolo Bonzini omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */ 104753018216SPaolo Bonzini omap_writel(0x48008540, /* CM_CLKSEL1_PLL */ 104853018216SPaolo Bonzini (0x78 << 12) | (6 << 8)); 104953018216SPaolo Bonzini omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */ 105053018216SPaolo Bonzini 105153018216SPaolo Bonzini /* GPMC setup */ 105253018216SPaolo Bonzini n800_gpmc_init(s); 105353018216SPaolo Bonzini 105453018216SPaolo Bonzini /* Video setup */ 105553018216SPaolo Bonzini n800_dss_init(&s->blizzard); 105653018216SPaolo Bonzini 105753018216SPaolo Bonzini /* CPU setup */ 105853018216SPaolo Bonzini s->mpu->cpu->env.GE = 0x5; 105953018216SPaolo Bonzini 106053018216SPaolo Bonzini /* If the machine has a slided keyboard, open it */ 1061fddbd80cSPaolo Bonzini if (s->kbd) { 106253018216SPaolo Bonzini qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO)); 106353018216SPaolo Bonzini } 1064fddbd80cSPaolo Bonzini } 106553018216SPaolo Bonzini 106653018216SPaolo Bonzini #define OMAP_TAG_NOKIA_BT 0x4e01 106753018216SPaolo Bonzini #define OMAP_TAG_WLAN_CX3110X 0x4e02 106853018216SPaolo Bonzini #define OMAP_TAG_CBUS 0x4e03 106953018216SPaolo Bonzini #define OMAP_TAG_EM_ASIC_BB5 0x4e04 107053018216SPaolo Bonzini 107153018216SPaolo Bonzini static struct omap_gpiosw_info_s { 107253018216SPaolo Bonzini const char *name; 107353018216SPaolo Bonzini int line; 107453018216SPaolo Bonzini int type; 107553018216SPaolo Bonzini } n800_gpiosw_info[] = { 107653018216SPaolo Bonzini { 107753018216SPaolo Bonzini "bat_cover", N800_BAT_COVER_GPIO, 107853018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED, 107953018216SPaolo Bonzini }, { 108053018216SPaolo Bonzini "cam_act", N800_CAM_ACT_GPIO, 108153018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY, 108253018216SPaolo Bonzini }, { 108353018216SPaolo Bonzini "cam_turn", N800_CAM_TURN_GPIO, 108453018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED, 108553018216SPaolo Bonzini }, { 108653018216SPaolo Bonzini "headphone", N8X0_HEADPHONE_GPIO, 108753018216SPaolo Bonzini OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED, 108853018216SPaolo Bonzini }, 108953018216SPaolo Bonzini { NULL } 109053018216SPaolo Bonzini }, n810_gpiosw_info[] = { 109153018216SPaolo Bonzini { 109253018216SPaolo Bonzini "gps_reset", N810_GPS_RESET_GPIO, 109353018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT, 109453018216SPaolo Bonzini }, { 109553018216SPaolo Bonzini "gps_wakeup", N810_GPS_WAKEUP_GPIO, 109653018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT, 109753018216SPaolo Bonzini }, { 109853018216SPaolo Bonzini "headphone", N8X0_HEADPHONE_GPIO, 109953018216SPaolo Bonzini OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED, 110053018216SPaolo Bonzini }, { 110153018216SPaolo Bonzini "kb_lock", N810_KB_LOCK_GPIO, 110253018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED, 110353018216SPaolo Bonzini }, { 110453018216SPaolo Bonzini "sleepx_led", N810_SLEEPX_LED_GPIO, 110553018216SPaolo Bonzini OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT, 110653018216SPaolo Bonzini }, { 110753018216SPaolo Bonzini "slide", N810_SLIDE_GPIO, 110853018216SPaolo Bonzini OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED, 110953018216SPaolo Bonzini }, 111053018216SPaolo Bonzini { NULL } 111153018216SPaolo Bonzini }; 111253018216SPaolo Bonzini 111353018216SPaolo Bonzini static struct omap_partition_info_s { 111453018216SPaolo Bonzini uint32_t offset; 111553018216SPaolo Bonzini uint32_t size; 111653018216SPaolo Bonzini int mask; 111753018216SPaolo Bonzini const char *name; 111853018216SPaolo Bonzini } n800_part_info[] = { 111953018216SPaolo Bonzini { 0x00000000, 0x00020000, 0x3, "bootloader" }, 112053018216SPaolo Bonzini { 0x00020000, 0x00060000, 0x0, "config" }, 112153018216SPaolo Bonzini { 0x00080000, 0x00200000, 0x0, "kernel" }, 112253018216SPaolo Bonzini { 0x00280000, 0x00200000, 0x3, "initfs" }, 112353018216SPaolo Bonzini { 0x00480000, 0x0fb80000, 0x3, "rootfs" }, 112453018216SPaolo Bonzini 112553018216SPaolo Bonzini { 0, 0, 0, NULL } 112653018216SPaolo Bonzini }, n810_part_info[] = { 112753018216SPaolo Bonzini { 0x00000000, 0x00020000, 0x3, "bootloader" }, 112853018216SPaolo Bonzini { 0x00020000, 0x00060000, 0x0, "config" }, 112953018216SPaolo Bonzini { 0x00080000, 0x00220000, 0x0, "kernel" }, 113053018216SPaolo Bonzini { 0x002a0000, 0x00400000, 0x0, "initfs" }, 113153018216SPaolo Bonzini { 0x006a0000, 0x0f960000, 0x0, "rootfs" }, 113253018216SPaolo Bonzini 113353018216SPaolo Bonzini { 0, 0, 0, NULL } 113453018216SPaolo Bonzini }; 113553018216SPaolo Bonzini 113653018216SPaolo Bonzini static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }}; 113753018216SPaolo Bonzini 113853018216SPaolo Bonzini static int n8x0_atag_setup(void *p, int model) 113953018216SPaolo Bonzini { 114053018216SPaolo Bonzini uint8_t *b; 114153018216SPaolo Bonzini uint16_t *w; 114253018216SPaolo Bonzini uint32_t *l; 114353018216SPaolo Bonzini struct omap_gpiosw_info_s *gpiosw; 114453018216SPaolo Bonzini struct omap_partition_info_s *partition; 114553018216SPaolo Bonzini const char *tag; 114653018216SPaolo Bonzini 114753018216SPaolo Bonzini w = p; 114853018216SPaolo Bonzini 11490983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_UART); /* u16 tag */ 11500983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */ 11510983979bSPaolo Bonzini stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */ 115253018216SPaolo Bonzini w++; 115353018216SPaolo Bonzini 115453018216SPaolo Bonzini #if 0 11550983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */ 11560983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */ 11570983979bSPaolo Bonzini stw_p(w++, XLDR_LL_UART + 1); /* u8 console_uart */ 11580983979bSPaolo Bonzini stw_p(w++, 115200); /* u32 console_speed */ 115953018216SPaolo Bonzini #endif 116053018216SPaolo Bonzini 11610983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_LCD); /* u16 tag */ 11620983979bSPaolo Bonzini stw_p(w++, 36); /* u16 len */ 116353018216SPaolo Bonzini strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */ 116453018216SPaolo Bonzini w += 8; 116553018216SPaolo Bonzini strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */ 116653018216SPaolo Bonzini w += 8; 11670983979bSPaolo Bonzini stw_p(w++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */ 11680983979bSPaolo Bonzini stw_p(w++, 24); /* u8 data_lines */ 116953018216SPaolo Bonzini 11700983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_CBUS); /* u16 tag */ 11710983979bSPaolo Bonzini stw_p(w++, 8); /* u16 len */ 11720983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */ 11730983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */ 11740983979bSPaolo Bonzini stw_p(w++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */ 117553018216SPaolo Bonzini w++; 117653018216SPaolo Bonzini 11770983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */ 11780983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */ 11790983979bSPaolo Bonzini stw_p(w++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */ 11800983979bSPaolo Bonzini stw_p(w++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */ 118153018216SPaolo Bonzini 118253018216SPaolo Bonzini gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info; 118353018216SPaolo Bonzini for (; gpiosw->name; gpiosw++) { 11840983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ 11850983979bSPaolo Bonzini stw_p(w++, 20); /* u16 len */ 118653018216SPaolo Bonzini strcpy((void *) w, gpiosw->name); /* char name[12] */ 118753018216SPaolo Bonzini w += 6; 11880983979bSPaolo Bonzini stw_p(w++, gpiosw->line); /* u16 gpio */ 11890983979bSPaolo Bonzini stw_p(w++, gpiosw->type); 11900983979bSPaolo Bonzini stw_p(w++, 0); 11910983979bSPaolo Bonzini stw_p(w++, 0); 119253018216SPaolo Bonzini } 119353018216SPaolo Bonzini 11940983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_NOKIA_BT); /* u16 tag */ 11950983979bSPaolo Bonzini stw_p(w++, 12); /* u16 len */ 119653018216SPaolo Bonzini b = (void *) w; 11970983979bSPaolo Bonzini stb_p(b++, 0x01); /* u8 chip_type (CSR) */ 11980983979bSPaolo Bonzini stb_p(b++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */ 11990983979bSPaolo Bonzini stb_p(b++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */ 12000983979bSPaolo Bonzini stb_p(b++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */ 12010983979bSPaolo Bonzini stb_p(b++, BT_UART + 1); /* u8 bt_uart */ 120253018216SPaolo Bonzini memcpy(b, &n8x0_bd_addr, 6); /* u8 bd_addr[6] */ 120353018216SPaolo Bonzini b += 6; 12040983979bSPaolo Bonzini stb_p(b++, 0x02); /* u8 bt_sysclk (38.4) */ 120553018216SPaolo Bonzini w = (void *) b; 120653018216SPaolo Bonzini 12070983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */ 12080983979bSPaolo Bonzini stw_p(w++, 8); /* u16 len */ 12090983979bSPaolo Bonzini stw_p(w++, 0x25); /* u8 chip_type */ 12100983979bSPaolo Bonzini stw_p(w++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */ 12110983979bSPaolo Bonzini stw_p(w++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */ 12120983979bSPaolo Bonzini stw_p(w++, -1); /* s16 spi_cs_gpio */ 121353018216SPaolo Bonzini 12140983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_MMC); /* u16 tag */ 12150983979bSPaolo Bonzini stw_p(w++, 16); /* u16 len */ 121653018216SPaolo Bonzini if (model == 810) { 12170983979bSPaolo Bonzini stw_p(w++, 0x23f); /* unsigned flags */ 12180983979bSPaolo Bonzini stw_p(w++, -1); /* s16 power_pin */ 12190983979bSPaolo Bonzini stw_p(w++, -1); /* s16 switch_pin */ 12200983979bSPaolo Bonzini stw_p(w++, -1); /* s16 wp_pin */ 12210983979bSPaolo Bonzini stw_p(w++, 0x240); /* unsigned flags */ 12220983979bSPaolo Bonzini stw_p(w++, 0xc000); /* s16 power_pin */ 12230983979bSPaolo Bonzini stw_p(w++, 0x0248); /* s16 switch_pin */ 12240983979bSPaolo Bonzini stw_p(w++, 0xc000); /* s16 wp_pin */ 122553018216SPaolo Bonzini } else { 12260983979bSPaolo Bonzini stw_p(w++, 0xf); /* unsigned flags */ 12270983979bSPaolo Bonzini stw_p(w++, -1); /* s16 power_pin */ 12280983979bSPaolo Bonzini stw_p(w++, -1); /* s16 switch_pin */ 12290983979bSPaolo Bonzini stw_p(w++, -1); /* s16 wp_pin */ 12300983979bSPaolo Bonzini stw_p(w++, 0); /* unsigned flags */ 12310983979bSPaolo Bonzini stw_p(w++, 0); /* s16 power_pin */ 12320983979bSPaolo Bonzini stw_p(w++, 0); /* s16 switch_pin */ 12330983979bSPaolo Bonzini stw_p(w++, 0); /* s16 wp_pin */ 123453018216SPaolo Bonzini } 123553018216SPaolo Bonzini 12360983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_TEA5761); /* u16 tag */ 12370983979bSPaolo Bonzini stw_p(w++, 4); /* u16 len */ 12380983979bSPaolo Bonzini stw_p(w++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */ 123953018216SPaolo Bonzini w++; 124053018216SPaolo Bonzini 124153018216SPaolo Bonzini partition = (model == 810) ? n810_part_info : n800_part_info; 124253018216SPaolo Bonzini for (; partition->name; partition++) { 12430983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_PARTITION); /* u16 tag */ 12440983979bSPaolo Bonzini stw_p(w++, 28); /* u16 len */ 124553018216SPaolo Bonzini strcpy((void *) w, partition->name); /* char name[16] */ 124653018216SPaolo Bonzini l = (void *) (w + 8); 12470983979bSPaolo Bonzini stl_p(l++, partition->size); /* unsigned int size */ 12480983979bSPaolo Bonzini stl_p(l++, partition->offset); /* unsigned int offset */ 12490983979bSPaolo Bonzini stl_p(l++, partition->mask); /* unsigned int mask_flags */ 125053018216SPaolo Bonzini w = (void *) l; 125153018216SPaolo Bonzini } 125253018216SPaolo Bonzini 12530983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_BOOT_REASON); /* u16 tag */ 12540983979bSPaolo Bonzini stw_p(w++, 12); /* u16 len */ 125553018216SPaolo Bonzini #if 0 125653018216SPaolo Bonzini strcpy((void *) w, "por"); /* char reason_str[12] */ 125753018216SPaolo Bonzini strcpy((void *) w, "charger"); /* char reason_str[12] */ 125853018216SPaolo Bonzini strcpy((void *) w, "32wd_to"); /* char reason_str[12] */ 125953018216SPaolo Bonzini strcpy((void *) w, "sw_rst"); /* char reason_str[12] */ 126053018216SPaolo Bonzini strcpy((void *) w, "mbus"); /* char reason_str[12] */ 126153018216SPaolo Bonzini strcpy((void *) w, "unknown"); /* char reason_str[12] */ 126253018216SPaolo Bonzini strcpy((void *) w, "swdg_to"); /* char reason_str[12] */ 126353018216SPaolo Bonzini strcpy((void *) w, "sec_vio"); /* char reason_str[12] */ 126453018216SPaolo Bonzini strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ 126553018216SPaolo Bonzini strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */ 126653018216SPaolo Bonzini #else 126753018216SPaolo Bonzini strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ 126853018216SPaolo Bonzini #endif 126953018216SPaolo Bonzini w += 6; 127053018216SPaolo Bonzini 127153018216SPaolo Bonzini tag = (model == 810) ? "RX-44" : "RX-34"; 12720983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */ 12730983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */ 127453018216SPaolo Bonzini strcpy((void *) w, "product"); /* char component[12] */ 127553018216SPaolo Bonzini w += 6; 127653018216SPaolo Bonzini strcpy((void *) w, tag); /* char version[12] */ 127753018216SPaolo Bonzini w += 6; 127853018216SPaolo Bonzini 12790983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */ 12800983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */ 128153018216SPaolo Bonzini strcpy((void *) w, "hw-build"); /* char component[12] */ 128253018216SPaolo Bonzini w += 6; 128353018216SPaolo Bonzini strcpy((void *) w, "QEMU "); 128435c2c8dcSEduardo Habkost pstrcat((void *) w, 12, qemu_hw_version()); /* char version[12] */ 128553018216SPaolo Bonzini w += 6; 128653018216SPaolo Bonzini 128753018216SPaolo Bonzini tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu"; 12880983979bSPaolo Bonzini stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */ 12890983979bSPaolo Bonzini stw_p(w++, 24); /* u16 len */ 129053018216SPaolo Bonzini strcpy((void *) w, "nolo"); /* char component[12] */ 129153018216SPaolo Bonzini w += 6; 129253018216SPaolo Bonzini strcpy((void *) w, tag); /* char version[12] */ 129353018216SPaolo Bonzini w += 6; 129453018216SPaolo Bonzini 129553018216SPaolo Bonzini return (void *) w - p; 129653018216SPaolo Bonzini } 129753018216SPaolo Bonzini 129853018216SPaolo Bonzini static int n800_atag_setup(const struct arm_boot_info *info, void *p) 129953018216SPaolo Bonzini { 130053018216SPaolo Bonzini return n8x0_atag_setup(p, 800); 130153018216SPaolo Bonzini } 130253018216SPaolo Bonzini 130353018216SPaolo Bonzini static int n810_atag_setup(const struct arm_boot_info *info, void *p) 130453018216SPaolo Bonzini { 130553018216SPaolo Bonzini return n8x0_atag_setup(p, 810); 130653018216SPaolo Bonzini } 130753018216SPaolo Bonzini 13083ef96221SMarcel Apfelbaum static void n8x0_init(MachineState *machine, 130953018216SPaolo Bonzini struct arm_boot_info *binfo, int model) 131053018216SPaolo Bonzini { 131153018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 131253018216SPaolo Bonzini struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); 131353018216SPaolo Bonzini int sdram_size = binfo->ram_size; 131453018216SPaolo Bonzini 1315ba1ba5ccSIgor Mammedov s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_type); 131653018216SPaolo Bonzini 131753018216SPaolo Bonzini /* Setup peripherals 131853018216SPaolo Bonzini * 131953018216SPaolo Bonzini * Believed external peripherals layout in the N810: 132053018216SPaolo Bonzini * (spi bus 1) 132153018216SPaolo Bonzini * tsc2005 132253018216SPaolo Bonzini * lcd_mipid 132353018216SPaolo Bonzini * (spi bus 2) 132453018216SPaolo Bonzini * Conexant cx3110x (WLAN) 132553018216SPaolo Bonzini * optional: pc2400m (WiMAX) 132653018216SPaolo Bonzini * (i2c bus 0) 132753018216SPaolo Bonzini * TLV320AIC33 (audio codec) 132853018216SPaolo Bonzini * TCM825x (camera by Toshiba) 132953018216SPaolo Bonzini * lp5521 (clever LEDs) 133053018216SPaolo Bonzini * tsl2563 (light sensor, hwmon, model 7, rev. 0) 133153018216SPaolo Bonzini * lm8323 (keypad, manf 00, rev 04) 133253018216SPaolo Bonzini * (i2c bus 1) 133353018216SPaolo Bonzini * tmp105 (temperature sensor, hwmon) 133453018216SPaolo Bonzini * menelaus (pm) 133553018216SPaolo Bonzini * (somewhere on i2c - maybe N800-only) 133653018216SPaolo Bonzini * tea5761 (FM tuner) 133753018216SPaolo Bonzini * (serial 0) 133853018216SPaolo Bonzini * GPS 133953018216SPaolo Bonzini * (some serial port) 134053018216SPaolo Bonzini * csr41814 (Bluetooth) 134153018216SPaolo Bonzini */ 134253018216SPaolo Bonzini n8x0_gpio_setup(s); 134353018216SPaolo Bonzini n8x0_nand_setup(s); 134453018216SPaolo Bonzini n8x0_i2c_setup(s); 1345fddbd80cSPaolo Bonzini if (model == 800) { 134653018216SPaolo Bonzini n800_tsc_kbd_setup(s); 1347fddbd80cSPaolo Bonzini } else if (model == 810) { 134853018216SPaolo Bonzini n810_tsc_setup(s); 134953018216SPaolo Bonzini n810_kbd_setup(s); 135053018216SPaolo Bonzini } 135153018216SPaolo Bonzini n8x0_spi_setup(s); 135253018216SPaolo Bonzini n8x0_dss_setup(s); 135353018216SPaolo Bonzini n8x0_cbus_setup(s); 135453018216SPaolo Bonzini n8x0_uart_setup(s); 13554bcbe0b6SEduardo Habkost if (machine_usb(machine)) { 135653018216SPaolo Bonzini n8x0_usb_setup(s); 135753018216SPaolo Bonzini } 135853018216SPaolo Bonzini 13593ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 136053018216SPaolo Bonzini /* Or at the linux loader. */ 13613ef96221SMarcel Apfelbaum binfo->kernel_filename = machine->kernel_filename; 13623ef96221SMarcel Apfelbaum binfo->kernel_cmdline = machine->kernel_cmdline; 13633ef96221SMarcel Apfelbaum binfo->initrd_filename = machine->initrd_filename; 136453018216SPaolo Bonzini arm_load_kernel(s->mpu->cpu, binfo); 136553018216SPaolo Bonzini 136653018216SPaolo Bonzini qemu_register_reset(n8x0_boot_init, s); 136753018216SPaolo Bonzini } 136853018216SPaolo Bonzini 136953018216SPaolo Bonzini if (option_rom[0].name && 13703ef96221SMarcel Apfelbaum (machine->boot_order[0] == 'n' || !machine->kernel_filename)) { 13710b062eb0SZhou Jie uint8_t *nolo_tags = g_new(uint8_t, 0x10000); 137253018216SPaolo Bonzini /* No, wait, better start at the ROM. */ 137353018216SPaolo Bonzini s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; 137453018216SPaolo Bonzini 137553018216SPaolo Bonzini /* This is intended for loading the `secondary.bin' program from 137653018216SPaolo Bonzini * Nokia images (the NOLO bootloader). The entry point seems 137753018216SPaolo Bonzini * to be at OMAP2_Q2_BASE + 0x400000. 137853018216SPaolo Bonzini * 137953018216SPaolo Bonzini * The `2nd.bin' files contain some kind of earlier boot code and 138053018216SPaolo Bonzini * for them the entry point needs to be set to OMAP2_SRAM_BASE. 138153018216SPaolo Bonzini * 138253018216SPaolo Bonzini * The code above is for loading the `zImage' file from Nokia 138353018216SPaolo Bonzini * images. */ 1384591f73f6SPeter Maydell load_image_targphys(option_rom[0].name, 138553018216SPaolo Bonzini OMAP2_Q2_BASE + 0x400000, 138653018216SPaolo Bonzini sdram_size - 0x400000); 138753018216SPaolo Bonzini 138853018216SPaolo Bonzini n800_setup_nolo_tags(nolo_tags); 138953018216SPaolo Bonzini cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000); 13900b062eb0SZhou Jie g_free(nolo_tags); 139153018216SPaolo Bonzini } 139253018216SPaolo Bonzini } 139353018216SPaolo Bonzini 139453018216SPaolo Bonzini static struct arm_boot_info n800_binfo = { 139553018216SPaolo Bonzini .loader_start = OMAP2_Q2_BASE, 139653018216SPaolo Bonzini /* Actually two chips of 0x4000000 bytes each */ 139753018216SPaolo Bonzini .ram_size = 0x08000000, 139853018216SPaolo Bonzini .board_id = 0x4f7, 139953018216SPaolo Bonzini .atag_board = n800_atag_setup, 140053018216SPaolo Bonzini }; 140153018216SPaolo Bonzini 140253018216SPaolo Bonzini static struct arm_boot_info n810_binfo = { 140353018216SPaolo Bonzini .loader_start = OMAP2_Q2_BASE, 140453018216SPaolo Bonzini /* Actually two chips of 0x4000000 bytes each */ 140553018216SPaolo Bonzini .ram_size = 0x08000000, 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 14133ef96221SMarcel Apfelbaum static void n800_init(MachineState *machine) 141453018216SPaolo Bonzini { 141530d76f13SStefan Weil n8x0_init(machine, &n800_binfo, 800); 141653018216SPaolo Bonzini } 141753018216SPaolo Bonzini 14183ef96221SMarcel Apfelbaum static void n810_init(MachineState *machine) 141953018216SPaolo Bonzini { 142030d76f13SStefan Weil n8x0_init(machine, &n810_binfo, 810); 142153018216SPaolo Bonzini } 142253018216SPaolo Bonzini 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"); 143253018216SPaolo Bonzini } 143353018216SPaolo Bonzini 14348a661aeaSAndreas Färber static const TypeInfo n800_type = { 14358a661aeaSAndreas Färber .name = MACHINE_TYPE_NAME("n800"), 14368a661aeaSAndreas Färber .parent = TYPE_MACHINE, 14378a661aeaSAndreas Färber .class_init = n800_class_init, 14388a661aeaSAndreas Färber }; 1439e264d29dSEduardo Habkost 14408a661aeaSAndreas Färber static void n810_class_init(ObjectClass *oc, void *data) 1441e264d29dSEduardo Habkost { 14428a661aeaSAndreas Färber MachineClass *mc = MACHINE_CLASS(oc); 14438a661aeaSAndreas Färber 1444e264d29dSEduardo Habkost mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)"; 1445e264d29dSEduardo Habkost mc->init = n810_init; 1446e264d29dSEduardo Habkost mc->default_boot_order = ""; 14474672cbd7SPeter Maydell mc->ignore_memory_transaction_failures = true; 1448ba1ba5ccSIgor Mammedov mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm1136-r2"); 1449e264d29dSEduardo Habkost } 1450e264d29dSEduardo Habkost 14518a661aeaSAndreas Färber static const TypeInfo n810_type = { 14528a661aeaSAndreas Färber .name = MACHINE_TYPE_NAME("n810"), 14538a661aeaSAndreas Färber .parent = TYPE_MACHINE, 14548a661aeaSAndreas Färber .class_init = n810_class_init, 14558a661aeaSAndreas Färber }; 14568a661aeaSAndreas Färber 14578a661aeaSAndreas Färber static void nseries_machine_init(void) 14588a661aeaSAndreas Färber { 14598a661aeaSAndreas Färber type_register_static(&n800_type); 14608a661aeaSAndreas Färber type_register_static(&n810_type); 14618a661aeaSAndreas Färber } 14628a661aeaSAndreas Färber 14630e6aac87SEduardo Habkost type_init(nseries_machine_init) 1464