vmstate: port cirrus_vga device
[qemu] / hw / zaurus.c
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 along
16  * with this program; if not, see <http://www.gnu.org/licenses/>.
17  */
18 #include "hw.h"
19 #include "pxa.h"
20 #include "sharpsl.h"
21
22 #undef REG_FMT
23 #define REG_FMT                 "0x%02lx"
24
25 /* SCOOP devices */
26
27 struct ScoopInfo {
28     qemu_irq handler[16];
29     qemu_irq *in;
30     uint16_t status;
31     uint16_t power;
32     uint32_t gpio_level;
33     uint32_t gpio_dir;
34     uint32_t prev_level;
35
36     uint16_t mcr;
37     uint16_t cdr;
38     uint16_t ccr;
39     uint16_t irr;
40     uint16_t imr;
41     uint16_t isr;
42 };
43
44 #define SCOOP_MCR       0x00
45 #define SCOOP_CDR       0x04
46 #define SCOOP_CSR       0x08
47 #define SCOOP_CPR       0x0c
48 #define SCOOP_CCR       0x10
49 #define SCOOP_IRR_IRM   0x14
50 #define SCOOP_IMR       0x18
51 #define SCOOP_ISR       0x1c
52 #define SCOOP_GPCR      0x20
53 #define SCOOP_GPWR      0x24
54 #define SCOOP_GPRR      0x28
55
56 static inline void scoop_gpio_handler_update(ScoopInfo *s) {
57     uint32_t level, diff;
58     int bit;
59     level = s->gpio_level & s->gpio_dir;
60
61     for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
62         bit = ffs(diff) - 1;
63         qemu_set_irq(s->handler[bit], (level >> bit) & 1);
64     }
65
66     s->prev_level = level;
67 }
68
69 static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
70 {
71     ScoopInfo *s = (ScoopInfo *) opaque;
72
73     switch (addr) {
74     case SCOOP_MCR:
75         return s->mcr;
76     case SCOOP_CDR:
77         return s->cdr;
78     case SCOOP_CSR:
79         return s->status;
80     case SCOOP_CPR:
81         return s->power;
82     case SCOOP_CCR:
83         return s->ccr;
84     case SCOOP_IRR_IRM:
85         return s->irr;
86     case SCOOP_IMR:
87         return s->imr;
88     case SCOOP_ISR:
89         return s->isr;
90     case SCOOP_GPCR:
91         return s->gpio_dir;
92     case SCOOP_GPWR:
93     case SCOOP_GPRR:
94         return s->gpio_level;
95     default:
96         zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
97     }
98
99     return 0;
100 }
101
102 static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
103 {
104     ScoopInfo *s = (ScoopInfo *) opaque;
105     value &= 0xffff;
106
107     switch (addr) {
108     case SCOOP_MCR:
109         s->mcr = value;
110         break;
111     case SCOOP_CDR:
112         s->cdr = value;
113         break;
114     case SCOOP_CPR:
115         s->power = value;
116         if (value & 0x80)
117             s->power |= 0x8040;
118         break;
119     case SCOOP_CCR:
120         s->ccr = value;
121         break;
122     case SCOOP_IRR_IRM:
123         s->irr = value;
124         break;
125     case SCOOP_IMR:
126         s->imr = value;
127         break;
128     case SCOOP_ISR:
129         s->isr = value;
130         break;
131     case SCOOP_GPCR:
132         s->gpio_dir = value;
133         scoop_gpio_handler_update(s);
134         break;
135     case SCOOP_GPWR:
136     case SCOOP_GPRR:    /* GPRR is probably R/O in real HW */
137         s->gpio_level = value & s->gpio_dir;
138         scoop_gpio_handler_update(s);
139         break;
140     default:
141         zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
142     }
143 }
144
145 static CPUReadMemoryFunc * const scoop_readfn[] = {
146     scoop_readb,
147     scoop_readb,
148     scoop_readb,
149 };
150 static CPUWriteMemoryFunc * const scoop_writefn[] = {
151     scoop_writeb,
152     scoop_writeb,
153     scoop_writeb,
154 };
155
156 void scoop_gpio_set(void *opaque, int line, int level)
157 {
158     ScoopInfo *s = (ScoopInfo *) opaque;
159
160     if (level)
161         s->gpio_level |= (1 << line);
162     else
163         s->gpio_level &= ~(1 << line);
164 }
165
166 qemu_irq *scoop_gpio_in_get(ScoopInfo *s)
167 {
168     return s->in;
169 }
170
171 void scoop_gpio_out_set(ScoopInfo *s, int line,
172                 qemu_irq handler) {
173     if (line >= 16) {
174         fprintf(stderr, "No GPIO pin %i\n", line);
175         exit(-1);
176     }
177
178     s->handler[line] = handler;
179 }
180
181 static void scoop_save(QEMUFile *f, void *opaque)
182 {
183     ScoopInfo *s = (ScoopInfo *) opaque;
184     qemu_put_be16s(f, &s->status);
185     qemu_put_be16s(f, &s->power);
186     qemu_put_be32s(f, &s->gpio_level);
187     qemu_put_be32s(f, &s->gpio_dir);
188     qemu_put_be32s(f, &s->prev_level);
189     qemu_put_be16s(f, &s->mcr);
190     qemu_put_be16s(f, &s->cdr);
191     qemu_put_be16s(f, &s->ccr);
192     qemu_put_be16s(f, &s->irr);
193     qemu_put_be16s(f, &s->imr);
194     qemu_put_be16s(f, &s->isr);
195 }
196
197 static int scoop_load(QEMUFile *f, void *opaque, int version_id)
198 {
199     uint16_t dummy;
200     ScoopInfo *s = (ScoopInfo *) opaque;
201     qemu_get_be16s(f, &s->status);
202     qemu_get_be16s(f, &s->power);
203     qemu_get_be32s(f, &s->gpio_level);
204     qemu_get_be32s(f, &s->gpio_dir);
205     qemu_get_be32s(f, &s->prev_level);
206     qemu_get_be16s(f, &s->mcr);
207     qemu_get_be16s(f, &s->cdr);
208     qemu_get_be16s(f, &s->ccr);
209     qemu_get_be16s(f, &s->irr);
210     qemu_get_be16s(f, &s->imr);
211     qemu_get_be16s(f, &s->isr);
212     if (version_id < 1)
213             qemu_get_be16s(f, &dummy);
214
215     return 0;
216 }
217
218 ScoopInfo *scoop_init(PXA2xxState *cpu,
219                 int instance,
220                 target_phys_addr_t target_base) {
221     int iomemtype;
222     ScoopInfo *s;
223
224     s = (ScoopInfo *)
225             qemu_mallocz(sizeof(ScoopInfo));
226     memset(s, 0, sizeof(ScoopInfo));
227
228     s->status = 0x02;
229     s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16);
230     iomemtype = cpu_register_io_memory(scoop_readfn,
231                     scoop_writefn, s);
232     cpu_register_physical_memory(target_base, 0x1000, iomemtype);
233     register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
234
235     return s;
236 }
237
238 /* Write the bootloader parameters memory area.  */
239
240 #define MAGIC_CHG(a, b, c, d)   ((d << 24) | (c << 16) | (b << 8) | a)
241
242 static struct __attribute__ ((__packed__)) sl_param_info {
243     uint32_t comadj_keyword;
244     int32_t comadj;
245
246     uint32_t uuid_keyword;
247     char uuid[16];
248
249     uint32_t touch_keyword;
250     int32_t touch_xp;
251     int32_t touch_yp;
252     int32_t touch_xd;
253     int32_t touch_yd;
254
255     uint32_t adadj_keyword;
256     int32_t adadj;
257
258     uint32_t phad_keyword;
259     int32_t phadadj;
260 } zaurus_bootparam = {
261     .comadj_keyword     = MAGIC_CHG('C', 'M', 'A', 'D'),
262     .comadj             = 125,
263     .uuid_keyword       = MAGIC_CHG('U', 'U', 'I', 'D'),
264     .uuid               = { -1 },
265     .touch_keyword      = MAGIC_CHG('T', 'U', 'C', 'H'),
266     .touch_xp           = -1,
267     .adadj_keyword      = MAGIC_CHG('B', 'V', 'A', 'D'),
268     .adadj              = -1,
269     .phad_keyword       = MAGIC_CHG('P', 'H', 'A', 'D'),
270     .phadadj            = 0x01,
271 };
272
273 void sl_bootparam_write(target_phys_addr_t ptr)
274 {
275     cpu_physical_memory_write(ptr, (void *)&zaurus_bootparam,
276                               sizeof(struct sl_param_info));
277 }