Commit e33d8cdb556cf20b0452d24cee82562ee5ee9ada
1 parent
5c49b363
Factor out common SharpSL PDA code (Dmitry Baryshkov).
Factor out to sharpsl code to support devices that are present not only in spitz-family PDAs but also in outher Sharp Zaurus PDAs Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4642 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
324 additions
and
288 deletions
Makefile.target
| ... | ... | @@ -585,7 +585,7 @@ OBJS+= arm-semi.o |
| 585 | 585 | OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o |
| 586 | 586 | OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o |
| 587 | 587 | OBJS+= pflash_cfi01.o gumstix.o |
| 588 | -OBJS+= spitz.o ide.o serial.o nand.o ecc.o | |
| 588 | +OBJS+= spitz.o zaurus.o ide.o serial.o nand.o ecc.o | |
| 589 | 589 | OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o |
| 590 | 590 | OBJS+= omap2.o omap_dss.o |
| 591 | 591 | OBJS+= palm.o tsc210x.o | ... | ... |
hw/sharpsl.h
0 → 100644
| 1 | +#ifndef QEMU_SHARPSL_H | |
| 2 | +#define QEMU_SHARPSL_H | |
| 3 | + | |
| 4 | +/* zaurus.c */ | |
| 5 | +struct scoop_info_s *scoop_init(struct pxa2xx_state_s *cpu, | |
| 6 | + int instance, target_phys_addr_t target_base); | |
| 7 | +void scoop_gpio_set(void *opaque, int line, int level); | |
| 8 | +qemu_irq *scoop_gpio_in_get(struct scoop_info_s *s); | |
| 9 | +void scoop_gpio_out_set(struct scoop_info_s *s, int line, | |
| 10 | + qemu_irq handler); | |
| 11 | + | |
| 12 | +#define SL_PXA_PARAM_BASE 0xa0000a00 | |
| 13 | +void sl_bootparam_write(uint32_t ptr); | |
| 14 | + | |
| 15 | +#endif | ... | ... |
hw/spitz.c
| ... | ... | @@ -16,6 +16,7 @@ |
| 16 | 16 | #include "flash.h" |
| 17 | 17 | #include "qemu-timer.h" |
| 18 | 18 | #include "devices.h" |
| 19 | +#include "sharpsl.h" | |
| 19 | 20 | #include "console.h" |
| 20 | 21 | #include "block.h" |
| 21 | 22 | #include "audio/audio.h" |
| ... | ... | @@ -520,238 +521,6 @@ static void spitz_keyboard_register(struct pxa2xx_state_s *cpu) |
| 520 | 521 | spitz_keyboard_save, spitz_keyboard_load, s); |
| 521 | 522 | } |
| 522 | 523 | |
| 523 | -/* SCOOP devices */ | |
| 524 | - | |
| 525 | -struct scoop_info_s { | |
| 526 | - target_phys_addr_t target_base; | |
| 527 | - qemu_irq handler[16]; | |
| 528 | - qemu_irq *in; | |
| 529 | - uint16_t status; | |
| 530 | - uint16_t power; | |
| 531 | - uint32_t gpio_level; | |
| 532 | - uint32_t gpio_dir; | |
| 533 | - uint32_t prev_level; | |
| 534 | - | |
| 535 | - uint16_t mcr; | |
| 536 | - uint16_t cdr; | |
| 537 | - uint16_t ccr; | |
| 538 | - uint16_t irr; | |
| 539 | - uint16_t imr; | |
| 540 | - uint16_t isr; | |
| 541 | - uint16_t gprr; | |
| 542 | -}; | |
| 543 | - | |
| 544 | -#define SCOOP_MCR 0x00 | |
| 545 | -#define SCOOP_CDR 0x04 | |
| 546 | -#define SCOOP_CSR 0x08 | |
| 547 | -#define SCOOP_CPR 0x0c | |
| 548 | -#define SCOOP_CCR 0x10 | |
| 549 | -#define SCOOP_IRR_IRM 0x14 | |
| 550 | -#define SCOOP_IMR 0x18 | |
| 551 | -#define SCOOP_ISR 0x1c | |
| 552 | -#define SCOOP_GPCR 0x20 | |
| 553 | -#define SCOOP_GPWR 0x24 | |
| 554 | -#define SCOOP_GPRR 0x28 | |
| 555 | - | |
| 556 | -static inline void scoop_gpio_handler_update(struct scoop_info_s *s) { | |
| 557 | - uint32_t level, diff; | |
| 558 | - int bit; | |
| 559 | - level = s->gpio_level & s->gpio_dir; | |
| 560 | - | |
| 561 | - for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { | |
| 562 | - bit = ffs(diff) - 1; | |
| 563 | - qemu_set_irq(s->handler[bit], (level >> bit) & 1); | |
| 564 | - } | |
| 565 | - | |
| 566 | - s->prev_level = level; | |
| 567 | -} | |
| 568 | - | |
| 569 | -static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr) | |
| 570 | -{ | |
| 571 | - struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 572 | - addr -= s->target_base; | |
| 573 | - | |
| 574 | - switch (addr) { | |
| 575 | - case SCOOP_MCR: | |
| 576 | - return s->mcr; | |
| 577 | - case SCOOP_CDR: | |
| 578 | - return s->cdr; | |
| 579 | - case SCOOP_CSR: | |
| 580 | - return s->status; | |
| 581 | - case SCOOP_CPR: | |
| 582 | - return s->power; | |
| 583 | - case SCOOP_CCR: | |
| 584 | - return s->ccr; | |
| 585 | - case SCOOP_IRR_IRM: | |
| 586 | - return s->irr; | |
| 587 | - case SCOOP_IMR: | |
| 588 | - return s->imr; | |
| 589 | - case SCOOP_ISR: | |
| 590 | - return s->isr; | |
| 591 | - case SCOOP_GPCR: | |
| 592 | - return s->gpio_dir; | |
| 593 | - case SCOOP_GPWR: | |
| 594 | - return s->gpio_level; | |
| 595 | - case SCOOP_GPRR: | |
| 596 | - return s->gprr; | |
| 597 | - default: | |
| 598 | - spitz_printf("Bad register offset " REG_FMT "\n", addr); | |
| 599 | - } | |
| 600 | - | |
| 601 | - return 0; | |
| 602 | -} | |
| 603 | - | |
| 604 | -static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) | |
| 605 | -{ | |
| 606 | - struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 607 | - addr -= s->target_base; | |
| 608 | - value &= 0xffff; | |
| 609 | - | |
| 610 | - switch (addr) { | |
| 611 | - case SCOOP_MCR: | |
| 612 | - s->mcr = value; | |
| 613 | - break; | |
| 614 | - case SCOOP_CDR: | |
| 615 | - s->cdr = value; | |
| 616 | - break; | |
| 617 | - case SCOOP_CPR: | |
| 618 | - s->power = value; | |
| 619 | - if (value & 0x80) | |
| 620 | - s->power |= 0x8040; | |
| 621 | - break; | |
| 622 | - case SCOOP_CCR: | |
| 623 | - s->ccr = value; | |
| 624 | - break; | |
| 625 | - case SCOOP_IRR_IRM: | |
| 626 | - s->irr = value; | |
| 627 | - break; | |
| 628 | - case SCOOP_IMR: | |
| 629 | - s->imr = value; | |
| 630 | - break; | |
| 631 | - case SCOOP_ISR: | |
| 632 | - s->isr = value; | |
| 633 | - break; | |
| 634 | - case SCOOP_GPCR: | |
| 635 | - s->gpio_dir = value; | |
| 636 | - scoop_gpio_handler_update(s); | |
| 637 | - break; | |
| 638 | - case SCOOP_GPWR: | |
| 639 | - s->gpio_level = value & s->gpio_dir; | |
| 640 | - scoop_gpio_handler_update(s); | |
| 641 | - break; | |
| 642 | - case SCOOP_GPRR: | |
| 643 | - s->gprr = value; | |
| 644 | - break; | |
| 645 | - default: | |
| 646 | - spitz_printf("Bad register offset " REG_FMT "\n", addr); | |
| 647 | - } | |
| 648 | -} | |
| 649 | - | |
| 650 | -CPUReadMemoryFunc *scoop_readfn[] = { | |
| 651 | - scoop_readb, | |
| 652 | - scoop_readb, | |
| 653 | - scoop_readb, | |
| 654 | -}; | |
| 655 | -CPUWriteMemoryFunc *scoop_writefn[] = { | |
| 656 | - scoop_writeb, | |
| 657 | - scoop_writeb, | |
| 658 | - scoop_writeb, | |
| 659 | -}; | |
| 660 | - | |
| 661 | -static void scoop_gpio_set(void *opaque, int line, int level) | |
| 662 | -{ | |
| 663 | - struct scoop_info_s *s = (struct scoop_info_s *) s; | |
| 664 | - | |
| 665 | - if (level) | |
| 666 | - s->gpio_level |= (1 << line); | |
| 667 | - else | |
| 668 | - s->gpio_level &= ~(1 << line); | |
| 669 | -} | |
| 670 | - | |
| 671 | -static inline qemu_irq *scoop_gpio_in_get(struct scoop_info_s *s) | |
| 672 | -{ | |
| 673 | - return s->in; | |
| 674 | -} | |
| 675 | - | |
| 676 | -static inline void scoop_gpio_out_set(struct scoop_info_s *s, int line, | |
| 677 | - qemu_irq handler) { | |
| 678 | - if (line >= 16) { | |
| 679 | - spitz_printf("No GPIO pin %i\n", line); | |
| 680 | - return; | |
| 681 | - } | |
| 682 | - | |
| 683 | - s->handler[line] = handler; | |
| 684 | -} | |
| 685 | - | |
| 686 | -static void scoop_save(QEMUFile *f, void *opaque) | |
| 687 | -{ | |
| 688 | - struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 689 | - qemu_put_be16s(f, &s->status); | |
| 690 | - qemu_put_be16s(f, &s->power); | |
| 691 | - qemu_put_be32s(f, &s->gpio_level); | |
| 692 | - qemu_put_be32s(f, &s->gpio_dir); | |
| 693 | - qemu_put_be32s(f, &s->prev_level); | |
| 694 | - qemu_put_be16s(f, &s->mcr); | |
| 695 | - qemu_put_be16s(f, &s->cdr); | |
| 696 | - qemu_put_be16s(f, &s->ccr); | |
| 697 | - qemu_put_be16s(f, &s->irr); | |
| 698 | - qemu_put_be16s(f, &s->imr); | |
| 699 | - qemu_put_be16s(f, &s->isr); | |
| 700 | - qemu_put_be16s(f, &s->gprr); | |
| 701 | -} | |
| 702 | - | |
| 703 | -static int scoop_load(QEMUFile *f, void *opaque, int version_id) | |
| 704 | -{ | |
| 705 | - struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 706 | - qemu_get_be16s(f, &s->status); | |
| 707 | - qemu_get_be16s(f, &s->power); | |
| 708 | - qemu_get_be32s(f, &s->gpio_level); | |
| 709 | - qemu_get_be32s(f, &s->gpio_dir); | |
| 710 | - qemu_get_be32s(f, &s->prev_level); | |
| 711 | - qemu_get_be16s(f, &s->mcr); | |
| 712 | - qemu_get_be16s(f, &s->cdr); | |
| 713 | - qemu_get_be16s(f, &s->ccr); | |
| 714 | - qemu_get_be16s(f, &s->irr); | |
| 715 | - qemu_get_be16s(f, &s->imr); | |
| 716 | - qemu_get_be16s(f, &s->isr); | |
| 717 | - qemu_get_be16s(f, &s->gprr); | |
| 718 | - | |
| 719 | - return 0; | |
| 720 | -} | |
| 721 | - | |
| 722 | -static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, | |
| 723 | - int count) { | |
| 724 | - int iomemtype; | |
| 725 | - struct scoop_info_s *s; | |
| 726 | - | |
| 727 | - s = (struct scoop_info_s *) | |
| 728 | - qemu_mallocz(sizeof(struct scoop_info_s) * 2); | |
| 729 | - memset(s, 0, sizeof(struct scoop_info_s) * count); | |
| 730 | - s[0].target_base = 0x10800000; | |
| 731 | - s[1].target_base = 0x08800040; | |
| 732 | - | |
| 733 | - /* Ready */ | |
| 734 | - s[0].status = 0x02; | |
| 735 | - s[1].status = 0x02; | |
| 736 | - | |
| 737 | - s[0].in = qemu_allocate_irqs(scoop_gpio_set, &s[0], 16); | |
| 738 | - iomemtype = cpu_register_io_memory(0, scoop_readfn, | |
| 739 | - scoop_writefn, &s[0]); | |
| 740 | - cpu_register_physical_memory(s[0].target_base, 0x1000, iomemtype); | |
| 741 | - register_savevm("scoop", 0, 0, scoop_save, scoop_load, &s[0]); | |
| 742 | - | |
| 743 | - if (count < 2) | |
| 744 | - return s; | |
| 745 | - | |
| 746 | - s[1].in = qemu_allocate_irqs(scoop_gpio_set, &s[1], 16); | |
| 747 | - iomemtype = cpu_register_io_memory(0, scoop_readfn, | |
| 748 | - scoop_writefn, &s[1]); | |
| 749 | - cpu_register_physical_memory(s[1].target_base, 0x1000, iomemtype); | |
| 750 | - register_savevm("scoop", 1, 0, scoop_save, scoop_load, &s[1]); | |
| 751 | - | |
| 752 | - return s; | |
| 753 | -} | |
| 754 | - | |
| 755 | 524 | /* LCD backlight controller */ |
| 756 | 525 | |
| 757 | 526 | #define LCDTG_RESCTL 0x00 |
| ... | ... | @@ -1050,21 +819,21 @@ static void spitz_out_switch(void *opaque, int line, int level) |
| 1050 | 819 | #define SPITZ_SCP2_MIC_BIAS 9 |
| 1051 | 820 | |
| 1052 | 821 | static void spitz_scoop_gpio_setup(struct pxa2xx_state_s *cpu, |
| 1053 | - struct scoop_info_s *scp, int num) | |
| 822 | + struct scoop_info_s *scp0, struct scoop_info_s *scp1) | |
| 1054 | 823 | { |
| 1055 | 824 | qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8); |
| 1056 | 825 | |
| 1057 | - scoop_gpio_out_set(&scp[0], SPITZ_SCP_CHRG_ON, outsignals[0]); | |
| 1058 | - scoop_gpio_out_set(&scp[0], SPITZ_SCP_JK_B, outsignals[1]); | |
| 1059 | - scoop_gpio_out_set(&scp[0], SPITZ_SCP_LED_GREEN, outsignals[2]); | |
| 1060 | - scoop_gpio_out_set(&scp[0], SPITZ_SCP_LED_ORANGE, outsignals[3]); | |
| 826 | + scoop_gpio_out_set(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]); | |
| 827 | + scoop_gpio_out_set(scp0, SPITZ_SCP_JK_B, outsignals[1]); | |
| 828 | + scoop_gpio_out_set(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]); | |
| 829 | + scoop_gpio_out_set(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]); | |
| 1061 | 830 | |
| 1062 | - if (num >= 2) { | |
| 1063 | - scoop_gpio_out_set(&scp[1], SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]); | |
| 1064 | - scoop_gpio_out_set(&scp[1], SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]); | |
| 831 | + if (scp1) { | |
| 832 | + scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]); | |
| 833 | + scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]); | |
| 1065 | 834 | } |
| 1066 | 835 | |
| 1067 | - scoop_gpio_out_set(&scp[0], SPITZ_SCP_ADC_TEMP_ON, outsignals[6]); | |
| 836 | + scoop_gpio_out_set(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]); | |
| 1068 | 837 | } |
| 1069 | 838 | |
| 1070 | 839 | #define SPITZ_GPIO_HSYNC 22 |
| ... | ... | @@ -1134,49 +903,6 @@ static void spitz_gpio_setup(struct pxa2xx_state_s *cpu, int slots) |
| 1134 | 903 | spitz_gpio_invert[4]); |
| 1135 | 904 | } |
| 1136 | 905 | |
| 1137 | -/* Write the bootloader parameters memory area. */ | |
| 1138 | - | |
| 1139 | -#define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) | |
| 1140 | - | |
| 1141 | -struct __attribute__ ((__packed__)) sl_param_info { | |
| 1142 | - uint32_t comadj_keyword; | |
| 1143 | - int32_t comadj; | |
| 1144 | - | |
| 1145 | - uint32_t uuid_keyword; | |
| 1146 | - char uuid[16]; | |
| 1147 | - | |
| 1148 | - uint32_t touch_keyword; | |
| 1149 | - int32_t touch_xp; | |
| 1150 | - int32_t touch_yp; | |
| 1151 | - int32_t touch_xd; | |
| 1152 | - int32_t touch_yd; | |
| 1153 | - | |
| 1154 | - uint32_t adadj_keyword; | |
| 1155 | - int32_t adadj; | |
| 1156 | - | |
| 1157 | - uint32_t phad_keyword; | |
| 1158 | - int32_t phadadj; | |
| 1159 | -} spitz_bootparam = { | |
| 1160 | - .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'), | |
| 1161 | - .comadj = 125, | |
| 1162 | - .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'), | |
| 1163 | - .uuid = { -1 }, | |
| 1164 | - .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'), | |
| 1165 | - .touch_xp = -1, | |
| 1166 | - .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'), | |
| 1167 | - .adadj = -1, | |
| 1168 | - .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'), | |
| 1169 | - .phadadj = 0x01, | |
| 1170 | -}; | |
| 1171 | - | |
| 1172 | -static void sl_bootparam_write(uint32_t ptr) | |
| 1173 | -{ | |
| 1174 | - memcpy(phys_ram_base + ptr, &spitz_bootparam, | |
| 1175 | - sizeof(struct sl_param_info)); | |
| 1176 | -} | |
| 1177 | - | |
| 1178 | -#define SL_PXA_PARAM_BASE 0xa0000a00 | |
| 1179 | - | |
| 1180 | 906 | /* Board init. */ |
| 1181 | 907 | enum spitz_model_e { spitz, akita, borzoi, terrier }; |
| 1182 | 908 | |
| ... | ... | @@ -1194,7 +920,7 @@ static void spitz_common_init(ram_addr_t ram_size, int vga_ram_size, |
| 1194 | 920 | const char *cpu_model, enum spitz_model_e model, int arm_id) |
| 1195 | 921 | { |
| 1196 | 922 | struct pxa2xx_state_s *cpu; |
| 1197 | - struct scoop_info_s *scp; | |
| 923 | + struct scoop_info_s *scp0, *scp1 = NULL; | |
| 1198 | 924 | |
| 1199 | 925 | if (!cpu_model) |
| 1200 | 926 | cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0"; |
| ... | ... | @@ -1217,9 +943,12 @@ static void spitz_common_init(ram_addr_t ram_size, int vga_ram_size, |
| 1217 | 943 | |
| 1218 | 944 | spitz_ssp_attach(cpu); |
| 1219 | 945 | |
| 1220 | - scp = spitz_scoop_init(cpu, (model == akita) ? 1 : 2); | |
| 946 | + scp0 = scoop_init(cpu, 0, 0x10800000); | |
| 947 | + if (model != akita) { | |
| 948 | + scp1 = scoop_init(cpu, 1, 0x08800040); | |
| 949 | + } | |
| 1221 | 950 | |
| 1222 | - spitz_scoop_gpio_setup(cpu, scp, (model == akita) ? 1 : 2); | |
| 951 | + spitz_scoop_gpio_setup(cpu, scp0, scp1); | |
| 1223 | 952 | |
| 1224 | 953 | spitz_gpio_setup(cpu, (model == akita) ? 1 : 2); |
| 1225 | 954 | ... | ... |
hw/zaurus.c
0 → 100644
| 1 | +/* | |
| 2 | + * Copyright (c) 2006-2008 Openedhand Ltd. | |
| 3 | + * Written by Andrzej Zaborowski <balrog@zabor.org> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or | |
| 6 | + * modify it under the terms of the GNU General Public License as | |
| 7 | + * published by the Free Software Foundation; either version 2 or | |
| 8 | + * (at your option) version 3 of the License. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the Free Software | |
| 17 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
| 18 | + * MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#include "hw.h" | |
| 21 | +#include "pxa.h" | |
| 22 | +#include "sharpsl.h" | |
| 23 | + | |
| 24 | +#define zaurus_printf(format, ...) \ | |
| 25 | + fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__) | |
| 26 | +#undef REG_FMT | |
| 27 | +#if TARGET_PHYS_ADDR_BITS == 32 | |
| 28 | +#define REG_FMT "0x%02x" | |
| 29 | +#else | |
| 30 | +#define REG_FMT "0x%02lx" | |
| 31 | +#endif | |
| 32 | + | |
| 33 | +/* SCOOP devices */ | |
| 34 | + | |
| 35 | +struct scoop_info_s { | |
| 36 | + target_phys_addr_t target_base; | |
| 37 | + qemu_irq handler[16]; | |
| 38 | + qemu_irq *in; | |
| 39 | + uint16_t status; | |
| 40 | + uint16_t power; | |
| 41 | + uint32_t gpio_level; | |
| 42 | + uint32_t gpio_dir; | |
| 43 | + uint32_t prev_level; | |
| 44 | + | |
| 45 | + uint16_t mcr; | |
| 46 | + uint16_t cdr; | |
| 47 | + uint16_t ccr; | |
| 48 | + uint16_t irr; | |
| 49 | + uint16_t imr; | |
| 50 | + uint16_t isr; | |
| 51 | + uint16_t gprr; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +#define SCOOP_MCR 0x00 | |
| 55 | +#define SCOOP_CDR 0x04 | |
| 56 | +#define SCOOP_CSR 0x08 | |
| 57 | +#define SCOOP_CPR 0x0c | |
| 58 | +#define SCOOP_CCR 0x10 | |
| 59 | +#define SCOOP_IRR_IRM 0x14 | |
| 60 | +#define SCOOP_IMR 0x18 | |
| 61 | +#define SCOOP_ISR 0x1c | |
| 62 | +#define SCOOP_GPCR 0x20 | |
| 63 | +#define SCOOP_GPWR 0x24 | |
| 64 | +#define SCOOP_GPRR 0x28 | |
| 65 | + | |
| 66 | +static inline void scoop_gpio_handler_update(struct scoop_info_s *s) { | |
| 67 | + uint32_t level, diff; | |
| 68 | + int bit; | |
| 69 | + level = s->gpio_level & s->gpio_dir; | |
| 70 | + | |
| 71 | + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { | |
| 72 | + bit = ffs(diff) - 1; | |
| 73 | + qemu_set_irq(s->handler[bit], (level >> bit) & 1); | |
| 74 | + } | |
| 75 | + | |
| 76 | + s->prev_level = level; | |
| 77 | +} | |
| 78 | + | |
| 79 | +static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr) | |
| 80 | +{ | |
| 81 | + struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 82 | + addr -= s->target_base; | |
| 83 | + | |
| 84 | + switch (addr) { | |
| 85 | + case SCOOP_MCR: | |
| 86 | + return s->mcr; | |
| 87 | + case SCOOP_CDR: | |
| 88 | + return s->cdr; | |
| 89 | + case SCOOP_CSR: | |
| 90 | + return s->status; | |
| 91 | + case SCOOP_CPR: | |
| 92 | + return s->power; | |
| 93 | + case SCOOP_CCR: | |
| 94 | + return s->ccr; | |
| 95 | + case SCOOP_IRR_IRM: | |
| 96 | + return s->irr; | |
| 97 | + case SCOOP_IMR: | |
| 98 | + return s->imr; | |
| 99 | + case SCOOP_ISR: | |
| 100 | + return s->isr; | |
| 101 | + case SCOOP_GPCR: | |
| 102 | + return s->gpio_dir; | |
| 103 | + case SCOOP_GPWR: | |
| 104 | + return s->gpio_level; | |
| 105 | + case SCOOP_GPRR: | |
| 106 | + return s->gprr; | |
| 107 | + default: | |
| 108 | + zaurus_printf("Bad register offset " REG_FMT "\n", addr); | |
| 109 | + } | |
| 110 | + | |
| 111 | + return 0; | |
| 112 | +} | |
| 113 | + | |
| 114 | +static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) | |
| 115 | +{ | |
| 116 | + struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 117 | + addr -= s->target_base; | |
| 118 | + value &= 0xffff; | |
| 119 | + | |
| 120 | + switch (addr) { | |
| 121 | + case SCOOP_MCR: | |
| 122 | + s->mcr = value; | |
| 123 | + break; | |
| 124 | + case SCOOP_CDR: | |
| 125 | + s->cdr = value; | |
| 126 | + break; | |
| 127 | + case SCOOP_CPR: | |
| 128 | + s->power = value; | |
| 129 | + if (value & 0x80) | |
| 130 | + s->power |= 0x8040; | |
| 131 | + break; | |
| 132 | + case SCOOP_CCR: | |
| 133 | + s->ccr = value; | |
| 134 | + break; | |
| 135 | + case SCOOP_IRR_IRM: | |
| 136 | + s->irr = value; | |
| 137 | + break; | |
| 138 | + case SCOOP_IMR: | |
| 139 | + s->imr = value; | |
| 140 | + break; | |
| 141 | + case SCOOP_ISR: | |
| 142 | + s->isr = value; | |
| 143 | + break; | |
| 144 | + case SCOOP_GPCR: | |
| 145 | + s->gpio_dir = value; | |
| 146 | + scoop_gpio_handler_update(s); | |
| 147 | + break; | |
| 148 | + case SCOOP_GPWR: | |
| 149 | + s->gpio_level = value & s->gpio_dir; | |
| 150 | + scoop_gpio_handler_update(s); | |
| 151 | + break; | |
| 152 | + case SCOOP_GPRR: | |
| 153 | + s->gprr = value; | |
| 154 | + break; | |
| 155 | + default: | |
| 156 | + zaurus_printf("Bad register offset " REG_FMT "\n", addr); | |
| 157 | + } | |
| 158 | +} | |
| 159 | + | |
| 160 | +CPUReadMemoryFunc *scoop_readfn[] = { | |
| 161 | + scoop_readb, | |
| 162 | + scoop_readb, | |
| 163 | + scoop_readb, | |
| 164 | +}; | |
| 165 | +CPUWriteMemoryFunc *scoop_writefn[] = { | |
| 166 | + scoop_writeb, | |
| 167 | + scoop_writeb, | |
| 168 | + scoop_writeb, | |
| 169 | +}; | |
| 170 | + | |
| 171 | +void scoop_gpio_set(void *opaque, int line, int level) | |
| 172 | +{ | |
| 173 | + struct scoop_info_s *s = (struct scoop_info_s *) s; | |
| 174 | + | |
| 175 | + if (level) | |
| 176 | + s->gpio_level |= (1 << line); | |
| 177 | + else | |
| 178 | + s->gpio_level &= ~(1 << line); | |
| 179 | +} | |
| 180 | + | |
| 181 | +qemu_irq *scoop_gpio_in_get(struct scoop_info_s *s) | |
| 182 | +{ | |
| 183 | + return s->in; | |
| 184 | +} | |
| 185 | + | |
| 186 | +void scoop_gpio_out_set(struct scoop_info_s *s, int line, | |
| 187 | + qemu_irq handler) { | |
| 188 | + if (line >= 16) { | |
| 189 | + fprintf(stderr, "No GPIO pin %i\n", line); | |
| 190 | + exit(-1); | |
| 191 | + } | |
| 192 | + | |
| 193 | + s->handler[line] = handler; | |
| 194 | +} | |
| 195 | + | |
| 196 | +static void scoop_save(QEMUFile *f, void *opaque) | |
| 197 | +{ | |
| 198 | + struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 199 | + qemu_put_be16s(f, &s->status); | |
| 200 | + qemu_put_be16s(f, &s->power); | |
| 201 | + qemu_put_be32s(f, &s->gpio_level); | |
| 202 | + qemu_put_be32s(f, &s->gpio_dir); | |
| 203 | + qemu_put_be32s(f, &s->prev_level); | |
| 204 | + qemu_put_be16s(f, &s->mcr); | |
| 205 | + qemu_put_be16s(f, &s->cdr); | |
| 206 | + qemu_put_be16s(f, &s->ccr); | |
| 207 | + qemu_put_be16s(f, &s->irr); | |
| 208 | + qemu_put_be16s(f, &s->imr); | |
| 209 | + qemu_put_be16s(f, &s->isr); | |
| 210 | + qemu_put_be16s(f, &s->gprr); | |
| 211 | +} | |
| 212 | + | |
| 213 | +static int scoop_load(QEMUFile *f, void *opaque, int version_id) | |
| 214 | +{ | |
| 215 | + struct scoop_info_s *s = (struct scoop_info_s *) opaque; | |
| 216 | + qemu_get_be16s(f, &s->status); | |
| 217 | + qemu_get_be16s(f, &s->power); | |
| 218 | + qemu_get_be32s(f, &s->gpio_level); | |
| 219 | + qemu_get_be32s(f, &s->gpio_dir); | |
| 220 | + qemu_get_be32s(f, &s->prev_level); | |
| 221 | + qemu_get_be16s(f, &s->mcr); | |
| 222 | + qemu_get_be16s(f, &s->cdr); | |
| 223 | + qemu_get_be16s(f, &s->ccr); | |
| 224 | + qemu_get_be16s(f, &s->irr); | |
| 225 | + qemu_get_be16s(f, &s->imr); | |
| 226 | + qemu_get_be16s(f, &s->isr); | |
| 227 | + qemu_get_be16s(f, &s->gprr); | |
| 228 | + | |
| 229 | + return 0; | |
| 230 | +} | |
| 231 | + | |
| 232 | +struct scoop_info_s *scoop_init(struct pxa2xx_state_s *cpu, | |
| 233 | + int instance, | |
| 234 | + target_phys_addr_t target_base) { | |
| 235 | + int iomemtype; | |
| 236 | + struct scoop_info_s *s; | |
| 237 | + | |
| 238 | + s = (struct scoop_info_s *) | |
| 239 | + qemu_mallocz(sizeof(struct scoop_info_s)); | |
| 240 | + memset(s, 0, sizeof(struct scoop_info_s)); | |
| 241 | + | |
| 242 | + s->target_base = target_base; | |
| 243 | + s->status = 0x02; | |
| 244 | + s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16); | |
| 245 | + iomemtype = cpu_register_io_memory(0, scoop_readfn, | |
| 246 | + scoop_writefn, s); | |
| 247 | + cpu_register_physical_memory(s->target_base, 0x1000, iomemtype); | |
| 248 | + register_savevm("scoop", instance, 0, scoop_save, scoop_load, s); | |
| 249 | + | |
| 250 | + return s; | |
| 251 | +} | |
| 252 | + | |
| 253 | +/* Write the bootloader parameters memory area. */ | |
| 254 | + | |
| 255 | +#define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) | |
| 256 | + | |
| 257 | +struct __attribute__ ((__packed__)) sl_param_info { | |
| 258 | + uint32_t comadj_keyword; | |
| 259 | + int32_t comadj; | |
| 260 | + | |
| 261 | + uint32_t uuid_keyword; | |
| 262 | + char uuid[16]; | |
| 263 | + | |
| 264 | + uint32_t touch_keyword; | |
| 265 | + int32_t touch_xp; | |
| 266 | + int32_t touch_yp; | |
| 267 | + int32_t touch_xd; | |
| 268 | + int32_t touch_yd; | |
| 269 | + | |
| 270 | + uint32_t adadj_keyword; | |
| 271 | + int32_t adadj; | |
| 272 | + | |
| 273 | + uint32_t phad_keyword; | |
| 274 | + int32_t phadadj; | |
| 275 | +} zaurus_bootparam = { | |
| 276 | + .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'), | |
| 277 | + .comadj = 125, | |
| 278 | + .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'), | |
| 279 | + .uuid = { -1 }, | |
| 280 | + .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'), | |
| 281 | + .touch_xp = -1, | |
| 282 | + .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'), | |
| 283 | + .adadj = -1, | |
| 284 | + .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'), | |
| 285 | + .phadadj = 0x01, | |
| 286 | +}; | |
| 287 | + | |
| 288 | +void sl_bootparam_write(uint32_t ptr) | |
| 289 | +{ | |
| 290 | + memcpy(phys_ram_base + ptr, &zaurus_bootparam, | |
| 291 | + sizeof(struct sl_param_info)); | |
| 292 | +} | ... | ... |