xref: /qemu/hw/arm/palm.c (revision a2531bb8)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * PalmOne's (TM) PDAs.
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog@zabor.org>
553018216SPaolo Bonzini  *
653018216SPaolo Bonzini  * This program is free software; you can redistribute it and/or
753018216SPaolo Bonzini  * modify it under the terms of the GNU General Public License as
853018216SPaolo Bonzini  * published by the Free Software Foundation; either version 2 or
953018216SPaolo Bonzini  * (at your option) version 3 of the License.
1053018216SPaolo Bonzini  *
1153018216SPaolo Bonzini  * This program is distributed in the hope that it will be useful,
1253018216SPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1353018216SPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1453018216SPaolo Bonzini  * GNU General Public License for more details.
1553018216SPaolo Bonzini  *
1653018216SPaolo Bonzini  * You should have received a copy of the GNU General Public License along
1753018216SPaolo Bonzini  * with this program; if not, see <http://www.gnu.org/licenses/>.
1853018216SPaolo Bonzini  */
1964552b6bSMarkus Armbruster 
2012b16722SPeter Maydell #include "qemu/osdep.h"
21da34e65cSMarkus Armbruster #include "qapi/error.h"
2253018216SPaolo Bonzini #include "audio/audio.h"
2353018216SPaolo Bonzini #include "sysemu/sysemu.h"
241ca8334eSAndreas Färber #include "sysemu/qtest.h"
2553018216SPaolo Bonzini #include "ui/console.h"
260d09e41aSPaolo Bonzini #include "hw/arm/omap.h"
2753018216SPaolo Bonzini #include "hw/boards.h"
2812ec8bd5SPeter Maydell #include "hw/arm/boot.h"
29a331dd02SPhilippe Mathieu-Daudé #include "hw/input/tsc2xxx.h"
3064552b6bSMarkus Armbruster #include "hw/irq.h"
3153018216SPaolo Bonzini #include "hw/loader.h"
327f1679dcSIgor Mammedov #include "qemu/cutils.h"
33db1015e9SEduardo Habkost #include "qom/object.h"
34cc37d98bSRichard Henderson #include "qemu/error-report.h"
35cc37d98bSRichard Henderson 
3653018216SPaolo Bonzini 
static_read(void * opaque,hwaddr offset,unsigned size)377b675f1fSPeter Maydell static uint64_t static_read(void *opaque, hwaddr offset, unsigned size)
3853018216SPaolo Bonzini {
3953018216SPaolo Bonzini     uint32_t *val = (uint32_t *)opaque;
407b675f1fSPeter Maydell     uint32_t sizemask = 7 >> size;
417b675f1fSPeter Maydell 
427b675f1fSPeter Maydell     return *val >> ((offset & sizemask) << 3);
4353018216SPaolo Bonzini }
4453018216SPaolo Bonzini 
static_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)457b675f1fSPeter Maydell static void static_write(void *opaque, hwaddr offset, uint64_t value,
467b675f1fSPeter Maydell                          unsigned size)
4753018216SPaolo Bonzini {
4853018216SPaolo Bonzini #ifdef SPY
4953018216SPaolo Bonzini     printf("%s: value %08lx written at " PA_FMT "\n",
50a89f364aSAlistair Francis                     __func__, value, offset);
5153018216SPaolo Bonzini #endif
5253018216SPaolo Bonzini }
5353018216SPaolo Bonzini 
5453018216SPaolo Bonzini static const MemoryRegionOps static_ops = {
557b675f1fSPeter Maydell     .read = static_read,
567b675f1fSPeter Maydell     .write = static_write,
577b675f1fSPeter Maydell     .valid.min_access_size = 1,
587b675f1fSPeter Maydell     .valid.max_access_size = 4,
5953018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
6053018216SPaolo Bonzini };
6153018216SPaolo Bonzini 
6253018216SPaolo Bonzini /* Palm Tunsgten|E support */
6353018216SPaolo Bonzini 
6453018216SPaolo Bonzini /* Shared GPIOs */
6553018216SPaolo Bonzini #define PALMTE_USBDETECT_GPIO   0
6653018216SPaolo Bonzini #define PALMTE_USB_OR_DC_GPIO   1
6753018216SPaolo Bonzini #define PALMTE_TSC_GPIO                 4
6853018216SPaolo Bonzini #define PALMTE_PINTDAV_GPIO     6
6953018216SPaolo Bonzini #define PALMTE_MMC_WP_GPIO      8
7053018216SPaolo Bonzini #define PALMTE_MMC_POWER_GPIO   9
7153018216SPaolo Bonzini #define PALMTE_HDQ_GPIO                 11
7253018216SPaolo Bonzini #define PALMTE_HEADPHONES_GPIO  14
7353018216SPaolo Bonzini #define PALMTE_SPEAKER_GPIO     15
7453018216SPaolo Bonzini /* MPU private GPIOs */
7553018216SPaolo Bonzini #define PALMTE_DC_GPIO          2
7653018216SPaolo Bonzini #define PALMTE_MMC_SWITCH_GPIO  4
7753018216SPaolo Bonzini #define PALMTE_MMC1_GPIO        6
7853018216SPaolo Bonzini #define PALMTE_MMC2_GPIO        7
7953018216SPaolo Bonzini #define PALMTE_MMC3_GPIO        11
8053018216SPaolo Bonzini 
8153018216SPaolo Bonzini static MouseTransformInfo palmte_pointercal = {
8253018216SPaolo Bonzini     .x = 320,
8353018216SPaolo Bonzini     .y = 320,
8453018216SPaolo Bonzini     .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
8553018216SPaolo Bonzini };
8653018216SPaolo Bonzini 
palmte_microwire_setup(struct omap_mpu_state_s * cpu)8753018216SPaolo Bonzini static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
8853018216SPaolo Bonzini {
8953018216SPaolo Bonzini     uWireSlave *tsc;
9053018216SPaolo Bonzini 
9153018216SPaolo Bonzini     tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
9253018216SPaolo Bonzini 
9353018216SPaolo Bonzini     omap_uwire_attach(cpu->microwire, tsc, 0);
9453018216SPaolo Bonzini     omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
9553018216SPaolo Bonzini 
9653018216SPaolo Bonzini     tsc210x_set_transform(tsc, &palmte_pointercal);
9753018216SPaolo Bonzini }
9853018216SPaolo Bonzini 
9953018216SPaolo Bonzini static struct {
10053018216SPaolo Bonzini     int row;
10153018216SPaolo Bonzini     int column;
10253018216SPaolo Bonzini } palmte_keymap[0x80] = {
10353018216SPaolo Bonzini     [0 ... 0x7f] = { -1, -1 },
10453018216SPaolo Bonzini     [0x3b] = { 0, 0 },  /* F1   -> Calendar */
10553018216SPaolo Bonzini     [0x3c] = { 1, 0 },  /* F2   -> Contacts */
10653018216SPaolo Bonzini     [0x3d] = { 2, 0 },  /* F3   -> Tasks List */
10753018216SPaolo Bonzini     [0x3e] = { 3, 0 },  /* F4   -> Note Pad */
10853018216SPaolo Bonzini     [0x01] = { 4, 0 },  /* Esc  -> Power */
10953018216SPaolo Bonzini     [0x4b] = { 0, 1 },  /*         Left */
11053018216SPaolo Bonzini     [0x50] = { 1, 1 },  /*         Down */
11153018216SPaolo Bonzini     [0x48] = { 2, 1 },  /*         Up */
11253018216SPaolo Bonzini     [0x4d] = { 3, 1 },  /*         Right */
11353018216SPaolo Bonzini     [0x4c] = { 4, 1 },  /*         Centre */
11453018216SPaolo Bonzini     [0x39] = { 4, 1 },  /* Spc  -> Centre */
11553018216SPaolo Bonzini };
11653018216SPaolo Bonzini 
palmte_button_event(void * opaque,int keycode)11753018216SPaolo Bonzini static void palmte_button_event(void *opaque, int keycode)
11853018216SPaolo Bonzini {
119a75ed3c4SPhilippe Mathieu-Daudé     struct omap_mpu_state_s *cpu = opaque;
12053018216SPaolo Bonzini 
12153018216SPaolo Bonzini     if (palmte_keymap[keycode & 0x7f].row != -1)
12253018216SPaolo Bonzini         omap_mpuio_key(cpu->mpuio,
12353018216SPaolo Bonzini                         palmte_keymap[keycode & 0x7f].row,
12453018216SPaolo Bonzini                         palmte_keymap[keycode & 0x7f].column,
12553018216SPaolo Bonzini                         !(keycode & 0x80));
12653018216SPaolo Bonzini }
12753018216SPaolo Bonzini 
128ad938fc1SPeter Maydell /*
129ad938fc1SPeter Maydell  * Encapsulation of some GPIO line behaviour for the Palm board
130ad938fc1SPeter Maydell  *
131ad938fc1SPeter Maydell  * QEMU interface:
132ad938fc1SPeter Maydell  *  + unnamed GPIO inputs 0..6: for the various miscellaneous input lines
133ad938fc1SPeter Maydell  */
134ad938fc1SPeter Maydell 
135ad938fc1SPeter Maydell #define TYPE_PALM_MISC_GPIO "palm-misc-gpio"
1368063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(PalmMiscGPIOState, PALM_MISC_GPIO)
137ad938fc1SPeter Maydell 
138db1015e9SEduardo Habkost struct PalmMiscGPIOState {
139ad938fc1SPeter Maydell     SysBusDevice parent_obj;
140db1015e9SEduardo Habkost };
141ad938fc1SPeter Maydell 
palmte_onoff_gpios(void * opaque,int line,int level)14253018216SPaolo Bonzini static void palmte_onoff_gpios(void *opaque, int line, int level)
14353018216SPaolo Bonzini {
14453018216SPaolo Bonzini     switch (line) {
14553018216SPaolo Bonzini     case 0:
14653018216SPaolo Bonzini         printf("%s: current to MMC/SD card %sabled.\n",
147a89f364aSAlistair Francis                         __func__, level ? "dis" : "en");
14853018216SPaolo Bonzini         break;
14953018216SPaolo Bonzini     case 1:
15053018216SPaolo Bonzini         printf("%s: internal speaker amplifier %s.\n",
151a89f364aSAlistair Francis                         __func__, level ? "down" : "on");
15253018216SPaolo Bonzini         break;
15353018216SPaolo Bonzini 
15453018216SPaolo Bonzini     /* These LCD & Audio output signals have not been identified yet.  */
15553018216SPaolo Bonzini     case 2:
15653018216SPaolo Bonzini     case 3:
15753018216SPaolo Bonzini     case 4:
15853018216SPaolo Bonzini         printf("%s: LCD GPIO%i %s.\n",
159a89f364aSAlistair Francis                         __func__, line - 1, level ? "high" : "low");
16053018216SPaolo Bonzini         break;
16153018216SPaolo Bonzini     case 5:
16253018216SPaolo Bonzini     case 6:
16353018216SPaolo Bonzini         printf("%s: Audio GPIO%i %s.\n",
164a89f364aSAlistair Francis                         __func__, line - 4, level ? "high" : "low");
16553018216SPaolo Bonzini         break;
16653018216SPaolo Bonzini     }
16753018216SPaolo Bonzini }
16853018216SPaolo Bonzini 
palm_misc_gpio_init(Object * obj)169ad938fc1SPeter Maydell static void palm_misc_gpio_init(Object *obj)
170ad938fc1SPeter Maydell {
171ad938fc1SPeter Maydell     DeviceState *dev = DEVICE(obj);
172ad938fc1SPeter Maydell 
173ad938fc1SPeter Maydell     qdev_init_gpio_in(dev, palmte_onoff_gpios, 7);
174ad938fc1SPeter Maydell }
175ad938fc1SPeter Maydell 
176ad938fc1SPeter Maydell static const TypeInfo palm_misc_gpio_info = {
177ad938fc1SPeter Maydell     .name = TYPE_PALM_MISC_GPIO,
178ad938fc1SPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
179ad938fc1SPeter Maydell     .instance_size = sizeof(PalmMiscGPIOState),
180ad938fc1SPeter Maydell     .instance_init = palm_misc_gpio_init,
181ad938fc1SPeter Maydell     /*
182ad938fc1SPeter Maydell      * No class init required: device has no internal state so does not
183ad938fc1SPeter Maydell      * need to set up reset or vmstate, and has no realize method.
184ad938fc1SPeter Maydell      */
185ad938fc1SPeter Maydell };
186ad938fc1SPeter Maydell 
palmte_gpio_setup(struct omap_mpu_state_s * cpu)18753018216SPaolo Bonzini static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
18853018216SPaolo Bonzini {
189ad938fc1SPeter Maydell     DeviceState *misc_gpio;
190ad938fc1SPeter Maydell 
191ad938fc1SPeter Maydell     misc_gpio = sysbus_create_simple(TYPE_PALM_MISC_GPIO, -1, NULL);
19253018216SPaolo Bonzini 
19353018216SPaolo Bonzini     omap_mmc_handlers(cpu->mmc,
19453018216SPaolo Bonzini                     qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
19553018216SPaolo Bonzini                     qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
19653018216SPaolo Bonzini                             [PALMTE_MMC_SWITCH_GPIO]));
19753018216SPaolo Bonzini 
198ad938fc1SPeter Maydell     qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,
199ad938fc1SPeter Maydell                           qdev_get_gpio_in(misc_gpio, 0));
200ad938fc1SPeter Maydell     qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,
201ad938fc1SPeter Maydell                           qdev_get_gpio_in(misc_gpio, 1));
202ad938fc1SPeter Maydell     qdev_connect_gpio_out(cpu->gpio, 11, qdev_get_gpio_in(misc_gpio, 2));
203ad938fc1SPeter Maydell     qdev_connect_gpio_out(cpu->gpio, 12, qdev_get_gpio_in(misc_gpio, 3));
204ad938fc1SPeter Maydell     qdev_connect_gpio_out(cpu->gpio, 13, qdev_get_gpio_in(misc_gpio, 4));
205ad938fc1SPeter Maydell     omap_mpuio_out_set(cpu->mpuio, 1, qdev_get_gpio_in(misc_gpio, 5));
206ad938fc1SPeter Maydell     omap_mpuio_out_set(cpu->mpuio, 3, qdev_get_gpio_in(misc_gpio, 6));
20753018216SPaolo Bonzini 
20853018216SPaolo Bonzini     /* Reset some inputs to initial state.  */
20953018216SPaolo Bonzini     qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
21053018216SPaolo Bonzini     qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
21153018216SPaolo Bonzini     qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
21253018216SPaolo Bonzini     qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
21353018216SPaolo Bonzini     qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
21453018216SPaolo Bonzini     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
21553018216SPaolo Bonzini     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
21653018216SPaolo Bonzini     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
21753018216SPaolo Bonzini }
21853018216SPaolo Bonzini 
21953018216SPaolo Bonzini static struct arm_boot_info palmte_binfo = {
22053018216SPaolo Bonzini     .loader_start = OMAP_EMIFF_BASE,
22153018216SPaolo Bonzini     .ram_size = 0x02000000,
22253018216SPaolo Bonzini     .board_id = 0x331,
22353018216SPaolo Bonzini };
22453018216SPaolo Bonzini 
palmte_init(MachineState * machine)2253ef96221SMarcel Apfelbaum static void palmte_init(MachineState *machine)
22653018216SPaolo Bonzini {
22753018216SPaolo Bonzini     MemoryRegion *address_space_mem = get_system_memory();
22853018216SPaolo Bonzini     struct omap_mpu_state_s *mpu;
22953018216SPaolo Bonzini     int flash_size = 0x00800000;
23053018216SPaolo Bonzini     static uint32_t cs0val = 0xffffffff;
23153018216SPaolo Bonzini     static uint32_t cs1val = 0x0000e1a0;
23253018216SPaolo Bonzini     static uint32_t cs2val = 0x0000e1a0;
23353018216SPaolo Bonzini     static uint32_t cs3val = 0xe1a0e1a0;
23453018216SPaolo Bonzini     int rom_size, rom_loaded = 0;
2357f1679dcSIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(machine);
23653018216SPaolo Bonzini     MemoryRegion *flash = g_new(MemoryRegion, 1);
23753018216SPaolo Bonzini     MemoryRegion *cs = g_new(MemoryRegion, 4);
23853018216SPaolo Bonzini 
2397f1679dcSIgor Mammedov     if (machine->ram_size != mc->default_ram_size) {
2407f1679dcSIgor Mammedov         char *sz = size_to_str(mc->default_ram_size);
2417f1679dcSIgor Mammedov         error_report("Invalid RAM size, should be %s", sz);
2427f1679dcSIgor Mammedov         g_free(sz);
2437f1679dcSIgor Mammedov         exit(EXIT_FAILURE);
2447f1679dcSIgor Mammedov     }
2454387b253SPhilippe Mathieu-Daudé 
2467f1679dcSIgor Mammedov     memory_region_add_subregion(address_space_mem, OMAP_EMIFF_BASE,
2477f1679dcSIgor Mammedov                                 machine->ram);
2487f1679dcSIgor Mammedov 
2497f1679dcSIgor Mammedov     mpu = omap310_mpu_init(machine->ram, machine->cpu_type);
25053018216SPaolo Bonzini 
25153018216SPaolo Bonzini     /* External Flash (EMIFS) */
25216260006SPhilippe Mathieu-Daudé     memory_region_init_rom(flash, NULL, "palmte.flash", flash_size,
253f8ed85acSMarkus Armbruster                            &error_fatal);
25453018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
25553018216SPaolo Bonzini 
2562c9b15caSPaolo Bonzini     memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, "palmte-cs0",
25753018216SPaolo Bonzini                           OMAP_CS0_SIZE - flash_size);
25853018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
25953018216SPaolo Bonzini                                 &cs[0]);
2602c9b15caSPaolo Bonzini     memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, "palmte-cs1",
26153018216SPaolo Bonzini                           OMAP_CS1_SIZE);
26253018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
2632c9b15caSPaolo Bonzini     memory_region_init_io(&cs[2], NULL, &static_ops, &cs2val, "palmte-cs2",
26453018216SPaolo Bonzini                           OMAP_CS2_SIZE);
26553018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
2662c9b15caSPaolo Bonzini     memory_region_init_io(&cs[3], NULL, &static_ops, &cs3val, "palmte-cs3",
26753018216SPaolo Bonzini                           OMAP_CS3_SIZE);
26853018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
26953018216SPaolo Bonzini 
27053018216SPaolo Bonzini     palmte_microwire_setup(mpu);
27153018216SPaolo Bonzini 
27253018216SPaolo Bonzini     qemu_add_kbd_event_handler(palmte_button_event, mpu);
27353018216SPaolo Bonzini 
27453018216SPaolo Bonzini     palmte_gpio_setup(mpu);
27553018216SPaolo Bonzini 
27653018216SPaolo Bonzini     /* Setup initial (reset) machine state */
27753018216SPaolo Bonzini     if (nb_option_roms) {
27853018216SPaolo Bonzini         rom_size = get_image_size(option_rom[0].name);
27953018216SPaolo Bonzini         if (rom_size > flash_size) {
28053018216SPaolo Bonzini             fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
281a89f364aSAlistair Francis                             __func__, rom_size, flash_size);
28253018216SPaolo Bonzini             rom_size = 0;
28353018216SPaolo Bonzini         }
28453018216SPaolo Bonzini         if (rom_size > 0) {
28553018216SPaolo Bonzini             rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
28653018216SPaolo Bonzini                                            flash_size);
28753018216SPaolo Bonzini             rom_loaded = 1;
28853018216SPaolo Bonzini         }
28953018216SPaolo Bonzini         if (rom_size < 0) {
29053018216SPaolo Bonzini             fprintf(stderr, "%s: error loading '%s'\n",
291a89f364aSAlistair Francis                             __func__, option_rom[0].name);
29253018216SPaolo Bonzini         }
29353018216SPaolo Bonzini     }
29453018216SPaolo Bonzini 
2952744ece8STao Xu     if (!rom_loaded && !machine->kernel_filename && !qtest_enabled()) {
29653018216SPaolo Bonzini         fprintf(stderr, "Kernel or ROM image must be specified\n");
29753018216SPaolo Bonzini         exit(1);
29853018216SPaolo Bonzini     }
29953018216SPaolo Bonzini 
30053018216SPaolo Bonzini     /* Load the kernel.  */
3012744ece8STao Xu     arm_load_kernel(mpu->cpu, machine, &palmte_binfo);
30253018216SPaolo Bonzini }
30353018216SPaolo Bonzini 
palmte_machine_init(MachineClass * mc)304e264d29dSEduardo Habkost static void palmte_machine_init(MachineClass *mc)
30553018216SPaolo Bonzini {
306e264d29dSEduardo Habkost     mc->desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)";
307e264d29dSEduardo Habkost     mc->init = palmte_init;
3084672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
309ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
3107f1679dcSIgor Mammedov     mc->default_ram_size = 0x02000000;
3117f1679dcSIgor Mammedov     mc->default_ram_id = "omap1.dram";
312a2531bb8SPeter Maydell     mc->deprecation_reason = "machine is old and unmaintained";
313b8ab0303SMartin Kletzander 
314b8ab0303SMartin Kletzander     machine_add_audiodev_property(mc);
31553018216SPaolo Bonzini }
31653018216SPaolo Bonzini 
317e264d29dSEduardo Habkost DEFINE_MACHINE("cheetah", palmte_machine_init)
318ad938fc1SPeter Maydell 
palm_register_types(void)319ad938fc1SPeter Maydell static void palm_register_types(void)
320ad938fc1SPeter Maydell {
321ad938fc1SPeter Maydell     type_register_static(&palm_misc_gpio_info);
322ad938fc1SPeter Maydell }
323ad938fc1SPeter Maydell 
324ad938fc1SPeter Maydell type_init(palm_register_types)
325