Statistics
| Branch: | Revision:

root / hw / palm.c @ b13ce26d

History | View | Annotate | Download (9.5 kB)

1 c3d2689d balrog
/*
2 c3d2689d balrog
 * PalmOne's (TM) PDAs.
3 c3d2689d balrog
 *
4 c3d2689d balrog
 * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog@zabor.org>
5 c3d2689d balrog
 *
6 c3d2689d balrog
 * This program is free software; you can redistribute it and/or
7 c3d2689d balrog
 * modify it under the terms of the GNU General Public License as
8 827df9f3 balrog
 * published by the Free Software Foundation; either version 2 or
9 827df9f3 balrog
 * (at your option) version 3 of the License.
10 c3d2689d balrog
 *
11 c3d2689d balrog
 * This program is distributed in the hope that it will be useful,
12 c3d2689d balrog
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 c3d2689d balrog
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 c3d2689d balrog
 * GNU General Public License for more details.
15 c3d2689d balrog
 *
16 fad6cb1a aurel32
 * You should have received a copy of the GNU General Public License along
17 8167ee88 Blue Swirl
 * with this program; if not, see <http://www.gnu.org/licenses/>.
18 c3d2689d balrog
 */
19 87ecb68b pbrook
#include "hw.h"
20 87ecb68b pbrook
#include "audio/audio.h"
21 87ecb68b pbrook
#include "sysemu.h"
22 87ecb68b pbrook
#include "console.h"
23 87ecb68b pbrook
#include "omap.h"
24 87ecb68b pbrook
#include "boards.h"
25 87ecb68b pbrook
#include "arm-misc.h"
26 827df9f3 balrog
#include "devices.h"
27 ca20cf32 Blue Swirl
#include "loader.h"
28 4b3fedf3 Avi Kivity
#include "exec-memory.h"
29 c3d2689d balrog
30 a8170e5e Avi Kivity
static uint32_t static_readb(void *opaque, hwaddr offset)
31 c3d2689d balrog
{
32 c3d2689d balrog
    uint32_t *val = (uint32_t *) opaque;
33 c3d2689d balrog
    return *val >> ((offset & 3) << 3);
34 c3d2689d balrog
}
35 c3d2689d balrog
36 a8170e5e Avi Kivity
static uint32_t static_readh(void *opaque, hwaddr offset)
37 827df9f3 balrog
{
38 c3d2689d balrog
    uint32_t *val = (uint32_t *) opaque;
39 c3d2689d balrog
    return *val >> ((offset & 1) << 3);
40 c3d2689d balrog
}
41 c3d2689d balrog
42 a8170e5e Avi Kivity
static uint32_t static_readw(void *opaque, hwaddr offset)
43 827df9f3 balrog
{
44 c3d2689d balrog
    uint32_t *val = (uint32_t *) opaque;
45 c3d2689d balrog
    return *val >> ((offset & 0) << 3);
46 c3d2689d balrog
}
47 c3d2689d balrog
48 a8170e5e Avi Kivity
static void static_write(void *opaque, hwaddr offset,
49 d951f6ff balrog
                uint32_t value)
