1
From 36e839a017f83cfcf0e1bfa35f5d77922bab501b Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Mon, 18 Feb 2013 16:58:32 +0000
4
Subject: [PATCH 54/70] hw/nseries.c: Add n900 machine
8
hw/arm/nseries.c | 1048 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
9
1 file changed, 1048 insertions(+)
11
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
12
index 27b2b33..110bb8e 100644
13
--- a/hw/arm/nseries.c
14
+++ b/hw/arm/nseries.c
18
#include "hw/loader.h"
20
#include "sysemu/blockdev.h"
21
#include "hw/sysbus.h"
22
#include "exec/address-spaces.h"
23
@@ -1556,8 +1557,1054 @@ static QEMUMachine n810_machine = {
24
.default_boot_order = "",
27
+#define N900_SDRAM_SIZE (256 * 1024 * 1024)
28
+#define N900_ONENAND_CS 0
29
+#define N900_ONENAND_BUFSIZE (0xc000 << 1)
30
+#define N900_SMC_CS 1
32
+#define N900_ONENAND_GPIO 65
33
+#define N900_CAMFOCUS_GPIO 68
34
+#define N900_CAMLAUNCH_GPIO 69
35
+#define N900_SLIDE_GPIO 71
36
+#define N900_PROXIMITY_GPIO 89
37
+#define N900_HEADPHONE_EN_GPIO 98
38
+#define N900_TSC2005_IRQ_GPIO 100
39
+#define N900_TSC2005_RESET_GPIO 104
40
+#define N900_CAMCOVER_GPIO 110
41
+#define N900_KBLOCK_GPIO 113
42
+#define N900_HEADPHONE_GPIO 177
43
+#define N900_LIS302DL_INT2_GPIO 180
44
+#define N900_LIS302DL_INT1_GPIO 181
46
+//#define DEBUG_BQ2415X
47
+//#define DEBUG_TPA6130
48
+//#define DEBUG_LIS302DL
50
+#define N900_TRACE(fmt, ...) \
51
+ fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
54
+#define TRACE_BQ2415X(fmt, ...) N900_TRACE(fmt, ##__VA_ARGS__)
56
+#define TRACE_BQ2415X(...)
59
+#define TRACE_TPA6130(fmt, ...) N900_TRACE(fmt, ##__VA_ARGS__)
61
+#define TRACE_TPA6130(...)
63
+#ifdef DEBUG_LIS302DL
64
+#define TRACE_LIS302DL(fmt, ...) N900_TRACE(fmt, ##__VA_ARGS__)
66
+#define TRACE_LIS302DL(...)
69
+static uint64_t ssi_read(void *opaque, hwaddr addr, unsigned size)
72
+ case 0x00: /* REVISION */
74
+ case 0x14: /* SYSSTATUS */
75
+ return 1; /* RESETDONE */
79
+ //printf("%s: addr= " OMAP_FMT_plx "\n", __FUNCTION__, addr);
83
+static void ssi_write(void *opaque, hwaddr addr, uint64_t value,
86
+ //printf("%s: addr=" OMAP_FMT_plx ", value=0x%08x\n", __FUNCTION__, addr, value);
89
+static const MemoryRegionOps ssi_ops = {
92
+ .endianness = DEVICE_NATIVE_ENDIAN,
95
+typedef struct LIS302DLState_s {
101
+ int8_t axis_max, axis_step;
102
+ int noise, dr_test_ack;
104
+ uint8_t ctrl1, ctrl2, ctrl3;
107
+ uint8_t cfg, src, ths, dur;
110
+ uint8_t cfg, src, thsy_x, thsz;
111
+ uint8_t timelimit, latency, window;
117
+static void lis302dl_interrupt_update(LIS302DLState *s)
119
+#ifdef DEBUG_LIS302DL
120
+ static const char *rules[8] = {
121
+ "GND", "FF_WU_1", "FF_WU_2", "FF_WU_1|2", "DR",
122
+ "???", "???", "CLICK"
125
+ int active = (s->ctrl3 & 0x80) ? 0 : 1;
128
+ for (i = 0; i < 2; i++) {
129
+ switch ((s->ctrl3 >> (i * 3)) & 0x07) {
134
+ cond = s->ff_wu[0].src & 0x40;
135
+ latch = s->ff_wu[0].cfg & 0x40;
138
+ cond = s->ff_wu[1].src & 0x40;
139
+ latch = s->ff_wu[1].cfg & 0x40;
142
+ cond = ((s->ff_wu[0].src | s->ff_wu[1].src) & 0x40);
143
+ latch = ((s->ff_wu[0].cfg | s->ff_wu[1].cfg) & 0x40);
146
+ cond = (((s->ff_wu[0].src | s->ff_wu[1].src) & 0x3f) &
147
+ (((s->ctrl1 & 0x01) ? 0x03 : 0x00) |
148
+ ((s->ctrl1 & 0x02) ? 0x0c : 0x00) |
149
+ ((s->ctrl1 & 0x04) ? 0x30 : 0x00)));
153
+ cond = s->click.src & 0x40;
154
+ latch = s->click.cfg & 0x40;
157
+ TRACE_LIS302DL("unsupported irq config (%d)",
158
+ (s->ctrl3 >> (i * 3)) & 0x07);
163
+ TRACE_LIS302DL("%s: %s irq%d", rules[(s->ctrl3 >> (i * 3)) & 0x07],
164
+ cond ? (latch ? "activate" : "pulse") : "deactivate",
166
+ qemu_set_irq(s->irq[i], cond ? active : !active);
167
+ if (cond && !latch) {
168
+ qemu_set_irq(s->irq[i], !active);
173
+static void lis302dl_trigger(LIS302DLState *s, int axis, int value)
175
+ if (value > s->axis_max) value = s->axis_max;
176
+ if (value < -s->axis_max) value = -s->axis_max;
178
+ case 0: s->x = value; break;
179
+ case 1: s->y = value; break;
180
+ case 2: s->z = value; break;
183
+ if (s->status & (0x01 << axis)) {
184
+ s->status |= 0x10 << axis;
186
+ s->status |= 0x01 << axis;
188
+ if ((s->status & 0x07) == 0x07) {
191
+ if ((s->status & 0x70) == 0x70) {
194
+ uint8_t bit = 0x02 << (axis << 1); /* over threshold */
195
+ s->ff_wu[0].src |= bit;
196
+ s->ff_wu[1].src |= bit;
199
+ for (; i < 2; i++) {
200
+ if (s->ff_wu[i].src & 0x3f) {
201
+ if (s->ff_wu[i].cfg & 0x80) {
202
+ if ((s->ff_wu[i].cfg & 0x3f) == (s->ff_wu[i].src & 0x3f)) {
203
+ s->ff_wu[i].src |= 0x40;
206
+ if (s->ff_wu[i].src & s->ff_wu[i].cfg & 0x3f) {
207
+ s->ff_wu[i].src |= 0x40;
211
+ TRACE_LIS302DL("FF_WU_%d: CFG=0x%02x, SRC=0x%02x",
212
+ i, s->ff_wu[i].cfg, s->ff_wu[i].src);
215
+ lis302dl_interrupt_update(s);
218
+static void lis302dl_step(void *opaque, int axis, int high, int activate)
220
+ TRACE_LIS302DL("axis=%d, high=%d, activate=%d", axis, high, activate);
221
+ LIS302DLState *s = opaque;
225
+ case 0: v = s->x + (high ? s->axis_step : -s->axis_step); break;
226
+ case 1: v = s->y + (high ? s->axis_step : -s->axis_step); break;
227
+ case 2: v = s->z + (high ? s->axis_step : -s->axis_step); break;
230
+ if (v > s->axis_max) v = -(s->axis_max - s->axis_step);
231
+ if (v < -s->axis_max) v = s->axis_max - s->axis_step;
232
+ lis302dl_trigger(s, axis, v);
236
+static void lis302dl_reset(DeviceState *ds)
238
+ LIS302DLState *s = FROM_I2C_SLAVE(LIS302DLState, I2C_SLAVE(ds));
244
+ s->dr_test_ack = 0;
251
+ memset(s->ff_wu, 0x00, sizeof(s->ff_wu));
252
+ memset(&s->click, 0x00, sizeof(s->click));
255
+ s->y = -s->axis_max;
258
+ lis302dl_interrupt_update(s);
261
+static void lis302dl_event(I2CSlave *i2c, enum i2c_event event)
263
+ LIS302DLState *s = FROM_I2C_SLAVE(LIS302DLState, i2c);
264
+ if (event == I2C_START_SEND)
268
+static uint8_t lis302dl_readcoord(LIS302DLState *s, int coord)
283
+ hw_error("%s: unknown axis %d", __FUNCTION__, coord);
286
+ s->status &= ~(0x88 | (0x11 << coord));
287
+ if (s->ctrl1 & 0x10) {
299
+ if (++s->noise == 32) {
302
+ int dr1 = ((s->ctrl3 & 0x07) == 4);
303
+ int dr2 = (((s->ctrl3 >> 3) & 0x07) == 4);
304
+ if (!s->dr_test_ack++) {
306
+ qemu_irq_pulse(s->irq[0]);
309
+ qemu_irq_pulse(s->irq[1]);
311
+ } else if (s->dr_test_ack == 1 + (dr1 + dr2) * 3) {
312
+ s->dr_test_ack = 0;
318
+static int lis302dl_rx(I2CSlave *i2c)
320
+ LIS302DLState *s = FROM_I2C_SLAVE(LIS302DLState, i2c);
323
+ switch (s->reg & 0x7f) {
324
+ case 0x00 ... 0x0e:
325
+ case 0x10 ... 0x1f:
326
+ case 0x23 ... 0x26:
330
+ case 0x2e ... 0x2f:
333
+ TRACE_LIS302DL("reg 0x%02x = 0x%02x (unused/reserved reg)",
334
+ s->reg & 0x7f, value);
338
+ TRACE_LIS302DL("WHOAMI = 0x%02x", value);
342
+ TRACE_LIS302DL("CTRL1 = 0x%02x", value);
346
+ TRACE_LIS302DL("CTRL2 = 0x%02x", value);
350
+ TRACE_LIS302DL("CTRL3 = 0x%02x", value);
354
+ TRACE_LIS302DL("STATUS = 0x%02x", value);
357
+ value = lis302dl_readcoord(s, 0);
358
+ TRACE_LIS302DL("X = 0x%02x", value);
361
+ value = lis302dl_readcoord(s, 1);
362
+ TRACE_LIS302DL("Y = 0x%02x", value);
365
+ value = lis302dl_readcoord(s, 2);
366
+ TRACE_LIS302DL("Z = 0x%02x", value);
370
+ value = s->ff_wu[n].cfg;
371
+ TRACE_LIS302DL("FF_WU%d.CFG = 0x%02x", n + 1, value);
375
+ value = s->ff_wu[n].src;
376
+ TRACE_LIS302DL("FF_WU%d.SRC = 0x%02x", n + 1, value);
377
+ s->ff_wu[n].src = 0; //&= ~0x40;
378
+ lis302dl_interrupt_update(s);
382
+ value = s->ff_wu[n].ths;
383
+ TRACE_LIS302DL("FF_WU%d.THS = 0x%02x", n + 1, value);
387
+ value = s->ff_wu[n].dur;
388
+ TRACE_LIS302DL("FF_WU%d.DUR = 0x%02x", n + 1, value);
391
+ value = s->click.cfg;
392
+ TRACE_LIS302DL("CLICK_CFG = 0x%02x", value);
395
+ value = s->click.src;
396
+ TRACE_LIS302DL("CLICK_SRC = 0x%02x", value);
397
+ s->click.src &= ~0x40;
398
+ lis302dl_interrupt_update(s);
401
+ value = s->click.thsy_x;
402
+ TRACE_LIS302DL("CLICK_THSY_X = 0x%02x", value);
405
+ value = s->click.thsz;
406
+ TRACE_LIS302DL("CLICK_THSZ = 0x%02x", value);
409
+ value = s->click.timelimit;
410
+ TRACE_LIS302DL("CLICK_TIMELIMIT = 0x%02x", value);
413
+ value = s->click.latency;
414
+ TRACE_LIS302DL("CLICK_LATENCY = 0x%02x", value);
417
+ value = s->click.window;
418
+ TRACE_LIS302DL("CLICK_WINDOW = 0x%02x", value);
421
+ hw_error("%s: unknown register 0x%02x", __FUNCTION__,
426
+ if (s->reg & 0x80) { /* auto-increment? */
427
+ s->reg = (s->reg + 1) | 0x80;
432
+static int lis302dl_tx(I2CSlave *i2c, uint8_t data)
434
+ LIS302DLState *s = FROM_I2C_SLAVE(LIS302DLState, i2c);
435
+ if (s->firstbyte) {
440
+ switch (s->reg & 0x7f) {
442
+ TRACE_LIS302DL("CTRL1 = 0x%02x", data);
446
+ TRACE_LIS302DL("CTRL2 = 0x%02x", data);
450
+ TRACE_LIS302DL("CTRL3 = 0x%02x", data);
452
+ lis302dl_interrupt_update(s);
456
+ TRACE_LIS302DL("FF_WU%d.CFG = 0x%02x", n + 1, data);
457
+ s->ff_wu[n].cfg = data;
461
+ TRACE_LIS302DL("FF_WU%d.THS = 0x%02x", n + 1, data);
462
+ s->ff_wu[n].ths = data;
466
+ TRACE_LIS302DL("FF_WU%d.DUR = 0x%02x", n + 1, data);
467
+ s->ff_wu[n].dur = data;
470
+ TRACE_LIS302DL("CLICK_CFG = 0x%02x", data);
471
+ s->click.cfg = data;
474
+ TRACE_LIS302DL("CLICK_SRC = 0x%02x", data);
475
+ s->click.src = data;
478
+ TRACE_LIS302DL("CLICK_THSY_X = 0x%02x", data);
479
+ s->click.thsy_x = data;
482
+ TRACE_LIS302DL("CLICK_THSZ = 0x%02x", data);
483
+ s->click.thsz = data;
486
+ TRACE_LIS302DL("CLICK_TIMELIMIT = 0x%02x", data);
487
+ s->click.timelimit = data;
490
+ TRACE_LIS302DL("CLICK_LATENCY = 0x%02x", data);
491
+ s->click.latency = data;
494
+ TRACE_LIS302DL("CLICK_WINDOW = 0x%02x", data);
495
+ s->click.window = data;
498
+ hw_error("%s: unknown register 0x%02x (value 0x%02x)",
499
+ __FUNCTION__, s->reg & 0x7f, data);
502
+ if (s->reg & 0x80) { /* auto-increment? */
503
+ s->reg = (s->reg + 1) | 0x80;
509
+static int lis302dl_init(I2CSlave *i2c)
511
+ LIS302DLState *s = FROM_I2C_SLAVE(LIS302DLState, i2c);
513
+ s->axis_step = s->axis_max;// / 2;
514
+ qdev_init_gpio_out(&i2c->qdev, s->irq, 2);
518
+/* TODO: ideally x, y, z should be runtime modifiable properties,
519
+ * which can be set by calling
520
+ * lis302dl_trigger(s, axis, value);
521
+ * where axis is 0,1,2 for x,y,z
523
+static Property lis302dl_properties[] = {
524
+ DEFINE_PROP_INT32("x", LIS302DLState, x, 0),
525
+ DEFINE_PROP_INT32("y", LIS302DLState, y, 0),
526
+ DEFINE_PROP_INT32("z", LIS302DLState, z, 0),
527
+ DEFINE_PROP_END_OF_LIST(),
530
+static void lis302dl_class_init(ObjectClass *klass, void *data)
532
+ DeviceClass *dc = DEVICE_CLASS(klass);
533
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
534
+ k->init = lis302dl_init;
535
+ k->event = lis302dl_event;
536
+ k->recv = lis302dl_rx;
537
+ k->send = lis302dl_tx;
538
+ dc->props = lis302dl_properties;
539
+ dc->reset = lis302dl_reset;
542
+static TypeInfo lis302dl_info = {
543
+ .name = "lis302dl",
544
+ .parent = TYPE_I2C_SLAVE,
545
+ .instance_size = sizeof(LIS302DLState),
546
+ .class_init = lis302dl_class_init,
549
+typedef struct BQ2415XState_s {
561
+static void bq2415x_reset(DeviceState *ds)
563
+ BQ2415XState *s = FROM_I2C_SLAVE(BQ2415XState, I2C_SLAVE(ds));
568
+ s->st_ctrl = 0x50 | 0x80; // 40
571
+ s->tcc = 0xa1; // 89
574
+static void bq2415x_event(I2CSlave *i2c, enum i2c_event event)
576
+ BQ2415XState *s = FROM_I2C_SLAVE(BQ2415XState, i2c);
577
+ if (event == I2C_START_SEND)
581
+static int bq2415x_rx(I2CSlave *i2c)
583
+ BQ2415XState *s = FROM_I2C_SLAVE(BQ2415XState, i2c);
587
+ value = s->st_ctrl;
588
+ TRACE_BQ2415X("st_ctrl = 0x%02x", value);
592
+ TRACE_BQ2415X("ctrl = 0x%02x", value);
596
+ TRACE_BQ2415X("bat_v = 0x%02x", value);
601
+ TRACE_BQ2415X("id = 0x%02x", value);
605
+ TRACE_BQ2415X("tcc = 0x%02x", value);
608
+ TRACE_BQ2415X("unknown register 0x%02x", s->reg);
616
+static int bq2415x_tx(I2CSlave *i2c, uint8_t data)
618
+ BQ2415XState *s = FROM_I2C_SLAVE(BQ2415XState, i2c);
619
+ if (s->firstbyte) {
625
+ TRACE_BQ2415X("st_ctrl = 0x%02x", data);
626
+ s->st_ctrl = (s->st_ctrl & 0x3f) | (data & 0x40) | 0x80;
629
+ TRACE_BQ2415X("ctrl = 0x%02x", data);
633
+ TRACE_BQ2415X("bat_v = 0x%02x", data);
637
+ TRACE_BQ2415X("tcc = 0x%02x", data);
638
+ s->tcc = data | 0x80;
641
+ TRACE_BQ2415X("unknown register 0x%02x (value 0x%02x)",
650
+static int bq2415x_init(I2CSlave *i2c)
655
+static Property bq2415x_properties[] = {
656
+ DEFINE_PROP_UINT8("id", BQ2415XState, id, 0x49),
657
+ DEFINE_PROP_END_OF_LIST(),
660
+static void bq2415x_class_init(ObjectClass *klass, void *data)
662
+ DeviceClass *dc = DEVICE_CLASS(klass);
663
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
664
+ k->init = bq2415x_init;
665
+ k->event = bq2415x_event;
666
+ k->recv = bq2415x_rx;
667
+ k->send = bq2415x_tx;
668
+ dc->props = bq2415x_properties;
669
+ dc->reset = bq2415x_reset;
672
+static TypeInfo bq2415x_info = {
674
+ .parent = TYPE_I2C_SLAVE,
675
+ .instance_size = sizeof(BQ2415XState),
676
+ .class_init = bq2415x_class_init,
679
+typedef struct tpa6130_s {
686
+static void tpa6130_reset(DeviceState *ds)
688
+ TPA6130State *s = FROM_I2C_SLAVE(TPA6130State, I2C_SLAVE(ds));
691
+ memset(s->data, 0, sizeof(s->data));
694
+static void tpa6130_event(I2CSlave *i2c, enum i2c_event event)
696
+ TPA6130State *s = FROM_I2C_SLAVE(TPA6130State, i2c);
697
+ if (event == I2C_START_SEND)
701
+static int tpa6130_rx(I2CSlave *i2c)
703
+ TPA6130State *s = FROM_I2C_SLAVE(TPA6130State, i2c);
707
+ value = s->data[s->reg - 1];
708
+ TRACE_TPA6130("reg %d = 0x%02x", s->reg, value);
710
+ case 4: /* VERSION */
712
+ TRACE_TPA6130("version = 0x%02x", value);
715
+ TRACE_TPA6130("unknown register 0x%02x", s->reg);
722
+static int tpa6130_tx(I2CSlave *i2c, uint8_t data)
724
+ TPA6130State *s = FROM_I2C_SLAVE(TPA6130State, i2c);
725
+ if (s->firstbyte) {
731
+ TRACE_TPA6130("reg %d = 0x%02x", s->reg, data);
732
+ s->data[s->reg - 1] = data;
735
+ TRACE_TPA6130("unknown register 0x%02x", s->reg);
743
+static void tpa6130_irq(void *opaque, int n, int level)
746
+ hw_error("%s: unknown interrupt source %d\n", __FUNCTION__, n);
748
+ /* headphone enable */
749
+ TRACE_TPA6130("enable = %d", level);
753
+static int tpa6130_init(I2CSlave *i2c)
755
+ qdev_init_gpio_in(&i2c->qdev, tpa6130_irq, 1);
759
+static void tpa6130_class_init(ObjectClass *klass, void *data)
761
+ DeviceClass *dc = DEVICE_CLASS(klass);
762
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
763
+ k->init = tpa6130_init;
764
+ k->event = tpa6130_event;
765
+ k->recv = tpa6130_rx;
766
+ k->send = tpa6130_tx;
767
+ dc->reset = tpa6130_reset;
770
+static TypeInfo tpa6130_info = {
772
+ .parent = TYPE_I2C_SLAVE,
773
+ .instance_size = sizeof(TPA6130State),
774
+ .class_init = tpa6130_class_init,
778
+ struct omap_mpu_state_s *cpu;
781
+ DeviceState *mipid;
782
+ DeviceState *tsc2005;
783
+ DeviceState *bq2415x;
784
+ DeviceState *tpa6130;
785
+ DeviceState *lis302dl;
792
+ int camera_cover_open;
793
+ int headphone_connected;
796
+/* this takes care of the keys which are not located on the
797
+ * n900 keypad (note that volume up/down keys are handled by
798
+ * the keypad eventhough the keys are not located on the keypad)
799
+ * as well as triggering some other hardware button/switch-like
800
+ * events that are mapped to the host keyboard:
803
+ * f1 ....... keypad slider open/close
804
+ * f2 ....... keypad lock
805
+ * f3 ....... camera lens cover open/close
806
+ * f4 ....... camera focus
807
+ * f5 ....... camera take picture
808
+ * f6 ....... stereo headphone connect/disconnect
809
+ * kp1 ...... decrease accelerometer x axis value
810
+ * kp2 ...... increase accelerometer x axis value
811
+ * kp4 ...... decrease accelerometer y axis value
812
+ * kp5 ...... increase accelerometer y axis value
813
+ * kp7 ...... decrease accelerometer z axis value
814
+ * kp8 ...... increase accelerometer z axis value
816
+static void n900_key_handler(void *opaque, int keycode)
818
+ struct n900_s *s = opaque;
819
+ if (!s->extended_key && keycode == 0xe0) {
820
+ s->extended_key = 0x80;
822
+ int release = keycode & 0x80;
823
+ keycode = (keycode & 0x7f) | s->extended_key;
824
+ s->extended_key = 0;
826
+ case 0x01: /* escape */
827
+ twl4030_set_powerbutton_state(s->twl4030, !release);
829
+ case 0x3b: /* f1 */
831
+ s->slide_open = !s->slide_open;
832
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio,
837
+ case 0x3c: /* f2 */
838
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio, N900_KBLOCK_GPIO),
841
+ case 0x3d: /* f3 */
843
+ s->camera_cover_open = !s->camera_cover_open;
844
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio,
845
+ N900_CAMCOVER_GPIO),
846
+ s->camera_cover_open);
849
+ case 0x3e: /* f4 */
850
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio,
851
+ N900_CAMFOCUS_GPIO),
854
+ case 0x3f: /* f5 */
855
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio,
856
+ N900_CAMLAUNCH_GPIO),
859
+ case 0x40: /* f6 */
861
+ s->headphone_connected = !s->headphone_connected;
862
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio,
863
+ N900_HEADPHONE_GPIO),
864
+ !s->headphone_connected);
867
+ case 0x4f ... 0x50: /* kp1,2 */
868
+ lis302dl_step(s->lis302dl, 0, keycode - 0x4f, !release);
870
+ case 0x4b ... 0x4c: /* kp4,5 */
871
+ lis302dl_step(s->lis302dl, 1, keycode - 0x4b, !release);
873
+ case 0x47 ... 0x48: /* kp7,8 */
874
+ lis302dl_step(s->lis302dl, 2, keycode - 0x47, !release);
882
+static void n900_reset(void *opaque)
884
+ struct n900_s *s = opaque;
886
+ s->camera_cover_open = 0;
887
+ s->headphone_connected = 0;
888
+ qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N900_KBLOCK_GPIO));
889
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio, N900_HEADPHONE_GPIO),
890
+ !s->headphone_connected);
891
+ qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N900_CAMLAUNCH_GPIO));
892
+ qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N900_CAMFOCUS_GPIO));
893
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio, N900_CAMCOVER_GPIO),
894
+ s->camera_cover_open);
895
+ qemu_set_irq(qdev_get_gpio_in(s->cpu->gpio, N900_SLIDE_GPIO),
897
+ omap3_boot_rom_emu(s->cpu);
901
+static uint16_t n900_twl4030_madc_callback(twl4030_adc_type type, int ch)
906
+static const TWL4030KeyMap n900_twl4030_keymap[] = {
907
+ {0x10, 0, 0}, /* Q */
908
+ {0x11, 0, 1}, /* W */
909
+ {0x12, 0, 2}, /* E */
910
+ {0x13, 0, 3}, /* R */
911
+ {0x14, 0, 4}, /* T */
912
+ {0x15, 0, 5}, /* Y */
913
+ {0x16, 0, 6}, /* U */
914
+ {0x17, 0, 7}, /* I */
915
+ {0x18, 1, 0}, /* O */
916
+ {0x20, 1, 1}, /* D */
917
+ {0x34, 1, 2}, /* . */
918
+ {0x2f, 1, 3}, /* V */
919
+ {0xd0, 1, 4}, /* DOWN */
920
+ {0x41, 1, 7}, /* F7 -- volume/zoom down */
921
+ {0x19, 2, 0}, /* P */
922
+ {0x21, 2, 1}, /* F */
923
+ {0xc8, 2, 2}, /* UP */
924
+ {0x30, 2, 3}, /* B */
925
+ {0xcd, 2, 4}, /* RIGHT */
926
+ {0x42, 2, 7}, /* F8 -- volume/zoom up */
927
+ {0x33, 3, 0}, /* , */
928
+ {0x22, 3, 1}, /* G */
929
+ {0x1c, 3, 2}, /* ENTER */
930
+ {0x31, 3, 3}, /* N */
931
+ {0x0e, 4, 0}, /* BACKSPACE */
932
+ {0x23, 4, 1}, /* H */
933
+ {0x32, 4, 3}, /* M */
934
+ {0x1d, 4, 4}, /* LEFTCTRL */
935
+ {0x9d, 4, 4}, /* RIGHTCTRL */
936
+ {0x24, 5, 1}, /* J */
937
+ {0x2c, 5, 2}, /* Z */
938
+ {0x39, 5, 3}, /* SPACE */
939
+ {0x38, 5, 4}, /* LEFTALT -- "fn" */
940
+ {0xb8, 5, 4}, /* RIGHTALT -- "fn" */
941
+ {0x1e, 6, 0}, /* A */
942
+ {0x25, 6, 1}, /* K */
943
+ {0x2d, 6, 2}, /* X */
944
+ {0x39, 6, 3}, /* SPACE */
945
+ {0x2a, 6, 4}, /* LEFTSHIFT */
946
+ {0x36, 6, 4}, /* RIGHTSHIFT */
947
+ {0x1f, 7, 0}, /* S */
948
+ {0x26, 7, 1}, /* L */
949
+ {0x2e, 7, 2}, /* C */
950
+ {0xcb, 7, 3}, /* LEFT */
951
+ // {0x10, 0xff, 2}, /* F9 */
952
+ // {0x10, 0xff, 4}, /* F10 */
953
+ // {0x10, 0xff, 5}, /* F11 */
957
+static MouseTransformInfo n900_pointercal = {
960
+ .a = {14114, 18, -2825064, 34, -8765, 32972906, 65536},
963
+static void n900_init(QEMUMachineInitArgs *args)
965
+ MemoryRegion *sysmem = get_system_memory();
966
+ MemoryRegion *ssi_iomem = g_new(MemoryRegion, 1);
967
+ struct n900_s *s = g_malloc0(sizeof(*s));
968
+ DriveInfo *dmtd = drive_get(IF_MTD, 0, 0);
969
+ DriveInfo *dsd = drive_get(IF_SD, 0, 0);
971
+ if (!dmtd && !dsd) {
972
+ hw_error("%s: SD or NAND image required", __FUNCTION__);
974
+#if MAX_SERIAL_PORTS < 3
975
+#error MAX_SERIAL_PORTS must be at least 3!
977
+ s->cpu = omap3_mpu_init(sysmem, omap3430, N900_SDRAM_SIZE,
978
+ serial_hds[1], serial_hds[2],
979
+ serial_hds[0], NULL);
980
+ omap_lcd_panel_attach(s->cpu->dss);
982
+ s->tsc2005 = spi_create_device(omap_mcspi_bus(s->cpu->mcspi, 0),
984
+ qdev_connect_gpio_out(s->tsc2005, 0,
985
+ qdev_get_gpio_in(s->cpu->gpio,
986
+ N900_TSC2005_IRQ_GPIO));
987
+ tsc2005_set_transform(s->tsc2005, &n900_pointercal, 600, 1500);
988
+ cursor_hide = 0; // who wants to use touchscreen without a pointer?
990
+ s->mipid = spi_create_device_noinit(omap_mcspi_bus(s->cpu->mcspi, 0),
992
+ qdev_prop_set_uint32(s->mipid, "id", 0x101234);
993
+ qdev_prop_set_uint8(s->mipid, "n900", 1);
994
+ qdev_init_nofail(s->mipid);
997
+ s->nand = qdev_create(NULL, "onenand");
998
+ qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
999
+ qdev_prop_set_uint16(s->nand, "device_id", 0x40);
1000
+ qdev_prop_set_uint16(s->nand, "version_id", 0x121);
1001
+ qdev_prop_set_int32(s->nand, "shift", 1);
1002
+ if (dmtd && dmtd->bdrv) {
1003
+ qdev_prop_set_drive_nofail(s->nand, "drive", dmtd->bdrv);
1005
+ qdev_init_nofail(s->nand);
1006
+ sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
1007
+ qdev_get_gpio_in(s->cpu->gpio, N900_ONENAND_GPIO));
1008
+ omap_gpmc_attach(s->cpu->gpmc, 0,
1009
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
1012
+ omap3_mmc_attach(s->cpu->omap3_mmc[1], dsd->bdrv, 0, 1);
1014
+ if ((dsd = drive_get(IF_SD, 0, 1)) != NULL) {
1015
+ omap3_mmc_attach(s->cpu->omap3_mmc[0], dsd->bdrv, 0, 0);
1016
+ //qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_SDCOVER_GPIO));
1019
+ memory_region_init_io(ssi_iomem, NULL, &ssi_ops, 0, "n900_ssi", 0x3c00);
1020
+ memory_region_add_subregion(sysmem, 0x48058000, ssi_iomem);
1022
+ s->twl4030 = twl4030_init(omap_i2c_bus(s->cpu->i2c[0]),
1023
+ qdev_get_gpio_in(s->cpu->ih[0],
1024
+ OMAP_INT_3XXX_SYS_NIRQ),
1025
+ NULL, n900_twl4030_keymap);
1026
+ twl4030_madc_attach(s->twl4030, n900_twl4030_madc_callback);
1027
+ i2c_bus *i2c2 = omap_i2c_bus(s->cpu->i2c[1]);
1028
+ s->bq2415x = i2c_create_slave(i2c2, "bq2415x", 0x6b);
1029
+ s->tpa6130 = i2c_create_slave(i2c2, "tpa6130", 0x60);
1030
+ qdev_connect_gpio_out(s->cpu->gpio, N900_HEADPHONE_EN_GPIO,
1031
+ qdev_get_gpio_in(s->tpa6130, 0));
1032
+ i2c_bus *i2c3 = omap_i2c_bus(s->cpu->i2c[2]);
1033
+ s->lis302dl = i2c_create_slave(i2c3, "lis302dl", 0x1d);
1034
+ qdev_connect_gpio_out(s->lis302dl, 0,
1035
+ qdev_get_gpio_in(s->cpu->gpio,
1036
+ N900_LIS302DL_INT1_GPIO));
1037
+ qdev_connect_gpio_out(s->lis302dl, 1,
1038
+ qdev_get_gpio_in(s->cpu->gpio,
1039
+ N900_LIS302DL_INT2_GPIO));
1042
+ for (i = 0; i < nb_nics; i++) {
1043
+ if (!nd_table[i].model || !strcmp(nd_table[i].model, "smc91c111")) {
1047
+ if (i < nb_nics) {
1048
+ s->smc = qdev_create(NULL, "smc91c111");
1049
+ qdev_set_nic_properties(s->smc, &nd_table[i]);
1050
+ qdev_init_nofail(s->smc);
1051
+ sysbus_connect_irq(SYS_BUS_DEVICE(s->smc), 0,
1052
+ qdev_get_gpio_in(s->cpu->gpio, 54));
1053
+ omap_gpmc_attach(s->cpu->gpmc, 1,
1054
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(s->smc), 0));
1056
+ hw_error("%s: no NIC for smc91c111\n", __FUNCTION__);
1059
+ qemu_add_kbd_event_handler(n900_key_handler, s);
1061
+ qemu_register_reset(n900_reset, s);
1064
+static QEMUMachine n900_machine = {
1066
+ .desc = "Nokia N900 (OMAP3)",
1067
+ .init = n900_init,
1070
static void nseries_register_types(void)
1072
+ type_register_static(&bq2415x_info);
1073
+ type_register_static(&tpa6130_info);
1074
+ type_register_static(&lis302dl_info);
1075
type_register_static(&mipid_info);
1078
@@ -1565,6 +2612,7 @@ static void nseries_machine_init(void)
1080
qemu_register_machine(&n800_machine);
1081
qemu_register_machine(&n810_machine);
1082
+ qemu_register_machine(&n900_machine);
1085
type_init(nseries_register_types);