musicpal.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. /*
  2. * Marvell MV88W8618 / Freecom MusicPal emulation.
  3. *
  4. * Copyright (c) 2008 Jan Kiszka
  5. *
  6. * This code is licensed under the GNU GPL v2.
  7. *
  8. * Contributions after 2012-01-13 are licensed under the terms of the
  9. * GNU GPL, version 2 or (at your option) any later version.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/units.h"
  13. #include "qapi/error.h"
  14. #include "hw/sysbus.h"
  15. #include "migration/vmstate.h"
  16. #include "hw/arm/boot.h"
  17. #include "net/net.h"
  18. #include "sysemu/sysemu.h"
  19. #include "hw/boards.h"
  20. #include "hw/char/serial-mm.h"
  21. #include "qemu/timer.h"
  22. #include "hw/ptimer.h"
  23. #include "hw/qdev-properties.h"
  24. #include "hw/block/flash.h"
  25. #include "ui/console.h"
  26. #include "hw/i2c/i2c.h"
  27. #include "hw/i2c/bitbang_i2c.h"
  28. #include "hw/irq.h"
  29. #include "hw/or-irq.h"
  30. #include "hw/audio/wm8750.h"
  31. #include "sysemu/block-backend.h"
  32. #include "sysemu/runstate.h"
  33. #include "sysemu/dma.h"
  34. #include "ui/pixel_ops.h"
  35. #include "qemu/cutils.h"
  36. #include "qom/object.h"
  37. #include "hw/net/mv88w8618_eth.h"
  38. #include "audio/audio.h"
  39. #include "qemu/error-report.h"
  40. #include "target/arm/cpu-qom.h"
  41. #define MP_MISC_BASE 0x80002000
  42. #define MP_MISC_SIZE 0x00001000
  43. #define MP_ETH_BASE 0x80008000
  44. #define MP_WLAN_BASE 0x8000C000
  45. #define MP_WLAN_SIZE 0x00000800
  46. #define MP_UART1_BASE 0x8000C840
  47. #define MP_UART2_BASE 0x8000C940
  48. #define MP_GPIO_BASE 0x8000D000
  49. #define MP_GPIO_SIZE 0x00001000
  50. #define MP_FLASHCFG_BASE 0x90006000
  51. #define MP_FLASHCFG_SIZE 0x00001000
  52. #define MP_AUDIO_BASE 0x90007000
  53. #define MP_PIC_BASE 0x90008000
  54. #define MP_PIC_SIZE 0x00001000
  55. #define MP_PIT_BASE 0x90009000
  56. #define MP_PIT_SIZE 0x00001000
  57. #define MP_LCD_BASE 0x9000c000
  58. #define MP_LCD_SIZE 0x00001000
  59. #define MP_SRAM_BASE 0xC0000000
  60. #define MP_SRAM_SIZE 0x00020000
  61. #define MP_RAM_DEFAULT_SIZE 32*1024*1024
  62. #define MP_FLASH_SIZE_MAX 32*1024*1024
  63. #define MP_TIMER1_IRQ 4
  64. #define MP_TIMER2_IRQ 5
  65. #define MP_TIMER3_IRQ 6
  66. #define MP_TIMER4_IRQ 7
  67. #define MP_EHCI_IRQ 8
  68. #define MP_ETH_IRQ 9
  69. #define MP_UART_SHARED_IRQ 11
  70. #define MP_GPIO_IRQ 12
  71. #define MP_RTC_IRQ 28
  72. #define MP_AUDIO_IRQ 30
  73. /* Wolfson 8750 I2C address */
  74. #define MP_WM_ADDR 0x1A
  75. /* LCD register offsets */
  76. #define MP_LCD_IRQCTRL 0x180
  77. #define MP_LCD_IRQSTAT 0x184
  78. #define MP_LCD_SPICTRL 0x1ac
  79. #define MP_LCD_INST 0x1bc
  80. #define MP_LCD_DATA 0x1c0
  81. /* Mode magics */
  82. #define MP_LCD_SPI_DATA 0x00100011
  83. #define MP_LCD_SPI_CMD 0x00104011
  84. #define MP_LCD_SPI_INVALID 0x00000000
  85. /* Commands */
  86. #define MP_LCD_INST_SETPAGE0 0xB0
  87. /* ... */
  88. #define MP_LCD_INST_SETPAGE7 0xB7
  89. #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
  90. #define TYPE_MUSICPAL_LCD "musicpal_lcd"
  91. OBJECT_DECLARE_SIMPLE_TYPE(musicpal_lcd_state, MUSICPAL_LCD)
  92. struct musicpal_lcd_state {
  93. /*< private >*/
  94. SysBusDevice parent_obj;
  95. /*< public >*/
  96. MemoryRegion iomem;
  97. uint32_t brightness;
  98. uint32_t mode;
  99. uint32_t irqctrl;
  100. uint32_t page;
  101. uint32_t page_off;
  102. QemuConsole *con;
  103. uint8_t video_ram[128*64/8];
  104. };
  105. static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
  106. {
  107. switch (s->brightness) {
  108. case 7:
  109. return col;
  110. case 0:
  111. return 0;
  112. default:
  113. return (col * s->brightness) / 7;
  114. }
  115. }
  116. static inline void set_lcd_pixel32(musicpal_lcd_state *s,
  117. int x, int y, uint32_t col)
  118. {
  119. int dx, dy;
  120. DisplaySurface *surface = qemu_console_surface(s->con);
  121. uint32_t *pixel =
  122. &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
  123. for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
  124. for (dx = 0; dx < 3; dx++, pixel++) {
  125. *pixel = col;
  126. }
  127. }
  128. }
  129. static void lcd_refresh(void *opaque)
  130. {
  131. musicpal_lcd_state *s = opaque;
  132. int x, y, col;
  133. col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
  134. scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
  135. scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
  136. for (x = 0; x < 128; x++) {
  137. for (y = 0; y < 64; y++) {
  138. if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
  139. set_lcd_pixel32(s, x, y, col);
  140. } else {
  141. set_lcd_pixel32(s, x, y, 0);
  142. }
  143. }
  144. }
  145. dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
  146. }
  147. static void lcd_invalidate(void *opaque)
  148. {
  149. }
  150. static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
  151. {
  152. musicpal_lcd_state *s = opaque;
  153. s->brightness &= ~(1 << irq);
  154. s->brightness |= level << irq;
  155. }
  156. static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
  157. unsigned size)
  158. {
  159. musicpal_lcd_state *s = opaque;
  160. switch (offset) {
  161. case MP_LCD_IRQCTRL:
  162. return s->irqctrl;
  163. default:
  164. return 0;
  165. }
  166. }
  167. static void musicpal_lcd_write(void *opaque, hwaddr offset,
  168. uint64_t value, unsigned size)
  169. {
  170. musicpal_lcd_state *s = opaque;
  171. switch (offset) {
  172. case MP_LCD_IRQCTRL:
  173. s->irqctrl = value;
  174. break;
  175. case MP_LCD_SPICTRL:
  176. if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
  177. s->mode = value;
  178. } else {
  179. s->mode = MP_LCD_SPI_INVALID;
  180. }
  181. break;
  182. case MP_LCD_INST:
  183. if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
  184. s->page = value - MP_LCD_INST_SETPAGE0;
  185. s->page_off = 0;
  186. }
  187. break;
  188. case MP_LCD_DATA:
  189. if (s->mode == MP_LCD_SPI_CMD) {
  190. if (value >= MP_LCD_INST_SETPAGE0 &&
  191. value <= MP_LCD_INST_SETPAGE7) {
  192. s->page = value - MP_LCD_INST_SETPAGE0;
  193. s->page_off = 0;
  194. }
  195. } else if (s->mode == MP_LCD_SPI_DATA) {
  196. s->video_ram[s->page*128 + s->page_off] = value;
  197. s->page_off = (s->page_off + 1) & 127;
  198. }
  199. break;
  200. }
  201. }
  202. static const MemoryRegionOps musicpal_lcd_ops = {
  203. .read = musicpal_lcd_read,
  204. .write = musicpal_lcd_write,
  205. .endianness = DEVICE_NATIVE_ENDIAN,
  206. };
  207. static const GraphicHwOps musicpal_gfx_ops = {
  208. .invalidate = lcd_invalidate,
  209. .gfx_update = lcd_refresh,
  210. };
  211. static void musicpal_lcd_realize(DeviceState *dev, Error **errp)
  212. {
  213. musicpal_lcd_state *s = MUSICPAL_LCD(dev);
  214. s->con = graphic_console_init(dev, 0, &musicpal_gfx_ops, s);
  215. qemu_console_resize(s->con, 128 * 3, 64 * 3);
  216. }
  217. static void musicpal_lcd_init(Object *obj)
  218. {
  219. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  220. DeviceState *dev = DEVICE(sbd);
  221. musicpal_lcd_state *s = MUSICPAL_LCD(dev);
  222. s->brightness = 7;
  223. memory_region_init_io(&s->iomem, obj, &musicpal_lcd_ops, s,
  224. "musicpal-lcd", MP_LCD_SIZE);
  225. sysbus_init_mmio(sbd, &s->iomem);
  226. qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
  227. }
  228. static const VMStateDescription musicpal_lcd_vmsd = {
  229. .name = "musicpal_lcd",
  230. .version_id = 1,
  231. .minimum_version_id = 1,
  232. .fields = (const VMStateField[]) {
  233. VMSTATE_UINT32(brightness, musicpal_lcd_state),
  234. VMSTATE_UINT32(mode, musicpal_lcd_state),
  235. VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
  236. VMSTATE_UINT32(page, musicpal_lcd_state),
  237. VMSTATE_UINT32(page_off, musicpal_lcd_state),
  238. VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
  239. VMSTATE_END_OF_LIST()
  240. }
  241. };
  242. static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
  243. {
  244. DeviceClass *dc = DEVICE_CLASS(klass);
  245. dc->vmsd = &musicpal_lcd_vmsd;
  246. dc->realize = musicpal_lcd_realize;
  247. }
  248. static const TypeInfo musicpal_lcd_info = {
  249. .name = TYPE_MUSICPAL_LCD,
  250. .parent = TYPE_SYS_BUS_DEVICE,
  251. .instance_size = sizeof(musicpal_lcd_state),
  252. .instance_init = musicpal_lcd_init,
  253. .class_init = musicpal_lcd_class_init,
  254. };
  255. /* PIC register offsets */
  256. #define MP_PIC_STATUS 0x00
  257. #define MP_PIC_ENABLE_SET 0x08
  258. #define MP_PIC_ENABLE_CLR 0x0C
  259. #define TYPE_MV88W8618_PIC "mv88w8618_pic"
  260. OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pic_state, MV88W8618_PIC)
  261. struct mv88w8618_pic_state {
  262. /*< private >*/
  263. SysBusDevice parent_obj;
  264. /*< public >*/
  265. MemoryRegion iomem;
  266. uint32_t level;
  267. uint32_t enabled;
  268. qemu_irq parent_irq;
  269. };
  270. static void mv88w8618_pic_update(mv88w8618_pic_state *s)
  271. {
  272. qemu_set_irq(s->parent_irq, (s->level & s->enabled));
  273. }
  274. static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
  275. {
  276. mv88w8618_pic_state *s = opaque;
  277. if (level) {
  278. s->level |= 1 << irq;
  279. } else {
  280. s->level &= ~(1 << irq);
  281. }
  282. mv88w8618_pic_update(s);
  283. }
  284. static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
  285. unsigned size)
  286. {
  287. mv88w8618_pic_state *s = opaque;
  288. switch (offset) {
  289. case MP_PIC_STATUS:
  290. return s->level & s->enabled;
  291. default:
  292. return 0;
  293. }
  294. }
  295. static void mv88w8618_pic_write(void *opaque, hwaddr offset,
  296. uint64_t value, unsigned size)
  297. {
  298. mv88w8618_pic_state *s = opaque;
  299. switch (offset) {
  300. case MP_PIC_ENABLE_SET:
  301. s->enabled |= value;
  302. break;
  303. case MP_PIC_ENABLE_CLR:
  304. s->enabled &= ~value;
  305. s->level &= ~value;
  306. break;
  307. }
  308. mv88w8618_pic_update(s);
  309. }
  310. static void mv88w8618_pic_reset(DeviceState *d)
  311. {
  312. mv88w8618_pic_state *s = MV88W8618_PIC(d);
  313. s->level = 0;
  314. s->enabled = 0;
  315. }
  316. static const MemoryRegionOps mv88w8618_pic_ops = {
  317. .read = mv88w8618_pic_read,
  318. .write = mv88w8618_pic_write,
  319. .endianness = DEVICE_NATIVE_ENDIAN,
  320. };
  321. static void mv88w8618_pic_init(Object *obj)
  322. {
  323. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  324. mv88w8618_pic_state *s = MV88W8618_PIC(dev);
  325. qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
  326. sysbus_init_irq(dev, &s->parent_irq);
  327. memory_region_init_io(&s->iomem, obj, &mv88w8618_pic_ops, s,
  328. "musicpal-pic", MP_PIC_SIZE);
  329. sysbus_init_mmio(dev, &s->iomem);
  330. }
  331. static const VMStateDescription mv88w8618_pic_vmsd = {
  332. .name = "mv88w8618_pic",
  333. .version_id = 1,
  334. .minimum_version_id = 1,
  335. .fields = (const VMStateField[]) {
  336. VMSTATE_UINT32(level, mv88w8618_pic_state),
  337. VMSTATE_UINT32(enabled, mv88w8618_pic_state),
  338. VMSTATE_END_OF_LIST()
  339. }
  340. };
  341. static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
  342. {
  343. DeviceClass *dc = DEVICE_CLASS(klass);
  344. device_class_set_legacy_reset(dc, mv88w8618_pic_reset);
  345. dc->vmsd = &mv88w8618_pic_vmsd;
  346. }
  347. static const TypeInfo mv88w8618_pic_info = {
  348. .name = TYPE_MV88W8618_PIC,
  349. .parent = TYPE_SYS_BUS_DEVICE,
  350. .instance_size = sizeof(mv88w8618_pic_state),
  351. .instance_init = mv88w8618_pic_init,
  352. .class_init = mv88w8618_pic_class_init,
  353. };
  354. /* PIT register offsets */
  355. #define MP_PIT_TIMER1_LENGTH 0x00
  356. /* ... */
  357. #define MP_PIT_TIMER4_LENGTH 0x0C
  358. #define MP_PIT_CONTROL 0x10
  359. #define MP_PIT_TIMER1_VALUE 0x14
  360. /* ... */
  361. #define MP_PIT_TIMER4_VALUE 0x20
  362. #define MP_BOARD_RESET 0x34
  363. /* Magic board reset value (probably some watchdog behind it) */
  364. #define MP_BOARD_RESET_MAGIC 0x10000
  365. typedef struct mv88w8618_timer_state {
  366. ptimer_state *ptimer;
  367. uint32_t limit;
  368. int freq;
  369. qemu_irq irq;
  370. } mv88w8618_timer_state;
  371. #define TYPE_MV88W8618_PIT "mv88w8618_pit"
  372. OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pit_state, MV88W8618_PIT)
  373. struct mv88w8618_pit_state {
  374. /*< private >*/
  375. SysBusDevice parent_obj;
  376. /*< public >*/
  377. MemoryRegion iomem;
  378. mv88w8618_timer_state timer[4];
  379. };
  380. static void mv88w8618_timer_tick(void *opaque)
  381. {
  382. mv88w8618_timer_state *s = opaque;
  383. qemu_irq_raise(s->irq);
  384. }
  385. static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
  386. uint32_t freq)
  387. {
  388. sysbus_init_irq(dev, &s->irq);
  389. s->freq = freq;
  390. s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_LEGACY);
  391. }
  392. static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
  393. unsigned size)
  394. {
  395. mv88w8618_pit_state *s = opaque;
  396. mv88w8618_timer_state *t;
  397. switch (offset) {
  398. case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
  399. t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
  400. return ptimer_get_count(t->ptimer);
  401. default:
  402. return 0;
  403. }
  404. }
  405. static void mv88w8618_pit_write(void *opaque, hwaddr offset,
  406. uint64_t value, unsigned size)
  407. {
  408. mv88w8618_pit_state *s = opaque;
  409. mv88w8618_timer_state *t;
  410. int i;
  411. switch (offset) {
  412. case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
  413. t = &s->timer[offset >> 2];
  414. t->limit = value;
  415. ptimer_transaction_begin(t->ptimer);
  416. if (t->limit > 0) {
  417. ptimer_set_limit(t->ptimer, t->limit, 1);
  418. } else {
  419. ptimer_stop(t->ptimer);
  420. }
  421. ptimer_transaction_commit(t->ptimer);
  422. break;
  423. case MP_PIT_CONTROL:
  424. for (i = 0; i < 4; i++) {
  425. t = &s->timer[i];
  426. ptimer_transaction_begin(t->ptimer);
  427. if (value & 0xf && t->limit > 0) {
  428. ptimer_set_limit(t->ptimer, t->limit, 0);
  429. ptimer_set_freq(t->ptimer, t->freq);
  430. ptimer_run(t->ptimer, 0);
  431. } else {
  432. ptimer_stop(t->ptimer);
  433. }
  434. ptimer_transaction_commit(t->ptimer);
  435. value >>= 4;
  436. }
  437. break;
  438. case MP_BOARD_RESET:
  439. if (value == MP_BOARD_RESET_MAGIC) {
  440. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  441. }
  442. break;
  443. }
  444. }
  445. static void mv88w8618_pit_reset(DeviceState *d)
  446. {
  447. mv88w8618_pit_state *s = MV88W8618_PIT(d);
  448. int i;
  449. for (i = 0; i < 4; i++) {
  450. mv88w8618_timer_state *t = &s->timer[i];
  451. ptimer_transaction_begin(t->ptimer);
  452. ptimer_stop(t->ptimer);
  453. ptimer_transaction_commit(t->ptimer);
  454. t->limit = 0;
  455. }
  456. }
  457. static const MemoryRegionOps mv88w8618_pit_ops = {
  458. .read = mv88w8618_pit_read,
  459. .write = mv88w8618_pit_write,
  460. .endianness = DEVICE_NATIVE_ENDIAN,
  461. };
  462. static void mv88w8618_pit_init(Object *obj)
  463. {
  464. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  465. mv88w8618_pit_state *s = MV88W8618_PIT(dev);
  466. int i;
  467. /* Letting them all run at 1 MHz is likely just a pragmatic
  468. * simplification. */
  469. for (i = 0; i < 4; i++) {
  470. mv88w8618_timer_init(dev, &s->timer[i], 1000000);
  471. }
  472. memory_region_init_io(&s->iomem, obj, &mv88w8618_pit_ops, s,
  473. "musicpal-pit", MP_PIT_SIZE);
  474. sysbus_init_mmio(dev, &s->iomem);
  475. }
  476. static void mv88w8618_pit_finalize(Object *obj)
  477. {
  478. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  479. mv88w8618_pit_state *s = MV88W8618_PIT(dev);
  480. int i;
  481. for (i = 0; i < 4; i++) {
  482. ptimer_free(s->timer[i].ptimer);
  483. }
  484. }
  485. static const VMStateDescription mv88w8618_timer_vmsd = {
  486. .name = "timer",
  487. .version_id = 1,
  488. .minimum_version_id = 1,
  489. .fields = (const VMStateField[]) {
  490. VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
  491. VMSTATE_UINT32(limit, mv88w8618_timer_state),
  492. VMSTATE_END_OF_LIST()
  493. }
  494. };
  495. static const VMStateDescription mv88w8618_pit_vmsd = {
  496. .name = "mv88w8618_pit",
  497. .version_id = 1,
  498. .minimum_version_id = 1,
  499. .fields = (const VMStateField[]) {
  500. VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
  501. mv88w8618_timer_vmsd, mv88w8618_timer_state),
  502. VMSTATE_END_OF_LIST()
  503. }
  504. };
  505. static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
  506. {
  507. DeviceClass *dc = DEVICE_CLASS(klass);
  508. device_class_set_legacy_reset(dc, mv88w8618_pit_reset);
  509. dc->vmsd = &mv88w8618_pit_vmsd;
  510. }
  511. static const TypeInfo mv88w8618_pit_info = {
  512. .name = TYPE_MV88W8618_PIT,
  513. .parent = TYPE_SYS_BUS_DEVICE,
  514. .instance_size = sizeof(mv88w8618_pit_state),
  515. .instance_init = mv88w8618_pit_init,
  516. .instance_finalize = mv88w8618_pit_finalize,
  517. .class_init = mv88w8618_pit_class_init,
  518. };
  519. /* Flash config register offsets */
  520. #define MP_FLASHCFG_CFGR0 0x04
  521. #define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
  522. OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG)
  523. struct mv88w8618_flashcfg_state {
  524. /*< private >*/
  525. SysBusDevice parent_obj;
  526. /*< public >*/
  527. MemoryRegion iomem;
  528. uint32_t cfgr0;
  529. };
  530. static uint64_t mv88w8618_flashcfg_read(void *opaque,
  531. hwaddr offset,
  532. unsigned size)
  533. {
  534. mv88w8618_flashcfg_state *s = opaque;
  535. switch (offset) {
  536. case MP_FLASHCFG_CFGR0:
  537. return s->cfgr0;
  538. default:
  539. return 0;
  540. }
  541. }
  542. static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
  543. uint64_t value, unsigned size)
  544. {
  545. mv88w8618_flashcfg_state *s = opaque;
  546. switch (offset) {
  547. case MP_FLASHCFG_CFGR0:
  548. s->cfgr0 = value;
  549. break;
  550. }
  551. }
  552. static const MemoryRegionOps mv88w8618_flashcfg_ops = {
  553. .read = mv88w8618_flashcfg_read,
  554. .write = mv88w8618_flashcfg_write,
  555. .endianness = DEVICE_NATIVE_ENDIAN,
  556. };
  557. static void mv88w8618_flashcfg_init(Object *obj)
  558. {
  559. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  560. mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
  561. s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
  562. memory_region_init_io(&s->iomem, obj, &mv88w8618_flashcfg_ops, s,
  563. "musicpal-flashcfg", MP_FLASHCFG_SIZE);
  564. sysbus_init_mmio(dev, &s->iomem);
  565. }
  566. static const VMStateDescription mv88w8618_flashcfg_vmsd = {
  567. .name = "mv88w8618_flashcfg",
  568. .version_id = 1,
  569. .minimum_version_id = 1,
  570. .fields = (const VMStateField[]) {
  571. VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
  572. VMSTATE_END_OF_LIST()
  573. }
  574. };
  575. static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
  576. {
  577. DeviceClass *dc = DEVICE_CLASS(klass);
  578. dc->vmsd = &mv88w8618_flashcfg_vmsd;
  579. }
  580. static const TypeInfo mv88w8618_flashcfg_info = {
  581. .name = TYPE_MV88W8618_FLASHCFG,
  582. .parent = TYPE_SYS_BUS_DEVICE,
  583. .instance_size = sizeof(mv88w8618_flashcfg_state),
  584. .instance_init = mv88w8618_flashcfg_init,
  585. .class_init = mv88w8618_flashcfg_class_init,
  586. };
  587. /* Misc register offsets */
  588. #define MP_MISC_BOARD_REVISION 0x18
  589. #define MP_BOARD_REVISION 0x31
  590. struct MusicPalMiscState {
  591. SysBusDevice parent_obj;
  592. MemoryRegion iomem;
  593. };
  594. #define TYPE_MUSICPAL_MISC "musicpal-misc"
  595. OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMiscState, MUSICPAL_MISC)
  596. static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
  597. unsigned size)
  598. {
  599. switch (offset) {
  600. case MP_MISC_BOARD_REVISION:
  601. return MP_BOARD_REVISION;
  602. default:
  603. return 0;
  604. }
  605. }
  606. static void musicpal_misc_write(void *opaque, hwaddr offset,
  607. uint64_t value, unsigned size)
  608. {
  609. }
  610. static const MemoryRegionOps musicpal_misc_ops = {
  611. .read = musicpal_misc_read,
  612. .write = musicpal_misc_write,
  613. .endianness = DEVICE_NATIVE_ENDIAN,
  614. };
  615. static void musicpal_misc_init(Object *obj)
  616. {
  617. SysBusDevice *sd = SYS_BUS_DEVICE(obj);
  618. MusicPalMiscState *s = MUSICPAL_MISC(obj);
  619. memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
  620. "musicpal-misc", MP_MISC_SIZE);
  621. sysbus_init_mmio(sd, &s->iomem);
  622. }
  623. static const TypeInfo musicpal_misc_info = {
  624. .name = TYPE_MUSICPAL_MISC,
  625. .parent = TYPE_SYS_BUS_DEVICE,
  626. .instance_init = musicpal_misc_init,
  627. .instance_size = sizeof(MusicPalMiscState),
  628. };
  629. /* WLAN register offsets */
  630. #define MP_WLAN_MAGIC1 0x11c
  631. #define MP_WLAN_MAGIC2 0x124
  632. static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
  633. unsigned size)
  634. {
  635. switch (offset) {
  636. /* Workaround to allow loading the binary-only wlandrv.ko crap
  637. * from the original Freecom firmware. */
  638. case MP_WLAN_MAGIC1:
  639. return ~3;
  640. case MP_WLAN_MAGIC2:
  641. return -1;
  642. default:
  643. return 0;
  644. }
  645. }
  646. static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
  647. uint64_t value, unsigned size)
  648. {
  649. }
  650. static const MemoryRegionOps mv88w8618_wlan_ops = {
  651. .read = mv88w8618_wlan_read,
  652. .write =mv88w8618_wlan_write,
  653. .endianness = DEVICE_NATIVE_ENDIAN,
  654. };
  655. static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
  656. {
  657. MemoryRegion *iomem = g_new(MemoryRegion, 1);
  658. memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
  659. "musicpal-wlan", MP_WLAN_SIZE);
  660. sysbus_init_mmio(SYS_BUS_DEVICE(dev), iomem);
  661. }
  662. /* GPIO register offsets */
  663. #define MP_GPIO_OE_LO 0x008
  664. #define MP_GPIO_OUT_LO 0x00c
  665. #define MP_GPIO_IN_LO 0x010
  666. #define MP_GPIO_IER_LO 0x014
  667. #define MP_GPIO_IMR_LO 0x018
  668. #define MP_GPIO_ISR_LO 0x020
  669. #define MP_GPIO_OE_HI 0x508
  670. #define MP_GPIO_OUT_HI 0x50c
  671. #define MP_GPIO_IN_HI 0x510
  672. #define MP_GPIO_IER_HI 0x514
  673. #define MP_GPIO_IMR_HI 0x518
  674. #define MP_GPIO_ISR_HI 0x520
  675. /* GPIO bits & masks */
  676. #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
  677. #define MP_GPIO_I2C_DATA_BIT 29
  678. #define MP_GPIO_I2C_CLOCK_BIT 30
  679. /* LCD brightness bits in GPIO_OE_HI */
  680. #define MP_OE_LCD_BRIGHTNESS 0x0007
  681. #define TYPE_MUSICPAL_GPIO "musicpal_gpio"
  682. OBJECT_DECLARE_SIMPLE_TYPE(musicpal_gpio_state, MUSICPAL_GPIO)
  683. struct musicpal_gpio_state {
  684. /*< private >*/
  685. SysBusDevice parent_obj;
  686. /*< public >*/
  687. MemoryRegion iomem;
  688. uint32_t lcd_brightness;
  689. uint32_t out_state;
  690. uint32_t in_state;
  691. uint32_t ier;
  692. uint32_t imr;
  693. uint32_t isr;
  694. qemu_irq irq;
  695. qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
  696. };
  697. static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
  698. int i;
  699. uint32_t brightness;
  700. /* compute brightness ratio */
  701. switch (s->lcd_brightness) {
  702. case 0x00000007:
  703. brightness = 0;
  704. break;
  705. case 0x00020000:
  706. brightness = 1;
  707. break;
  708. case 0x00020001:
  709. brightness = 2;
  710. break;
  711. case 0x00040000:
  712. brightness = 3;
  713. break;
  714. case 0x00010006:
  715. brightness = 4;
  716. break;
  717. case 0x00020005:
  718. brightness = 5;
  719. break;
  720. case 0x00040003:
  721. brightness = 6;
  722. break;
  723. case 0x00030004:
  724. default:
  725. brightness = 7;
  726. }
  727. /* set lcd brightness GPIOs */
  728. for (i = 0; i <= 2; i++) {
  729. qemu_set_irq(s->out[i], (brightness >> i) & 1);
  730. }
  731. }
  732. static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
  733. {
  734. musicpal_gpio_state *s = opaque;
  735. uint32_t mask = 1 << pin;
  736. uint32_t delta = level << pin;
  737. uint32_t old = s->in_state & mask;
  738. s->in_state &= ~mask;
  739. s->in_state |= delta;
  740. if ((old ^ delta) &&
  741. ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
  742. s->isr = mask;
  743. qemu_irq_raise(s->irq);
  744. }
  745. }
  746. static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
  747. unsigned size)
  748. {
  749. musicpal_gpio_state *s = opaque;
  750. switch (offset) {
  751. case MP_GPIO_OE_HI: /* used for LCD brightness control */
  752. return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
  753. case MP_GPIO_OUT_LO:
  754. return s->out_state & 0xFFFF;
  755. case MP_GPIO_OUT_HI:
  756. return s->out_state >> 16;
  757. case MP_GPIO_IN_LO:
  758. return s->in_state & 0xFFFF;
  759. case MP_GPIO_IN_HI:
  760. return s->in_state >> 16;
  761. case MP_GPIO_IER_LO:
  762. return s->ier & 0xFFFF;
  763. case MP_GPIO_IER_HI:
  764. return s->ier >> 16;
  765. case MP_GPIO_IMR_LO:
  766. return s->imr & 0xFFFF;
  767. case MP_GPIO_IMR_HI:
  768. return s->imr >> 16;
  769. case MP_GPIO_ISR_LO:
  770. return s->isr & 0xFFFF;
  771. case MP_GPIO_ISR_HI:
  772. return s->isr >> 16;
  773. default:
  774. return 0;
  775. }
  776. }
  777. static void musicpal_gpio_write(void *opaque, hwaddr offset,
  778. uint64_t value, unsigned size)
  779. {
  780. musicpal_gpio_state *s = opaque;
  781. switch (offset) {
  782. case MP_GPIO_OE_HI: /* used for LCD brightness control */
  783. s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
  784. (value & MP_OE_LCD_BRIGHTNESS);
  785. musicpal_gpio_brightness_update(s);
  786. break;
  787. case MP_GPIO_OUT_LO:
  788. s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
  789. break;
  790. case MP_GPIO_OUT_HI:
  791. s->out_state = (s->out_state & 0xFFFF) | (value << 16);
  792. s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
  793. (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
  794. musicpal_gpio_brightness_update(s);
  795. qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
  796. qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
  797. break;
  798. case MP_GPIO_IER_LO:
  799. s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
  800. break;
  801. case MP_GPIO_IER_HI:
  802. s->ier = (s->ier & 0xFFFF) | (value << 16);
  803. break;
  804. case MP_GPIO_IMR_LO:
  805. s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
  806. break;
  807. case MP_GPIO_IMR_HI:
  808. s->imr = (s->imr & 0xFFFF) | (value << 16);
  809. break;
  810. }
  811. }
  812. static const MemoryRegionOps musicpal_gpio_ops = {
  813. .read = musicpal_gpio_read,
  814. .write = musicpal_gpio_write,
  815. .endianness = DEVICE_NATIVE_ENDIAN,
  816. };
  817. static void musicpal_gpio_reset(DeviceState *d)
  818. {
  819. musicpal_gpio_state *s = MUSICPAL_GPIO(d);
  820. s->lcd_brightness = 0;
  821. s->out_state = 0;
  822. s->in_state = 0xffffffff;
  823. s->ier = 0;
  824. s->imr = 0;
  825. s->isr = 0;
  826. }
  827. static void musicpal_gpio_init(Object *obj)
  828. {
  829. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  830. DeviceState *dev = DEVICE(sbd);
  831. musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
  832. sysbus_init_irq(sbd, &s->irq);
  833. memory_region_init_io(&s->iomem, obj, &musicpal_gpio_ops, s,
  834. "musicpal-gpio", MP_GPIO_SIZE);
  835. sysbus_init_mmio(sbd, &s->iomem);
  836. qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
  837. qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
  838. }
  839. static const VMStateDescription musicpal_gpio_vmsd = {
  840. .name = "musicpal_gpio",
  841. .version_id = 1,
  842. .minimum_version_id = 1,
  843. .fields = (const VMStateField[]) {
  844. VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
  845. VMSTATE_UINT32(out_state, musicpal_gpio_state),
  846. VMSTATE_UINT32(in_state, musicpal_gpio_state),
  847. VMSTATE_UINT32(ier, musicpal_gpio_state),
  848. VMSTATE_UINT32(imr, musicpal_gpio_state),
  849. VMSTATE_UINT32(isr, musicpal_gpio_state),
  850. VMSTATE_END_OF_LIST()
  851. }
  852. };
  853. static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
  854. {
  855. DeviceClass *dc = DEVICE_CLASS(klass);
  856. device_class_set_legacy_reset(dc, musicpal_gpio_reset);
  857. dc->vmsd = &musicpal_gpio_vmsd;
  858. }
  859. static const TypeInfo musicpal_gpio_info = {
  860. .name = TYPE_MUSICPAL_GPIO,
  861. .parent = TYPE_SYS_BUS_DEVICE,
  862. .instance_size = sizeof(musicpal_gpio_state),
  863. .instance_init = musicpal_gpio_init,
  864. .class_init = musicpal_gpio_class_init,
  865. };
  866. /* Keyboard codes & masks */
  867. #define MP_KEY_WHEEL_VOL (1 << 0)
  868. #define MP_KEY_WHEEL_VOL_INV (1 << 1)
  869. #define MP_KEY_WHEEL_NAV (1 << 2)
  870. #define MP_KEY_WHEEL_NAV_INV (1 << 3)
  871. #define MP_KEY_BTN_FAVORITS (1 << 4)
  872. #define MP_KEY_BTN_MENU (1 << 5)
  873. #define MP_KEY_BTN_VOLUME (1 << 6)
  874. #define MP_KEY_BTN_NAVIGATION (1 << 7)
  875. #define TYPE_MUSICPAL_KEY "musicpal_key"
  876. OBJECT_DECLARE_SIMPLE_TYPE(musicpal_key_state, MUSICPAL_KEY)
  877. struct musicpal_key_state {
  878. /*< private >*/
  879. SysBusDevice parent_obj;
  880. /*< public >*/
  881. uint32_t pressed_keys;
  882. qemu_irq out[8];
  883. };
  884. static void musicpal_key_event(DeviceState *dev, QemuConsole *src,
  885. InputEvent *evt)
  886. {
  887. musicpal_key_state *s = MUSICPAL_KEY(dev);
  888. InputKeyEvent *key = evt->u.key.data;
  889. int qcode = qemu_input_key_value_to_qcode(key->key);
  890. uint32_t event = 0;
  891. int i;
  892. switch (qcode) {
  893. case Q_KEY_CODE_UP:
  894. event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
  895. break;
  896. case Q_KEY_CODE_DOWN:
  897. event = MP_KEY_WHEEL_NAV;
  898. break;
  899. case Q_KEY_CODE_LEFT:
  900. event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
  901. break;
  902. case Q_KEY_CODE_RIGHT:
  903. event = MP_KEY_WHEEL_VOL;
  904. break;
  905. case Q_KEY_CODE_F:
  906. event = MP_KEY_BTN_FAVORITS;
  907. break;
  908. case Q_KEY_CODE_TAB:
  909. event = MP_KEY_BTN_VOLUME;
  910. break;
  911. case Q_KEY_CODE_RET:
  912. event = MP_KEY_BTN_NAVIGATION;
  913. break;
  914. case Q_KEY_CODE_M:
  915. event = MP_KEY_BTN_MENU;
  916. break;
  917. }
  918. /*
  919. * We allow repeated wheel-events when the arrow keys are held down,
  920. * but do not repeat already-pressed buttons for the other key inputs.
  921. */
  922. if (!(event & (MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_VOL))) {
  923. if (key->down && (s->pressed_keys & event)) {
  924. event = 0;
  925. }
  926. }
  927. if (event) {
  928. /* Raise GPIO pin first if repeating a key */
  929. if (key->down && (s->pressed_keys & event)) {
  930. for (i = 0; i <= 7; i++) {
  931. if (event & (1 << i)) {
  932. qemu_set_irq(s->out[i], 1);
  933. }
  934. }
  935. }
  936. for (i = 0; i <= 7; i++) {
  937. if (event & (1 << i)) {
  938. qemu_set_irq(s->out[i], !key->down);
  939. }
  940. }
  941. if (key->down) {
  942. s->pressed_keys |= event;
  943. } else {
  944. s->pressed_keys &= ~event;
  945. }
  946. }
  947. }
  948. static void musicpal_key_init(Object *obj)
  949. {
  950. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  951. DeviceState *dev = DEVICE(sbd);
  952. musicpal_key_state *s = MUSICPAL_KEY(dev);
  953. s->pressed_keys = 0;
  954. qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
  955. }
  956. static const QemuInputHandler musicpal_key_handler = {
  957. .name = "musicpal_key",
  958. .mask = INPUT_EVENT_MASK_KEY,
  959. .event = musicpal_key_event,
  960. };
  961. static void musicpal_key_realize(DeviceState *dev, Error **errp)
  962. {
  963. qemu_input_handler_register(dev, &musicpal_key_handler);
  964. }
  965. static const VMStateDescription musicpal_key_vmsd = {
  966. .name = "musicpal_key",
  967. .version_id = 2,
  968. .minimum_version_id = 2,
  969. .fields = (const VMStateField[]) {
  970. VMSTATE_UINT32(pressed_keys, musicpal_key_state),
  971. VMSTATE_END_OF_LIST()
  972. }
  973. };
  974. static void musicpal_key_class_init(ObjectClass *klass, void *data)
  975. {
  976. DeviceClass *dc = DEVICE_CLASS(klass);
  977. dc->vmsd = &musicpal_key_vmsd;
  978. dc->realize = musicpal_key_realize;
  979. }
  980. static const TypeInfo musicpal_key_info = {
  981. .name = TYPE_MUSICPAL_KEY,
  982. .parent = TYPE_SYS_BUS_DEVICE,
  983. .instance_size = sizeof(musicpal_key_state),
  984. .instance_init = musicpal_key_init,
  985. .class_init = musicpal_key_class_init,
  986. };
  987. #define FLASH_SECTOR_SIZE (64 * KiB)
  988. static struct arm_boot_info musicpal_binfo = {
  989. .loader_start = 0x0,
  990. .board_id = 0x20e,
  991. };
  992. static void musicpal_init(MachineState *machine)
  993. {
  994. ARMCPU *cpu;
  995. DeviceState *dev;
  996. DeviceState *pic;
  997. DeviceState *uart_orgate;
  998. DeviceState *i2c_dev;
  999. DeviceState *lcd_dev;
  1000. DeviceState *key_dev;
  1001. I2CSlave *wm8750_dev;
  1002. SysBusDevice *s;
  1003. I2CBus *i2c;
  1004. int i;
  1005. unsigned long flash_size;
  1006. DriveInfo *dinfo;
  1007. MachineClass *mc = MACHINE_GET_CLASS(machine);
  1008. MemoryRegion *address_space_mem = get_system_memory();
  1009. MemoryRegion *sram = g_new(MemoryRegion, 1);
  1010. /* For now we use a fixed - the original - RAM size */
  1011. if (machine->ram_size != mc->default_ram_size) {
  1012. char *sz = size_to_str(mc->default_ram_size);
  1013. error_report("Invalid RAM size, should be %s", sz);
  1014. g_free(sz);
  1015. exit(EXIT_FAILURE);
  1016. }
  1017. cpu = ARM_CPU(cpu_create(machine->cpu_type));
  1018. memory_region_add_subregion(address_space_mem, 0, machine->ram);
  1019. memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
  1020. &error_fatal);
  1021. memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
  1022. pic = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
  1023. qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
  1024. sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE,
  1025. qdev_get_gpio_in(pic, MP_TIMER1_IRQ),
  1026. qdev_get_gpio_in(pic, MP_TIMER2_IRQ),
  1027. qdev_get_gpio_in(pic, MP_TIMER3_IRQ),
  1028. qdev_get_gpio_in(pic, MP_TIMER4_IRQ), NULL);
  1029. /* Logically OR both UART IRQs together */
  1030. uart_orgate = DEVICE(object_new(TYPE_OR_IRQ));
  1031. object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
  1032. qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
  1033. qdev_connect_gpio_out(uart_orgate, 0,
  1034. qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
  1035. serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
  1036. qdev_get_gpio_in(uart_orgate, 0),
  1037. 1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN);
  1038. serial_mm_init(address_space_mem, MP_UART2_BASE, 2,
  1039. qdev_get_gpio_in(uart_orgate, 1),
  1040. 1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN);
  1041. /* Register flash */
  1042. dinfo = drive_get(IF_PFLASH, 0, 0);
  1043. if (dinfo) {
  1044. BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
  1045. flash_size = blk_getlength(blk);
  1046. if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
  1047. flash_size != 32 * MiB) {
  1048. error_report("Invalid flash image size");
  1049. exit(1);
  1050. }
  1051. /*
  1052. * The original U-Boot accesses the flash at 0xFE000000 instead of
  1053. * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
  1054. * image is smaller than 32 MB.
  1055. */
  1056. pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
  1057. "musicpal.flash", flash_size,
  1058. blk, FLASH_SECTOR_SIZE,
  1059. MP_FLASH_SIZE_MAX / flash_size,
  1060. 2, 0x00BF, 0x236D, 0x0000, 0x0000,
  1061. 0x5555, 0x2AAA, 0);
  1062. }
  1063. sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
  1064. dev = qdev_new(TYPE_MV88W8618_ETH);
  1065. qemu_configure_nic_device(dev, true, "mv88w8618");
  1066. object_property_set_link(OBJECT(dev), "dma-memory",
  1067. OBJECT(get_system_memory()), &error_fatal);
  1068. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  1069. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
  1070. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
  1071. qdev_get_gpio_in(pic, MP_ETH_IRQ));
  1072. sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
  1073. sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
  1074. dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
  1075. qdev_get_gpio_in(pic, MP_GPIO_IRQ));
  1076. i2c_dev = sysbus_create_simple(TYPE_GPIO_I2C, -1, NULL);
  1077. i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
  1078. lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
  1079. key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
  1080. /* I2C read data */
  1081. qdev_connect_gpio_out(i2c_dev, 0,
  1082. qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
  1083. /* I2C data */
  1084. qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
  1085. /* I2C clock */
  1086. qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
  1087. for (i = 0; i < 3; i++) {
  1088. qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
  1089. }
  1090. for (i = 0; i < 4; i++) {
  1091. qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
  1092. }
  1093. for (i = 4; i < 8; i++) {
  1094. qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
  1095. }
  1096. wm8750_dev = i2c_slave_new(TYPE_WM8750, MP_WM_ADDR);
  1097. if (machine->audiodev) {
  1098. qdev_prop_set_string(DEVICE(wm8750_dev), "audiodev", machine->audiodev);
  1099. }
  1100. i2c_slave_realize_and_unref(wm8750_dev, i2c, &error_abort);
  1101. dev = qdev_new(TYPE_MV88W8618_AUDIO);
  1102. s = SYS_BUS_DEVICE(dev);
  1103. object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev),
  1104. NULL);
  1105. sysbus_realize_and_unref(s, &error_fatal);
  1106. sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
  1107. sysbus_connect_irq(s, 0, qdev_get_gpio_in(pic, MP_AUDIO_IRQ));
  1108. musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
  1109. arm_load_kernel(cpu, machine, &musicpal_binfo);
  1110. }
  1111. static void musicpal_machine_init(MachineClass *mc)
  1112. {
  1113. mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
  1114. mc->init = musicpal_init;
  1115. mc->ignore_memory_transaction_failures = true;
  1116. mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
  1117. mc->default_ram_size = MP_RAM_DEFAULT_SIZE;
  1118. mc->default_ram_id = "musicpal.ram";
  1119. machine_add_audiodev_property(mc);
  1120. }
  1121. DEFINE_MACHINE("musicpal", musicpal_machine_init)
  1122. static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
  1123. {
  1124. DeviceClass *dc = DEVICE_CLASS(klass);
  1125. dc->realize = mv88w8618_wlan_realize;
  1126. }
  1127. static const TypeInfo mv88w8618_wlan_info = {
  1128. .name = "mv88w8618_wlan",
  1129. .parent = TYPE_SYS_BUS_DEVICE,
  1130. .instance_size = sizeof(SysBusDevice),
  1131. .class_init = mv88w8618_wlan_class_init,
  1132. };
  1133. static void musicpal_register_types(void)
  1134. {
  1135. type_register_static(&mv88w8618_pic_info);
  1136. type_register_static(&mv88w8618_pit_info);
  1137. type_register_static(&mv88w8618_flashcfg_info);
  1138. type_register_static(&mv88w8618_wlan_info);
  1139. type_register_static(&musicpal_lcd_info);
  1140. type_register_static(&musicpal_gpio_info);
  1141. type_register_static(&musicpal_key_info);
  1142. type_register_static(&musicpal_misc_info);
  1143. }
  1144. type_init(musicpal_register_types)