50 d951f6ff balrog
{
51 c3d2689d balrog
#ifdef SPY
52 c3d2689d balrog
    printf("%s: value %08lx written at " PA_FMT "\n",
53 c3d2689d balrog
                    __FUNCTION__, value, offset);
54 c3d2689d balrog
#endif
55 c3d2689d balrog
}
56 c3d2689d balrog
57 ced52fa6 Avi Kivity
static const MemoryRegionOps static_ops = {
58 ced52fa6 Avi Kivity
    .old_mmio = {
59 ced52fa6 Avi Kivity
        .read = { static_readb, static_readh, static_readw, },
60 ced52fa6 Avi Kivity
        .write = { static_write, static_write, static_write, },
61 ced52fa6 Avi Kivity
    },
62 ced52fa6 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
63 c3d2689d balrog
};
64 c3d2689d balrog
65 c3d2689d balrog
/* Palm Tunsgten|E support */
66 8e129e07 balrog
67 8e129e07 balrog
/* Shared GPIOs */
68 8e129e07 balrog
#define PALMTE_USBDETECT_GPIO        0
69 8e129e07 balrog
#define PALMTE_USB_OR_DC_GPIO        1
70 8e129e07 balrog
#define PALMTE_TSC_GPIO                4
71 8e129e07 balrog
#define PALMTE_PINTDAV_GPIO        6
72 8e129e07 balrog
#define PALMTE_MMC_WP_GPIO        8
73 8e129e07 balrog
#define PALMTE_MMC_POWER_GPIO        9
74 8e129e07 balrog
#define PALMTE_HDQ_GPIO                11
75 8e129e07 balrog
#define PALMTE_HEADPHONES_GPIO        14
76 8e129e07 balrog
#define PALMTE_SPEAKER_GPIO        15
77 8e129e07 balrog
/* MPU private GPIOs */
78 8e129e07 balrog
#define PALMTE_DC_GPIO                2
79 8e129e07 balrog
#define PALMTE_MMC_SWITCH_GPIO        4
80 8e129e07 balrog
#define PALMTE_MMC1_GPIO        6
81 8e129e07 balrog
#define PALMTE_MMC2_GPIO        7
82 8e129e07 balrog
#define PALMTE_MMC3_GPIO        11
83 8e129e07 balrog
84 bc24a225 Paul Brook
static MouseTransformInfo palmte_pointercal = {
85 c38b6e25 balrog
    .x = 320,
86 c38b6e25 balrog
    .y = 320,
87 c38b6e25 balrog
    .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
88 c38b6e25 balrog
};
89 c38b6e25 balrog
90 c3d2689d balrog
static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
91 c3d2689d balrog
{
92 bc24a225 Paul Brook
    uWireSlave *tsc;
93 d8f699cb balrog
94 77831c20 Juha Riihimäki
    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
95 d8f699cb balrog
96 d8f699cb balrog
    omap_uwire_attach(cpu->microwire, tsc, 0);
97 d8f699cb balrog
    omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
98 c38b6e25 balrog
99 c38b6e25 balrog
    tsc210x_set_transform(tsc, &palmte_pointercal);
100 c3d2689d balrog
}
101 c3d2689d balrog
102 38a34e1d balrog
static struct {
103 38a34e1d balrog
    int row;
104 38a34e1d balrog
    int column;
105 38a34e1d balrog
} palmte_keymap[0x80] = {
106 38a34e1d balrog
    [0 ... 0x7f] = { -1, -1 },
107 38a34e1d balrog
    [0x3b] = { 0, 0 },        /* F1        -> Calendar */
108 38a34e1d balrog
    [0x3c] = { 1, 0 },        /* F2        -> Contacts */
109 38a34e1d balrog
    [0x3d] = { 2, 0 },        /* F3        -> Tasks List */
110 38a34e1d balrog
    [0x3e] = { 3, 0 },        /* F4        -> Note Pad */
111 38a34e1d balrog
    [0x01] = { 4, 0 },        /* Esc        -> Power */
112 38a34e1d balrog
    [0x4b] = { 0, 1 },        /*            Left */
113 38a34e1d balrog
    [0x50] = { 1, 1 },        /*            Down */
114 38a34e1d balrog
    [0x48] = { 2, 1 },        /*           Up */
115 38a34e1d balrog
    [0x4d] = { 3, 1 },        /*           Right */
116 38a34e1d balrog
    [0x4c] = { 4, 1 },        /*            Centre */
117 38a34e1d balrog
    [0x39] = { 4, 1 },        /* Spc        -> Centre */
118 38a34e1d balrog
};
119 38a34e1d balrog
120 38a34e1d balrog
static void palmte_button_event(void *opaque, int keycode)
121 38a34e1d balrog
{
122 38a34e1d balrog
    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
123 38a34e1d balrog
124 38a34e1d balrog
    if (palmte_keymap[keycode & 0x7f].row != -1)
125 38a34e1d balrog
        omap_mpuio_key(cpu->mpuio,
126 38a34e1d balrog
                        palmte_keymap[keycode & 0x7f].row,
127 38a34e1d balrog
                        palmte_keymap[keycode & 0x7f].column,
128 38a34e1d balrog
                        !(keycode & 0x80));
129 38a34e1d balrog
}
130 38a34e1d balrog
131 7fc42b4b balrog
static void palmte_onoff_gpios(void *opaque, int line, int level)
132 7fc42b4b balrog
{
133 7fc42b4b balrog
    switch (line) {
134 7fc42b4b balrog
    case 0:
135 7fc42b4b balrog
        printf("%s: current to MMC/SD card %sabled.\n",
136 7fc42b4b balrog
                        __FUNCTION__, level ? "dis" : "en");
137 7fc42b4b balrog
        break;
138 7fc42b4b balrog
    case 1:
139 7fc42b4b balrog
        printf("%s: internal speaker amplifier %s.\n",
140 7fc42b4b balrog
                        __FUNCTION__, level ? "down" : "on");
141 7fc42b4b balrog
        break;
142 7fc42b4b balrog
143 7fc42b4b balrog
    /* These LCD & Audio output signals have not been identified yet.  */
144 7fc42b4b balrog
    case 2:
145 7fc42b4b balrog
    case 3:
146 7fc42b4b balrog
    case 4:
147 7fc42b4b balrog
        printf("%s: LCD GPIO%i %s.\n",
148 7fc42b4b balrog
                        __FUNCTION__, line - 1, level ? "high" : "low");
149 7fc42b4b balrog
        break;
150 7fc42b4b balrog
    case 5:
151 7fc42b4b balrog
    case 6:
152 7fc42b4b balrog
        printf("%s: Audio GPIO%i %s.\n",
153 7fc42b4b balrog
                        __FUNCTION__, line - 4, level ? "high" : "low");
154 7fc42b4b balrog
        break;
155 7fc42b4b balrog
    }
156 7fc42b4b balrog
}
157 7fc42b4b balrog
158 7fc42b4b balrog
static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
159 7fc42b4b balrog
{
160 7fc42b4b balrog
    qemu_irq *misc_gpio;
161 7fc42b4b balrog
162 7fc42b4b balrog
    omap_mmc_handlers(cpu->mmc,
163 77831c20 Juha Riihimäki
                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
164 7fc42b4b balrog
                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
165 7fc42b4b balrog
                            [PALMTE_MMC_SWITCH_GPIO]));
166 7fc42b4b balrog
167 7fc42b4b balrog
    misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
168 77831c20 Juha Riihimäki
    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,        misc_gpio[0]);
169 77831c20 Juha Riihimäki
    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,        misc_gpio[1]);
170 77831c20 Juha Riihimäki
    qdev_connect_gpio_out(cpu->gpio, 11,                        misc_gpio[2]);
171 77831c20 Juha Riihimäki
    qdev_connect_gpio_out(cpu->gpio, 12,                        misc_gpio[3]);
172 77831c20 Juha Riihimäki
    qdev_connect_gpio_out(cpu->gpio, 13,                        misc_gpio[4]);
173 77831c20 Juha Riihimäki
    omap_mpuio_out_set(cpu->mpuio, 1,                                misc_gpio[5]);
174 77831c20 Juha Riihimäki
    omap_mpuio_out_set(cpu->mpuio, 3,                                misc_gpio[6]);
175 7fc42b4b balrog
176 7fc42b4b balrog
    /* Reset some inputs to initial state.  */
177 77831c20 Juha Riihimäki
    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
178 77831c20 Juha Riihimäki
    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
179 77831c20 Juha Riihimäki
    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
180 77831c20 Juha Riihimäki
    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
181 7fc42b4b balrog
    qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
182 7fc42b4b balrog
    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
183 7fc42b4b balrog
    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
184 7fc42b4b balrog
    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
185 7fc42b4b balrog
}
186 7fc42b4b balrog
187 f93eb9ff balrog
static struct arm_boot_info palmte_binfo = {
188 f93eb9ff balrog
    .loader_start = OMAP_EMIFF_BASE,
189 f93eb9ff balrog
    .ram_size = 0x02000000,
190 f93eb9ff balrog
    .board_id = 0x331,
191 f93eb9ff balrog
};
192 f93eb9ff balrog
193 5f072e1f Eduardo Habkost
static void palmte_init(QEMUMachineInitArgs *args)
194 c3d2689d balrog
{
195 5f072e1f Eduardo Habkost
    const char *cpu_model = args->cpu_model;
196 5f072e1f Eduardo Habkost
    const char *kernel_filename = args->kernel_filename;
197 5f072e1f Eduardo Habkost
    const char *kernel_cmdline = args->kernel_cmdline;
198 5f072e1f Eduardo Habkost
    const char *initrd_filename = args->initrd_filename;
199 4b3fedf3 Avi Kivity
    MemoryRegion *address_space_mem = get_system_memory();
200 f1eea068 Andreas Färber
    struct omap_mpu_state_s *mpu;
201 c3d2689d balrog
    int flash_size = 0x00800000;
202 f93eb9ff balrog
    int sdram_size = palmte_binfo.ram_size;
203 c3d2689d balrog
    static uint32_t cs0val = 0xffffffff;
204 c3d2689d balrog
    static uint32_t cs1val = 0x0000e1a0;
205 c3d2689d balrog
    static uint32_t cs2val = 0x0000e1a0;
206 c3d2689d balrog
    static uint32_t cs3val = 0xe1a0e1a0;
207 c3d2689d balrog
    int rom_size, rom_loaded = 0;
208 3023f332 aliguori
    DisplayState *ds = get_displaystate();
209 ced52fa6 Avi Kivity
    MemoryRegion *flash = g_new(MemoryRegion, 1);
210 ced52fa6 Avi Kivity
    MemoryRegion *cs = g_new(MemoryRegion, 4);
211 c3d2689d balrog
212 f1eea068 Andreas Färber
    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
213 c3d2689d balrog
214 c3d2689d balrog
    /* External Flash (EMIFS) */
215 c5705a77 Avi Kivity
    memory_region_init_ram(flash, "palmte.flash", flash_size);
216 c5705a77 Avi Kivity
    vmstate_register_ram_global(flash);
217 ced52fa6 Avi Kivity
    memory_region_set_readonly(flash, true);
218 ced52fa6 Avi Kivity
    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
219 ced52fa6 Avi Kivity
220 ced52fa6 Avi Kivity
    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
221 ced52fa6 Avi Kivity
                          OMAP_CS0_SIZE - flash_size);
222 ced52fa6 Avi Kivity
    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
223 ced52fa6 Avi Kivity
                                &cs[0]);
224 ced52fa6 Avi Kivity
    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
225 ced52fa6 Avi Kivity
                          OMAP_CS1_SIZE);
226 ced52fa6 Avi Kivity
    memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
227 ced52fa6 Avi Kivity
    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
228 ced52fa6 Avi Kivity
                          OMAP_CS2_SIZE);
229 ced52fa6 Avi Kivity
    memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
230 ced52fa6 Avi Kivity
    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
231 ced52fa6 Avi Kivity
                          OMAP_CS3_SIZE);
232 ced52fa6 Avi Kivity
    memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
233 c3d2689d balrog
234 f1eea068 Andreas Färber
    palmte_microwire_setup(mpu);
235 c3d2689d balrog
236 f1eea068 Andreas Färber
    qemu_add_kbd_event_handler(palmte_button_event, mpu);
237 38a34e1d balrog
238 f1eea068 Andreas Färber
    palmte_gpio_setup(mpu);
239 8e129e07 balrog
240 c3d2689d balrog
    /* Setup initial (reset) machine state */
241 c3d2689d balrog
    if (nb_option_roms) {
242 2e55e842 Gleb Natapov
        rom_size = get_image_size(option_rom[0].name);
243 dcac9679 pbrook
        if (rom_size > flash_size) {
244 c3d2689d balrog
            fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
245 c3d2689d balrog
                            __FUNCTION__, rom_size, flash_size);
246 dcac9679 pbrook
            rom_size = 0;
247 dcac9679 pbrook
        }
248 dcac9679 pbrook
        if (rom_size > 0) {
249 2e55e842 Gleb Natapov
            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
250 dcac9679 pbrook
                                           flash_size);
251 c3d2689d balrog
            rom_loaded = 1;
252 dcac9679 pbrook
        }
253 dcac9679 pbrook
        if (rom_size < 0) {
254 c3d2689d balrog
            fprintf(stderr, "%s: error loading '%s'\n",
255 2e55e842 Gleb Natapov
                            __FUNCTION__, option_rom[0].name);
256 dcac9679 pbrook
        }
257 c3d2689d balrog
    }
258 c3d2689d balrog
259 c3d2689d balrog
    if (!rom_loaded && !kernel_filename) {
260 c3d2689d balrog
        fprintf(stderr, "Kernel or ROM image must be specified\n");
261 c3d2689d balrog
        exit(1);
262 c3d2689d balrog
    }
263 c3d2689d balrog
264 c3d2689d balrog
    /* Load the kernel.  */
265 c3d2689d balrog
    if (kernel_filename) {
266 f93eb9ff balrog
        palmte_binfo.kernel_filename = kernel_filename;
267 f93eb9ff balrog
        palmte_binfo.kernel_cmdline = kernel_cmdline;
268 f93eb9ff balrog
        palmte_binfo.initrd_filename = initrd_filename;
269 3aaa8dfa Andreas Färber
        arm_load_kernel(mpu->cpu, &palmte_binfo);
270 c3d2689d balrog
    }
271 c3d2689d balrog
272 c60e08d9 pbrook
    /* FIXME: We shouldn't really be doing this here.  The LCD controller
273 c60e08d9 pbrook
       will set the size once configured, so this just sets an initial
274 c60e08d9 pbrook
       size until the guest activates the display.  */
275 7b5d76da aliguori
    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
276 7d957bd8 aliguori
    dpy_resize(ds);
277 c3d2689d balrog
}
278 c3d2689d balrog
279 f80f9ec9 Anthony Liguori
static QEMUMachine palmte_machine = {
280 4b32e168 aliguori
    .name = "cheetah",
281 4b32e168 aliguori
    .desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)",
282 4b32e168 aliguori
    .init = palmte_init,
283 c3d2689d balrog
};
284 f80f9ec9 Anthony Liguori
285 f80f9ec9 Anthony Liguori
static void palmte_machine_init(void)
286 f80f9ec9 Anthony Liguori
{
287 f80f9ec9 Anthony Liguori
    qemu_register_machine(&palmte_machine);
288 f80f9ec9 Anthony Liguori
}
289 f80f9ec9 Anthony Liguori
290 f80f9ec9 Anthony Liguori
machine_init(palmte_machine_init);