]> git.proxmox.com Git - qemu.git/blame - hw/omap.c
Fix incompatible declaration in previous commit.
[qemu.git] / hw / omap.c
CommitLineData
c3d2689d
AZ
1/*
2 * TI OMAP processors emulation.
3 *
4 * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
87ecb68b
PB
21#include "hw.h"
22#include "arm-misc.h"
23#include "omap.h"
24#include "sysemu.h"
25#include "qemu-timer.h"
26/* We use pc-style serial ports. */
27#include "pc.h"
c3d2689d
AZ
28
29/* Should signal the TCMI */
66450b15
AZ
30uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
31{
02645926
AZ
32 uint8_t ret;
33
66450b15 34 OMAP_8B_REG(addr);
b854bc19 35 cpu_physical_memory_read(addr, (void *) &ret, 1);
02645926 36 return ret;
66450b15
AZ
37}
38
39void omap_badwidth_write8(void *opaque, target_phys_addr_t addr,
40 uint32_t value)
41{
b854bc19
AZ
42 uint8_t val8 = value;
43
66450b15 44 OMAP_8B_REG(addr);
b854bc19 45 cpu_physical_memory_write(addr, (void *) &val8, 1);
66450b15
AZ
46}
47
b30bb3a2 48uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr)
c3d2689d 49{
b854bc19
AZ
50 uint16_t ret;
51
c3d2689d 52 OMAP_16B_REG(addr);
b854bc19
AZ
53 cpu_physical_memory_read(addr, (void *) &ret, 2);
54 return ret;
c3d2689d
AZ
55}
56
b30bb3a2 57void omap_badwidth_write16(void *opaque, target_phys_addr_t addr,
c3d2689d
AZ
58 uint32_t value)
59{
b854bc19
AZ
60 uint16_t val16 = value;
61
c3d2689d 62 OMAP_16B_REG(addr);
b854bc19 63 cpu_physical_memory_write(addr, (void *) &val16, 2);
c3d2689d
AZ
64}
65
b30bb3a2 66uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr)
c3d2689d 67{
b854bc19
AZ
68 uint32_t ret;
69
c3d2689d 70 OMAP_32B_REG(addr);
b854bc19
AZ
71 cpu_physical_memory_read(addr, (void *) &ret, 4);
72 return ret;
c3d2689d
AZ
73}
74
b30bb3a2 75void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
c3d2689d
AZ
76 uint32_t value)
77{
78 OMAP_32B_REG(addr);
b854bc19 79 cpu_physical_memory_write(addr, (void *) &value, 4);
c3d2689d
AZ
80}
81
c3d2689d 82/* Interrupt Handlers */
106627d0 83struct omap_intr_handler_bank_s {
c3d2689d 84 uint32_t irqs;
106627d0 85 uint32_t inputs;
c3d2689d 86 uint32_t mask;
c3d2689d 87 uint32_t fiq;
106627d0
AZ
88 uint32_t sens_edge;
89 unsigned char priority[32];
c3d2689d
AZ
90};
91
106627d0
AZ
92struct omap_intr_handler_s {
93 qemu_irq *pins;
94 qemu_irq parent_intr[2];
95 target_phys_addr_t base;
96 unsigned char nbanks;
c3d2689d 97
106627d0
AZ
98 /* state */
99 uint32_t new_agr[2];
100 int sir_intr[2];
101 struct omap_intr_handler_bank_s banks[];
102};
c3d2689d 103
106627d0
AZ
104static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
105{
106 int i, j, sir_intr, p_intr, p, f;
107 uint32_t level;
108 sir_intr = 0;
109 p_intr = 255;
110
111 /* Find the interrupt line with the highest dynamic priority.
112 * Note: 0 denotes the hightest priority.
113 * If all interrupts have the same priority, the default order is IRQ_N,
114 * IRQ_N-1,...,IRQ_0. */
115 for (j = 0; j < s->nbanks; ++j) {
116 level = s->banks[j].irqs & ~s->banks[j].mask &
117 (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq);
118 for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
119 level >>= f) {
120 p = s->banks[j].priority[i];
121 if (p <= p_intr) {
122 p_intr = p;
123 sir_intr = 32 * j + i;
124 }
125 f = ffs(level >> 1);
126 }
cfa0b71d 127 }
106627d0 128 s->sir_intr[is_fiq] = sir_intr;
c3d2689d
AZ
129}
130
106627d0 131static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
c3d2689d 132{
106627d0
AZ
133 int i;
134 uint32_t has_intr = 0;
c3d2689d 135
106627d0
AZ
136 for (i = 0; i < s->nbanks; ++i)
137 has_intr |= s->banks[i].irqs & ~s->banks[i].mask &
138 (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq);
c3d2689d 139
106627d0
AZ
140 if (s->new_agr[is_fiq] && has_intr) {
141 s->new_agr[is_fiq] = 0;
142 omap_inth_sir_update(s, is_fiq);
143 qemu_set_irq(s->parent_intr[is_fiq], 1);
c3d2689d 144 }
c3d2689d
AZ
145}
146
147#define INT_FALLING_EDGE 0
148#define INT_LOW_LEVEL 1
149
150static void omap_set_intr(void *opaque, int irq, int req)
151{
152 struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
153 uint32_t rise;
154
106627d0
AZ
155 struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5];
156 int n = irq & 31;
157
c3d2689d 158 if (req) {
106627d0
AZ
159 rise = ~bank->irqs & (1 << n);
160 if (~bank->sens_edge & (1 << n))
161 rise &= ~bank->inputs & (1 << n);
162
163 bank->inputs |= (1 << n);
164 if (rise) {
165 bank->irqs |= rise;
166 omap_inth_update(ih, 0);
167 omap_inth_update(ih, 1);
168 }
c3d2689d 169 } else {
106627d0
AZ
170 rise = bank->sens_edge & bank->irqs & (1 << n);
171 bank->irqs &= ~rise;
172 bank->inputs &= ~(1 << n);
c3d2689d
AZ
173 }
174}
175
176static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
177{
178 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
179 int i, offset = addr - s->base;
106627d0
AZ
180 int bank_no = offset >> 8;
181 int line_no;
182 struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
183 offset &= 0xff;
c3d2689d
AZ
184
185 switch (offset) {
186 case 0x00: /* ITR */
106627d0 187 return bank->irqs;
c3d2689d
AZ
188
189 case 0x04: /* MIR */
106627d0 190 return bank->mask;
c3d2689d
AZ
191
192 case 0x10: /* SIR_IRQ_CODE */
106627d0
AZ
193 case 0x14: /* SIR_FIQ_CODE */
194 if (bank_no != 0)
195 break;
196 line_no = s->sir_intr[(offset - 0x10) >> 2];
197 bank = &s->banks[line_no >> 5];
198 i = line_no & 31;
199 if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
200 bank->irqs &= ~(1 << i);
f2df5260 201 return line_no;
c3d2689d
AZ
202
203 case 0x18: /* CONTROL_REG */
106627d0
AZ
204 if (bank_no != 0)
205 break;
c3d2689d
AZ
206 return 0;
207
208 case 0x1c: /* ILR0 */
209 case 0x20: /* ILR1 */
210 case 0x24: /* ILR2 */
211 case 0x28: /* ILR3 */
212 case 0x2c: /* ILR4 */
213 case 0x30: /* ILR5 */
214 case 0x34: /* ILR6 */
215 case 0x38: /* ILR7 */
216 case 0x3c: /* ILR8 */
217 case 0x40: /* ILR9 */
218 case 0x44: /* ILR10 */
219 case 0x48: /* ILR11 */
220 case 0x4c: /* ILR12 */
221 case 0x50: /* ILR13 */
222 case 0x54: /* ILR14 */
223 case 0x58: /* ILR15 */
224 case 0x5c: /* ILR16 */
225 case 0x60: /* ILR17 */
226 case 0x64: /* ILR18 */
227 case 0x68: /* ILR19 */
228 case 0x6c: /* ILR20 */
229 case 0x70: /* ILR21 */
230 case 0x74: /* ILR22 */
231 case 0x78: /* ILR23 */
232 case 0x7c: /* ILR24 */
233 case 0x80: /* ILR25 */
234 case 0x84: /* ILR26 */
235 case 0x88: /* ILR27 */
236 case 0x8c: /* ILR28 */
237 case 0x90: /* ILR29 */
238 case 0x94: /* ILR30 */
239 case 0x98: /* ILR31 */
240 i = (offset - 0x1c) >> 2;
106627d0
AZ
241 return (bank->priority[i] << 2) |
242 (((bank->sens_edge >> i) & 1) << 1) |
243 ((bank->fiq >> i) & 1);
c3d2689d
AZ
244
245 case 0x9c: /* ISR */
246 return 0x00000000;
247
c3d2689d 248 }
106627d0 249 OMAP_BAD_REG(addr);
c3d2689d
AZ
250 return 0;
251}
252
253static void omap_inth_write(void *opaque, target_phys_addr_t addr,
254 uint32_t value)
255{
256 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
257 int i, offset = addr - s->base;
106627d0
AZ
258 int bank_no = offset >> 8;
259 struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
260 offset &= 0xff;
c3d2689d
AZ
261
262 switch (offset) {
263 case 0x00: /* ITR */
106627d0
AZ
264 /* Important: ignore the clearing if the IRQ is level-triggered and
265 the input bit is 1 */
266 bank->irqs &= value | (bank->inputs & bank->sens_edge);
c3d2689d
AZ
267 return;
268
269 case 0x04: /* MIR */
106627d0
AZ
270 bank->mask = value;
271 omap_inth_update(s, 0);
272 omap_inth_update(s, 1);
c3d2689d
AZ
273 return;
274
275 case 0x10: /* SIR_IRQ_CODE */
276 case 0x14: /* SIR_FIQ_CODE */
277 OMAP_RO_REG(addr);
278 break;
279
280 case 0x18: /* CONTROL_REG */
106627d0
AZ
281 if (bank_no != 0)
282 break;
283 if (value & 2) {
284 qemu_set_irq(s->parent_intr[1], 0);
285 s->new_agr[1] = ~0;
286 omap_inth_update(s, 1);
287 }
288 if (value & 1) {
289 qemu_set_irq(s->parent_intr[0], 0);
290 s->new_agr[0] = ~0;
291 omap_inth_update(s, 0);
292 }
c3d2689d
AZ
293 return;
294
295 case 0x1c: /* ILR0 */
296 case 0x20: /* ILR1 */
297 case 0x24: /* ILR2 */
298 case 0x28: /* ILR3 */
299 case 0x2c: /* ILR4 */
300 case 0x30: /* ILR5 */
301 case 0x34: /* ILR6 */
302 case 0x38: /* ILR7 */
303 case 0x3c: /* ILR8 */
304 case 0x40: /* ILR9 */
305 case 0x44: /* ILR10 */
306 case 0x48: /* ILR11 */
307 case 0x4c: /* ILR12 */
308 case 0x50: /* ILR13 */
309 case 0x54: /* ILR14 */
310 case 0x58: /* ILR15 */
311 case 0x5c: /* ILR16 */
312 case 0x60: /* ILR17 */
313 case 0x64: /* ILR18 */
314 case 0x68: /* ILR19 */
315 case 0x6c: /* ILR20 */
316 case 0x70: /* ILR21 */
317 case 0x74: /* ILR22 */
318 case 0x78: /* ILR23 */
319 case 0x7c: /* ILR24 */
320 case 0x80: /* ILR25 */
321 case 0x84: /* ILR26 */
322 case 0x88: /* ILR27 */
323 case 0x8c: /* ILR28 */
324 case 0x90: /* ILR29 */
325 case 0x94: /* ILR30 */
326 case 0x98: /* ILR31 */
327 i = (offset - 0x1c) >> 2;
106627d0
AZ
328 bank->priority[i] = (value >> 2) & 0x1f;
329 bank->sens_edge &= ~(1 << i);
330 bank->sens_edge |= ((value >> 1) & 1) << i;
331 bank->fiq &= ~(1 << i);
332 bank->fiq |= (value & 1) << i;
c3d2689d
AZ
333 return;
334
335 case 0x9c: /* ISR */
336 for (i = 0; i < 32; i ++)
337 if (value & (1 << i)) {
106627d0 338 omap_set_intr(s, 32 * bank_no + i, 1);
c3d2689d
AZ
339 return;
340 }
341 return;
c3d2689d 342 }
106627d0 343 OMAP_BAD_REG(addr);
c3d2689d
AZ
344}
345
346static CPUReadMemoryFunc *omap_inth_readfn[] = {
347 omap_badwidth_read32,
348 omap_badwidth_read32,
349 omap_inth_read,
350};
351
352static CPUWriteMemoryFunc *omap_inth_writefn[] = {
353 omap_inth_write,
354 omap_inth_write,
355 omap_inth_write,
356};
357
106627d0 358void omap_inth_reset(struct omap_intr_handler_s *s)
c3d2689d 359{
106627d0
AZ
360 int i;
361
362 for (i = 0; i < s->nbanks; ++i){
363 s->banks[i].irqs = 0x00000000;
364 s->banks[i].mask = 0xffffffff;
365 s->banks[i].sens_edge = 0x00000000;
366 s->banks[i].fiq = 0x00000000;
367 s->banks[i].inputs = 0x00000000;
368 memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority));
369 }
c3d2689d 370
106627d0
AZ
371 s->new_agr[0] = ~0;
372 s->new_agr[1] = ~0;
373 s->sir_intr[0] = 0;
374 s->sir_intr[1] = 0;
375
376 qemu_set_irq(s->parent_intr[0], 0);
377 qemu_set_irq(s->parent_intr[1], 0);
c3d2689d
AZ
378}
379
380struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
106627d0
AZ
381 unsigned long size, unsigned char nbanks,
382 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
c3d2689d
AZ
383{
384 int iomemtype;
385 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
106627d0
AZ
386 qemu_mallocz(sizeof(struct omap_intr_handler_s) +
387 sizeof(struct omap_intr_handler_bank_s) * nbanks);
c3d2689d 388
106627d0
AZ
389 s->parent_intr[0] = parent_irq;
390 s->parent_intr[1] = parent_fiq;
c3d2689d 391 s->base = base;
106627d0
AZ
392 s->nbanks = nbanks;
393 s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
394
c3d2689d
AZ
395 omap_inth_reset(s);
396
397 iomemtype = cpu_register_io_memory(0, omap_inth_readfn,
398 omap_inth_writefn, s);
399 cpu_register_physical_memory(s->base, size, iomemtype);
400
401 return s;
402}
403
404/* OMAP1 DMA module */
c3d2689d 405struct omap_dma_channel_s {
089b7c0a 406 /* transfer data */
c3d2689d
AZ
407 int burst[2];
408 int pack[2];
409 enum omap_dma_port port[2];
410 target_phys_addr_t addr[2];
411 omap_dma_addressing_t mode[2];
089b7c0a
AZ
412 uint16_t elements;
413 uint16_t frames;
414 int16_t frame_index[2];
415 int16_t element_index[2];
c3d2689d 416 int data_type;
089b7c0a
AZ
417
418 /* transfer type */
419 int transparent_copy;
420 int constant_fill;
421 uint32_t color;
422
423 /* auto init and linked channel data */
c3d2689d
AZ
424 int end_prog;
425 int repeat;
426 int auto_init;
089b7c0a
AZ
427 int link_enabled;
428 int link_next_ch;
429
430 /* interruption data */
c3d2689d
AZ
431 int interrupts;
432 int status;
089b7c0a
AZ
433
434 /* state data */
435 int active;
436 int enable;
437 int sync;
438 int pending_request;
439 int waiting_end_prog;
c3d2689d
AZ
440 uint16_t cpc;
441
089b7c0a
AZ
442 /* sync type */
443 int fs;
444 int bs;
445
446 /* compatibility */
447 int omap_3_1_compatible_disable;
448
11e0fc3f
AZ
449 qemu_irq irq;
450 struct omap_dma_channel_s *sibling;
451
c3d2689d
AZ
452 struct omap_dma_reg_set_s {
453 target_phys_addr_t src, dest;
454 int frame;
455 int element;
456 int frame_delta[2];
457 int elem_delta[2];
458 int frames;
459 int elements;
460 } active_set;
089b7c0a
AZ
461
462 /* unused parameters */
463 int priority;
464 int interleave_disabled;
465 int type;
c3d2689d
AZ
466};
467
468struct omap_dma_s {
c3d2689d
AZ
469 QEMUTimer *tm;
470 struct omap_mpu_state_s *mpu;
471 target_phys_addr_t base;
472 omap_clk clk;
473 int64_t delay;
1af2b62d 474 uint32_t drq;
089b7c0a
AZ
475 enum omap_dma_model model;
476 int omap_3_1_mapping_disabled;
c3d2689d
AZ
477
478 uint16_t gcr;
479 int run_count;
480
481 int chans;
482 struct omap_dma_channel_s ch[16];
483 struct omap_dma_lcd_channel_s lcd_ch;
484};
485
089b7c0a
AZ
486/* Interrupts */
487#define TIMEOUT_INTR (1 << 0)
488#define EVENT_DROP_INTR (1 << 1)
489#define HALF_FRAME_INTR (1 << 2)
490#define END_FRAME_INTR (1 << 3)
491#define LAST_FRAME_INTR (1 << 4)
492#define END_BLOCK_INTR (1 << 5)
493#define SYNC (1 << 6)
494
c3d2689d
AZ
495static void omap_dma_interrupts_update(struct omap_dma_s *s)
496{
11e0fc3f
AZ
497 struct omap_dma_channel_s *ch = s->ch;
498 int i;
089b7c0a
AZ
499
500 if (s->omap_3_1_mapping_disabled) {
11e0fc3f
AZ
501 for (i = 0; i < s->chans; i ++, ch ++)
502 if (ch->status)
503 qemu_irq_raise(ch->irq);
089b7c0a
AZ
504 } else {
505 /* First three interrupts are shared between two channels each. */
11e0fc3f
AZ
506 for (i = 0; i < 6; i ++, ch ++) {
507 if (ch->status || (ch->sibling && ch->sibling->status))
508 qemu_irq_raise(ch->irq);
089b7c0a
AZ
509 }
510 }
c3d2689d
AZ
511}
512
11e0fc3f
AZ
513static void omap_dma_channel_load(struct omap_dma_s *s,
514 struct omap_dma_channel_s *ch)
c3d2689d 515{
11e0fc3f 516 struct omap_dma_reg_set_s *a = &ch->active_set;
c3d2689d 517 int i;
11e0fc3f 518 int omap_3_1 = !ch->omap_3_1_compatible_disable;
c3d2689d
AZ
519
520 /*
521 * TODO: verify address ranges and alignment
522 * TODO: port endianness
523 */
524
11e0fc3f
AZ
525 a->src = ch->addr[0];
526 a->dest = ch->addr[1];
527 a->frames = ch->frames;
528 a->elements = ch->elements;
c3d2689d
AZ
529 a->frame = 0;
530 a->element = 0;
531
11e0fc3f 532 if (unlikely(!ch->elements || !ch->frames)) {
c3d2689d
AZ
533 printf("%s: bad DMA request\n", __FUNCTION__);
534 return;
535 }
536
537 for (i = 0; i < 2; i ++)
11e0fc3f 538 switch (ch->mode[i]) {
c3d2689d
AZ
539 case constant:
540 a->elem_delta[i] = 0;
541 a->frame_delta[i] = 0;
542 break;
543 case post_incremented:
11e0fc3f 544 a->elem_delta[i] = ch->data_type;
c3d2689d
AZ
545 a->frame_delta[i] = 0;
546 break;
547 case single_index:
11e0fc3f
AZ
548 a->elem_delta[i] = ch->data_type +
549 ch->element_index[omap_3_1 ? 0 : i] - 1;
c3d2689d
AZ
550 a->frame_delta[i] = 0;
551 break;
552 case double_index:
11e0fc3f
AZ
553 a->elem_delta[i] = ch->data_type +
554 ch->element_index[omap_3_1 ? 0 : i] - 1;
555 a->frame_delta[i] = ch->frame_index[omap_3_1 ? 0 : i] -
556 ch->element_index[omap_3_1 ? 0 : i];
c3d2689d
AZ
557 break;
558 default:
559 break;
560 }
561}
562
11e0fc3f
AZ
563static void omap_dma_activate_channel(struct omap_dma_s *s,
564 struct omap_dma_channel_s *ch)
c3d2689d 565{
11e0fc3f
AZ
566 if (!ch->active) {
567 ch->active = 1;
568 if (ch->sync)
569 ch->status |= SYNC;
089b7c0a
AZ
570 s->run_count ++;
571 }
572
573 if (s->delay && !qemu_timer_pending(s->tm))
574 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
575}
576
11e0fc3f
AZ
577static void omap_dma_deactivate_channel(struct omap_dma_s *s,
578 struct omap_dma_channel_s *ch)
089b7c0a
AZ
579{
580 /* Update cpc */
11e0fc3f 581 ch->cpc = ch->active_set.dest & 0xffff;
089b7c0a 582
11e0fc3f 583 if (ch->pending_request && !ch->waiting_end_prog) {
089b7c0a 584 /* Don't deactivate the channel */
11e0fc3f 585 ch->pending_request = 0;
c3d2689d 586 return;
089b7c0a 587 }
c3d2689d 588
089b7c0a
AZ
589 /* Don't deactive the channel if it is synchronized and the DMA request is
590 active */
11e0fc3f 591 if (ch->sync && (s->drq & (1 << ch->sync)))
c3d2689d 592 return;
089b7c0a 593
11e0fc3f
AZ
594 if (ch->active) {
595 ch->active = 0;
596 ch->status &= ~SYNC;
089b7c0a 597 s->run_count --;
c3d2689d
AZ
598 }
599
089b7c0a
AZ
600 if (!s->run_count)
601 qemu_del_timer(s->tm);
602}
c3d2689d 603
11e0fc3f
AZ
604static void omap_dma_enable_channel(struct omap_dma_s *s,
605 struct omap_dma_channel_s *ch)
089b7c0a 606{
11e0fc3f
AZ
607 if (!ch->enable) {
608 ch->enable = 1;
609 ch->waiting_end_prog = 0;
610 omap_dma_channel_load(s, ch);
611 if ((!ch->sync) || (s->drq & (1 << ch->sync)))
612 omap_dma_activate_channel(s, ch);
089b7c0a
AZ
613 }
614}
c3d2689d 615
11e0fc3f
AZ
616static void omap_dma_disable_channel(struct omap_dma_s *s,
617 struct omap_dma_channel_s *ch)
089b7c0a 618{
11e0fc3f
AZ
619 if (ch->enable) {
620 ch->enable = 0;
089b7c0a 621 /* Discard any pending request */
11e0fc3f
AZ
622 ch->pending_request = 0;
623 omap_dma_deactivate_channel(s, ch);
089b7c0a
AZ
624 }
625}
c3d2689d 626
11e0fc3f
AZ
627static void omap_dma_channel_end_prog(struct omap_dma_s *s,
628 struct omap_dma_channel_s *ch)
089b7c0a 629{
11e0fc3f
AZ
630 if (ch->waiting_end_prog) {
631 ch->waiting_end_prog = 0;
632 if (!ch->sync || ch->pending_request) {
633 ch->pending_request = 0;
634 omap_dma_activate_channel(s, ch);
089b7c0a 635 }
c3d2689d
AZ
636 }
637}
638
089b7c0a 639static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
c3d2689d 640{
089b7c0a
AZ
641 s->omap_3_1_mapping_disabled = 0;
642 s->chans = 9;
643}
c3d2689d 644
089b7c0a
AZ
645static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
646{
647 s->omap_3_1_mapping_disabled = 1;
648 s->chans = 16;
649}
650
651static void omap_dma_process_request(struct omap_dma_s *s, int request)
652{
653 int channel;
654 int drop_event = 0;
11e0fc3f
AZ
655 struct omap_dma_channel_s *ch = s->ch;
656
657 for (channel = 0; channel < s->chans; channel ++, ch ++) {
658 if (ch->enable && ch->sync == request) {
659 if (!ch->active)
660 omap_dma_activate_channel(s, ch);
661 else if (!ch->pending_request)
662 ch->pending_request = 1;
089b7c0a
AZ
663 else {
664 /* Request collision */
665 /* Second request received while processing other request */
11e0fc3f 666 ch->status |= EVENT_DROP_INTR;
089b7c0a
AZ
667 drop_event = 1;
668 }
669 }
670 }
671
672 if (drop_event)
673 omap_dma_interrupts_update(s);
c3d2689d
AZ
674}
675
676static void omap_dma_channel_run(struct omap_dma_s *s)
677{
11e0fc3f 678 int n = s->chans;
c3d2689d
AZ
679 uint16_t status;
680 uint8_t value[4];
681 struct omap_dma_port_if_s *src_p, *dest_p;
682 struct omap_dma_reg_set_s *a;
11e0fc3f 683 struct omap_dma_channel_s *ch;
c3d2689d 684
11e0fc3f
AZ
685 for (ch = s->ch; n; n --, ch ++) {
686 if (!ch->active)
089b7c0a
AZ
687 continue;
688
11e0fc3f 689 a = &ch->active_set;
c3d2689d 690
11e0fc3f
AZ
691 src_p = &s->mpu->port[ch->port[0]];
692 dest_p = &s->mpu->port[ch->port[1]];
693 if ((!ch->constant_fill && !src_p->addr_valid(s->mpu, a->src)) ||
089b7c0a 694 (!dest_p->addr_valid(s->mpu, a->dest))) {
c3d2689d
AZ
695#if 0
696 /* Bus time-out */
11e0fc3f
AZ
697 if (ch->interrupts & TIMEOUT_INTR)
698 ch->status |= TIMEOUT_INTR;
089b7c0a 699 omap_dma_deactivate_channel(s, ch);
c3d2689d
AZ
700 continue;
701#endif
11e0fc3f
AZ
702 printf("%s: Bus time-out in DMA%i operation\n",
703 __FUNCTION__, s->chans - n);
c3d2689d
AZ
704 }
705
11e0fc3f
AZ
706 status = ch->status;
707 while (status == ch->status && ch->active) {
c3d2689d 708 /* Transfer a single element */
089b7c0a 709 /* FIXME: check the endianness */
11e0fc3f
AZ
710 if (!ch->constant_fill)
711 cpu_physical_memory_read(a->src, value, ch->data_type);
089b7c0a 712 else
11e0fc3f 713 *(uint32_t *) value = ch->color;
089b7c0a 714
11e0fc3f
AZ
715 if (!ch->transparent_copy ||
716 *(uint32_t *) value != ch->color)
717 cpu_physical_memory_write(a->dest, value, ch->data_type);
c3d2689d
AZ
718
719 a->src += a->elem_delta[0];
720 a->dest += a->elem_delta[1];
721 a->element ++;
722
089b7c0a 723 /* If the channel is element synchronized, deactivate it */
11e0fc3f 724 if (ch->sync && !ch->fs && !ch->bs)
089b7c0a
AZ
725 omap_dma_deactivate_channel(s, ch);
726
727 /* If it is the last frame, set the LAST_FRAME interrupt */
728 if (a->element == 1 && a->frame == a->frames - 1)
11e0fc3f
AZ
729 if (ch->interrupts & LAST_FRAME_INTR)
730 ch->status |= LAST_FRAME_INTR;
089b7c0a
AZ
731
732 /* If the half of the frame was reached, set the HALF_FRAME
733 interrupt */
734 if (a->element == (a->elements >> 1))
11e0fc3f
AZ
735 if (ch->interrupts & HALF_FRAME_INTR)
736 ch->status |= HALF_FRAME_INTR;
089b7c0a 737
c3d2689d 738 if (a->element == a->elements) {
089b7c0a 739 /* End of Frame */
c3d2689d
AZ
740 a->element = 0;
741 a->src += a->frame_delta[0];
742 a->dest += a->frame_delta[1];
743 a->frame ++;
744
089b7c0a 745 /* If the channel is frame synchronized, deactivate it */
11e0fc3f 746 if (ch->sync && ch->fs)
089b7c0a 747 omap_dma_deactivate_channel(s, ch);
c3d2689d 748
089b7c0a 749 /* If the channel is async, update cpc */
11e0fc3f
AZ
750 if (!ch->sync)
751 ch->cpc = a->dest & 0xffff;
c3d2689d 752
089b7c0a 753 /* Set the END_FRAME interrupt */
11e0fc3f
AZ
754 if (ch->interrupts & END_FRAME_INTR)
755 ch->status |= END_FRAME_INTR;
c3d2689d 756
089b7c0a
AZ
757 if (a->frame == a->frames) {
758 /* End of Block */
759 /* Disable the channel */
760
11e0fc3f 761 if (ch->omap_3_1_compatible_disable) {
089b7c0a 762 omap_dma_disable_channel(s, ch);
11e0fc3f
AZ
763 if (ch->link_enabled)
764 omap_dma_enable_channel(s,
765 &s->ch[ch->link_next_ch]);
089b7c0a 766 } else {
11e0fc3f 767 if (!ch->auto_init)
089b7c0a 768 omap_dma_disable_channel(s, ch);
11e0fc3f 769 else if (ch->repeat || ch->end_prog)
089b7c0a
AZ
770 omap_dma_channel_load(s, ch);
771 else {
11e0fc3f 772 ch->waiting_end_prog = 1;
089b7c0a
AZ
773 omap_dma_deactivate_channel(s, ch);
774 }
775 }
776
11e0fc3f
AZ
777 if (ch->interrupts & END_BLOCK_INTR)
778 ch->status |= END_BLOCK_INTR;
c3d2689d
AZ
779 }
780 }
c3d2689d 781 }
c3d2689d
AZ
782 }
783
784 omap_dma_interrupts_update(s);
785 if (s->run_count && s->delay)
786 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
787}
788
089b7c0a
AZ
789static void omap_dma_reset(struct omap_dma_s *s)
790{
791 int i;
792
793 qemu_del_timer(s->tm);
794 s->gcr = 0x0004;
795 s->drq = 0x00000000;
796 s->run_count = 0;
797 s->lcd_ch.src = emiff;
798 s->lcd_ch.condition = 0;
799 s->lcd_ch.interrupts = 0;
800 s->lcd_ch.dual = 0;
801 omap_dma_enable_3_1_mapping(s);
11e0fc3f
AZ
802 for (i = 0; i < s->chans; i ++) {
803 memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst));
804 memset(&s->ch[i].port, 0, sizeof(s->ch[i].port));
805 memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode));
806 memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements));
807 memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames));
808 memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index));
809 memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index));
810 memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type));
811 memset(&s->ch[i].transparent_copy, 0,
812 sizeof(s->ch[i].transparent_copy));
813 memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill));
814 memset(&s->ch[i].color, 0, sizeof(s->ch[i].color));
815 memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog));
816 memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat));
817 memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init));
818 memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled));
819 memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch));
089b7c0a 820 s->ch[i].interrupts = 0x0003;
11e0fc3f
AZ
821 memset(&s->ch[i].status, 0, sizeof(s->ch[i].status));
822 memset(&s->ch[i].active, 0, sizeof(s->ch[i].active));
823 memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable));
824 memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync));
825 memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request));
826 memset(&s->ch[i].waiting_end_prog, 0,
827 sizeof(s->ch[i].waiting_end_prog));
828 memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc));
829 memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs));
830 memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs));
831 memset(&s->ch[i].omap_3_1_compatible_disable, 0,
832 sizeof(s->ch[i].omap_3_1_compatible_disable));
833 memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set));
834 memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority));
835 memset(&s->ch[i].interleave_disabled, 0,
836 sizeof(s->ch[i].interleave_disabled));
837 memset(&s->ch[i].type, 0, sizeof(s->ch[i].type));
838 }
089b7c0a
AZ
839}
840
11e0fc3f
AZ
841static int omap_dma_ch_reg_read(struct omap_dma_s *s,
842 struct omap_dma_channel_s *ch, int reg, uint16_t *value)
089b7c0a 843{
c3d2689d
AZ
844 switch (reg) {
845 case 0x00: /* SYS_DMA_CSDP_CH0 */
11e0fc3f
AZ
846 *value = (ch->burst[1] << 14) |
847 (ch->pack[1] << 13) |
848 (ch->port[1] << 9) |
849 (ch->burst[0] << 7) |
850 (ch->pack[0] << 6) |
851 (ch->port[0] << 2) |
852 (ch->data_type >> 1);
c3d2689d
AZ
853 break;
854
855 case 0x02: /* SYS_DMA_CCR_CH0 */
089b7c0a 856 if (s->model == omap_dma_3_1)
11e0fc3f 857 *value = 0 << 10; /* FIFO_FLUSH reads as 0 */
089b7c0a 858 else
11e0fc3f
AZ
859 *value = ch->omap_3_1_compatible_disable << 10;
860 *value |= (ch->mode[1] << 14) |
861 (ch->mode[0] << 12) |
862 (ch->end_prog << 11) |
863 (ch->repeat << 9) |
864 (ch->auto_init << 8) |
865 (ch->enable << 7) |
866 (ch->priority << 6) |
867 (ch->fs << 5) | ch->sync;
c3d2689d
AZ
868 break;
869
870 case 0x04: /* SYS_DMA_CICR_CH0 */
11e0fc3f 871 *value = ch->interrupts;
c3d2689d
AZ
872 break;
873
874 case 0x06: /* SYS_DMA_CSR_CH0 */
11e0fc3f
AZ
875 *value = ch->status;
876 ch->status &= SYNC;
877 if (!ch->omap_3_1_compatible_disable && ch->sibling) {
878 *value |= (ch->sibling->status & 0x3f) << 6;
879 ch->sibling->status &= SYNC;
089b7c0a 880 }
11e0fc3f 881 qemu_irq_lower(ch->irq);
c3d2689d
AZ
882 break;
883
884 case 0x08: /* SYS_DMA_CSSA_L_CH0 */
11e0fc3f 885 *value = ch->addr[0] & 0x0000ffff;
c3d2689d
AZ
886 break;
887
888 case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
11e0fc3f 889 *value = ch->addr[0] >> 16;
c3d2689d
AZ
890 break;
891
892 case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
11e0fc3f 893 *value = ch->addr[1] & 0x0000ffff;
c3d2689d
AZ
894 break;
895
896 case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
11e0fc3f 897 *value = ch->addr[1] >> 16;
c3d2689d
AZ
898 break;
899
900 case 0x10: /* SYS_DMA_CEN_CH0 */
11e0fc3f 901 *value = ch->elements;
c3d2689d
AZ
902 break;
903
904 case 0x12: /* SYS_DMA_CFN_CH0 */
11e0fc3f 905 *value = ch->frames;
c3d2689d
AZ
906 break;
907
908 case 0x14: /* SYS_DMA_CFI_CH0 */
11e0fc3f 909 *value = ch->frame_index[0];
c3d2689d
AZ
910 break;
911
912 case 0x16: /* SYS_DMA_CEI_CH0 */
11e0fc3f 913 *value = ch->element_index[0];
089b7c0a
AZ
914 break;
915
916 case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
11e0fc3f
AZ
917 if (ch->omap_3_1_compatible_disable)
918 *value = ch->active_set.src & 0xffff; /* CSAC */
089b7c0a 919 else
11e0fc3f 920 *value = ch->cpc;
089b7c0a
AZ
921 break;
922
923 case 0x1a: /* DMA_CDAC */
11e0fc3f 924 *value = ch->active_set.dest & 0xffff; /* CDAC */
089b7c0a
AZ
925 break;
926
927 case 0x1c: /* DMA_CDEI */
11e0fc3f 928 *value = ch->element_index[1];
089b7c0a
AZ
929 break;
930
931 case 0x1e: /* DMA_CDFI */
11e0fc3f 932 *value = ch->frame_index[1];
089b7c0a
AZ
933 break;
934
935 case 0x20: /* DMA_COLOR_L */
11e0fc3f 936 *value = ch->color & 0xffff;
089b7c0a
AZ
937 break;
938
939 case 0x22: /* DMA_COLOR_U */
11e0fc3f 940 *value = ch->color >> 16;
c3d2689d
AZ
941 break;
942
089b7c0a 943 case 0x24: /* DMA_CCR2 */
11e0fc3f
AZ
944 *value = (ch->bs << 2) |
945 (ch->transparent_copy << 1) |
946 ch->constant_fill;
089b7c0a
AZ
947 break;
948
949 case 0x28: /* DMA_CLNK_CTRL */
11e0fc3f
AZ
950 *value = (ch->link_enabled << 15) |
951 (ch->link_next_ch & 0xf);
089b7c0a
AZ
952 break;
953
954 case 0x2a: /* DMA_LCH_CTRL */
11e0fc3f
AZ
955 *value = (ch->interleave_disabled << 15) |
956 ch->type;
c3d2689d
AZ
957 break;
958
959 default:
960 return 1;
961 }
962 return 0;
963}
964
965static int omap_dma_ch_reg_write(struct omap_dma_s *s,
11e0fc3f 966 struct omap_dma_channel_s *ch, int reg, uint16_t value)
089b7c0a 967{
c3d2689d
AZ
968 switch (reg) {
969 case 0x00: /* SYS_DMA_CSDP_CH0 */
11e0fc3f
AZ
970 ch->burst[1] = (value & 0xc000) >> 14;
971 ch->pack[1] = (value & 0x2000) >> 13;
972 ch->port[1] = (enum omap_dma_port) ((value & 0x1e00) >> 9);
973 ch->burst[0] = (value & 0x0180) >> 7;
974 ch->pack[0] = (value & 0x0040) >> 6;
975 ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
976 ch->data_type = (1 << (value & 3));
977 if (ch->port[0] >= omap_dma_port_last)
c3d2689d 978 printf("%s: invalid DMA port %i\n", __FUNCTION__,
11e0fc3f
AZ
979 ch->port[0]);
980 if (ch->port[1] >= omap_dma_port_last)
c3d2689d 981 printf("%s: invalid DMA port %i\n", __FUNCTION__,
11e0fc3f 982 ch->port[1]);
c3d2689d 983 if ((value & 3) == 3)
11e0fc3f 984 printf("%s: bad data_type for DMA channel\n", __FUNCTION__);
c3d2689d
AZ
985 break;
986
987 case 0x02: /* SYS_DMA_CCR_CH0 */
11e0fc3f
AZ
988 ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
989 ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
990 ch->end_prog = (value & 0x0800) >> 11;
089b7c0a 991 if (s->model > omap_dma_3_1)
11e0fc3f
AZ
992 ch->omap_3_1_compatible_disable = (value >> 10) & 0x1;
993 ch->repeat = (value & 0x0200) >> 9;
994 ch->auto_init = (value & 0x0100) >> 8;
995 ch->priority = (value & 0x0040) >> 6;
996 ch->fs = (value & 0x0020) >> 5;
997 ch->sync = value & 0x001f;
089b7c0a
AZ
998
999 if (value & 0x0080)
1000 omap_dma_enable_channel(s, ch);
1001 else
1002 omap_dma_disable_channel(s, ch);
1003
11e0fc3f 1004 if (ch->end_prog)
089b7c0a
AZ
1005 omap_dma_channel_end_prog(s, ch);
1006
c3d2689d
AZ
1007 break;
1008
1009 case 0x04: /* SYS_DMA_CICR_CH0 */
11e0fc3f 1010 ch->interrupts = value;
c3d2689d
AZ
1011 break;
1012
1013 case 0x06: /* SYS_DMA_CSR_CH0 */
11e0fc3f
AZ
1014 OMAP_RO_REG((target_phys_addr_t) reg);
1015 break;
c3d2689d
AZ
1016
1017 case 0x08: /* SYS_DMA_CSSA_L_CH0 */
11e0fc3f
AZ
1018 ch->addr[0] &= 0xffff0000;
1019 ch->addr[0] |= value;
c3d2689d
AZ
1020 break;
1021
1022 case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
11e0fc3f
AZ
1023 ch->addr[0] &= 0x0000ffff;
1024 ch->addr[0] |= (uint32_t) value << 16;
c3d2689d
AZ
1025 break;
1026
1027 case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
11e0fc3f
AZ
1028 ch->addr[1] &= 0xffff0000;
1029 ch->addr[1] |= value;
c3d2689d
AZ
1030 break;
1031
1032 case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
11e0fc3f
AZ
1033 ch->addr[1] &= 0x0000ffff;
1034 ch->addr[1] |= (uint32_t) value << 16;
c3d2689d
AZ
1035 break;
1036
1037 case 0x10: /* SYS_DMA_CEN_CH0 */
11e0fc3f 1038 ch->elements = value;
c3d2689d
AZ
1039 break;
1040
1041 case 0x12: /* SYS_DMA_CFN_CH0 */
11e0fc3f 1042 ch->frames = value;
c3d2689d
AZ
1043 break;
1044
1045 case 0x14: /* SYS_DMA_CFI_CH0 */
11e0fc3f 1046 ch->frame_index[0] = (int16_t) value;
c3d2689d
AZ
1047 break;
1048
1049 case 0x16: /* SYS_DMA_CEI_CH0 */
11e0fc3f 1050 ch->element_index[0] = (int16_t) value;
c3d2689d
AZ
1051 break;
1052
089b7c0a
AZ
1053 case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
1054 OMAP_RO_REG((target_phys_addr_t) reg);
1055 break;
1056
1057 case 0x1c: /* DMA_CDEI */
11e0fc3f 1058 ch->element_index[1] = (int16_t) value;
089b7c0a
AZ
1059 break;
1060
1061 case 0x1e: /* DMA_CDFI */
11e0fc3f 1062 ch->frame_index[1] = (int16_t) value;
089b7c0a
AZ
1063 break;
1064
1065 case 0x20: /* DMA_COLOR_L */
11e0fc3f
AZ
1066 ch->color &= 0xffff0000;
1067 ch->color |= value;
089b7c0a
AZ
1068 break;
1069
1070 case 0x22: /* DMA_COLOR_U */
11e0fc3f
AZ
1071 ch->color &= 0xffff;
1072 ch->color |= value << 16;
089b7c0a
AZ
1073 break;
1074
1075 case 0x24: /* DMA_CCR2 */
11e0fc3f
AZ
1076 ch->bs = (value >> 2) & 0x1;
1077 ch->transparent_copy = (value >> 1) & 0x1;
1078 ch->constant_fill = value & 0x1;
089b7c0a
AZ
1079 break;
1080
1081 case 0x28: /* DMA_CLNK_CTRL */
11e0fc3f 1082 ch->link_enabled = (value >> 15) & 0x1;
089b7c0a 1083 if (value & (1 << 14)) { /* Stop_Lnk */
11e0fc3f 1084 ch->link_enabled = 0;
089b7c0a
AZ
1085 omap_dma_disable_channel(s, ch);
1086 }
11e0fc3f 1087 ch->link_next_ch = value & 0x1f;
089b7c0a
AZ
1088 break;
1089
1090 case 0x2a: /* DMA_LCH_CTRL */
11e0fc3f
AZ
1091 ch->interleave_disabled = (value >> 15) & 0x1;
1092 ch->type = value & 0xf;
089b7c0a 1093 break;
c3d2689d
AZ
1094
1095 default:
089b7c0a 1096 return 1;
c3d2689d
AZ
1097 }
1098 return 0;
1099}
1100
11e0fc3f 1101static int omap_dma_3_2_lcd_write(struct omap_dma_lcd_channel_s *s, int offset,
089b7c0a 1102 uint16_t value)
c3d2689d 1103{
c3d2689d 1104 switch (offset) {
089b7c0a 1105 case 0xbc0: /* DMA_LCD_CSDP */
11e0fc3f
AZ
1106 s->brust_f2 = (value >> 14) & 0x3;
1107 s->pack_f2 = (value >> 13) & 0x1;
1108 s->data_type_f2 = (1 << ((value >> 11) & 0x3));
1109 s->brust_f1 = (value >> 7) & 0x3;
1110 s->pack_f1 = (value >> 6) & 0x1;
1111 s->data_type_f1 = (1 << ((value >> 0) & 0x3));
089b7c0a 1112 break;
c3d2689d 1113
089b7c0a 1114 case 0xbc2: /* DMA_LCD_CCR */
11e0fc3f
AZ
1115 s->mode_f2 = (value >> 14) & 0x3;
1116 s->mode_f1 = (value >> 12) & 0x3;
1117 s->end_prog = (value >> 11) & 0x1;
1118 s->omap_3_1_compatible_disable = (value >> 10) & 0x1;
1119 s->repeat = (value >> 9) & 0x1;
1120 s->auto_init = (value >> 8) & 0x1;
1121 s->running = (value >> 7) & 0x1;
1122 s->priority = (value >> 6) & 0x1;
1123 s->bs = (value >> 4) & 0x1;
089b7c0a
AZ
1124 break;
1125
1126 case 0xbc4: /* DMA_LCD_CTRL */
11e0fc3f
AZ
1127 s->dst = (value >> 8) & 0x1;
1128 s->src = ((value >> 6) & 0x3) << 1;
1129 s->condition = 0;
089b7c0a 1130 /* Assume no bus errors and thus no BUS_ERROR irq bits. */
11e0fc3f
AZ
1131 s->interrupts = (value >> 1) & 1;
1132 s->dual = value & 1;
089b7c0a 1133 break;
c3d2689d 1134
089b7c0a 1135 case 0xbc8: /* TOP_B1_L */
11e0fc3f
AZ
1136 s->src_f1_top &= 0xffff0000;
1137 s->src_f1_top |= 0x0000ffff & value;
089b7c0a 1138 break;
c3d2689d 1139
089b7c0a 1140 case 0xbca: /* TOP_B1_U */
11e0fc3f
AZ
1141 s->src_f1_top &= 0x0000ffff;
1142 s->src_f1_top |= value << 16;
089b7c0a 1143 break;
c3d2689d 1144
089b7c0a 1145 case 0xbcc: /* BOT_B1_L */
11e0fc3f
AZ
1146 s->src_f1_bottom &= 0xffff0000;
1147 s->src_f1_bottom |= 0x0000ffff & value;
089b7c0a 1148 break;
c3d2689d 1149
089b7c0a 1150 case 0xbce: /* BOT_B1_U */
11e0fc3f
AZ
1151 s->src_f1_bottom &= 0x0000ffff;
1152 s->src_f1_bottom |= (uint32_t) value << 16;
089b7c0a 1153 break;
c3d2689d 1154
089b7c0a 1155 case 0xbd0: /* TOP_B2_L */
11e0fc3f
AZ
1156 s->src_f2_top &= 0xffff0000;
1157 s->src_f2_top |= 0x0000ffff & value;
089b7c0a 1158 break;
c3d2689d 1159
089b7c0a 1160 case 0xbd2: /* TOP_B2_U */
11e0fc3f
AZ
1161 s->src_f2_top &= 0x0000ffff;
1162 s->src_f2_top |= (uint32_t) value << 16;
089b7c0a 1163 break;
c3d2689d 1164
089b7c0a 1165 case 0xbd4: /* BOT_B2_L */
11e0fc3f
AZ
1166 s->src_f2_bottom &= 0xffff0000;
1167 s->src_f2_bottom |= 0x0000ffff & value;
089b7c0a 1168 break;
c3d2689d 1169
089b7c0a 1170 case 0xbd6: /* BOT_B2_U */
11e0fc3f
AZ
1171 s->src_f2_bottom &= 0x0000ffff;
1172 s->src_f2_bottom |= (uint32_t) value << 16;
089b7c0a 1173 break;
c3d2689d 1174
089b7c0a 1175 case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
11e0fc3f 1176 s->element_index_f1 = value;
089b7c0a 1177 break;
c3d2689d 1178
089b7c0a 1179 case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
11e0fc3f
AZ
1180 s->frame_index_f1 &= 0xffff0000;
1181 s->frame_index_f1 |= 0x0000ffff & value;
089b7c0a
AZ
1182 break;
1183
1184 case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
11e0fc3f
AZ
1185 s->frame_index_f1 &= 0x0000ffff;
1186 s->frame_index_f1 |= (uint32_t) value << 16;
089b7c0a
AZ
1187 break;
1188
1189 case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
11e0fc3f 1190 s->element_index_f2 = value;
089b7c0a
AZ
1191 break;
1192
1193 case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
11e0fc3f
AZ
1194 s->frame_index_f2 &= 0xffff0000;
1195 s->frame_index_f2 |= 0x0000ffff & value;
089b7c0a
AZ
1196 break;
1197
1198 case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
11e0fc3f
AZ
1199 s->frame_index_f2 &= 0x0000ffff;
1200 s->frame_index_f2 |= (uint32_t) value << 16;
089b7c0a
AZ
1201 break;
1202
1203 case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
11e0fc3f 1204 s->elements_f1 = value;
089b7c0a
AZ
1205 break;
1206
1207 case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
11e0fc3f 1208 s->frames_f1 = value;
089b7c0a
AZ
1209 break;
1210
1211 case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
11e0fc3f 1212 s->elements_f2 = value;
089b7c0a
AZ
1213 break;
1214
1215 case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
11e0fc3f 1216 s->frames_f2 = value;
089b7c0a
AZ
1217 break;
1218
1219 case 0xbea: /* DMA_LCD_LCH_CTRL */
11e0fc3f 1220 s->lch_type = value & 0xf;
089b7c0a
AZ
1221 break;
1222
1223 default:
1224 return 1;
1225 }
c3d2689d
AZ
1226 return 0;
1227}
1228
11e0fc3f 1229static int omap_dma_3_2_lcd_read(struct omap_dma_lcd_channel_s *s, int offset,
089b7c0a 1230 uint16_t *ret)
c3d2689d 1231{
c3d2689d 1232 switch (offset) {
089b7c0a 1233 case 0xbc0: /* DMA_LCD_CSDP */
11e0fc3f
AZ
1234 *ret = (s->brust_f2 << 14) |
1235 (s->pack_f2 << 13) |
1236 ((s->data_type_f2 >> 1) << 11) |
1237 (s->brust_f1 << 7) |
1238 (s->pack_f1 << 6) |
1239 ((s->data_type_f1 >> 1) << 0);
089b7c0a
AZ
1240 break;
1241
1242 case 0xbc2: /* DMA_LCD_CCR */
11e0fc3f
AZ
1243 *ret = (s->mode_f2 << 14) |
1244 (s->mode_f1 << 12) |
1245 (s->end_prog << 11) |
1246 (s->omap_3_1_compatible_disable << 10) |
1247 (s->repeat << 9) |
1248 (s->auto_init << 8) |
1249 (s->running << 7) |
1250 (s->priority << 6) |
1251 (s->bs << 4);
089b7c0a
AZ
1252 break;
1253
1254 case 0xbc4: /* DMA_LCD_CTRL */
11e0fc3f
AZ
1255 qemu_irq_lower(s->irq);
1256 *ret = (s->dst << 8) |
1257 ((s->src & 0x6) << 5) |
1258 (s->condition << 3) |
1259 (s->interrupts << 1) |
1260 s->dual;
089b7c0a
AZ
1261 break;
1262
1263 case 0xbc8: /* TOP_B1_L */
11e0fc3f 1264 *ret = s->src_f1_top & 0xffff;
089b7c0a
AZ
1265 break;
1266
1267 case 0xbca: /* TOP_B1_U */
11e0fc3f 1268 *ret = s->src_f1_top >> 16;
089b7c0a
AZ
1269 break;
1270
1271 case 0xbcc: /* BOT_B1_L */
11e0fc3f 1272 *ret = s->src_f1_bottom & 0xffff;
089b7c0a
AZ
1273 break;
1274
1275 case 0xbce: /* BOT_B1_U */
11e0fc3f 1276 *ret = s->src_f1_bottom >> 16;
089b7c0a
AZ
1277 break;
1278
1279 case 0xbd0: /* TOP_B2_L */
11e0fc3f 1280 *ret = s->src_f2_top & 0xffff;
089b7c0a
AZ
1281 break;
1282
1283 case 0xbd2: /* TOP_B2_U */
11e0fc3f 1284 *ret = s->src_f2_top >> 16;
089b7c0a
AZ
1285 break;
1286
1287 case 0xbd4: /* BOT_B2_L */
11e0fc3f 1288 *ret = s->src_f2_bottom & 0xffff;
c3d2689d
AZ
1289 break;
1290
089b7c0a 1291 case 0xbd6: /* BOT_B2_U */
11e0fc3f 1292 *ret = s->src_f2_bottom >> 16;
089b7c0a
AZ
1293 break;
1294
1295 case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
11e0fc3f 1296 *ret = s->element_index_f1;
089b7c0a
AZ
1297 break;
1298
1299 case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
11e0fc3f 1300 *ret = s->frame_index_f1 & 0xffff;
089b7c0a
AZ
1301 break;
1302
1303 case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
11e0fc3f 1304 *ret = s->frame_index_f1 >> 16;
089b7c0a
AZ
1305 break;
1306
1307 case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
11e0fc3f 1308 *ret = s->element_index_f2;
089b7c0a
AZ
1309 break;
1310
1311 case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
11e0fc3f 1312 *ret = s->frame_index_f2 & 0xffff;
089b7c0a
AZ
1313 break;
1314
1315 case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
11e0fc3f 1316 *ret = s->frame_index_f2 >> 16;
089b7c0a
AZ
1317 break;
1318
1319 case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
11e0fc3f 1320 *ret = s->elements_f1;
089b7c0a
AZ
1321 break;
1322
1323 case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
11e0fc3f 1324 *ret = s->frames_f1;
089b7c0a
AZ
1325 break;
1326
1327 case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
11e0fc3f 1328 *ret = s->elements_f2;
089b7c0a
AZ
1329 break;
1330
1331 case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
11e0fc3f 1332 *ret = s->frames_f2;
089b7c0a
AZ
1333 break;
1334
1335 case 0xbea: /* DMA_LCD_LCH_CTRL */
11e0fc3f 1336 *ret = s->lch_type;
089b7c0a
AZ
1337 break;
1338
1339 default:
1340 return 1;
1341 }
1342 return 0;
1343}
1344
11e0fc3f 1345static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset,
089b7c0a
AZ
1346 uint16_t value)
1347{
1348 switch (offset) {
c3d2689d 1349 case 0x300: /* SYS_DMA_LCD_CTRL */
11e0fc3f
AZ
1350 s->src = (value & 0x40) ? imif : emiff;
1351 s->condition = 0;
c3d2689d 1352 /* Assume no bus errors and thus no BUS_ERROR irq bits. */
11e0fc3f
AZ
1353 s->interrupts = (value >> 1) & 1;
1354 s->dual = value & 1;
c3d2689d
AZ
1355 break;
1356
1357 case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
11e0fc3f
AZ
1358 s->src_f1_top &= 0xffff0000;
1359 s->src_f1_top |= 0x0000ffff & value;
c3d2689d
AZ
1360 break;
1361
1362 case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
11e0fc3f
AZ
1363 s->src_f1_top &= 0x0000ffff;
1364 s->src_f1_top |= value << 16;
c3d2689d
AZ
1365 break;
1366
1367 case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
11e0fc3f
AZ
1368 s->src_f1_bottom &= 0xffff0000;
1369 s->src_f1_bottom |= 0x0000ffff & value;
c3d2689d
AZ
1370 break;
1371
1372 case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
11e0fc3f
AZ
1373 s->src_f1_bottom &= 0x0000ffff;
1374 s->src_f1_bottom |= value << 16;
c3d2689d
AZ
1375 break;
1376
1377 case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
11e0fc3f
AZ
1378 s->src_f2_top &= 0xffff0000;
1379 s->src_f2_top |= 0x0000ffff & value;
c3d2689d
AZ
1380 break;
1381
1382 case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
11e0fc3f
AZ
1383 s->src_f2_top &= 0x0000ffff;
1384 s->src_f2_top |= value << 16;
c3d2689d
AZ
1385 break;
1386
1387 case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
11e0fc3f
AZ
1388 s->src_f2_bottom &= 0xffff0000;
1389 s->src_f2_bottom |= 0x0000ffff & value;
c3d2689d
AZ
1390 break;
1391
1392 case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
11e0fc3f
AZ
1393 s->src_f2_bottom &= 0x0000ffff;
1394 s->src_f2_bottom |= value << 16;
c3d2689d
AZ
1395 break;
1396
089b7c0a
AZ
1397 default:
1398 return 1;
1399 }
1400 return 0;
1401}
1402
11e0fc3f 1403static int omap_dma_3_1_lcd_read(struct omap_dma_lcd_channel_s *s, int offset,
089b7c0a
AZ
1404 uint16_t *ret)
1405{
1406 int i;
1407
1408 switch (offset) {
1409 case 0x300: /* SYS_DMA_LCD_CTRL */
11e0fc3f
AZ
1410 i = s->condition;
1411 s->condition = 0;
1412 qemu_irq_lower(s->irq);
1413 *ret = ((s->src == imif) << 6) | (i << 3) |
1414 (s->interrupts << 1) | s->dual;
089b7c0a
AZ
1415 break;
1416
1417 case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
11e0fc3f 1418 *ret = s->src_f1_top & 0xffff;
089b7c0a
AZ
1419 break;
1420
1421 case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
11e0fc3f 1422 *ret = s->src_f1_top >> 16;
089b7c0a
AZ
1423 break;
1424
1425 case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
11e0fc3f 1426 *ret = s->src_f1_bottom & 0xffff;
089b7c0a
AZ
1427 break;
1428
1429 case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
11e0fc3f 1430 *ret = s->src_f1_bottom >> 16;
089b7c0a
AZ
1431 break;
1432
1433 case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
11e0fc3f 1434 *ret = s->src_f2_top & 0xffff;
089b7c0a
AZ
1435 break;
1436
1437 case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
11e0fc3f 1438 *ret = s->src_f2_top >> 16;
089b7c0a
AZ
1439 break;
1440
1441 case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
11e0fc3f 1442 *ret = s->src_f2_bottom & 0xffff;
089b7c0a
AZ
1443 break;
1444
1445 case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
11e0fc3f 1446 *ret = s->src_f2_bottom >> 16;
089b7c0a
AZ
1447 break;
1448
1449 default:
1450 return 1;
1451 }
1452 return 0;
1453}
1454
1455static int omap_dma_sys_write(struct omap_dma_s *s, int offset, uint16_t value)
1456{
1457 switch (offset) {
c3d2689d 1458 case 0x400: /* SYS_DMA_GCR */
089b7c0a
AZ
1459 s->gcr = value;
1460 break;
1461
1462 case 0x404: /* DMA_GSCR */
1463 if (value & 0x8)
1464 omap_dma_disable_3_1_mapping(s);
1465 else
1466 omap_dma_enable_3_1_mapping(s);
1467 break;
1468
1469 case 0x408: /* DMA_GRST */
1470 if (value & 0x1)
1471 omap_dma_reset(s);
c3d2689d
AZ
1472 break;
1473
1474 default:
089b7c0a 1475 return 1;
c3d2689d 1476 }
089b7c0a
AZ
1477 return 0;
1478}
1479
1480static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
1481 uint16_t *ret)
1482{
1483 switch (offset) {
1484 case 0x400: /* SYS_DMA_GCR */
1485 *ret = s->gcr;
1486 break;
1487
1488 case 0x404: /* DMA_GSCR */
1489 *ret = s->omap_3_1_mapping_disabled << 3;
1490 break;
1491
1492 case 0x408: /* DMA_GRST */
1493 *ret = 0;
1494 break;
1495
1496 case 0x442: /* DMA_HW_ID */
1497 case 0x444: /* DMA_PCh2_ID */
1498 case 0x446: /* DMA_PCh0_ID */
1499 case 0x448: /* DMA_PCh1_ID */
1500 case 0x44a: /* DMA_PChG_ID */
1501 case 0x44c: /* DMA_PChD_ID */
1502 *ret = 1;
1503 break;
1504
1505 case 0x44e: /* DMA_CAPS_0_U */
1506 *ret = (1 << 3) | /* Constant Fill Capacity */
1507 (1 << 2); /* Transparent BLT Capacity */
1508 break;
1509
1510 case 0x450: /* DMA_CAPS_0_L */
1511 case 0x452: /* DMA_CAPS_1_U */
1512 *ret = 0;
1513 break;
1514
1515 case 0x454: /* DMA_CAPS_1_L */
1516 *ret = (1 << 1); /* 1-bit palletized capability */
1517 break;
1518
1519 case 0x456: /* DMA_CAPS_2 */
1520 *ret = (1 << 8) | /* SSDIC */
1521 (1 << 7) | /* DDIAC */
1522 (1 << 6) | /* DSIAC */
1523 (1 << 5) | /* DPIAC */
1524 (1 << 4) | /* DCAC */
1525 (1 << 3) | /* SDIAC */
1526 (1 << 2) | /* SSIAC */
1527 (1 << 1) | /* SPIAC */
1528 1; /* SCAC */
1529 break;
1530
1531 case 0x458: /* DMA_CAPS_3 */
1532 *ret = (1 << 5) | /* CCC */
1533 (1 << 4) | /* IC */
1534 (1 << 3) | /* ARC */
1535 (1 << 2) | /* AEC */
1536 (1 << 1) | /* FSC */
1537 1; /* ESC */
1538 break;
1539
1540 case 0x45a: /* DMA_CAPS_4 */
1541 *ret = (1 << 6) | /* SSC */
1542 (1 << 5) | /* BIC */
1543 (1 << 4) | /* LFIC */
1544 (1 << 3) | /* FIC */
1545 (1 << 2) | /* HFIC */
1546 (1 << 1) | /* EDIC */
1547 1; /* TOIC */
1548 break;
1549
1550 case 0x460: /* DMA_PCh2_SR */
1551 case 0x480: /* DMA_PCh0_SR */
1552 case 0x482: /* DMA_PCh1_SR */
1553 case 0x4c0: /* DMA_PChD_SR_0 */
1554 printf("%s: Physical Channel Status Registers not implemented.\n",
1555 __FUNCTION__);
1556 *ret = 0xff;
1557 break;
1558
1559 default:
1560 return 1;
1561 }
1562 return 0;
1563}
1564
1565static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
1566{
1567 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
1568 int reg, ch, offset = addr - s->base;
1569 uint16_t ret;
1570
1571 switch (offset) {
1572 case 0x300 ... 0x3fe:
1573 if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
11e0fc3f 1574 if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret))
089b7c0a
AZ
1575 break;
1576 return ret;
1577 }
1578 /* Fall through. */
1579 case 0x000 ... 0x2fe:
1580 reg = offset & 0x3f;
1581 ch = (offset >> 6) & 0x0f;
11e0fc3f 1582 if (omap_dma_ch_reg_read(s, &s->ch[ch], reg, &ret))
089b7c0a
AZ
1583 break;
1584 return ret;
1585
1586 case 0x404 ... 0x4fe:
1587 if (s->model == omap_dma_3_1)
1588 break;
1589 /* Fall through. */
1590 case 0x400:
1591 if (omap_dma_sys_read(s, offset, &ret))
1592 break;
1593 return ret;
1594
1595 case 0xb00 ... 0xbfe:
1596 if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
11e0fc3f 1597 if (omap_dma_3_2_lcd_read(&s->lcd_ch, offset, &ret))
089b7c0a
AZ
1598 break;
1599 return ret;
1600 }
1601 break;
1602 }
1603
1604 OMAP_BAD_REG(addr);
1605 return 0;
1606}
1607
1608static void omap_dma_write(void *opaque, target_phys_addr_t addr,
1609 uint32_t value)
1610{
1611 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
1612 int reg, ch, offset = addr - s->base;
1613
1614 switch (offset) {
1615 case 0x300 ... 0x3fe:
1616 if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
11e0fc3f 1617 if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value))
089b7c0a
AZ
1618 break;
1619 return;
1620 }
1621 /* Fall through. */
1622 case 0x000 ... 0x2fe:
1623 reg = offset & 0x3f;
1624 ch = (offset >> 6) & 0x0f;
11e0fc3f 1625 if (omap_dma_ch_reg_write(s, &s->ch[ch], reg, value))
089b7c0a
AZ
1626 break;
1627 return;
1628
1629 case 0x404 ... 0x4fe:
1630 if (s->model == omap_dma_3_1)
1631 break;
1632 case 0x400:
1633 /* Fall through. */
1634 if (omap_dma_sys_write(s, offset, value))
1635 break;
1636 return;
1637
1638 case 0xb00 ... 0xbfe:
1639 if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
11e0fc3f 1640 if (omap_dma_3_2_lcd_write(&s->lcd_ch, offset, value))
089b7c0a
AZ
1641 break;
1642 return;
1643 }
1644 break;
1645 }
1646
1647 OMAP_BAD_REG(addr);
c3d2689d
AZ
1648}
1649
1650static CPUReadMemoryFunc *omap_dma_readfn[] = {
1651 omap_badwidth_read16,
1652 omap_dma_read,
1653 omap_badwidth_read16,
1654};
1655
1656static CPUWriteMemoryFunc *omap_dma_writefn[] = {
1657 omap_badwidth_write16,
1658 omap_dma_write,
1659 omap_badwidth_write16,
1660};
1661
1662static void omap_dma_request(void *opaque, int drq, int req)
1663{
1664 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
1af2b62d
AZ
1665 /* The request pins are level triggered. */
1666 if (req) {
1667 if (~s->drq & (1 << drq)) {
1668 s->drq |= 1 << drq;
089b7c0a 1669 omap_dma_process_request(s, drq);
1af2b62d
AZ
1670 }
1671 } else
1672 s->drq &= ~(1 << drq);
c3d2689d
AZ
1673}
1674
1675static void omap_dma_clk_update(void *opaque, int line, int on)
1676{
1677 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
1678
1679 if (on) {
73560bc8
AZ
1680 /* TODO: make a clever calculation */
1681 s->delay = ticks_per_sec >> 8;
c3d2689d
AZ
1682 if (s->run_count)
1683 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
1684 } else {
1685 s->delay = 0;
1686 qemu_del_timer(s->tm);
1687 }
1688}
1689
089b7c0a
AZ
1690struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
1691 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
1692 enum omap_dma_model model)
c3d2689d 1693{
11e0fc3f 1694 int iomemtype, num_irqs, memsize, i;
c3d2689d
AZ
1695 struct omap_dma_s *s = (struct omap_dma_s *)
1696 qemu_mallocz(sizeof(struct omap_dma_s));
1697
089b7c0a
AZ
1698 if (model == omap_dma_3_1) {
1699 num_irqs = 6;
1700 memsize = 0x800;
1701 } else {
1702 num_irqs = 16;
1703 memsize = 0xc00;
1704 }
c3d2689d 1705 s->base = base;
089b7c0a 1706 s->model = model;
c3d2689d
AZ
1707 s->mpu = mpu;
1708 s->clk = clk;
089b7c0a 1709 s->lcd_ch.irq = lcd_irq;
c3d2689d 1710 s->lcd_ch.mpu = mpu;
11e0fc3f
AZ
1711 while (num_irqs --)
1712 s->ch[num_irqs].irq = irqs[num_irqs];
1713 for (i = 0; i < 3; i ++) {
1714 s->ch[i].sibling = &s->ch[i + 6];
1715 s->ch[i + 6].sibling = &s->ch[i];
1716 }
c3d2689d
AZ
1717 s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
1718 omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
1719 mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32);
1720 omap_dma_reset(s);
1af2b62d 1721 omap_dma_clk_update(s, 0, 1);
c3d2689d
AZ
1722
1723 iomemtype = cpu_register_io_memory(0, omap_dma_readfn,
1724 omap_dma_writefn, s);
089b7c0a 1725 cpu_register_physical_memory(s->base, memsize, iomemtype);
c3d2689d
AZ
1726
1727 return s;
1728}
1729
1730/* DMA ports */
b854bc19 1731static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1732 target_phys_addr_t addr)
1733{
1734 return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size;
1735}
1736
b854bc19 1737static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1738 target_phys_addr_t addr)
1739{
1740 return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE;
1741}
1742
b854bc19 1743static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1744 target_phys_addr_t addr)
1745{
1746 return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size;
1747}
1748
b854bc19 1749static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1750 target_phys_addr_t addr)
1751{
1752 return addr >= 0xfffb0000 && addr < 0xffff0000;
1753}
1754
b854bc19 1755static int omap_validate_local_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1756 target_phys_addr_t addr)
1757{
1758 return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000;
1759}
1760
b854bc19 1761static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1762 target_phys_addr_t addr)
1763{
1764 return addr >= 0xe1010000 && addr < 0xe1020004;
1765}
1766
1767/* MPU OS timers */
1768struct omap_mpu_timer_s {
1769 qemu_irq irq;
1770 omap_clk clk;
1771 target_phys_addr_t base;
1772 uint32_t val;
1773 int64_t time;
1774 QEMUTimer *timer;
1775 int64_t rate;
1776 int it_ena;
1777
1778 int enable;
1779 int ptv;
1780 int ar;
1781 int st;
1782 uint32_t reset_val;
1783};
1784
1785static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
1786{
1787 uint64_t distance = qemu_get_clock(vm_clock) - timer->time;
1788
1789 if (timer->st && timer->enable && timer->rate)
1790 return timer->val - muldiv64(distance >> (timer->ptv + 1),
1791 timer->rate, ticks_per_sec);
1792 else
1793 return timer->val;
1794}
1795
1796static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
1797{
1798 timer->val = omap_timer_read(timer);
1799 timer->time = qemu_get_clock(vm_clock);
1800}
1801
1802static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
1803{
1804 int64_t expires;
1805
1806 if (timer->enable && timer->st && timer->rate) {
1807 timer->val = timer->reset_val; /* Should skip this on clk enable */
b854bc19 1808 expires = muldiv64(timer->val << (timer->ptv + 1),
c3d2689d 1809 ticks_per_sec, timer->rate);
b854bc19
AZ
1810
1811 /* If timer expiry would be sooner than in about 1 ms and
1812 * auto-reload isn't set, then fire immediately. This is a hack
1813 * to make systems like PalmOS run in acceptable time. PalmOS
1814 * sets the interval to a very low value and polls the status bit
1815 * in a busy loop when it wants to sleep just a couple of CPU
1816 * ticks. */
1817 if (expires > (ticks_per_sec >> 10) || timer->ar)
1818 qemu_mod_timer(timer->timer, timer->time + expires);
1819 else {
1820 timer->val = 0;
1821 timer->st = 0;
1822 if (timer->it_ena)
106627d0
AZ
1823 /* Edge-triggered irq */
1824 qemu_irq_pulse(timer->irq);
b854bc19 1825 }
c3d2689d
AZ
1826 } else
1827 qemu_del_timer(timer->timer);
1828}
1829
1830static void omap_timer_tick(void *opaque)
1831{
1832 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
1833 omap_timer_sync(timer);
1834
1835 if (!timer->ar) {
1836 timer->val = 0;
1837 timer->st = 0;
1838 }
1839
1840 if (timer->it_ena)
106627d0
AZ
1841 /* Edge-triggered irq */
1842 qemu_irq_pulse(timer->irq);
c3d2689d
AZ
1843 omap_timer_update(timer);
1844}
1845
1846static void omap_timer_clk_update(void *opaque, int line, int on)
1847{
1848 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
1849
1850 omap_timer_sync(timer);
1851 timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
1852 omap_timer_update(timer);
1853}
1854
1855static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
1856{
1857 omap_clk_adduser(timer->clk,
1858 qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
1859 timer->rate = omap_clk_getrate(timer->clk);
1860}
1861
1862static uint32_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr)
1863{
1864 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
1865 int offset = addr - s->base;
1866
1867 switch (offset) {
1868 case 0x00: /* CNTL_TIMER */
1869 return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
1870
1871 case 0x04: /* LOAD_TIM */
1872 break;
1873
1874 case 0x08: /* READ_TIM */
1875 return omap_timer_read(s);
1876 }
1877
1878 OMAP_BAD_REG(addr);
1879 return 0;
1880}
1881
1882static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr,
1883 uint32_t value)
1884{
1885 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
1886 int offset = addr - s->base;
1887
1888 switch (offset) {
1889 case 0x00: /* CNTL_TIMER */
1890 omap_timer_sync(s);
1891 s->enable = (value >> 5) & 1;
1892 s->ptv = (value >> 2) & 7;
1893 s->ar = (value >> 1) & 1;
1894 s->st = value & 1;
1895 omap_timer_update(s);
1896 return;
1897
1898 case 0x04: /* LOAD_TIM */
1899 s->reset_val = value;
1900 return;
1901
1902 case 0x08: /* READ_TIM */
1903 OMAP_RO_REG(addr);
1904 break;
1905
1906 default:
1907 OMAP_BAD_REG(addr);
1908 }
1909}
1910
1911static CPUReadMemoryFunc *omap_mpu_timer_readfn[] = {
1912 omap_badwidth_read32,
1913 omap_badwidth_read32,
1914 omap_mpu_timer_read,
1915};
1916
1917static CPUWriteMemoryFunc *omap_mpu_timer_writefn[] = {
1918 omap_badwidth_write32,
1919 omap_badwidth_write32,
1920 omap_mpu_timer_write,
1921};
1922
1923static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
1924{
1925 qemu_del_timer(s->timer);
1926 s->enable = 0;
1927 s->reset_val = 31337;
1928 s->val = 0;
1929 s->ptv = 0;
1930 s->ar = 0;
1931 s->st = 0;
1932 s->it_ena = 1;
1933}
1934
1935struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
1936 qemu_irq irq, omap_clk clk)
1937{
1938 int iomemtype;
1939 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
1940 qemu_mallocz(sizeof(struct omap_mpu_timer_s));
1941
1942 s->irq = irq;
1943 s->clk = clk;
1944 s->base = base;
1945 s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s);
1946 omap_mpu_timer_reset(s);
1947 omap_timer_clk_setup(s);
1948
1949 iomemtype = cpu_register_io_memory(0, omap_mpu_timer_readfn,
1950 omap_mpu_timer_writefn, s);
1951 cpu_register_physical_memory(s->base, 0x100, iomemtype);
1952
1953 return s;
1954}
1955
1956/* Watchdog timer */
1957struct omap_watchdog_timer_s {
1958 struct omap_mpu_timer_s timer;
1959 uint8_t last_wr;
1960 int mode;
1961 int free;
1962 int reset;
1963};
1964
1965static uint32_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr)
1966{
1967 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
1968 int offset = addr - s->timer.base;
1969
1970 switch (offset) {
1971 case 0x00: /* CNTL_TIMER */
1972 return (s->timer.ptv << 9) | (s->timer.ar << 8) |
1973 (s->timer.st << 7) | (s->free << 1);
1974
1975 case 0x04: /* READ_TIMER */
1976 return omap_timer_read(&s->timer);
1977
1978 case 0x08: /* TIMER_MODE */
1979 return s->mode << 15;
1980 }
1981
1982 OMAP_BAD_REG(addr);
1983 return 0;
1984}
1985
1986static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr,
1987 uint32_t value)
1988{
1989 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
1990 int offset = addr - s->timer.base;
1991
1992 switch (offset) {
1993 case 0x00: /* CNTL_TIMER */
1994 omap_timer_sync(&s->timer);
1995 s->timer.ptv = (value >> 9) & 7;
1996 s->timer.ar = (value >> 8) & 1;
1997 s->timer.st = (value >> 7) & 1;
1998 s->free = (value >> 1) & 1;
1999 omap_timer_update(&s->timer);
2000 break;
2001
2002 case 0x04: /* LOAD_TIMER */
2003 s->timer.reset_val = value & 0xffff;
2004 break;
2005
2006 case 0x08: /* TIMER_MODE */
2007 if (!s->mode && ((value >> 15) & 1))
2008 omap_clk_get(s->timer.clk);
2009 s->mode |= (value >> 15) & 1;
2010 if (s->last_wr == 0xf5) {
2011 if ((value & 0xff) == 0xa0) {
d8f699cb
AZ
2012 if (s->mode) {
2013 s->mode = 0;
2014 omap_clk_put(s->timer.clk);
2015 }
c3d2689d
AZ
2016 } else {
2017 /* XXX: on T|E hardware somehow this has no effect,
2018 * on Zire 71 it works as specified. */
2019 s->reset = 1;
2020 qemu_system_reset_request();
2021 }
2022 }
2023 s->last_wr = value & 0xff;
2024 break;
2025
2026 default:
2027 OMAP_BAD_REG(addr);
2028 }
2029}
2030
2031static CPUReadMemoryFunc *omap_wd_timer_readfn[] = {
2032 omap_badwidth_read16,
2033 omap_wd_timer_read,
2034 omap_badwidth_read16,
2035};
2036
2037static CPUWriteMemoryFunc *omap_wd_timer_writefn[] = {
2038 omap_badwidth_write16,
2039 omap_wd_timer_write,
2040 omap_badwidth_write16,
2041};
2042
2043static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
2044{
2045 qemu_del_timer(s->timer.timer);
2046 if (!s->mode)
2047 omap_clk_get(s->timer.clk);
2048 s->mode = 1;
2049 s->free = 1;
2050 s->reset = 0;
2051 s->timer.enable = 1;
2052 s->timer.it_ena = 1;
2053 s->timer.reset_val = 0xffff;
2054 s->timer.val = 0;
2055 s->timer.st = 0;
2056 s->timer.ptv = 0;
2057 s->timer.ar = 0;
2058 omap_timer_update(&s->timer);
2059}
2060
2061struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
2062 qemu_irq irq, omap_clk clk)
2063{
2064 int iomemtype;
2065 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
2066 qemu_mallocz(sizeof(struct omap_watchdog_timer_s));
2067
2068 s->timer.irq = irq;
2069 s->timer.clk = clk;
2070 s->timer.base = base;
2071 s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
2072 omap_wd_timer_reset(s);
2073 omap_timer_clk_setup(&s->timer);
2074
2075 iomemtype = cpu_register_io_memory(0, omap_wd_timer_readfn,
2076 omap_wd_timer_writefn, s);
2077 cpu_register_physical_memory(s->timer.base, 0x100, iomemtype);
2078
2079 return s;
2080}
2081
2082/* 32-kHz timer */
2083struct omap_32khz_timer_s {
2084 struct omap_mpu_timer_s timer;
2085};
2086
2087static uint32_t omap_os_timer_read(void *opaque, target_phys_addr_t addr)
2088{
2089 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
cf965d24 2090 int offset = addr & OMAP_MPUI_REG_MASK;
c3d2689d
AZ
2091
2092 switch (offset) {
2093 case 0x00: /* TVR */
2094 return s->timer.reset_val;
2095
2096 case 0x04: /* TCR */
2097 return omap_timer_read(&s->timer);
2098
2099 case 0x08: /* CR */
2100 return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
2101
2102 default:
2103 break;
2104 }
2105 OMAP_BAD_REG(addr);
2106 return 0;
2107}
2108
2109static void omap_os_timer_write(void *opaque, target_phys_addr_t addr,
2110 uint32_t value)
2111{
2112 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
cf965d24 2113 int offset = addr & OMAP_MPUI_REG_MASK;
c3d2689d
AZ
2114
2115 switch (offset) {
2116 case 0x00: /* TVR */
2117 s->timer.reset_val = value & 0x00ffffff;
2118 break;
2119
2120 case 0x04: /* TCR */
2121 OMAP_RO_REG(addr);
2122 break;
2123
2124 case 0x08: /* CR */
2125 s->timer.ar = (value >> 3) & 1;
2126 s->timer.it_ena = (value >> 2) & 1;
2127 if (s->timer.st != (value & 1) || (value & 2)) {
2128 omap_timer_sync(&s->timer);
2129 s->timer.enable = value & 1;
2130 s->timer.st = value & 1;
2131 omap_timer_update(&s->timer);
2132 }
2133 break;
2134
2135 default:
2136 OMAP_BAD_REG(addr);
2137 }
2138}
2139
2140static CPUReadMemoryFunc *omap_os_timer_readfn[] = {
2141 omap_badwidth_read32,
2142 omap_badwidth_read32,
2143 omap_os_timer_read,
2144};
2145
2146static CPUWriteMemoryFunc *omap_os_timer_writefn[] = {
2147 omap_badwidth_write32,
2148 omap_badwidth_write32,
2149 omap_os_timer_write,
2150};
2151
2152static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
2153{
2154 qemu_del_timer(s->timer.timer);
2155 s->timer.enable = 0;
2156 s->timer.it_ena = 0;
2157 s->timer.reset_val = 0x00ffffff;
2158 s->timer.val = 0;
2159 s->timer.st = 0;
2160 s->timer.ptv = 0;
2161 s->timer.ar = 1;
2162}
2163
2164struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
2165 qemu_irq irq, omap_clk clk)
2166{
2167 int iomemtype;
2168 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
2169 qemu_mallocz(sizeof(struct omap_32khz_timer_s));
2170
2171 s->timer.irq = irq;
2172 s->timer.clk = clk;
2173 s->timer.base = base;
2174 s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
2175 omap_os_timer_reset(s);
2176 omap_timer_clk_setup(&s->timer);
2177
2178 iomemtype = cpu_register_io_memory(0, omap_os_timer_readfn,
2179 omap_os_timer_writefn, s);
2180 cpu_register_physical_memory(s->timer.base, 0x800, iomemtype);
2181
2182 return s;
2183}
2184
2185/* Ultra Low-Power Device Module */
2186static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr)
2187{
2188 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2189 int offset = addr - s->ulpd_pm_base;
2190 uint16_t ret;
2191
2192 switch (offset) {
2193 case 0x14: /* IT_STATUS */
2194 ret = s->ulpd_pm_regs[offset >> 2];
2195 s->ulpd_pm_regs[offset >> 2] = 0;
2196 qemu_irq_lower(s->irq[1][OMAP_INT_GAUGE_32K]);
2197 return ret;
2198
2199 case 0x18: /* Reserved */
2200 case 0x1c: /* Reserved */
2201 case 0x20: /* Reserved */
2202 case 0x28: /* Reserved */
2203 case 0x2c: /* Reserved */
2204 OMAP_BAD_REG(addr);
2205 case 0x00: /* COUNTER_32_LSB */
2206 case 0x04: /* COUNTER_32_MSB */
2207 case 0x08: /* COUNTER_HIGH_FREQ_LSB */
2208 case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
2209 case 0x10: /* GAUGING_CTRL */
2210 case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
2211 case 0x30: /* CLOCK_CTRL */
2212 case 0x34: /* SOFT_REQ */
2213 case 0x38: /* COUNTER_32_FIQ */
2214 case 0x3c: /* DPLL_CTRL */
2215 case 0x40: /* STATUS_REQ */
2216 /* XXX: check clk::usecount state for every clock */
2217 case 0x48: /* LOCL_TIME */
2218 case 0x4c: /* APLL_CTRL */
2219 case 0x50: /* POWER_CTRL */
2220 return s->ulpd_pm_regs[offset >> 2];
2221 }
2222
2223 OMAP_BAD_REG(addr);
2224 return 0;
2225}
2226
2227static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
2228 uint16_t diff, uint16_t value)
2229{
2230 if (diff & (1 << 4)) /* USB_MCLK_EN */
2231 omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
2232 if (diff & (1 << 5)) /* DIS_USB_PVCI_CLK */
2233 omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
2234}
2235
2236static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
2237 uint16_t diff, uint16_t value)
2238{
2239 if (diff & (1 << 0)) /* SOFT_DPLL_REQ */
2240 omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
2241 if (diff & (1 << 1)) /* SOFT_COM_REQ */
2242 omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
2243 if (diff & (1 << 2)) /* SOFT_SDW_REQ */
2244 omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
2245 if (diff & (1 << 3)) /* SOFT_USB_REQ */
2246 omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
2247}
2248
2249static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
2250 uint32_t value)
2251{
2252 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2253 int offset = addr - s->ulpd_pm_base;
2254 int64_t now, ticks;
2255 int div, mult;
2256 static const int bypass_div[4] = { 1, 2, 4, 4 };
2257 uint16_t diff;
2258
2259 switch (offset) {
2260 case 0x00: /* COUNTER_32_LSB */
2261 case 0x04: /* COUNTER_32_MSB */
2262 case 0x08: /* COUNTER_HIGH_FREQ_LSB */
2263 case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
2264 case 0x14: /* IT_STATUS */
2265 case 0x40: /* STATUS_REQ */
2266 OMAP_RO_REG(addr);
2267 break;
2268
2269 case 0x10: /* GAUGING_CTRL */
2270 /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
2271 if ((s->ulpd_pm_regs[offset >> 2] ^ value) & 1) {
2272 now = qemu_get_clock(vm_clock);
2273
2274 if (value & 1)
2275 s->ulpd_gauge_start = now;
2276 else {
2277 now -= s->ulpd_gauge_start;
2278
2279 /* 32-kHz ticks */
2280 ticks = muldiv64(now, 32768, ticks_per_sec);
2281 s->ulpd_pm_regs[0x00 >> 2] = (ticks >> 0) & 0xffff;
2282 s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
2283 if (ticks >> 32) /* OVERFLOW_32K */
2284 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
2285
2286 /* High frequency ticks */
2287 ticks = muldiv64(now, 12000000, ticks_per_sec);
2288 s->ulpd_pm_regs[0x08 >> 2] = (ticks >> 0) & 0xffff;
2289 s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
2290 if (ticks >> 32) /* OVERFLOW_HI_FREQ */
2291 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
2292
2293 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0; /* IT_GAUGING */
2294 qemu_irq_raise(s->irq[1][OMAP_INT_GAUGE_32K]);
2295 }
2296 }
2297 s->ulpd_pm_regs[offset >> 2] = value;
2298 break;
2299
2300 case 0x18: /* Reserved */
2301 case 0x1c: /* Reserved */
2302 case 0x20: /* Reserved */
2303 case 0x28: /* Reserved */
2304 case 0x2c: /* Reserved */
2305 OMAP_BAD_REG(addr);
2306 case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
2307 case 0x38: /* COUNTER_32_FIQ */
2308 case 0x48: /* LOCL_TIME */
2309 case 0x50: /* POWER_CTRL */
2310 s->ulpd_pm_regs[offset >> 2] = value;
2311 break;
2312
2313 case 0x30: /* CLOCK_CTRL */
2314 diff = s->ulpd_pm_regs[offset >> 2] ^ value;
2315 s->ulpd_pm_regs[offset >> 2] = value & 0x3f;
2316 omap_ulpd_clk_update(s, diff, value);
2317 break;
2318
2319 case 0x34: /* SOFT_REQ */
2320 diff = s->ulpd_pm_regs[offset >> 2] ^ value;
2321 s->ulpd_pm_regs[offset >> 2] = value & 0x1f;
2322 omap_ulpd_req_update(s, diff, value);
2323 break;
2324
2325 case 0x3c: /* DPLL_CTRL */
2326 /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
2327 * omitted altogether, probably a typo. */
2328 /* This register has identical semantics with DPLL(1:3) control
2329 * registers, see omap_dpll_write() */
2330 diff = s->ulpd_pm_regs[offset >> 2] & value;
2331 s->ulpd_pm_regs[offset >> 2] = value & 0x2fff;
2332 if (diff & (0x3ff << 2)) {
2333 if (value & (1 << 4)) { /* PLL_ENABLE */
2334 div = ((value >> 5) & 3) + 1; /* PLL_DIV */
2335 mult = MIN((value >> 7) & 0x1f, 1); /* PLL_MULT */
2336 } else {
2337 div = bypass_div[((value >> 2) & 3)]; /* BYPASS_DIV */
2338 mult = 1;
2339 }
2340 omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
2341 }
2342
2343 /* Enter the desired mode. */
2344 s->ulpd_pm_regs[offset >> 2] =
2345 (s->ulpd_pm_regs[offset >> 2] & 0xfffe) |
2346 ((s->ulpd_pm_regs[offset >> 2] >> 4) & 1);
2347
2348 /* Act as if the lock is restored. */
2349 s->ulpd_pm_regs[offset >> 2] |= 2;
2350 break;
2351
2352 case 0x4c: /* APLL_CTRL */
2353 diff = s->ulpd_pm_regs[offset >> 2] & value;
2354 s->ulpd_pm_regs[offset >> 2] = value & 0xf;
2355 if (diff & (1 << 0)) /* APLL_NDPLL_SWITCH */
2356 omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
2357 (value & (1 << 0)) ? "apll" : "dpll4"));
2358 break;
2359
2360 default:
2361 OMAP_BAD_REG(addr);
2362 }
2363}
2364
2365static CPUReadMemoryFunc *omap_ulpd_pm_readfn[] = {
2366 omap_badwidth_read16,
2367 omap_ulpd_pm_read,
2368 omap_badwidth_read16,
2369};
2370
2371static CPUWriteMemoryFunc *omap_ulpd_pm_writefn[] = {
2372 omap_badwidth_write16,
2373 omap_ulpd_pm_write,
2374 omap_badwidth_write16,
2375};
2376
2377static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
2378{
2379 mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
2380 mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
2381 mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
2382 mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
2383 mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
2384 mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
2385 mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
2386 mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
2387 mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
2388 mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
2389 mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
2390 omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
2391 mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
2392 omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
2393 mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
2394 mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
2395 mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
2396 mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
2397 mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
2398 mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
2399 mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
2400 omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
2401 omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
2402}
2403
2404static void omap_ulpd_pm_init(target_phys_addr_t base,
2405 struct omap_mpu_state_s *mpu)
2406{
2407 int iomemtype = cpu_register_io_memory(0, omap_ulpd_pm_readfn,
2408 omap_ulpd_pm_writefn, mpu);
2409
2410 mpu->ulpd_pm_base = base;
2411 cpu_register_physical_memory(mpu->ulpd_pm_base, 0x800, iomemtype);
2412 omap_ulpd_pm_reset(mpu);
2413}
2414
2415/* OMAP Pin Configuration */
2416static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr)
2417{
2418 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2419 int offset = addr - s->pin_cfg_base;
2420
2421 switch (offset) {
2422 case 0x00: /* FUNC_MUX_CTRL_0 */
2423 case 0x04: /* FUNC_MUX_CTRL_1 */
2424 case 0x08: /* FUNC_MUX_CTRL_2 */
2425 return s->func_mux_ctrl[offset >> 2];
2426
2427 case 0x0c: /* COMP_MODE_CTRL_0 */
2428 return s->comp_mode_ctrl[0];
2429
2430 case 0x10: /* FUNC_MUX_CTRL_3 */
2431 case 0x14: /* FUNC_MUX_CTRL_4 */
2432 case 0x18: /* FUNC_MUX_CTRL_5 */
2433 case 0x1c: /* FUNC_MUX_CTRL_6 */
2434 case 0x20: /* FUNC_MUX_CTRL_7 */
2435 case 0x24: /* FUNC_MUX_CTRL_8 */
2436 case 0x28: /* FUNC_MUX_CTRL_9 */
2437 case 0x2c: /* FUNC_MUX_CTRL_A */
2438 case 0x30: /* FUNC_MUX_CTRL_B */
2439 case 0x34: /* FUNC_MUX_CTRL_C */
2440 case 0x38: /* FUNC_MUX_CTRL_D */
2441 return s->func_mux_ctrl[(offset >> 2) - 1];
2442
2443 case 0x40: /* PULL_DWN_CTRL_0 */
2444 case 0x44: /* PULL_DWN_CTRL_1 */
2445 case 0x48: /* PULL_DWN_CTRL_2 */
2446 case 0x4c: /* PULL_DWN_CTRL_3 */
2447 return s->pull_dwn_ctrl[(offset & 0xf) >> 2];
2448
2449 case 0x50: /* GATE_INH_CTRL_0 */
2450 return s->gate_inh_ctrl[0];
2451
2452 case 0x60: /* VOLTAGE_CTRL_0 */
2453 return s->voltage_ctrl[0];
2454
2455 case 0x70: /* TEST_DBG_CTRL_0 */
2456 return s->test_dbg_ctrl[0];
2457
2458 case 0x80: /* MOD_CONF_CTRL_0 */
2459 return s->mod_conf_ctrl[0];
2460 }
2461
2462 OMAP_BAD_REG(addr);
2463 return 0;
2464}
2465
2466static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
2467 uint32_t diff, uint32_t value)
2468{
2469 if (s->compat1509) {
2470 if (diff & (1 << 9)) /* BLUETOOTH */
2471 omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
2472 (~value >> 9) & 1);
2473 if (diff & (1 << 7)) /* USB.CLKO */
2474 omap_clk_onoff(omap_findclk(s, "usb.clko"),
2475 (value >> 7) & 1);
2476 }
2477}
2478
2479static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
2480 uint32_t diff, uint32_t value)
2481{
2482 if (s->compat1509) {
2483 if (diff & (1 << 31)) /* MCBSP3_CLK_HIZ_DI */
2484 omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
2485 (value >> 31) & 1);
2486 if (diff & (1 << 1)) /* CLK32K */
2487 omap_clk_onoff(omap_findclk(s, "clk32k_out"),
2488 (~value >> 1) & 1);
2489 }
2490}
2491
2492static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
2493 uint32_t diff, uint32_t value)
2494{
2495 if (diff & (1 << 31)) /* CONF_MOD_UART3_CLK_MODE_R */
2496 omap_clk_reparent(omap_findclk(s, "uart3_ck"),
2497 omap_findclk(s, ((value >> 31) & 1) ?
2498 "ck_48m" : "armper_ck"));
2499 if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */
2500 omap_clk_reparent(omap_findclk(s, "uart2_ck"),
2501 omap_findclk(s, ((value >> 30) & 1) ?
2502 "ck_48m" : "armper_ck"));
2503 if (diff & (1 << 29)) /* CONF_MOD_UART1_CLK_MODE_R */
2504 omap_clk_reparent(omap_findclk(s, "uart1_ck"),
2505 omap_findclk(s, ((value >> 29) & 1) ?
2506 "ck_48m" : "armper_ck"));
2507 if (diff & (1 << 23)) /* CONF_MOD_MMC_SD_CLK_REQ_R */
2508 omap_clk_reparent(omap_findclk(s, "mmc_ck"),
2509 omap_findclk(s, ((value >> 23) & 1) ?
2510 "ck_48m" : "armper_ck"));
2511 if (diff & (1 << 12)) /* CONF_MOD_COM_MCLK_12_48_S */
2512 omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
2513 omap_findclk(s, ((value >> 12) & 1) ?
2514 "ck_48m" : "armper_ck"));
2515 if (diff & (1 << 9)) /* CONF_MOD_USB_HOST_HHC_UHO */
2516 omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
2517}
2518
2519static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr,
2520 uint32_t value)
2521{
2522 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2523 int offset = addr - s->pin_cfg_base;
2524 uint32_t diff;
2525
2526 switch (offset) {
2527 case 0x00: /* FUNC_MUX_CTRL_0 */
2528 diff = s->func_mux_ctrl[offset >> 2] ^ value;
2529 s->func_mux_ctrl[offset >> 2] = value;
2530 omap_pin_funcmux0_update(s, diff, value);
2531 return;
2532
2533 case 0x04: /* FUNC_MUX_CTRL_1 */
2534 diff = s->func_mux_ctrl[offset >> 2] ^ value;
2535 s->func_mux_ctrl[offset >> 2] = value;
2536 omap_pin_funcmux1_update(s, diff, value);
2537 return;
2538
2539 case 0x08: /* FUNC_MUX_CTRL_2 */
2540 s->func_mux_ctrl[offset >> 2] = value;
2541 return;
2542
2543 case 0x0c: /* COMP_MODE_CTRL_0 */
2544 s->comp_mode_ctrl[0] = value;
2545 s->compat1509 = (value != 0x0000eaef);
2546 omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
2547 omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
2548 return;
2549
2550 case 0x10: /* FUNC_MUX_CTRL_3 */
2551 case 0x14: /* FUNC_MUX_CTRL_4 */
2552 case 0x18: /* FUNC_MUX_CTRL_5 */
2553 case 0x1c: /* FUNC_MUX_CTRL_6 */
2554 case 0x20: /* FUNC_MUX_CTRL_7 */
2555 case 0x24: /* FUNC_MUX_CTRL_8 */
2556 case 0x28: /* FUNC_MUX_CTRL_9 */
2557 case 0x2c: /* FUNC_MUX_CTRL_A */
2558 case 0x30: /* FUNC_MUX_CTRL_B */
2559 case 0x34: /* FUNC_MUX_CTRL_C */
2560 case 0x38: /* FUNC_MUX_CTRL_D */
2561 s->func_mux_ctrl[(offset >> 2) - 1] = value;
2562 return;
2563
2564 case 0x40: /* PULL_DWN_CTRL_0 */
2565 case 0x44: /* PULL_DWN_CTRL_1 */
2566 case 0x48: /* PULL_DWN_CTRL_2 */
2567 case 0x4c: /* PULL_DWN_CTRL_3 */
2568 s->pull_dwn_ctrl[(offset & 0xf) >> 2] = value;
2569 return;
2570
2571 case 0x50: /* GATE_INH_CTRL_0 */
2572 s->gate_inh_ctrl[0] = value;
2573 return;
2574
2575 case 0x60: /* VOLTAGE_CTRL_0 */
2576 s->voltage_ctrl[0] = value;
2577 return;
2578
2579 case 0x70: /* TEST_DBG_CTRL_0 */
2580 s->test_dbg_ctrl[0] = value;
2581 return;
2582
2583 case 0x80: /* MOD_CONF_CTRL_0 */
2584 diff = s->mod_conf_ctrl[0] ^ value;
2585 s->mod_conf_ctrl[0] = value;
2586 omap_pin_modconf1_update(s, diff, value);
2587 return;
2588
2589 default:
2590 OMAP_BAD_REG(addr);
2591 }
2592}
2593
2594static CPUReadMemoryFunc *omap_pin_cfg_readfn[] = {
2595 omap_badwidth_read32,
2596 omap_badwidth_read32,
2597 omap_pin_cfg_read,
2598};
2599
2600static CPUWriteMemoryFunc *omap_pin_cfg_writefn[] = {
2601 omap_badwidth_write32,
2602 omap_badwidth_write32,
2603 omap_pin_cfg_write,
2604};
2605
2606static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
2607{
2608 /* Start in Compatibility Mode. */
2609 mpu->compat1509 = 1;
2610 omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
2611 omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
2612 omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
2613 memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
2614 memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
2615 memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
2616 memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
2617 memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
2618 memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
2619 memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
2620}
2621
2622static void omap_pin_cfg_init(target_phys_addr_t base,
2623 struct omap_mpu_state_s *mpu)
2624{
2625 int iomemtype = cpu_register_io_memory(0, omap_pin_cfg_readfn,
2626 omap_pin_cfg_writefn, mpu);
2627
2628 mpu->pin_cfg_base = base;
2629 cpu_register_physical_memory(mpu->pin_cfg_base, 0x800, iomemtype);
2630 omap_pin_cfg_reset(mpu);
2631}
2632
2633/* Device Identification, Die Identification */
2634static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
2635{
2636 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2637
2638 switch (addr) {
2639 case 0xfffe1800: /* DIE_ID_LSB */
2640 return 0xc9581f0e;
2641 case 0xfffe1804: /* DIE_ID_MSB */
2642 return 0xa8858bfa;
2643
2644 case 0xfffe2000: /* PRODUCT_ID_LSB */
2645 return 0x00aaaafc;
2646 case 0xfffe2004: /* PRODUCT_ID_MSB */
2647 return 0xcafeb574;
2648
2649 case 0xfffed400: /* JTAG_ID_LSB */
2650 switch (s->mpu_model) {
2651 case omap310:
2652 return 0x03310315;
2653 case omap1510:
2654 return 0x03310115;
2655 }
2656 break;
2657
2658 case 0xfffed404: /* JTAG_ID_MSB */
2659 switch (s->mpu_model) {
2660 case omap310:
2661 return 0xfb57402f;
2662 case omap1510:
2663 return 0xfb47002f;
2664 }
2665 break;
2666 }
2667
2668 OMAP_BAD_REG(addr);
2669 return 0;
2670}
2671
2672static void omap_id_write(void *opaque, target_phys_addr_t addr,
2673 uint32_t value)
2674{
2675 OMAP_BAD_REG(addr);
2676}
2677
2678static CPUReadMemoryFunc *omap_id_readfn[] = {
2679 omap_badwidth_read32,
2680 omap_badwidth_read32,
2681 omap_id_read,
2682};
2683
2684static CPUWriteMemoryFunc *omap_id_writefn[] = {
2685 omap_badwidth_write32,
2686 omap_badwidth_write32,
2687 omap_id_write,
2688};
2689
2690static void omap_id_init(struct omap_mpu_state_s *mpu)
2691{
2692 int iomemtype = cpu_register_io_memory(0, omap_id_readfn,
2693 omap_id_writefn, mpu);
2694 cpu_register_physical_memory(0xfffe1800, 0x800, iomemtype);
2695 cpu_register_physical_memory(0xfffed400, 0x100, iomemtype);
2696 if (!cpu_is_omap15xx(mpu))
2697 cpu_register_physical_memory(0xfffe2000, 0x800, iomemtype);
2698}
2699
2700/* MPUI Control (Dummy) */
2701static uint32_t omap_mpui_read(void *opaque, target_phys_addr_t addr)
2702{
2703 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2704 int offset = addr - s->mpui_base;
2705
2706 switch (offset) {
2707 case 0x00: /* CTRL */
2708 return s->mpui_ctrl;
2709 case 0x04: /* DEBUG_ADDR */
2710 return 0x01ffffff;
2711 case 0x08: /* DEBUG_DATA */
2712 return 0xffffffff;
2713 case 0x0c: /* DEBUG_FLAG */
2714 return 0x00000800;
2715 case 0x10: /* STATUS */
2716 return 0x00000000;
2717
2718 /* Not in OMAP310 */
2719 case 0x14: /* DSP_STATUS */
2720 case 0x18: /* DSP_BOOT_CONFIG */
2721 return 0x00000000;
2722 case 0x1c: /* DSP_MPUI_CONFIG */
2723 return 0x0000ffff;
2724 }
2725
2726 OMAP_BAD_REG(addr);
2727 return 0;
2728}
2729
2730static void omap_mpui_write(void *opaque, target_phys_addr_t addr,
2731 uint32_t value)
2732{
2733 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2734 int offset = addr - s->mpui_base;
2735
2736 switch (offset) {
2737 case 0x00: /* CTRL */
2738 s->mpui_ctrl = value & 0x007fffff;
2739 break;
2740
2741 case 0x04: /* DEBUG_ADDR */
2742 case 0x08: /* DEBUG_DATA */
2743 case 0x0c: /* DEBUG_FLAG */
2744 case 0x10: /* STATUS */
2745 /* Not in OMAP310 */
2746 case 0x14: /* DSP_STATUS */
2747 OMAP_RO_REG(addr);
2748 case 0x18: /* DSP_BOOT_CONFIG */
2749 case 0x1c: /* DSP_MPUI_CONFIG */
2750 break;
2751
2752 default:
2753 OMAP_BAD_REG(addr);
2754 }
2755}
2756
2757static CPUReadMemoryFunc *omap_mpui_readfn[] = {
2758 omap_badwidth_read32,
2759 omap_badwidth_read32,
2760 omap_mpui_read,
2761};
2762
2763static CPUWriteMemoryFunc *omap_mpui_writefn[] = {
2764 omap_badwidth_write32,
2765 omap_badwidth_write32,
2766 omap_mpui_write,
2767};
2768
2769static void omap_mpui_reset(struct omap_mpu_state_s *s)
2770{
2771 s->mpui_ctrl = 0x0003ff1b;
2772}
2773
2774static void omap_mpui_init(target_phys_addr_t base,
2775 struct omap_mpu_state_s *mpu)
2776{
2777 int iomemtype = cpu_register_io_memory(0, omap_mpui_readfn,
2778 omap_mpui_writefn, mpu);
2779
2780 mpu->mpui_base = base;
2781 cpu_register_physical_memory(mpu->mpui_base, 0x100, iomemtype);
2782
2783 omap_mpui_reset(mpu);
2784}
2785
2786/* TIPB Bridges */
2787struct omap_tipb_bridge_s {
2788 target_phys_addr_t base;
2789 qemu_irq abort;
2790
2791 int width_intr;
2792 uint16_t control;
2793 uint16_t alloc;
2794 uint16_t buffer;
2795 uint16_t enh_control;
2796};
2797
2798static uint32_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr)
2799{
2800 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
2801 int offset = addr - s->base;
2802
2803 switch (offset) {
2804 case 0x00: /* TIPB_CNTL */
2805 return s->control;
2806 case 0x04: /* TIPB_BUS_ALLOC */
2807 return s->alloc;
2808 case 0x08: /* MPU_TIPB_CNTL */
2809 return s->buffer;
2810 case 0x0c: /* ENHANCED_TIPB_CNTL */
2811 return s->enh_control;
2812 case 0x10: /* ADDRESS_DBG */
2813 case 0x14: /* DATA_DEBUG_LOW */
2814 case 0x18: /* DATA_DEBUG_HIGH */
2815 return 0xffff;
2816 case 0x1c: /* DEBUG_CNTR_SIG */
2817 return 0x00f8;
2818 }
2819
2820 OMAP_BAD_REG(addr);
2821 return 0;
2822}
2823
2824static void omap_tipb_bridge_write(void *opaque, target_phys_addr_t addr,
2825 uint32_t value)
2826{
2827 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
2828 int offset = addr - s->base;
2829
2830 switch (offset) {
2831 case 0x00: /* TIPB_CNTL */
2832 s->control = value & 0xffff;
2833 break;
2834
2835 case 0x04: /* TIPB_BUS_ALLOC */
2836 s->alloc = value & 0x003f;
2837 break;
2838
2839 case 0x08: /* MPU_TIPB_CNTL */
2840 s->buffer = value & 0x0003;
2841 break;
2842
2843 case 0x0c: /* ENHANCED_TIPB_CNTL */
2844 s->width_intr = !(value & 2);
2845 s->enh_control = value & 0x000f;
2846 break;
2847
2848 case 0x10: /* ADDRESS_DBG */
2849 case 0x14: /* DATA_DEBUG_LOW */
2850 case 0x18: /* DATA_DEBUG_HIGH */
2851 case 0x1c: /* DEBUG_CNTR_SIG */
2852 OMAP_RO_REG(addr);
2853 break;
2854
2855 default:
2856 OMAP_BAD_REG(addr);
2857 }
2858}
2859
2860static CPUReadMemoryFunc *omap_tipb_bridge_readfn[] = {
2861 omap_badwidth_read16,
2862 omap_tipb_bridge_read,
2863 omap_tipb_bridge_read,
2864};
2865
2866static CPUWriteMemoryFunc *omap_tipb_bridge_writefn[] = {
2867 omap_badwidth_write16,
2868 omap_tipb_bridge_write,
2869 omap_tipb_bridge_write,
2870};
2871
2872static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
2873{
2874 s->control = 0xffff;
2875 s->alloc = 0x0009;
2876 s->buffer = 0x0000;
2877 s->enh_control = 0x000f;
2878}
2879
2880struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
2881 qemu_irq abort_irq, omap_clk clk)
2882{
2883 int iomemtype;
2884 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
2885 qemu_mallocz(sizeof(struct omap_tipb_bridge_s));
2886
2887 s->abort = abort_irq;
2888 s->base = base;
2889 omap_tipb_bridge_reset(s);
2890
2891 iomemtype = cpu_register_io_memory(0, omap_tipb_bridge_readfn,
2892 omap_tipb_bridge_writefn, s);
2893 cpu_register_physical_memory(s->base, 0x100, iomemtype);
2894
2895 return s;
2896}
2897
2898/* Dummy Traffic Controller's Memory Interface */
2899static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
2900{
2901 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2902 int offset = addr - s->tcmi_base;
2903 uint32_t ret;
2904
2905 switch (offset) {
d8f699cb
AZ
2906 case 0x00: /* IMIF_PRIO */
2907 case 0x04: /* EMIFS_PRIO */
2908 case 0x08: /* EMIFF_PRIO */
2909 case 0x0c: /* EMIFS_CONFIG */
2910 case 0x10: /* EMIFS_CS0_CONFIG */
2911 case 0x14: /* EMIFS_CS1_CONFIG */
2912 case 0x18: /* EMIFS_CS2_CONFIG */
2913 case 0x1c: /* EMIFS_CS3_CONFIG */
2914 case 0x24: /* EMIFF_MRS */
2915 case 0x28: /* TIMEOUT1 */
2916 case 0x2c: /* TIMEOUT2 */
2917 case 0x30: /* TIMEOUT3 */
2918 case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
2919 case 0x40: /* EMIFS_CFG_DYN_WAIT */
c3d2689d
AZ
2920 return s->tcmi_regs[offset >> 2];
2921
d8f699cb 2922 case 0x20: /* EMIFF_SDRAM_CONFIG */
c3d2689d
AZ
2923 ret = s->tcmi_regs[offset >> 2];
2924 s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
2925 /* XXX: We can try using the VGA_DIRTY flag for this */
2926 return ret;
2927 }
2928
2929 OMAP_BAD_REG(addr);
2930 return 0;
2931}
2932
2933static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
2934 uint32_t value)
2935{
2936 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2937 int offset = addr - s->tcmi_base;
2938
2939 switch (offset) {
d8f699cb
AZ
2940 case 0x00: /* IMIF_PRIO */
2941 case 0x04: /* EMIFS_PRIO */
2942 case 0x08: /* EMIFF_PRIO */
2943 case 0x10: /* EMIFS_CS0_CONFIG */
2944 case 0x14: /* EMIFS_CS1_CONFIG */
2945 case 0x18: /* EMIFS_CS2_CONFIG */
2946 case 0x1c: /* EMIFS_CS3_CONFIG */
2947 case 0x20: /* EMIFF_SDRAM_CONFIG */
2948 case 0x24: /* EMIFF_MRS */
2949 case 0x28: /* TIMEOUT1 */
2950 case 0x2c: /* TIMEOUT2 */
2951 case 0x30: /* TIMEOUT3 */
2952 case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
2953 case 0x40: /* EMIFS_CFG_DYN_WAIT */
c3d2689d
AZ
2954 s->tcmi_regs[offset >> 2] = value;
2955 break;
d8f699cb 2956 case 0x0c: /* EMIFS_CONFIG */
c3d2689d
AZ
2957 s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4);
2958 break;
2959
2960 default:
2961 OMAP_BAD_REG(addr);
2962 }
2963}
2964
2965static CPUReadMemoryFunc *omap_tcmi_readfn[] = {
2966 omap_badwidth_read32,
2967 omap_badwidth_read32,
2968 omap_tcmi_read,
2969};
2970
2971static CPUWriteMemoryFunc *omap_tcmi_writefn[] = {
2972 omap_badwidth_write32,
2973 omap_badwidth_write32,
2974 omap_tcmi_write,
2975};
2976
2977static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
2978{
2979 mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
2980 mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
2981 mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
2982 mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
2983 mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
2984 mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
2985 mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
2986 mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
2987 mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
2988 mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
2989 mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
2990 mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
2991 mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
2992 mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
2993 mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
2994}
2995
2996static void omap_tcmi_init(target_phys_addr_t base,
2997 struct omap_mpu_state_s *mpu)
2998{
2999 int iomemtype = cpu_register_io_memory(0, omap_tcmi_readfn,
3000 omap_tcmi_writefn, mpu);
3001
3002 mpu->tcmi_base = base;
3003 cpu_register_physical_memory(mpu->tcmi_base, 0x100, iomemtype);
3004 omap_tcmi_reset(mpu);
3005}
3006
3007/* Digital phase-locked loops control */
3008static uint32_t omap_dpll_read(void *opaque, target_phys_addr_t addr)
3009{
3010 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
3011 int offset = addr - s->base;
3012
3013 if (offset == 0x00) /* CTL_REG */
3014 return s->mode;
3015
3016 OMAP_BAD_REG(addr);
3017 return 0;
3018}
3019
3020static void omap_dpll_write(void *opaque, target_phys_addr_t addr,
3021 uint32_t value)
3022{
3023 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
3024 uint16_t diff;
3025 int offset = addr - s->base;
3026 static const int bypass_div[4] = { 1, 2, 4, 4 };
3027 int div, mult;
3028
3029 if (offset == 0x00) { /* CTL_REG */
3030 /* See omap_ulpd_pm_write() too */
3031 diff = s->mode & value;
3032 s->mode = value & 0x2fff;
3033 if (diff & (0x3ff << 2)) {
3034 if (value & (1 << 4)) { /* PLL_ENABLE */
3035 div = ((value >> 5) & 3) + 1; /* PLL_DIV */
3036 mult = MIN((value >> 7) & 0x1f, 1); /* PLL_MULT */
3037 } else {
3038 div = bypass_div[((value >> 2) & 3)]; /* BYPASS_DIV */
3039 mult = 1;
3040 }
3041 omap_clk_setrate(s->dpll, div, mult);
3042 }
3043
3044 /* Enter the desired mode. */
3045 s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
3046
3047 /* Act as if the lock is restored. */
3048 s->mode |= 2;
3049 } else {
3050 OMAP_BAD_REG(addr);
3051 }
3052}
3053
3054static CPUReadMemoryFunc *omap_dpll_readfn[] = {
3055 omap_badwidth_read16,
3056 omap_dpll_read,
3057 omap_badwidth_read16,
3058};
3059
3060static CPUWriteMemoryFunc *omap_dpll_writefn[] = {
3061 omap_badwidth_write16,
3062 omap_dpll_write,
3063 omap_badwidth_write16,
3064};
3065
3066static void omap_dpll_reset(struct dpll_ctl_s *s)
3067{
3068 s->mode = 0x2002;
3069 omap_clk_setrate(s->dpll, 1, 1);
3070}
3071
3072static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
3073 omap_clk clk)
3074{
3075 int iomemtype = cpu_register_io_memory(0, omap_dpll_readfn,
3076 omap_dpll_writefn, s);
3077
3078 s->base = base;
3079 s->dpll = clk;
3080 omap_dpll_reset(s);
3081
3082 cpu_register_physical_memory(s->base, 0x100, iomemtype);
3083}
3084
3085/* UARTs */
3086struct omap_uart_s {
3087 SerialState *serial; /* TODO */
3088};
3089
3090static void omap_uart_reset(struct omap_uart_s *s)
3091{
3092}
3093
3094struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
3095 qemu_irq irq, omap_clk clk, CharDriverState *chr)
3096{
3097 struct omap_uart_s *s = (struct omap_uart_s *)
3098 qemu_mallocz(sizeof(struct omap_uart_s));
3099 if (chr)
3100 s->serial = serial_mm_init(base, 2, irq, chr, 1);
3101 return s;
3102}
3103
3104/* MPU Clock/Reset/Power Mode Control */
3105static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
3106{
3107 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
3108 int offset = addr - s->clkm.mpu_base;
3109
3110 switch (offset) {
3111 case 0x00: /* ARM_CKCTL */
3112 return s->clkm.arm_ckctl;
3113
3114 case 0x04: /* ARM_IDLECT1 */
3115 return s->clkm.arm_idlect1;
3116
3117 case 0x08: /* ARM_IDLECT2 */
3118 return s->clkm.arm_idlect2;
3119
3120 case 0x0c: /* ARM_EWUPCT */
3121 return s->clkm.arm_ewupct;
3122
3123 case 0x10: /* ARM_RSTCT1 */
3124 return s->clkm.arm_rstct1;
3125
3126 case 0x14: /* ARM_RSTCT2 */
3127 return s->clkm.arm_rstct2;
3128
3129 case 0x18: /* ARM_SYSST */
d8f699cb 3130 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
c3d2689d
AZ
3131
3132 case 0x1c: /* ARM_CKOUT1 */
3133 return s->clkm.arm_ckout1;
3134
3135 case 0x20: /* ARM_CKOUT2 */
3136 break;
3137 }
3138
3139 OMAP_BAD_REG(addr);
3140 return 0;
3141}
3142
3143static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
3144 uint16_t diff, uint16_t value)
3145{
3146 omap_clk clk;
3147
3148 if (diff & (1 << 14)) { /* ARM_INTHCK_SEL */
3149 if (value & (1 << 14))
3150 /* Reserved */;
3151 else {
3152 clk = omap_findclk(s, "arminth_ck");
3153 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
3154 }
3155 }
3156 if (diff & (1 << 12)) { /* ARM_TIMXO */
3157 clk = omap_findclk(s, "armtim_ck");
3158 if (value & (1 << 12))
3159 omap_clk_reparent(clk, omap_findclk(s, "clkin"));
3160 else
3161 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
3162 }
3163 /* XXX: en_dspck */
3164 if (diff & (3 << 10)) { /* DSPMMUDIV */
3165 clk = omap_findclk(s, "dspmmu_ck");
3166 omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
3167 }
3168 if (diff & (3 << 8)) { /* TCDIV */
3169 clk = omap_findclk(s, "tc_ck");
3170 omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
3171 }
3172 if (diff & (3 << 6)) { /* DSPDIV */
3173 clk = omap_findclk(s, "dsp_ck");
3174 omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
3175 }
3176 if (diff & (3 << 4)) { /* ARMDIV */
3177 clk = omap_findclk(s, "arm_ck");
3178 omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
3179 }
3180 if (diff & (3 << 2)) { /* LCDDIV */
3181 clk = omap_findclk(s, "lcd_ck");
3182 omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
3183 }
3184 if (diff & (3 << 0)) { /* PERDIV */
3185 clk = omap_findclk(s, "armper_ck");
3186 omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
3187 }
3188}
3189
3190static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
3191 uint16_t diff, uint16_t value)
3192{
3193 omap_clk clk;
3194
3195 if (value & (1 << 11)) /* SETARM_IDLE */
3196 cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
3197 if (!(value & (1 << 10))) /* WKUP_MODE */
3198 qemu_system_shutdown_request(); /* XXX: disable wakeup from IRQ */
3199
3200#define SET_CANIDLE(clock, bit) \
3201 if (diff & (1 << bit)) { \
3202 clk = omap_findclk(s, clock); \
3203 omap_clk_canidle(clk, (value >> bit) & 1); \
3204 }
3205 SET_CANIDLE("mpuwd_ck", 0) /* IDLWDT_ARM */
3206 SET_CANIDLE("armxor_ck", 1) /* IDLXORP_ARM */
3207 SET_CANIDLE("mpuper_ck", 2) /* IDLPER_ARM */
3208 SET_CANIDLE("lcd_ck", 3) /* IDLLCD_ARM */
3209 SET_CANIDLE("lb_ck", 4) /* IDLLB_ARM */
3210 SET_CANIDLE("hsab_ck", 5) /* IDLHSAB_ARM */
3211 SET_CANIDLE("tipb_ck", 6) /* IDLIF_ARM */
3212 SET_CANIDLE("dma_ck", 6) /* IDLIF_ARM */
3213 SET_CANIDLE("tc_ck", 6) /* IDLIF_ARM */
3214 SET_CANIDLE("dpll1", 7) /* IDLDPLL_ARM */
3215 SET_CANIDLE("dpll2", 7) /* IDLDPLL_ARM */
3216 SET_CANIDLE("dpll3", 7) /* IDLDPLL_ARM */
3217 SET_CANIDLE("mpui_ck", 8) /* IDLAPI_ARM */
3218 SET_CANIDLE("armtim_ck", 9) /* IDLTIM_ARM */
3219}
3220
3221static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
3222 uint16_t diff, uint16_t value)
3223{
3224 omap_clk clk;
3225
3226#define SET_ONOFF(clock, bit) \
3227 if (diff & (1 << bit)) { \
3228 clk = omap_findclk(s, clock); \
3229 omap_clk_onoff(clk, (value >> bit) & 1); \
3230 }
3231 SET_ONOFF("mpuwd_ck", 0) /* EN_WDTCK */
3232 SET_ONOFF("armxor_ck", 1) /* EN_XORPCK */
3233 SET_ONOFF("mpuper_ck", 2) /* EN_PERCK */
3234 SET_ONOFF("lcd_ck", 3) /* EN_LCDCK */
3235 SET_ONOFF("lb_ck", 4) /* EN_LBCK */
3236 SET_ONOFF("hsab_ck", 5) /* EN_HSABCK */
3237 SET_ONOFF("mpui_ck", 6) /* EN_APICK */
3238 SET_ONOFF("armtim_ck", 7) /* EN_TIMCK */
3239 SET_CANIDLE("dma_ck", 8) /* DMACK_REQ */
3240 SET_ONOFF("arm_gpio_ck", 9) /* EN_GPIOCK */
3241 SET_ONOFF("lbfree_ck", 10) /* EN_LBFREECK */
3242}
3243
3244static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
3245 uint16_t diff, uint16_t value)
3246{
3247 omap_clk clk;
3248
3249 if (diff & (3 << 4)) { /* TCLKOUT */
3250 clk = omap_findclk(s, "tclk_out");
3251 switch ((value >> 4) & 3) {
3252 case 1:
3253 omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
3254 omap_clk_onoff(clk, 1);
3255 break;
3256 case 2:
3257 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
3258 omap_clk_onoff(clk, 1);
3259 break;
3260 default:
3261 omap_clk_onoff(clk, 0);
3262 }
3263 }
3264 if (diff & (3 << 2)) { /* DCLKOUT */
3265 clk = omap_findclk(s, "dclk_out");
3266 switch ((value >> 2) & 3) {
3267 case 0:
3268 omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
3269 break;
3270 case 1:
3271 omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
3272 break;
3273 case 2:
3274 omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
3275 break;
3276 case 3:
3277 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
3278 break;
3279 }
3280 }
3281 if (diff & (3 << 0)) { /* ACLKOUT */
3282 clk = omap_findclk(s, "aclk_out");
3283 switch ((value >> 0) & 3) {
3284 case 1:
3285 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
3286 omap_clk_onoff(clk, 1);
3287 break;
3288 case 2:
3289 omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
3290 omap_clk_onoff(clk, 1);
3291 break;
3292 case 3:
3293 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
3294 omap_clk_onoff(clk, 1);
3295 break;
3296 default:
3297 omap_clk_onoff(clk, 0);
3298 }
3299 }
3300}
3301
3302static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
3303 uint32_t value)
3304{
3305 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
3306 int offset = addr - s->clkm.mpu_base;
3307 uint16_t diff;
3308 omap_clk clk;
3309 static const char *clkschemename[8] = {
3310 "fully synchronous", "fully asynchronous", "synchronous scalable",
3311 "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
3312 };
3313
3314 switch (offset) {
3315 case 0x00: /* ARM_CKCTL */
3316 diff = s->clkm.arm_ckctl ^ value;
3317 s->clkm.arm_ckctl = value & 0x7fff;
3318 omap_clkm_ckctl_update(s, diff, value);
3319 return;
3320
3321 case 0x04: /* ARM_IDLECT1 */
3322 diff = s->clkm.arm_idlect1 ^ value;
3323 s->clkm.arm_idlect1 = value & 0x0fff;
3324 omap_clkm_idlect1_update(s, diff, value);
3325 return;
3326
3327 case 0x08: /* ARM_IDLECT2 */
3328 diff = s->clkm.arm_idlect2 ^ value;
3329 s->clkm.arm_idlect2 = value & 0x07ff;
3330 omap_clkm_idlect2_update(s, diff, value);
3331 return;
3332
3333 case 0x0c: /* ARM_EWUPCT */
3334 diff = s->clkm.arm_ewupct ^ value;
3335 s->clkm.arm_ewupct = value & 0x003f;
3336 return;
3337
3338 case 0x10: /* ARM_RSTCT1 */
3339 diff = s->clkm.arm_rstct1 ^ value;
3340 s->clkm.arm_rstct1 = value & 0x0007;
3341 if (value & 9) {
3342 qemu_system_reset_request();
3343 s->clkm.cold_start = 0xa;
3344 }
3345 if (diff & ~value & 4) { /* DSP_RST */
3346 omap_mpui_reset(s);
3347 omap_tipb_bridge_reset(s->private_tipb);
3348 omap_tipb_bridge_reset(s->public_tipb);
3349 }
3350 if (diff & 2) { /* DSP_EN */
3351 clk = omap_findclk(s, "dsp_ck");
3352 omap_clk_canidle(clk, (~value >> 1) & 1);
3353 }
3354 return;
3355
3356 case 0x14: /* ARM_RSTCT2 */
3357 s->clkm.arm_rstct2 = value & 0x0001;
3358 return;
3359
3360 case 0x18: /* ARM_SYSST */
3361 if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
3362 s->clkm.clocking_scheme = (value >> 11) & 7;
3363 printf("%s: clocking scheme set to %s\n", __FUNCTION__,
3364 clkschemename[s->clkm.clocking_scheme]);
3365 }
3366 s->clkm.cold_start &= value & 0x3f;
3367 return;
3368
3369 case 0x1c: /* ARM_CKOUT1 */
3370 diff = s->clkm.arm_ckout1 ^ value;
3371 s->clkm.arm_ckout1 = value & 0x003f;
3372 omap_clkm_ckout1_update(s, diff, value);
3373 return;
3374
3375 case 0x20: /* ARM_CKOUT2 */
3376 default:
3377 OMAP_BAD_REG(addr);
3378 }
3379}
3380
3381static CPUReadMemoryFunc *omap_clkm_readfn[] = {
3382 omap_badwidth_read16,
3383 omap_clkm_read,
3384 omap_badwidth_read16,
3385};
3386
3387static CPUWriteMemoryFunc *omap_clkm_writefn[] = {
3388 omap_badwidth_write16,
3389 omap_clkm_write,
3390 omap_badwidth_write16,
3391};
3392
3393static uint32_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr)
3394{
3395 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
3396 int offset = addr - s->clkm.dsp_base;
3397
3398 switch (offset) {
3399 case 0x04: /* DSP_IDLECT1 */
3400 return s->clkm.dsp_idlect1;
3401
3402 case 0x08: /* DSP_IDLECT2 */
3403 return s->clkm.dsp_idlect2;
3404
3405 case 0x14: /* DSP_RSTCT2 */
3406 return s->clkm.dsp_rstct2;
3407
3408 case 0x18: /* DSP_SYSST */
d8f699cb 3409 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
c3d2689d
AZ
3410 (s->env->halted << 6); /* Quite useless... */
3411 }
3412
3413 OMAP_BAD_REG(addr);
3414 return 0;
3415}
3416
3417static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
3418 uint16_t diff, uint16_t value)
3419{
3420 omap_clk clk;
3421
3422 SET_CANIDLE("dspxor_ck", 1); /* IDLXORP_DSP */
3423}
3424
3425static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
3426 uint16_t diff, uint16_t value)
3427{
3428 omap_clk clk;
3429
3430 SET_ONOFF("dspxor_ck", 1); /* EN_XORPCK */
3431}
3432
3433static void omap_clkdsp_write(void *opaque, target_phys_addr_t addr,
3434 uint32_t value)
3435{
3436 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
3437 int offset = addr - s->clkm.dsp_base;
3438 uint16_t diff;
3439
3440 switch (offset) {
3441 case 0x04: /* DSP_IDLECT1 */
3442 diff = s->clkm.dsp_idlect1 ^ value;
3443 s->clkm.dsp_idlect1 = value & 0x01f7;
3444 omap_clkdsp_idlect1_update(s, diff, value);
3445 break;
3446
3447 case 0x08: /* DSP_IDLECT2 */
3448 s->clkm.dsp_idlect2 = value & 0x0037;
3449 diff = s->clkm.dsp_idlect1 ^ value;
3450 omap_clkdsp_idlect2_update(s, diff, value);
3451 break;
3452
3453 case 0x14: /* DSP_RSTCT2 */
3454 s->clkm.dsp_rstct2 = value & 0x0001;
3455 break;
3456
3457 case 0x18: /* DSP_SYSST */
3458 s->clkm.cold_start &= value & 0x3f;
3459 break;
3460
3461 default:
3462 OMAP_BAD_REG(addr);
3463 }
3464}
3465
3466static CPUReadMemoryFunc *omap_clkdsp_readfn[] = {
3467 omap_badwidth_read16,
3468 omap_clkdsp_read,
3469 omap_badwidth_read16,
3470};
3471
3472static CPUWriteMemoryFunc *omap_clkdsp_writefn[] = {
3473 omap_badwidth_write16,
3474 omap_clkdsp_write,
3475 omap_badwidth_write16,
3476};
3477
3478static void omap_clkm_reset(struct omap_mpu_state_s *s)
3479{
3480 if (s->wdt && s->wdt->reset)
3481 s->clkm.cold_start = 0x6;
3482 s->clkm.clocking_scheme = 0;
3483 omap_clkm_ckctl_update(s, ~0, 0x3000);
3484 s->clkm.arm_ckctl = 0x3000;
d8f699cb 3485 omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
c3d2689d 3486 s->clkm.arm_idlect1 = 0x0400;
d8f699cb 3487 omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
c3d2689d
AZ
3488 s->clkm.arm_idlect2 = 0x0100;
3489 s->clkm.arm_ewupct = 0x003f;
3490 s->clkm.arm_rstct1 = 0x0000;
3491 s->clkm.arm_rstct2 = 0x0000;
3492 s->clkm.arm_ckout1 = 0x0015;
3493 s->clkm.dpll1_mode = 0x2002;
3494 omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
3495 s->clkm.dsp_idlect1 = 0x0040;
3496 omap_clkdsp_idlect2_update(s, ~0, 0x0000);
3497 s->clkm.dsp_idlect2 = 0x0000;
3498 s->clkm.dsp_rstct2 = 0x0000;
3499}
3500
3501static void omap_clkm_init(target_phys_addr_t mpu_base,
3502 target_phys_addr_t dsp_base, struct omap_mpu_state_s *s)
3503{
3504 int iomemtype[2] = {
3505 cpu_register_io_memory(0, omap_clkm_readfn, omap_clkm_writefn, s),
3506 cpu_register_io_memory(0, omap_clkdsp_readfn, omap_clkdsp_writefn, s),
3507 };
3508
3509 s->clkm.mpu_base = mpu_base;
3510 s->clkm.dsp_base = dsp_base;
d8f699cb
AZ
3511 s->clkm.arm_idlect1 = 0x03ff;
3512 s->clkm.arm_idlect2 = 0x0100;
3513 s->clkm.dsp_idlect1 = 0x0002;
c3d2689d 3514 omap_clkm_reset(s);
d8f699cb 3515 s->clkm.cold_start = 0x3a;
c3d2689d
AZ
3516
3517 cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]);
3518 cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
3519}
3520
fe71e81a
AZ
3521/* MPU I/O */
3522struct omap_mpuio_s {
3523 target_phys_addr_t base;
3524 qemu_irq irq;
3525 qemu_irq kbd_irq;
3526 qemu_irq *in;
3527 qemu_irq handler[16];
3528 qemu_irq wakeup;
3529
3530 uint16_t inputs;
3531 uint16_t outputs;
3532 uint16_t dir;
3533 uint16_t edge;
3534 uint16_t mask;
3535 uint16_t ints;
3536
3537 uint16_t debounce;
3538 uint16_t latch;
3539 uint8_t event;
3540
3541 uint8_t buttons[5];
3542 uint8_t row_latch;
3543 uint8_t cols;
3544 int kbd_mask;
3545 int clk;
3546};
3547
3548static void omap_mpuio_set(void *opaque, int line, int level)
3549{
3550 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
3551 uint16_t prev = s->inputs;
3552
3553 if (level)
3554 s->inputs |= 1 << line;
3555 else
3556 s->inputs &= ~(1 << line);
3557
3558 if (((1 << line) & s->dir & ~s->mask) && s->clk) {
3559 if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
3560 s->ints |= 1 << line;
3561 qemu_irq_raise(s->irq);
3562 /* TODO: wakeup */
3563 }
3564 if ((s->event & (1 << 0)) && /* SET_GPIO_EVENT_MODE */
3565 (s->event >> 1) == line) /* PIN_SELECT */
3566 s->latch = s->inputs;
3567 }
3568}
3569
3570static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
3571{
3572 int i;
3573 uint8_t *row, rows = 0, cols = ~s->cols;
3574
38a34e1d 3575 for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
fe71e81a 3576 if (*row & cols)
38a34e1d 3577 rows |= i;
fe71e81a 3578
38a34e1d 3579 qemu_set_irq(s->kbd_irq, rows && ~s->kbd_mask && s->clk);
fe71e81a
AZ
3580 s->row_latch = rows ^ 0x1f;
3581}
3582
3583static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
3584{
3585 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
cf965d24 3586 int offset = addr & OMAP_MPUI_REG_MASK;
fe71e81a
AZ
3587 uint16_t ret;
3588
3589 switch (offset) {
3590 case 0x00: /* INPUT_LATCH */
3591 return s->inputs;
3592
3593 case 0x04: /* OUTPUT_REG */
3594 return s->outputs;
3595
3596 case 0x08: /* IO_CNTL */
3597 return s->dir;
3598
3599 case 0x10: /* KBR_LATCH */
3600 return s->row_latch;
3601
3602 case 0x14: /* KBC_REG */
3603 return s->cols;
3604
3605 case 0x18: /* GPIO_EVENT_MODE_REG */
3606 return s->event;
3607
3608 case 0x1c: /* GPIO_INT_EDGE_REG */
3609 return s->edge;
3610
3611 case 0x20: /* KBD_INT */
3612 return (s->row_latch != 0x1f) && !s->kbd_mask;
3613
3614 case 0x24: /* GPIO_INT */
3615 ret = s->ints;
8e129e07
AZ
3616 s->ints &= s->mask;
3617 if (ret)
3618 qemu_irq_lower(s->irq);
fe71e81a
AZ
3619 return ret;
3620
3621 case 0x28: /* KBD_MASKIT */
3622 return s->kbd_mask;
3623
3624 case 0x2c: /* GPIO_MASKIT */
3625 return s->mask;
3626
3627 case 0x30: /* GPIO_DEBOUNCING_REG */
3628 return s->debounce;
3629
3630 case 0x34: /* GPIO_LATCH_REG */
3631 return s->latch;
3632 }
3633
3634 OMAP_BAD_REG(addr);
3635 return 0;
3636}
3637
3638static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
3639 uint32_t value)
3640{
3641 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
cf965d24 3642 int offset = addr & OMAP_MPUI_REG_MASK;
fe71e81a
AZ
3643 uint16_t diff;
3644 int ln;
3645
3646 switch (offset) {
3647 case 0x04: /* OUTPUT_REG */
d8f699cb 3648 diff = (s->outputs ^ value) & ~s->dir;
fe71e81a 3649 s->outputs = value;
fe71e81a
AZ
3650 while ((ln = ffs(diff))) {
3651 ln --;
3652 if (s->handler[ln])
3653 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3654 diff &= ~(1 << ln);
3655 }
3656 break;
3657
3658 case 0x08: /* IO_CNTL */
3659 diff = s->outputs & (s->dir ^ value);
3660 s->dir = value;
3661
3662 value = s->outputs & ~s->dir;
3663 while ((ln = ffs(diff))) {
3664 ln --;
3665 if (s->handler[ln])
3666 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3667 diff &= ~(1 << ln);
3668 }
3669 break;
3670
3671 case 0x14: /* KBC_REG */
3672 s->cols = value;
3673 omap_mpuio_kbd_update(s);
3674 break;
3675
3676 case 0x18: /* GPIO_EVENT_MODE_REG */
3677 s->event = value & 0x1f;
3678 break;
3679
3680 case 0x1c: /* GPIO_INT_EDGE_REG */
3681 s->edge = value;
3682 break;
3683
3684 case 0x28: /* KBD_MASKIT */
3685 s->kbd_mask = value & 1;
3686 omap_mpuio_kbd_update(s);
3687 break;
3688
3689 case 0x2c: /* GPIO_MASKIT */
3690 s->mask = value;
3691 break;
3692
3693 case 0x30: /* GPIO_DEBOUNCING_REG */
3694 s->debounce = value & 0x1ff;
3695 break;
3696
3697 case 0x00: /* INPUT_LATCH */
3698 case 0x10: /* KBR_LATCH */
3699 case 0x20: /* KBD_INT */
3700 case 0x24: /* GPIO_INT */
3701 case 0x34: /* GPIO_LATCH_REG */
3702 OMAP_RO_REG(addr);
3703 return;
3704
3705 default:
3706 OMAP_BAD_REG(addr);
3707 return;
3708 }
3709}
3710
3711static CPUReadMemoryFunc *omap_mpuio_readfn[] = {
3712 omap_badwidth_read16,
3713 omap_mpuio_read,
3714 omap_badwidth_read16,
3715};
3716
3717static CPUWriteMemoryFunc *omap_mpuio_writefn[] = {
3718 omap_badwidth_write16,
3719 omap_mpuio_write,
3720 omap_badwidth_write16,
3721};
3722
9596ebb7 3723static void omap_mpuio_reset(struct omap_mpuio_s *s)
fe71e81a
AZ
3724{
3725 s->inputs = 0;
3726 s->outputs = 0;
3727 s->dir = ~0;
3728 s->event = 0;
3729 s->edge = 0;
3730 s->kbd_mask = 0;
3731 s->mask = 0;
3732 s->debounce = 0;
3733 s->latch = 0;
3734 s->ints = 0;
3735 s->row_latch = 0x1f;
38a34e1d 3736 s->clk = 1;
fe71e81a
AZ
3737}
3738
3739static void omap_mpuio_onoff(void *opaque, int line, int on)
3740{
3741 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
3742
3743 s->clk = on;
3744 if (on)
3745 omap_mpuio_kbd_update(s);
3746}
3747
3748struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
3749 qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
3750 omap_clk clk)
3751{
3752 int iomemtype;
3753 struct omap_mpuio_s *s = (struct omap_mpuio_s *)
3754 qemu_mallocz(sizeof(struct omap_mpuio_s));
3755
3756 s->base = base;
3757 s->irq = gpio_int;
3758 s->kbd_irq = kbd_int;
3759 s->wakeup = wakeup;
3760 s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
3761 omap_mpuio_reset(s);
3762
3763 iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
3764 omap_mpuio_writefn, s);
3765 cpu_register_physical_memory(s->base, 0x800, iomemtype);
3766
3767 omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
3768
3769 return s;
3770}
3771
3772qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
3773{
3774 return s->in;
3775}
3776
3777void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
3778{
3779 if (line >= 16 || line < 0)
3780 cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3781 s->handler[line] = handler;
3782}
3783
3784void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
3785{
3786 if (row >= 5 || row < 0)
3787 cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
3788 __FUNCTION__, col, row);
3789
3790 if (down)
38a34e1d 3791 s->buttons[row] |= 1 << col;
fe71e81a 3792 else
38a34e1d 3793 s->buttons[row] &= ~(1 << col);
fe71e81a
AZ
3794
3795 omap_mpuio_kbd_update(s);
3796}
3797
64330148
AZ
3798/* General-Purpose I/O */
3799struct omap_gpio_s {
3800 target_phys_addr_t base;
3801 qemu_irq irq;
3802 qemu_irq *in;
3803 qemu_irq handler[16];
3804
3805 uint16_t inputs;
3806 uint16_t outputs;
3807 uint16_t dir;
3808 uint16_t edge;
3809 uint16_t mask;
3810 uint16_t ints;
d8f699cb 3811 uint16_t pins;
64330148
AZ
3812};
3813
3814static void omap_gpio_set(void *opaque, int line, int level)
3815{
3816 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3817 uint16_t prev = s->inputs;
3818
3819 if (level)
3820 s->inputs |= 1 << line;
3821 else
3822 s->inputs &= ~(1 << line);
3823
3824 if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
3825 (1 << line) & s->dir & ~s->mask) {
3826 s->ints |= 1 << line;
3827 qemu_irq_raise(s->irq);
3828 }
3829}
3830
3831static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3832{
3833 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
cf965d24 3834 int offset = addr & OMAP_MPUI_REG_MASK;
64330148
AZ
3835
3836 switch (offset) {
3837 case 0x00: /* DATA_INPUT */
d8f699cb 3838 return s->inputs & s->pins;
64330148
AZ
3839
3840 case 0x04: /* DATA_OUTPUT */
3841 return s->outputs;
3842
3843 case 0x08: /* DIRECTION_CONTROL */
3844 return s->dir;
3845
3846 case 0x0c: /* INTERRUPT_CONTROL */
3847 return s->edge;
3848
3849 case 0x10: /* INTERRUPT_MASK */
3850 return s->mask;
3851
3852 case 0x14: /* INTERRUPT_STATUS */
3853 return s->ints;
d8f699cb
AZ
3854
3855 case 0x18: /* PIN_CONTROL (not in OMAP310) */
3856 OMAP_BAD_REG(addr);
3857 return s->pins;
64330148
AZ
3858 }
3859
3860 OMAP_BAD_REG(addr);
3861 return 0;
3862}
3863
3864static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3865 uint32_t value)
3866{
3867 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
cf965d24 3868 int offset = addr & OMAP_MPUI_REG_MASK;
64330148
AZ
3869 uint16_t diff;
3870 int ln;
3871
3872 switch (offset) {
3873 case 0x00: /* DATA_INPUT */
3874 OMAP_RO_REG(addr);
3875 return;
3876
3877 case 0x04: /* DATA_OUTPUT */
66450b15 3878 diff = (s->outputs ^ value) & ~s->dir;
64330148 3879 s->outputs = value;
64330148
AZ
3880 while ((ln = ffs(diff))) {
3881 ln --;
3882 if (s->handler[ln])
3883 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3884 diff &= ~(1 << ln);
3885 }
3886 break;
3887
3888 case 0x08: /* DIRECTION_CONTROL */
3889 diff = s->outputs & (s->dir ^ value);
3890 s->dir = value;
3891
3892 value = s->outputs & ~s->dir;
3893 while ((ln = ffs(diff))) {
3894 ln --;
3895 if (s->handler[ln])
3896 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3897 diff &= ~(1 << ln);
3898 }
3899 break;
3900
3901 case 0x0c: /* INTERRUPT_CONTROL */
3902 s->edge = value;
3903 break;
3904
3905 case 0x10: /* INTERRUPT_MASK */
3906 s->mask = value;
3907 break;
3908
3909 case 0x14: /* INTERRUPT_STATUS */
3910 s->ints &= ~value;
3911 if (!s->ints)
3912 qemu_irq_lower(s->irq);
3913 break;
3914
d8f699cb
AZ
3915 case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
3916 OMAP_BAD_REG(addr);
3917 s->pins = value;
3918 break;
3919
64330148
AZ
3920 default:
3921 OMAP_BAD_REG(addr);
3922 return;
3923 }
3924}
3925
3efda49d 3926/* *Some* sources say the memory region is 32-bit. */
64330148 3927static CPUReadMemoryFunc *omap_gpio_readfn[] = {
3efda49d 3928 omap_badwidth_read16,
64330148 3929 omap_gpio_read,
3efda49d 3930 omap_badwidth_read16,
64330148
AZ
3931};
3932
3933static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
3efda49d 3934 omap_badwidth_write16,
64330148 3935 omap_gpio_write,
3efda49d 3936 omap_badwidth_write16,
64330148
AZ
3937};
3938
9596ebb7 3939static void omap_gpio_reset(struct omap_gpio_s *s)
64330148
AZ
3940{
3941 s->inputs = 0;
3942 s->outputs = ~0;
3943 s->dir = ~0;
3944 s->edge = ~0;
3945 s->mask = ~0;
3946 s->ints = 0;
d8f699cb 3947 s->pins = ~0;
64330148
AZ
3948}
3949
3950struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
3951 qemu_irq irq, omap_clk clk)
3952{
3953 int iomemtype;
3954 struct omap_gpio_s *s = (struct omap_gpio_s *)
3955 qemu_mallocz(sizeof(struct omap_gpio_s));
3956
3957 s->base = base;
3958 s->irq = irq;
3959 s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
3960 omap_gpio_reset(s);
3961
3962 iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
3963 omap_gpio_writefn, s);
3964 cpu_register_physical_memory(s->base, 0x1000, iomemtype);
3965
3966 return s;
3967}
3968
3969qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
3970{
3971 return s->in;
3972}
3973
3974void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
3975{
3976 if (line >= 16 || line < 0)
3977 cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3978 s->handler[line] = handler;
3979}
3980
d951f6ff
AZ
3981/* MicroWire Interface */
3982struct omap_uwire_s {
3983 target_phys_addr_t base;
3984 qemu_irq txirq;
3985 qemu_irq rxirq;
3986 qemu_irq txdrq;
3987
3988 uint16_t txbuf;
3989 uint16_t rxbuf;
3990 uint16_t control;
3991 uint16_t setup[5];
3992
3993 struct uwire_slave_s *chip[4];
3994};
3995
3996static void omap_uwire_transfer_start(struct omap_uwire_s *s)
3997{
3998 int chipselect = (s->control >> 10) & 3; /* INDEX */
3999 struct uwire_slave_s *slave = s->chip[chipselect];
4000
4001 if ((s->control >> 5) & 0x1f) { /* NB_BITS_WR */
4002 if (s->control & (1 << 12)) /* CS_CMD */
4003 if (slave && slave->send)
4004 slave->send(slave->opaque,
4005 s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
4006 s->control &= ~(1 << 14); /* CSRB */
4007 /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
4008 * a DRQ. When is the level IRQ supposed to be reset? */
4009 }
4010
4011 if ((s->control >> 0) & 0x1f) { /* NB_BITS_RD */
4012 if (s->control & (1 << 12)) /* CS_CMD */
4013 if (slave && slave->receive)
4014 s->rxbuf = slave->receive(slave->opaque);
4015 s->control |= 1 << 15; /* RDRB */
4016 /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
4017 * a DRQ. When is the level IRQ supposed to be reset? */
4018 }
4019}
4020
4021static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
4022{
4023 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
cf965d24 4024 int offset = addr & OMAP_MPUI_REG_MASK;
d951f6ff
AZ
4025
4026 switch (offset) {
4027 case 0x00: /* RDR */
4028 s->control &= ~(1 << 15); /* RDRB */
4029 return s->rxbuf;
4030
4031 case 0x04: /* CSR */
4032 return s->control;
4033
4034 case 0x08: /* SR1 */
4035 return s->setup[0];
4036 case 0x0c: /* SR2 */
4037 return s->setup[1];
4038 case 0x10: /* SR3 */
4039 return s->setup[2];
4040 case 0x14: /* SR4 */
4041 return s->setup[3];
4042 case 0x18: /* SR5 */
4043 return s->setup[4];
4044 }
4045
4046 OMAP_BAD_REG(addr);
4047 return 0;
4048}
4049
4050static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
4051 uint32_t value)
4052{
4053 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
cf965d24 4054 int offset = addr & OMAP_MPUI_REG_MASK;
d951f6ff
AZ
4055
4056 switch (offset) {
4057 case 0x00: /* TDR */
4058 s->txbuf = value; /* TD */
d951f6ff
AZ
4059 if ((s->setup[4] & (1 << 2)) && /* AUTO_TX_EN */
4060 ((s->setup[4] & (1 << 3)) || /* CS_TOGGLE_TX_EN */
cf965d24
AZ
4061 (s->control & (1 << 12)))) { /* CS_CMD */
4062 s->control |= 1 << 14; /* CSRB */
d951f6ff 4063 omap_uwire_transfer_start(s);
cf965d24 4064 }
d951f6ff
AZ
4065 break;
4066
4067 case 0x04: /* CSR */
4068 s->control = value & 0x1fff;
4069 if (value & (1 << 13)) /* START */
4070 omap_uwire_transfer_start(s);
4071 break;
4072
4073 case 0x08: /* SR1 */
4074 s->setup[0] = value & 0x003f;
4075 break;
4076
4077 case 0x0c: /* SR2 */
4078 s->setup[1] = value & 0x0fc0;
4079 break;
4080
4081 case 0x10: /* SR3 */
4082 s->setup[2] = value & 0x0003;
4083 break;
4084
4085 case 0x14: /* SR4 */
4086 s->setup[3] = value & 0x0001;
4087 break;
4088
4089 case 0x18: /* SR5 */
4090 s->setup[4] = value & 0x000f;
4091 break;
4092
4093 default:
4094 OMAP_BAD_REG(addr);
4095 return;
4096 }
4097}
4098
4099static CPUReadMemoryFunc *omap_uwire_readfn[] = {
4100 omap_badwidth_read16,
4101 omap_uwire_read,
4102 omap_badwidth_read16,
4103};
4104
4105static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
4106 omap_badwidth_write16,
4107 omap_uwire_write,
4108 omap_badwidth_write16,
4109};
4110
9596ebb7 4111static void omap_uwire_reset(struct omap_uwire_s *s)
d951f6ff 4112{
66450b15 4113 s->control = 0;
d951f6ff
AZ
4114 s->setup[0] = 0;
4115 s->setup[1] = 0;
4116 s->setup[2] = 0;
4117 s->setup[3] = 0;
4118 s->setup[4] = 0;
4119}
4120
4121struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
4122 qemu_irq *irq, qemu_irq dma, omap_clk clk)
4123{
4124 int iomemtype;
4125 struct omap_uwire_s *s = (struct omap_uwire_s *)
4126 qemu_mallocz(sizeof(struct omap_uwire_s));
4127
4128 s->base = base;
4129 s->txirq = irq[0];
4130 s->rxirq = irq[1];
4131 s->txdrq = dma;
4132 omap_uwire_reset(s);
4133
4134 iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
4135 omap_uwire_writefn, s);
4136 cpu_register_physical_memory(s->base, 0x800, iomemtype);
4137
4138 return s;
4139}
4140
4141void omap_uwire_attach(struct omap_uwire_s *s,
4142 struct uwire_slave_s *slave, int chipselect)
4143{
4144 if (chipselect < 0 || chipselect > 3)
4145 cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
4146 chipselect);
4147
4148 s->chip[chipselect] = slave;
4149}
4150
66450b15 4151/* Pseudonoise Pulse-Width Light Modulator */
9596ebb7 4152static void omap_pwl_update(struct omap_mpu_state_s *s)
66450b15
AZ
4153{
4154 int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0;
4155
4156 if (output != s->pwl.output) {
4157 s->pwl.output = output;
4158 printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
4159 }
4160}
4161
4162static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr)
4163{
4164 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 4165 int offset = addr & OMAP_MPUI_REG_MASK;
66450b15
AZ
4166
4167 switch (offset) {
4168 case 0x00: /* PWL_LEVEL */
4169 return s->pwl.level;
4170 case 0x04: /* PWL_CTRL */
4171 return s->pwl.enable;
4172 }
4173 OMAP_BAD_REG(addr);
4174 return 0;
4175}
4176
4177static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
4178 uint32_t value)
4179{
4180 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 4181 int offset = addr & OMAP_MPUI_REG_MASK;
66450b15
AZ
4182
4183 switch (offset) {
4184 case 0x00: /* PWL_LEVEL */
4185 s->pwl.level = value;
4186 omap_pwl_update(s);
4187 break;
4188 case 0x04: /* PWL_CTRL */
4189 s->pwl.enable = value & 1;
4190 omap_pwl_update(s);
4191 break;
4192 default:
4193 OMAP_BAD_REG(addr);
4194 return;
4195 }
4196}
4197
4198static CPUReadMemoryFunc *omap_pwl_readfn[] = {
02645926 4199 omap_pwl_read,
66450b15
AZ
4200 omap_badwidth_read8,
4201 omap_badwidth_read8,
66450b15
AZ
4202};
4203
4204static CPUWriteMemoryFunc *omap_pwl_writefn[] = {
02645926 4205 omap_pwl_write,
66450b15
AZ
4206 omap_badwidth_write8,
4207 omap_badwidth_write8,
66450b15
AZ
4208};
4209
9596ebb7 4210static void omap_pwl_reset(struct omap_mpu_state_s *s)
66450b15
AZ
4211{
4212 s->pwl.output = 0;
4213 s->pwl.level = 0;
4214 s->pwl.enable = 0;
4215 s->pwl.clk = 1;
4216 omap_pwl_update(s);
4217}
4218
4219static void omap_pwl_clk_update(void *opaque, int line, int on)
4220{
4221 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
4222
4223 s->pwl.clk = on;
4224 omap_pwl_update(s);
4225}
4226
4227static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
4228 omap_clk clk)
4229{
4230 int iomemtype;
4231
66450b15
AZ
4232 omap_pwl_reset(s);
4233
4234 iomemtype = cpu_register_io_memory(0, omap_pwl_readfn,
4235 omap_pwl_writefn, s);
b854bc19 4236 cpu_register_physical_memory(base, 0x800, iomemtype);
66450b15
AZ
4237
4238 omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
4239}
4240
f34c417b
AZ
4241/* Pulse-Width Tone module */
4242static uint32_t omap_pwt_read(void *opaque, target_phys_addr_t addr)
4243{
4244 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 4245 int offset = addr & OMAP_MPUI_REG_MASK;
f34c417b
AZ
4246
4247 switch (offset) {
4248 case 0x00: /* FRC */
4249 return s->pwt.frc;
4250 case 0x04: /* VCR */
4251 return s->pwt.vrc;
4252 case 0x08: /* GCR */
4253 return s->pwt.gcr;
4254 }
4255 OMAP_BAD_REG(addr);
4256 return 0;
4257}
4258
4259static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
4260 uint32_t value)
4261{
4262 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 4263 int offset = addr & OMAP_MPUI_REG_MASK;
f34c417b
AZ
4264
4265 switch (offset) {
4266 case 0x00: /* FRC */
4267 s->pwt.frc = value & 0x3f;
4268 break;
4269 case 0x04: /* VRC */
4270 if ((value ^ s->pwt.vrc) & 1) {
4271 if (value & 1)
4272 printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
4273 /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
4274 ((omap_clk_getrate(s->pwt.clk) >> 3) /
4275 /* Pre-multiplexer divider */
4276 ((s->pwt.gcr & 2) ? 1 : 154) /
4277 /* Octave multiplexer */
4278 (2 << (value & 3)) *
4279 /* 101/107 divider */
4280 ((value & (1 << 2)) ? 101 : 107) *
4281 /* 49/55 divider */
4282 ((value & (1 << 3)) ? 49 : 55) *
4283 /* 50/63 divider */
4284 ((value & (1 << 4)) ? 50 : 63) *
4285 /* 80/127 divider */
4286 ((value & (1 << 5)) ? 80 : 127) /
4287 (107 * 55 * 63 * 127)));
4288 else
4289 printf("%s: silence!\n", __FUNCTION__);
4290 }
4291 s->pwt.vrc = value & 0x7f;
4292 break;
4293 case 0x08: /* GCR */
4294 s->pwt.gcr = value & 3;
4295 break;
4296 default:
4297 OMAP_BAD_REG(addr);
4298 return;
4299 }
4300}
4301
4302static CPUReadMemoryFunc *omap_pwt_readfn[] = {
02645926 4303 omap_pwt_read,
f34c417b
AZ
4304 omap_badwidth_read8,
4305 omap_badwidth_read8,
f34c417b
AZ
4306};
4307
4308static CPUWriteMemoryFunc *omap_pwt_writefn[] = {
02645926 4309 omap_pwt_write,
f34c417b
AZ
4310 omap_badwidth_write8,
4311 omap_badwidth_write8,
f34c417b
AZ
4312};
4313
9596ebb7 4314static void omap_pwt_reset(struct omap_mpu_state_s *s)
f34c417b
AZ
4315{
4316 s->pwt.frc = 0;
4317 s->pwt.vrc = 0;
4318 s->pwt.gcr = 0;
4319}
4320
4321static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
4322 omap_clk clk)
4323{
4324 int iomemtype;
4325
f34c417b
AZ
4326 s->pwt.clk = clk;
4327 omap_pwt_reset(s);
4328
4329 iomemtype = cpu_register_io_memory(0, omap_pwt_readfn,
4330 omap_pwt_writefn, s);
b854bc19 4331 cpu_register_physical_memory(base, 0x800, iomemtype);
f34c417b
AZ
4332}
4333
5c1c390f
AZ
4334/* Real-time Clock module */
4335struct omap_rtc_s {
4336 target_phys_addr_t base;
4337 qemu_irq irq;
4338 qemu_irq alarm;
4339 QEMUTimer *clk;
4340
4341 uint8_t interrupts;
4342 uint8_t status;
4343 int16_t comp_reg;
4344 int running;
4345 int pm_am;
4346 int auto_comp;
4347 int round;
4348 struct tm *(*convert)(const time_t *timep, struct tm *result);
4349 struct tm alarm_tm;
4350 time_t alarm_ti;
4351
4352 struct tm current_tm;
4353 time_t ti;
4354 uint64_t tick;
4355};
4356
4357static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
4358{
106627d0 4359 /* s->alarm is level-triggered */
5c1c390f
AZ
4360 qemu_set_irq(s->alarm, (s->status >> 6) & 1);
4361}
4362
4363static void omap_rtc_alarm_update(struct omap_rtc_s *s)
4364{
4365 s->alarm_ti = mktime(&s->alarm_tm);
4366 if (s->alarm_ti == -1)
4367 printf("%s: conversion failed\n", __FUNCTION__);
4368}
4369
4370static inline uint8_t omap_rtc_bcd(int num)
4371{
4372 return ((num / 10) << 4) | (num % 10);
4373}
4374
4375static inline int omap_rtc_bin(uint8_t num)
4376{
4377 return (num & 15) + 10 * (num >> 4);
4378}
4379
4380static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
4381{
4382 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
cf965d24 4383 int offset = addr & OMAP_MPUI_REG_MASK;
5c1c390f
AZ
4384 uint8_t i;
4385
4386 switch (offset) {
4387 case 0x00: /* SECONDS_REG */
4388 return omap_rtc_bcd(s->current_tm.tm_sec);
4389
4390 case 0x04: /* MINUTES_REG */
4391 return omap_rtc_bcd(s->current_tm.tm_min);
4392
4393 case 0x08: /* HOURS_REG */
4394 if (s->pm_am)
4395 return ((s->current_tm.tm_hour > 11) << 7) |
4396 omap_rtc_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
4397 else
4398 return omap_rtc_bcd(s->current_tm.tm_hour);
4399
4400 case 0x0c: /* DAYS_REG */
4401 return omap_rtc_bcd(s->current_tm.tm_mday);
4402
4403 case 0x10: /* MONTHS_REG */
4404 return omap_rtc_bcd(s->current_tm.tm_mon + 1);
4405
4406 case 0x14: /* YEARS_REG */
4407 return omap_rtc_bcd(s->current_tm.tm_year % 100);
4408
4409 case 0x18: /* WEEK_REG */
4410 return s->current_tm.tm_wday;
4411
4412 case 0x20: /* ALARM_SECONDS_REG */
4413 return omap_rtc_bcd(s->alarm_tm.tm_sec);
4414
4415 case 0x24: /* ALARM_MINUTES_REG */
4416 return omap_rtc_bcd(s->alarm_tm.tm_min);
4417
4418 case 0x28: /* ALARM_HOURS_REG */
4419 if (s->pm_am)
4420 return ((s->alarm_tm.tm_hour > 11) << 7) |
4421 omap_rtc_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
4422 else
4423 return omap_rtc_bcd(s->alarm_tm.tm_hour);
4424
4425 case 0x2c: /* ALARM_DAYS_REG */
4426 return omap_rtc_bcd(s->alarm_tm.tm_mday);
4427
4428 case 0x30: /* ALARM_MONTHS_REG */
4429 return omap_rtc_bcd(s->alarm_tm.tm_mon + 1);
4430
4431 case 0x34: /* ALARM_YEARS_REG */
4432 return omap_rtc_bcd(s->alarm_tm.tm_year % 100);
4433
4434 case 0x40: /* RTC_CTRL_REG */
4435 return (s->pm_am << 3) | (s->auto_comp << 2) |
4436 (s->round << 1) | s->running;
4437
4438 case 0x44: /* RTC_STATUS_REG */
4439 i = s->status;
4440 s->status &= ~0x3d;
4441 return i;
4442
4443 case 0x48: /* RTC_INTERRUPTS_REG */
4444 return s->interrupts;
4445
4446 case 0x4c: /* RTC_COMP_LSB_REG */
4447 return ((uint16_t) s->comp_reg) & 0xff;
4448
4449 case 0x50: /* RTC_COMP_MSB_REG */
4450 return ((uint16_t) s->comp_reg) >> 8;
4451 }
4452
4453 OMAP_BAD_REG(addr);
4454 return 0;
4455}
4456
4457static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
4458 uint32_t value)
4459{
4460 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
cf965d24 4461 int offset = addr & OMAP_MPUI_REG_MASK;
5c1c390f
AZ
4462 struct tm new_tm;
4463 time_t ti[2];
4464
4465 switch (offset) {
4466 case 0x00: /* SECONDS_REG */
4467#if ALMDEBUG
4468 printf("RTC SEC_REG <-- %02x\n", value);
4469#endif
4470 s->ti -= s->current_tm.tm_sec;
4471 s->ti += omap_rtc_bin(value);
4472 return;
4473
4474 case 0x04: /* MINUTES_REG */
4475#if ALMDEBUG
4476 printf("RTC MIN_REG <-- %02x\n", value);
4477#endif
4478 s->ti -= s->current_tm.tm_min * 60;
4479 s->ti += omap_rtc_bin(value) * 60;
4480 return;
4481
4482 case 0x08: /* HOURS_REG */
4483#if ALMDEBUG
4484 printf("RTC HRS_REG <-- %02x\n", value);
4485#endif
4486 s->ti -= s->current_tm.tm_hour * 3600;
4487 if (s->pm_am) {
4488 s->ti += (omap_rtc_bin(value & 0x3f) & 12) * 3600;
4489 s->ti += ((value >> 7) & 1) * 43200;
4490 } else
4491 s->ti += omap_rtc_bin(value & 0x3f) * 3600;
4492 return;
4493
4494 case 0x0c: /* DAYS_REG */
4495#if ALMDEBUG
4496 printf("RTC DAY_REG <-- %02x\n", value);
4497#endif
4498 s->ti -= s->current_tm.tm_mday * 86400;
4499 s->ti += omap_rtc_bin(value) * 86400;
4500 return;
4501
4502 case 0x10: /* MONTHS_REG */
4503#if ALMDEBUG
4504 printf("RTC MTH_REG <-- %02x\n", value);
4505#endif
4506 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
4507 new_tm.tm_mon = omap_rtc_bin(value);
4508 ti[0] = mktime(&s->current_tm);
4509 ti[1] = mktime(&new_tm);
4510
4511 if (ti[0] != -1 && ti[1] != -1) {
4512 s->ti -= ti[0];
4513 s->ti += ti[1];
4514 } else {
4515 /* A less accurate version */
4516 s->ti -= s->current_tm.tm_mon * 2592000;
4517 s->ti += omap_rtc_bin(value) * 2592000;
4518 }
4519 return;
4520
4521 case 0x14: /* YEARS_REG */
4522#if ALMDEBUG
4523 printf("RTC YRS_REG <-- %02x\n", value);
4524#endif
4525 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
4526 new_tm.tm_year += omap_rtc_bin(value) - (new_tm.tm_year % 100);
4527 ti[0] = mktime(&s->current_tm);
4528 ti[1] = mktime(&new_tm);
4529
4530 if (ti[0] != -1 && ti[1] != -1) {
4531 s->ti -= ti[0];
4532 s->ti += ti[1];
4533 } else {
4534 /* A less accurate version */
4535 s->ti -= (s->current_tm.tm_year % 100) * 31536000;
4536 s->ti += omap_rtc_bin(value) * 31536000;
4537 }
4538 return;
4539
4540 case 0x18: /* WEEK_REG */
4541 return; /* Ignored */
4542
4543 case 0x20: /* ALARM_SECONDS_REG */
4544#if ALMDEBUG
4545 printf("ALM SEC_REG <-- %02x\n", value);
4546#endif
4547 s->alarm_tm.tm_sec = omap_rtc_bin(value);
4548 omap_rtc_alarm_update(s);
4549 return;
4550
4551 case 0x24: /* ALARM_MINUTES_REG */
4552#if ALMDEBUG
4553 printf("ALM MIN_REG <-- %02x\n", value);
4554#endif
4555 s->alarm_tm.tm_min = omap_rtc_bin(value);
4556 omap_rtc_alarm_update(s);
4557 return;
4558
4559 case 0x28: /* ALARM_HOURS_REG */
4560#if ALMDEBUG
4561 printf("ALM HRS_REG <-- %02x\n", value);
4562#endif
4563 if (s->pm_am)
4564 s->alarm_tm.tm_hour =
4565 ((omap_rtc_bin(value & 0x3f)) % 12) +
4566 ((value >> 7) & 1) * 12;
4567 else
4568 s->alarm_tm.tm_hour = omap_rtc_bin(value);
4569 omap_rtc_alarm_update(s);
4570 return;
4571
4572 case 0x2c: /* ALARM_DAYS_REG */
4573#if ALMDEBUG
4574 printf("ALM DAY_REG <-- %02x\n", value);
4575#endif
4576 s->alarm_tm.tm_mday = omap_rtc_bin(value);
4577 omap_rtc_alarm_update(s);
4578 return;
4579
4580 case 0x30: /* ALARM_MONTHS_REG */
4581#if ALMDEBUG
4582 printf("ALM MON_REG <-- %02x\n", value);
4583#endif
4584 s->alarm_tm.tm_mon = omap_rtc_bin(value);
4585 omap_rtc_alarm_update(s);
4586 return;
4587
4588 case 0x34: /* ALARM_YEARS_REG */
4589#if ALMDEBUG
4590 printf("ALM YRS_REG <-- %02x\n", value);
4591#endif
4592 s->alarm_tm.tm_year = omap_rtc_bin(value);
4593 omap_rtc_alarm_update(s);
4594 return;
4595
4596 case 0x40: /* RTC_CTRL_REG */
4597#if ALMDEBUG
4598 printf("RTC CONTROL <-- %02x\n", value);
4599#endif
4600 s->pm_am = (value >> 3) & 1;
4601 s->auto_comp = (value >> 2) & 1;
4602 s->round = (value >> 1) & 1;
4603 s->running = value & 1;
4604 s->status &= 0xfd;
4605 s->status |= s->running << 1;
4606 return;
4607
4608 case 0x44: /* RTC_STATUS_REG */
4609#if ALMDEBUG
4610 printf("RTC STATUSL <-- %02x\n", value);
4611#endif
4612 s->status &= ~((value & 0xc0) ^ 0x80);
4613 omap_rtc_interrupts_update(s);
4614 return;
4615
4616 case 0x48: /* RTC_INTERRUPTS_REG */
4617#if ALMDEBUG
4618 printf("RTC INTRS <-- %02x\n", value);
4619#endif
4620 s->interrupts = value;
4621 return;
4622
4623 case 0x4c: /* RTC_COMP_LSB_REG */
4624#if ALMDEBUG
4625 printf("RTC COMPLSB <-- %02x\n", value);
4626#endif
4627 s->comp_reg &= 0xff00;
4628 s->comp_reg |= 0x00ff & value;
4629 return;
4630
4631 case 0x50: /* RTC_COMP_MSB_REG */
4632#if ALMDEBUG
4633 printf("RTC COMPMSB <-- %02x\n", value);
4634#endif
4635 s->comp_reg &= 0x00ff;
4636 s->comp_reg |= 0xff00 & (value << 8);
4637 return;
4638
4639 default:
4640 OMAP_BAD_REG(addr);
4641 return;
4642 }
4643}
4644
4645static CPUReadMemoryFunc *omap_rtc_readfn[] = {
4646 omap_rtc_read,
4647 omap_badwidth_read8,
4648 omap_badwidth_read8,
4649};
4650
4651static CPUWriteMemoryFunc *omap_rtc_writefn[] = {
4652 omap_rtc_write,
4653 omap_badwidth_write8,
4654 omap_badwidth_write8,
4655};
4656
4657static void omap_rtc_tick(void *opaque)
4658{
4659 struct omap_rtc_s *s = opaque;
4660
4661 if (s->round) {
4662 /* Round to nearest full minute. */
4663 if (s->current_tm.tm_sec < 30)
4664 s->ti -= s->current_tm.tm_sec;
4665 else
4666 s->ti += 60 - s->current_tm.tm_sec;
4667
4668 s->round = 0;
4669 }
4670
4671 localtime_r(&s->ti, &s->current_tm);
4672
4673 if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
4674 s->status |= 0x40;
4675 omap_rtc_interrupts_update(s);
4676 }
4677
4678 if (s->interrupts & 0x04)
4679 switch (s->interrupts & 3) {
4680 case 0:
4681 s->status |= 0x04;
106627d0 4682 qemu_irq_pulse(s->irq);
5c1c390f
AZ
4683 break;
4684 case 1:
4685 if (s->current_tm.tm_sec)
4686 break;
4687 s->status |= 0x08;
106627d0 4688 qemu_irq_pulse(s->irq);
5c1c390f
AZ
4689 break;
4690 case 2:
4691 if (s->current_tm.tm_sec || s->current_tm.tm_min)
4692 break;
4693 s->status |= 0x10;
106627d0 4694 qemu_irq_pulse(s->irq);
5c1c390f
AZ
4695 break;
4696 case 3:
4697 if (s->current_tm.tm_sec ||
4698 s->current_tm.tm_min || s->current_tm.tm_hour)
4699 break;
4700 s->status |= 0x20;
106627d0 4701 qemu_irq_pulse(s->irq);
5c1c390f
AZ
4702 break;
4703 }
4704
4705 /* Move on */
4706 if (s->running)
4707 s->ti ++;
4708 s->tick += 1000;
4709
4710 /*
4711 * Every full hour add a rough approximation of the compensation
4712 * register to the 32kHz Timer (which drives the RTC) value.
4713 */
4714 if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
4715 s->tick += s->comp_reg * 1000 / 32768;
4716
4717 qemu_mod_timer(s->clk, s->tick);
4718}
4719
9596ebb7 4720static void omap_rtc_reset(struct omap_rtc_s *s)
5c1c390f
AZ
4721{
4722 s->interrupts = 0;
4723 s->comp_reg = 0;
4724 s->running = 0;
4725 s->pm_am = 0;
4726 s->auto_comp = 0;
4727 s->round = 0;
4728 s->tick = qemu_get_clock(rt_clock);
4729 memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
4730 s->alarm_tm.tm_mday = 0x01;
4731 s->status = 1 << 7;
4732 time(&s->ti);
4733 s->ti = mktime(s->convert(&s->ti, &s->current_tm));
4734
4735 omap_rtc_alarm_update(s);
4736 omap_rtc_tick(s);
4737}
4738
4739struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
4740 qemu_irq *irq, omap_clk clk)
4741{
4742 int iomemtype;
4743 struct omap_rtc_s *s = (struct omap_rtc_s *)
4744 qemu_mallocz(sizeof(struct omap_rtc_s));
4745
4746 s->base = base;
4747 s->irq = irq[0];
4748 s->alarm = irq[1];
4749 s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
4750 s->convert = rtc_utc ? gmtime_r : localtime_r;
4751
4752 omap_rtc_reset(s);
4753
4754 iomemtype = cpu_register_io_memory(0, omap_rtc_readfn,
4755 omap_rtc_writefn, s);
4756 cpu_register_physical_memory(s->base, 0x800, iomemtype);
4757
4758 return s;
4759}
4760
d8f699cb
AZ
4761/* Multi-channel Buffered Serial Port interfaces */
4762struct omap_mcbsp_s {
4763 target_phys_addr_t base;
4764 qemu_irq txirq;
4765 qemu_irq rxirq;
4766 qemu_irq txdrq;
4767 qemu_irq rxdrq;
4768
4769 uint16_t spcr[2];
4770 uint16_t rcr[2];
4771 uint16_t xcr[2];
4772 uint16_t srgr[2];
4773 uint16_t mcr[2];
4774 uint16_t pcr;
4775 uint16_t rcer[8];
4776 uint16_t xcer[8];
4777 int tx_rate;
4778 int rx_rate;
4779 int tx_req;
73560bc8 4780 int rx_req;
d8f699cb
AZ
4781
4782 struct i2s_codec_s *codec;
73560bc8
AZ
4783 QEMUTimer *source_timer;
4784 QEMUTimer *sink_timer;
d8f699cb
AZ
4785};
4786
4787static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
4788{
4789 int irq;
4790
4791 switch ((s->spcr[0] >> 4) & 3) { /* RINTM */
4792 case 0:
4793 irq = (s->spcr[0] >> 1) & 1; /* RRDY */
4794 break;
4795 case 3:
4796 irq = (s->spcr[0] >> 3) & 1; /* RSYNCERR */
4797 break;
4798 default:
4799 irq = 0;
4800 break;
4801 }
4802
106627d0
AZ
4803 if (irq)
4804 qemu_irq_pulse(s->rxirq);
d8f699cb
AZ
4805
4806 switch ((s->spcr[1] >> 4) & 3) { /* XINTM */
4807 case 0:
4808 irq = (s->spcr[1] >> 1) & 1; /* XRDY */
4809 break;
4810 case 3:
4811 irq = (s->spcr[1] >> 3) & 1; /* XSYNCERR */
4812 break;
4813 default:
4814 irq = 0;
4815 break;
4816 }
4817
106627d0
AZ
4818 if (irq)
4819 qemu_irq_pulse(s->txirq);
d8f699cb
AZ
4820}
4821
73560bc8 4822static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
d8f699cb 4823{
73560bc8
AZ
4824 if ((s->spcr[0] >> 1) & 1) /* RRDY */
4825 s->spcr[0] |= 1 << 2; /* RFULL */
4826 s->spcr[0] |= 1 << 1; /* RRDY */
4827 qemu_irq_raise(s->rxdrq);
4828 omap_mcbsp_intr_update(s);
d8f699cb
AZ
4829}
4830
73560bc8 4831static void omap_mcbsp_source_tick(void *opaque)
d8f699cb 4832{
73560bc8
AZ
4833 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4834 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
4835
4836 if (!s->rx_rate)
d8f699cb 4837 return;
73560bc8
AZ
4838 if (s->rx_req)
4839 printf("%s: Rx FIFO overrun\n", __FUNCTION__);
d8f699cb 4840
73560bc8 4841 s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
d8f699cb 4842
73560bc8
AZ
4843 omap_mcbsp_rx_newdata(s);
4844 qemu_mod_timer(s->source_timer, qemu_get_clock(vm_clock) + ticks_per_sec);
d8f699cb
AZ
4845}
4846
4847static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
4848{
73560bc8
AZ
4849 if (!s->codec || !s->codec->rts)
4850 omap_mcbsp_source_tick(s);
4851 else if (s->codec->in.len) {
4852 s->rx_req = s->codec->in.len;
4853 omap_mcbsp_rx_newdata(s);
d8f699cb 4854 }
d8f699cb
AZ
4855}
4856
4857static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
73560bc8
AZ
4858{
4859 qemu_del_timer(s->source_timer);
4860}
4861
4862static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
d8f699cb
AZ
4863{
4864 s->spcr[0] &= ~(1 << 1); /* RRDY */
4865 qemu_irq_lower(s->rxdrq);
4866 omap_mcbsp_intr_update(s);
4867}
4868
73560bc8
AZ
4869static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
4870{
4871 s->spcr[1] |= 1 << 1; /* XRDY */
4872 qemu_irq_raise(s->txdrq);
4873 omap_mcbsp_intr_update(s);
4874}
4875
4876static void omap_mcbsp_sink_tick(void *opaque)
d8f699cb 4877{
73560bc8
AZ
4878 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4879 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
4880
4881 if (!s->tx_rate)
d8f699cb 4882 return;
73560bc8
AZ
4883 if (s->tx_req)
4884 printf("%s: Tx FIFO underrun\n", __FUNCTION__);
4885
4886 s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
4887
4888 omap_mcbsp_tx_newdata(s);
4889 qemu_mod_timer(s->sink_timer, qemu_get_clock(vm_clock) + ticks_per_sec);
4890}
4891
4892static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
4893{
4894 if (!s->codec || !s->codec->cts)
4895 omap_mcbsp_sink_tick(s);
4896 else if (s->codec->out.size) {
4897 s->tx_req = s->codec->out.size;
4898 omap_mcbsp_tx_newdata(s);
4899 }
4900}
4901
4902static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
4903{
4904 s->spcr[1] &= ~(1 << 1); /* XRDY */
4905 qemu_irq_lower(s->txdrq);
4906 omap_mcbsp_intr_update(s);
4907 if (s->codec && s->codec->cts)
4908 s->codec->tx_swallow(s->codec->opaque);
d8f699cb
AZ
4909}
4910
4911static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
4912{
73560bc8
AZ
4913 s->tx_req = 0;
4914 omap_mcbsp_tx_done(s);
4915 qemu_del_timer(s->sink_timer);
4916}
4917
4918static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
4919{
4920 int prev_rx_rate, prev_tx_rate;
4921 int rx_rate = 0, tx_rate = 0;
4922 int cpu_rate = 1500000; /* XXX */
4923
4924 /* TODO: check CLKSTP bit */
4925 if (s->spcr[1] & (1 << 6)) { /* GRST */
4926 if (s->spcr[0] & (1 << 0)) { /* RRST */
4927 if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
4928 (s->pcr & (1 << 8))) { /* CLKRM */
4929 if (~s->pcr & (1 << 7)) /* SCLKME */
4930 rx_rate = cpu_rate /
4931 ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
4932 } else
4933 if (s->codec)
4934 rx_rate = s->codec->rx_rate;
4935 }
4936
4937 if (s->spcr[1] & (1 << 0)) { /* XRST */
4938 if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
4939 (s->pcr & (1 << 9))) { /* CLKXM */
4940 if (~s->pcr & (1 << 7)) /* SCLKME */
4941 tx_rate = cpu_rate /
4942 ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
4943 } else
4944 if (s->codec)
4945 tx_rate = s->codec->tx_rate;
4946 }
4947 }
4948 prev_tx_rate = s->tx_rate;
4949 prev_rx_rate = s->rx_rate;
4950 s->tx_rate = tx_rate;
4951 s->rx_rate = rx_rate;
4952
4953 if (s->codec)
4954 s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
4955
4956 if (!prev_tx_rate && tx_rate)
4957 omap_mcbsp_tx_start(s);
4958 else if (s->tx_rate && !tx_rate)
4959 omap_mcbsp_tx_stop(s);
4960
4961 if (!prev_rx_rate && rx_rate)
4962 omap_mcbsp_rx_start(s);
4963 else if (prev_tx_rate && !tx_rate)
4964 omap_mcbsp_rx_stop(s);
d8f699cb
AZ
4965}
4966
4967static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr)
4968{
4969 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4970 int offset = addr & OMAP_MPUI_REG_MASK;
4971 uint16_t ret;
4972
4973 switch (offset) {
4974 case 0x00: /* DRR2 */
4975 if (((s->rcr[0] >> 5) & 7) < 3) /* RWDLEN1 */
4976 return 0x0000;
4977 /* Fall through. */
4978 case 0x02: /* DRR1 */
73560bc8 4979 if (s->rx_req < 2) {
d8f699cb 4980 printf("%s: Rx FIFO underrun\n", __FUNCTION__);
73560bc8 4981 omap_mcbsp_rx_done(s);
d8f699cb 4982 } else {
73560bc8
AZ
4983 s->tx_req -= 2;
4984 if (s->codec && s->codec->in.len >= 2) {
4985 ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
4986 ret |= s->codec->in.fifo[s->codec->in.start ++];
4987 s->codec->in.len -= 2;
4988 } else
4989 ret = 0x0000;
4990 if (!s->tx_req)
4991 omap_mcbsp_rx_done(s);
d8f699cb
AZ
4992 return ret;
4993 }
4994 return 0x0000;
4995
4996 case 0x04: /* DXR2 */
4997 case 0x06: /* DXR1 */
4998 return 0x0000;
4999
5000 case 0x08: /* SPCR2 */
5001 return s->spcr[1];
5002 case 0x0a: /* SPCR1 */
5003 return s->spcr[0];
5004 case 0x0c: /* RCR2 */
5005 return s->rcr[1];
5006 case 0x0e: /* RCR1 */
5007 return s->rcr[0];
5008 case 0x10: /* XCR2 */
5009 return s->xcr[1];
5010 case 0x12: /* XCR1 */
5011 return s->xcr[0];
5012 case 0x14: /* SRGR2 */
5013 return s->srgr[1];
5014 case 0x16: /* SRGR1 */
5015 return s->srgr[0];
5016 case 0x18: /* MCR2 */
5017 return s->mcr[1];
5018 case 0x1a: /* MCR1 */
5019 return s->mcr[0];
5020 case 0x1c: /* RCERA */
5021 return s->rcer[0];
5022 case 0x1e: /* RCERB */
5023 return s->rcer[1];
5024 case 0x20: /* XCERA */
5025 return s->xcer[0];
5026 case 0x22: /* XCERB */
5027 return s->xcer[1];
5028 case 0x24: /* PCR0 */
5029 return s->pcr;
5030 case 0x26: /* RCERC */
5031 return s->rcer[2];
5032 case 0x28: /* RCERD */
5033 return s->rcer[3];
5034 case 0x2a: /* XCERC */
5035 return s->xcer[2];
5036 case 0x2c: /* XCERD */
5037 return s->xcer[3];
5038 case 0x2e: /* RCERE */
5039 return s->rcer[4];
5040 case 0x30: /* RCERF */
5041 return s->rcer[5];
5042 case 0x32: /* XCERE */
5043 return s->xcer[4];
5044 case 0x34: /* XCERF */
5045 return s->xcer[5];
5046 case 0x36: /* RCERG */
5047 return s->rcer[6];
5048 case 0x38: /* RCERH */
5049 return s->rcer[7];
5050 case 0x3a: /* XCERG */
5051 return s->xcer[6];
5052 case 0x3c: /* XCERH */
5053 return s->xcer[7];
5054 }
5055
5056 OMAP_BAD_REG(addr);
5057 return 0;
5058}
5059
73560bc8 5060static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr,
d8f699cb
AZ
5061 uint32_t value)
5062{
5063 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
5064 int offset = addr & OMAP_MPUI_REG_MASK;
5065
5066 switch (offset) {
5067 case 0x00: /* DRR2 */
5068 case 0x02: /* DRR1 */
5069 OMAP_RO_REG(addr);
5070 return;
5071
5072 case 0x04: /* DXR2 */
5073 if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
5074 return;
5075 /* Fall through. */
5076 case 0x06: /* DXR1 */
73560bc8
AZ
5077 if (s->tx_req > 1) {
5078 s->tx_req -= 2;
5079 if (s->codec && s->codec->cts) {
d8f699cb
AZ
5080 s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
5081 s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
d8f699cb 5082 }
73560bc8
AZ
5083 if (s->tx_req < 2)
5084 omap_mcbsp_tx_done(s);
d8f699cb
AZ
5085 } else
5086 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
5087 return;
5088
5089 case 0x08: /* SPCR2 */
5090 s->spcr[1] &= 0x0002;
5091 s->spcr[1] |= 0x03f9 & value;
5092 s->spcr[1] |= 0x0004 & (value << 2); /* XEMPTY := XRST */
73560bc8 5093 if (~value & 1) /* XRST */
d8f699cb 5094 s->spcr[1] &= ~6;
d8f699cb
AZ
5095 omap_mcbsp_req_update(s);
5096 return;
5097 case 0x0a: /* SPCR1 */
5098 s->spcr[0] &= 0x0006;
5099 s->spcr[0] |= 0xf8f9 & value;
5100 if (value & (1 << 15)) /* DLB */
5101 printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
5102 if (~value & 1) { /* RRST */
5103 s->spcr[0] &= ~6;
73560bc8
AZ
5104 s->rx_req = 0;
5105 omap_mcbsp_rx_done(s);
d8f699cb 5106 }
d8f699cb
AZ
5107 omap_mcbsp_req_update(s);
5108 return;
5109
5110 case 0x0c: /* RCR2 */
5111 s->rcr[1] = value & 0xffff;
5112 return;
5113 case 0x0e: /* RCR1 */
5114 s->rcr[0] = value & 0x7fe0;
5115 return;
5116 case 0x10: /* XCR2 */
5117 s->xcr[1] = value & 0xffff;
5118 return;
5119 case 0x12: /* XCR1 */
5120 s->xcr[0] = value & 0x7fe0;
5121 return;
5122 case 0x14: /* SRGR2 */
5123 s->srgr[1] = value & 0xffff;
73560bc8 5124 omap_mcbsp_req_update(s);
d8f699cb
AZ
5125 return;
5126 case 0x16: /* SRGR1 */
5127 s->srgr[0] = value & 0xffff;
73560bc8 5128 omap_mcbsp_req_update(s);
d8f699cb
AZ
5129 return;
5130 case 0x18: /* MCR2 */
5131 s->mcr[1] = value & 0x03e3;
5132 if (value & 3) /* XMCM */
5133 printf("%s: Tx channel selection mode enable attempt\n",
5134 __FUNCTION__);
5135 return;
5136 case 0x1a: /* MCR1 */
5137 s->mcr[0] = value & 0x03e1;
5138 if (value & 1) /* RMCM */
5139 printf("%s: Rx channel selection mode enable attempt\n",
5140 __FUNCTION__);
5141 return;
5142 case 0x1c: /* RCERA */
5143 s->rcer[0] = value & 0xffff;
5144 return;
5145 case 0x1e: /* RCERB */
5146 s->rcer[1] = value & 0xffff;
5147 return;
5148 case 0x20: /* XCERA */
5149 s->xcer[0] = value & 0xffff;
5150 return;
5151 case 0x22: /* XCERB */
5152 s->xcer[1] = value & 0xffff;
5153 return;
5154 case 0x24: /* PCR0 */
5155 s->pcr = value & 0x7faf;
5156 return;
5157 case 0x26: /* RCERC */
5158 s->rcer[2] = value & 0xffff;
5159 return;
5160 case 0x28: /* RCERD */
5161 s->rcer[3] = value & 0xffff;
5162 return;
5163 case 0x2a: /* XCERC */
5164 s->xcer[2] = value & 0xffff;
5165 return;
5166 case 0x2c: /* XCERD */
5167 s->xcer[3] = value & 0xffff;
5168 return;
5169 case 0x2e: /* RCERE */
5170 s->rcer[4] = value & 0xffff;
5171 return;
5172 case 0x30: /* RCERF */
5173 s->rcer[5] = value & 0xffff;
5174 return;
5175 case 0x32: /* XCERE */
5176 s->xcer[4] = value & 0xffff;
5177 return;
5178 case 0x34: /* XCERF */
5179 s->xcer[5] = value & 0xffff;
5180 return;
5181 case 0x36: /* RCERG */
5182 s->rcer[6] = value & 0xffff;
5183 return;
5184 case 0x38: /* RCERH */
5185 s->rcer[7] = value & 0xffff;
5186 return;
5187 case 0x3a: /* XCERG */
5188 s->xcer[6] = value & 0xffff;
5189 return;
5190 case 0x3c: /* XCERH */
5191 s->xcer[7] = value & 0xffff;
5192 return;
5193 }
5194
5195 OMAP_BAD_REG(addr);
5196}
5197
73560bc8
AZ
5198static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr,
5199 uint32_t value)
5200{
5201 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
5202 int offset = addr & OMAP_MPUI_REG_MASK;
5203
5204 if (offset == 0x04) { /* DXR */
5205 if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
5206 return;
5207 if (s->tx_req > 3) {
5208 s->tx_req -= 4;
5209 if (s->codec && s->codec->cts) {
5210 s->codec->out.fifo[s->codec->out.len ++] =
5211 (value >> 24) & 0xff;
5212 s->codec->out.fifo[s->codec->out.len ++] =
5213 (value >> 16) & 0xff;
5214 s->codec->out.fifo[s->codec->out.len ++] =
5215 (value >> 8) & 0xff;
5216 s->codec->out.fifo[s->codec->out.len ++] =
5217 (value >> 0) & 0xff;
5218 }
5219 if (s->tx_req < 4)
5220 omap_mcbsp_tx_done(s);
5221 } else
5222 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
5223 return;
5224 }
5225
5226 omap_badwidth_write16(opaque, addr, value);
5227}
5228
d8f699cb
AZ
5229static CPUReadMemoryFunc *omap_mcbsp_readfn[] = {
5230 omap_badwidth_read16,
5231 omap_mcbsp_read,
5232 omap_badwidth_read16,
5233};
5234
5235static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = {
5236 omap_badwidth_write16,
73560bc8
AZ
5237 omap_mcbsp_writeh,
5238 omap_mcbsp_writew,
d8f699cb
AZ
5239};
5240
5241static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
5242{
5243 memset(&s->spcr, 0, sizeof(s->spcr));
5244 memset(&s->rcr, 0, sizeof(s->rcr));
5245 memset(&s->xcr, 0, sizeof(s->xcr));
5246 s->srgr[0] = 0x0001;
5247 s->srgr[1] = 0x2000;
5248 memset(&s->mcr, 0, sizeof(s->mcr));
5249 memset(&s->pcr, 0, sizeof(s->pcr));
5250 memset(&s->rcer, 0, sizeof(s->rcer));
5251 memset(&s->xcer, 0, sizeof(s->xcer));
5252 s->tx_req = 0;
73560bc8 5253 s->rx_req = 0;
d8f699cb
AZ
5254 s->tx_rate = 0;
5255 s->rx_rate = 0;
73560bc8
AZ
5256 qemu_del_timer(s->source_timer);
5257 qemu_del_timer(s->sink_timer);
d8f699cb
AZ
5258}
5259
5260struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
5261 qemu_irq *irq, qemu_irq *dma, omap_clk clk)
5262{
5263 int iomemtype;
5264 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
5265 qemu_mallocz(sizeof(struct omap_mcbsp_s));
5266
5267 s->base = base;
5268 s->txirq = irq[0];
5269 s->rxirq = irq[1];
5270 s->txdrq = dma[0];
5271 s->rxdrq = dma[1];
73560bc8
AZ
5272 s->sink_timer = qemu_new_timer(vm_clock, omap_mcbsp_sink_tick, s);
5273 s->source_timer = qemu_new_timer(vm_clock, omap_mcbsp_source_tick, s);
d8f699cb
AZ
5274 omap_mcbsp_reset(s);
5275
5276 iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn,
5277 omap_mcbsp_writefn, s);
5278 cpu_register_physical_memory(s->base, 0x800, iomemtype);
5279
5280 return s;
5281}
5282
9596ebb7 5283static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
d8f699cb
AZ
5284{
5285 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
5286
73560bc8
AZ
5287 if (s->rx_rate) {
5288 s->rx_req = s->codec->in.len;
5289 omap_mcbsp_rx_newdata(s);
5290 }
d8f699cb
AZ
5291}
5292
9596ebb7 5293static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
d8f699cb
AZ
5294{
5295 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
5296
73560bc8
AZ
5297 if (s->tx_rate) {
5298 s->tx_req = s->codec->out.size;
5299 omap_mcbsp_tx_newdata(s);
5300 }
d8f699cb
AZ
5301}
5302
5303void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
5304{
5305 s->codec = slave;
5306 slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
5307 slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
5308}
5309
f9d43072
AZ
5310/* LED Pulse Generators */
5311struct omap_lpg_s {
5312 target_phys_addr_t base;
5313 QEMUTimer *tm;
5314
5315 uint8_t control;
5316 uint8_t power;
5317 int64_t on;
5318 int64_t period;
5319 int clk;
5320 int cycle;
5321};
5322
5323static void omap_lpg_tick(void *opaque)
5324{
5325 struct omap_lpg_s *s = opaque;
5326
5327 if (s->cycle)
5328 qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->period - s->on);
5329 else
5330 qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->on);
5331
5332 s->cycle = !s->cycle;
5333 printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
5334}
5335
5336static void omap_lpg_update(struct omap_lpg_s *s)
5337{
5338 int64_t on, period = 1, ticks = 1000;
5339 static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
5340
5341 if (~s->control & (1 << 6)) /* LPGRES */
5342 on = 0;
5343 else if (s->control & (1 << 7)) /* PERM_ON */
5344 on = period;
5345 else {
5346 period = muldiv64(ticks, per[s->control & 7], /* PERCTRL */
5347 256 / 32);
5348 on = (s->clk && s->power) ? muldiv64(ticks,
5349 per[(s->control >> 3) & 7], 256) : 0; /* ONCTRL */
5350 }
5351
5352 qemu_del_timer(s->tm);
5353 if (on == period && s->on < s->period)
5354 printf("%s: LED is on\n", __FUNCTION__);
5355 else if (on == 0 && s->on)
5356 printf("%s: LED is off\n", __FUNCTION__);
5357 else if (on && (on != s->on || period != s->period)) {
5358 s->cycle = 0;
5359 s->on = on;
5360 s->period = period;
5361 omap_lpg_tick(s);
5362 return;
5363 }
5364
5365 s->on = on;
5366 s->period = period;
5367}
5368
5369static void omap_lpg_reset(struct omap_lpg_s *s)
5370{
5371 s->control = 0x00;
5372 s->power = 0x00;
5373 s->clk = 1;
5374 omap_lpg_update(s);
5375}
5376
5377static uint32_t omap_lpg_read(void *opaque, target_phys_addr_t addr)
5378{
5379 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
5380 int offset = addr & OMAP_MPUI_REG_MASK;
5381
5382 switch (offset) {
5383 case 0x00: /* LCR */
5384 return s->control;
5385
5386 case 0x04: /* PMR */
5387 return s->power;
5388 }
5389
5390 OMAP_BAD_REG(addr);
5391 return 0;
5392}
5393
5394static void omap_lpg_write(void *opaque, target_phys_addr_t addr,
5395 uint32_t value)
5396{
5397 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
5398 int offset = addr & OMAP_MPUI_REG_MASK;
5399
5400 switch (offset) {
5401 case 0x00: /* LCR */
5402 if (~value & (1 << 6)) /* LPGRES */
5403 omap_lpg_reset(s);
5404 s->control = value & 0xff;
5405 omap_lpg_update(s);
5406 return;
5407
5408 case 0x04: /* PMR */
5409 s->power = value & 0x01;
5410 omap_lpg_update(s);
5411 return;
5412
5413 default:
5414 OMAP_BAD_REG(addr);
5415 return;
5416 }
5417}
5418
5419static CPUReadMemoryFunc *omap_lpg_readfn[] = {
5420 omap_lpg_read,
5421 omap_badwidth_read8,
5422 omap_badwidth_read8,
5423};
5424
5425static CPUWriteMemoryFunc *omap_lpg_writefn[] = {
5426 omap_lpg_write,
5427 omap_badwidth_write8,
5428 omap_badwidth_write8,
5429};
5430
5431static void omap_lpg_clk_update(void *opaque, int line, int on)
5432{
5433 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
5434
5435 s->clk = on;
5436 omap_lpg_update(s);
5437}
5438
5439struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
5440{
5441 int iomemtype;
5442 struct omap_lpg_s *s = (struct omap_lpg_s *)
5443 qemu_mallocz(sizeof(struct omap_lpg_s));
5444
5445 s->base = base;
5446 s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s);
5447
5448 omap_lpg_reset(s);
5449
5450 iomemtype = cpu_register_io_memory(0, omap_lpg_readfn,
5451 omap_lpg_writefn, s);
5452 cpu_register_physical_memory(s->base, 0x800, iomemtype);
5453
5454 omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
5455
5456 return s;
5457}
5458
5459/* MPUI Peripheral Bridge configuration */
5460static uint32_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr)
5461{
5462 if (addr == OMAP_MPUI_BASE) /* CMR */
5463 return 0xfe4d;
5464
5465 OMAP_BAD_REG(addr);
5466 return 0;
5467}
5468
5469static CPUReadMemoryFunc *omap_mpui_io_readfn[] = {
5470 omap_badwidth_read16,
5471 omap_mpui_io_read,
5472 omap_badwidth_read16,
5473};
5474
5475static CPUWriteMemoryFunc *omap_mpui_io_writefn[] = {
5476 omap_badwidth_write16,
5477 omap_badwidth_write16,
5478 omap_badwidth_write16,
5479};
5480
5481static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
5482{
5483 int iomemtype = cpu_register_io_memory(0, omap_mpui_io_readfn,
5484 omap_mpui_io_writefn, mpu);
5485 cpu_register_physical_memory(OMAP_MPUI_BASE, 0x7fff, iomemtype);
5486}
5487
c3d2689d
AZ
5488/* General chip reset */
5489static void omap_mpu_reset(void *opaque)
5490{
5491 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
5492
c3d2689d
AZ
5493 omap_inth_reset(mpu->ih[0]);
5494 omap_inth_reset(mpu->ih[1]);
5495 omap_dma_reset(mpu->dma);
5496 omap_mpu_timer_reset(mpu->timer[0]);
5497 omap_mpu_timer_reset(mpu->timer[1]);
5498 omap_mpu_timer_reset(mpu->timer[2]);
5499 omap_wd_timer_reset(mpu->wdt);
5500 omap_os_timer_reset(mpu->os_timer);
5501 omap_lcdc_reset(mpu->lcd);
5502 omap_ulpd_pm_reset(mpu);
5503 omap_pin_cfg_reset(mpu);
5504 omap_mpui_reset(mpu);
5505 omap_tipb_bridge_reset(mpu->private_tipb);
5506 omap_tipb_bridge_reset(mpu->public_tipb);
5507 omap_dpll_reset(&mpu->dpll[0]);
5508 omap_dpll_reset(&mpu->dpll[1]);
5509 omap_dpll_reset(&mpu->dpll[2]);
d951f6ff
AZ
5510 omap_uart_reset(mpu->uart[0]);
5511 omap_uart_reset(mpu->uart[1]);
5512 omap_uart_reset(mpu->uart[2]);
b30bb3a2 5513 omap_mmc_reset(mpu->mmc);
fe71e81a 5514 omap_mpuio_reset(mpu->mpuio);
64330148 5515 omap_gpio_reset(mpu->gpio);
d951f6ff 5516 omap_uwire_reset(mpu->microwire);
66450b15 5517 omap_pwl_reset(mpu);
4a2c8ac2
AZ
5518 omap_pwt_reset(mpu);
5519 omap_i2c_reset(mpu->i2c);
5c1c390f 5520 omap_rtc_reset(mpu->rtc);
d8f699cb
AZ
5521 omap_mcbsp_reset(mpu->mcbsp1);
5522 omap_mcbsp_reset(mpu->mcbsp2);
5523 omap_mcbsp_reset(mpu->mcbsp3);
f9d43072
AZ
5524 omap_lpg_reset(mpu->led[0]);
5525 omap_lpg_reset(mpu->led[1]);
8ef6367e 5526 omap_clkm_reset(mpu);
c3d2689d
AZ
5527 cpu_reset(mpu->env);
5528}
5529
cf965d24
AZ
5530static const struct omap_map_s {
5531 target_phys_addr_t phys_dsp;
5532 target_phys_addr_t phys_mpu;
5533 uint32_t size;
5534 const char *name;
5535} omap15xx_dsp_mm[] = {
5536 /* Strobe 0 */
5537 { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" }, /* CS0 */
5538 { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" }, /* CS1 */
5539 { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" }, /* CS3 */
5540 { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" }, /* CS4 */
5541 { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" }, /* CS5 */
5542 { 0xe1013000, 0xfffb3000, 0x800, "uWire" }, /* CS6 */
5543 { 0xe1013800, 0xfffb3800, 0x800, "I^2C" }, /* CS7 */
5544 { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" }, /* CS8 */
5545 { 0xe1014800, 0xfffb4800, 0x800, "RTC" }, /* CS9 */
5546 { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" }, /* CS10 */
5547 { 0xe1015800, 0xfffb5800, 0x800, "PWL" }, /* CS11 */
5548 { 0xe1016000, 0xfffb6000, 0x800, "PWT" }, /* CS12 */
5549 { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" }, /* CS14 */
5550 { 0xe1017800, 0xfffb7800, 0x800, "MMC" }, /* CS15 */
5551 { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" }, /* CS18 */
5552 { 0xe1019800, 0xfffb9800, 0x800, "UART3" }, /* CS19 */
5553 { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" }, /* CS25 */
5554 /* Strobe 1 */
5555 { 0xe101e000, 0xfffce000, 0x800, "GPIOs" }, /* CS28 */
5556
5557 { 0 }
5558};
5559
5560static void omap_setup_dsp_mapping(const struct omap_map_s *map)
5561{
5562 int io;
5563
5564 for (; map->phys_dsp; map ++) {
5565 io = cpu_get_physical_page_desc(map->phys_mpu);
5566
5567 cpu_register_physical_memory(map->phys_dsp, map->size, io);
5568 }
5569}
5570
c3d2689d
AZ
5571static void omap_mpu_wakeup(void *opaque, int irq, int req)
5572{
5573 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
5574
fe71e81a
AZ
5575 if (mpu->env->halted)
5576 cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
c3d2689d
AZ
5577}
5578
089b7c0a
AZ
5579struct dma_irq_map {
5580 int ih;
5581 int intr;
5582};
5583
5584static const struct dma_irq_map omap_dma_irq_map[] = {
5585 { 0, OMAP_INT_DMA_CH0_6 },
5586 { 0, OMAP_INT_DMA_CH1_7 },
5587 { 0, OMAP_INT_DMA_CH2_8 },
5588 { 0, OMAP_INT_DMA_CH3 },
5589 { 0, OMAP_INT_DMA_CH4 },
5590 { 0, OMAP_INT_DMA_CH5 },
5591 { 1, OMAP_INT_1610_DMA_CH6 },
5592 { 1, OMAP_INT_1610_DMA_CH7 },
5593 { 1, OMAP_INT_1610_DMA_CH8 },
5594 { 1, OMAP_INT_1610_DMA_CH9 },
5595 { 1, OMAP_INT_1610_DMA_CH10 },
5596 { 1, OMAP_INT_1610_DMA_CH11 },
5597 { 1, OMAP_INT_1610_DMA_CH12 },
5598 { 1, OMAP_INT_1610_DMA_CH13 },
5599 { 1, OMAP_INT_1610_DMA_CH14 },
5600 { 1, OMAP_INT_1610_DMA_CH15 }
5601};
5602
c3d2689d
AZ
5603struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
5604 DisplayState *ds, const char *core)
5605{
089b7c0a 5606 int i;
c3d2689d
AZ
5607 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
5608 qemu_mallocz(sizeof(struct omap_mpu_state_s));
5609 ram_addr_t imif_base, emiff_base;
106627d0 5610 qemu_irq *cpu_irq;
089b7c0a 5611 qemu_irq dma_irqs[6];
9d413d1d 5612 int sdindex;
106627d0 5613
aaed909a
FB
5614 if (!core)
5615 core = "ti925t";
c3d2689d
AZ
5616
5617 /* Core */
5618 s->mpu_model = omap310;
aaed909a
FB
5619 s->env = cpu_init(core);
5620 if (!s->env) {
5621 fprintf(stderr, "Unable to find CPU definition\n");
5622 exit(1);
5623 }
c3d2689d
AZ
5624 s->sdram_size = sdram_size;
5625 s->sram_size = OMAP15XX_SRAM_SIZE;
5626
fe71e81a
AZ
5627 s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
5628
c3d2689d
AZ
5629 /* Clocks */
5630 omap_clk_init(s);
5631
5632 /* Memory-mapped stuff */
5633 cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
5634 (emiff_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
5635 cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
5636 (imif_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
5637
5638 omap_clkm_init(0xfffece00, 0xe1008000, s);
5639
106627d0
AZ
5640 cpu_irq = arm_pic_init_cpu(s->env);
5641 s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1,
5642 cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
c3d2689d 5643 omap_findclk(s, "arminth_ck"));
106627d0
AZ
5644 s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1,
5645 s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL,
c3d2689d
AZ
5646 omap_findclk(s, "arminth_ck"));
5647 s->irq[0] = s->ih[0]->pins;
5648 s->irq[1] = s->ih[1]->pins;
5649
089b7c0a
AZ
5650 for (i = 0; i < 6; i ++)
5651 dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
5652 s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
5653 s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
5654
c3d2689d
AZ
5655 s->port[emiff ].addr_valid = omap_validate_emiff_addr;
5656 s->port[emifs ].addr_valid = omap_validate_emifs_addr;
5657 s->port[imif ].addr_valid = omap_validate_imif_addr;
5658 s->port[tipb ].addr_valid = omap_validate_tipb_addr;
5659 s->port[local ].addr_valid = omap_validate_local_addr;
5660 s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
5661
5662 s->timer[0] = omap_mpu_timer_init(0xfffec500,
5663 s->irq[0][OMAP_INT_TIMER1],
5664 omap_findclk(s, "mputim_ck"));
5665 s->timer[1] = omap_mpu_timer_init(0xfffec600,
5666 s->irq[0][OMAP_INT_TIMER2],
5667 omap_findclk(s, "mputim_ck"));
5668 s->timer[2] = omap_mpu_timer_init(0xfffec700,
5669 s->irq[0][OMAP_INT_TIMER3],
5670 omap_findclk(s, "mputim_ck"));
5671
5672 s->wdt = omap_wd_timer_init(0xfffec800,
5673 s->irq[0][OMAP_INT_WD_TIMER],
5674 omap_findclk(s, "armwdt_ck"));
5675
5676 s->os_timer = omap_os_timer_init(0xfffb9000,
5677 s->irq[1][OMAP_INT_OS_TIMER],
5678 omap_findclk(s, "clk32-kHz"));
5679
5680 s->lcd = omap_lcdc_init(0xfffec000, s->irq[0][OMAP_INT_LCD_CTRL],
5681 &s->dma->lcd_ch, ds, imif_base, emiff_base,
5682 omap_findclk(s, "lcd_ck"));
5683
5684 omap_ulpd_pm_init(0xfffe0800, s);
5685 omap_pin_cfg_init(0xfffe1000, s);
5686 omap_id_init(s);
5687
5688 omap_mpui_init(0xfffec900, s);
5689
5690 s->private_tipb = omap_tipb_bridge_init(0xfffeca00,
5691 s->irq[0][OMAP_INT_BRIDGE_PRIV],
5692 omap_findclk(s, "tipb_ck"));
5693 s->public_tipb = omap_tipb_bridge_init(0xfffed300,
5694 s->irq[0][OMAP_INT_BRIDGE_PUB],
5695 omap_findclk(s, "tipb_ck"));
5696
5697 omap_tcmi_init(0xfffecc00, s);
5698
d951f6ff 5699 s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
c3d2689d
AZ
5700 omap_findclk(s, "uart1_ck"),
5701 serial_hds[0]);
d951f6ff 5702 s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
c3d2689d
AZ
5703 omap_findclk(s, "uart2_ck"),
5704 serial_hds[0] ? serial_hds[1] : 0);
d951f6ff 5705 s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
c3d2689d
AZ
5706 omap_findclk(s, "uart3_ck"),
5707 serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
5708
5709 omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
5710 omap_dpll_init(&s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2"));
5711 omap_dpll_init(&s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3"));
5712
9d413d1d
AZ
5713 sdindex = drive_get_index(IF_SD, 0, 0);
5714 if (sdindex == -1) {
e4bcb14c
TS
5715 fprintf(stderr, "qemu: missing SecureDigital device\n");
5716 exit(1);
5717 }
9d413d1d
AZ
5718 s->mmc = omap_mmc_init(0xfffb7800, drives_table[sdindex].bdrv,
5719 s->irq[1][OMAP_INT_OQN], &s->drq[OMAP_DMA_MMC_TX],
5720 omap_findclk(s, "mmc_ck"));
b30bb3a2 5721
fe71e81a
AZ
5722 s->mpuio = omap_mpuio_init(0xfffb5000,
5723 s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
5724 s->wakeup, omap_findclk(s, "clk32-kHz"));
5725
3efda49d 5726 s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
66450b15 5727 omap_findclk(s, "arm_gpio_ck"));
64330148 5728
d951f6ff
AZ
5729 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
5730 s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
5731
d8f699cb
AZ
5732 omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
5733 omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
66450b15 5734
4a2c8ac2
AZ
5735 s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
5736 &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
5737
5c1c390f
AZ
5738 s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
5739 omap_findclk(s, "clk32-kHz"));
02645926 5740
d8f699cb
AZ
5741 s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX],
5742 &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
5743 s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX],
5744 &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
5745 s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX],
5746 &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
5747
f9d43072
AZ
5748 s->led[0] = omap_lpg_init(0xfffbd000, omap_findclk(s, "clk32-kHz"));
5749 s->led[1] = omap_lpg_init(0xfffbd800, omap_findclk(s, "clk32-kHz"));
5750
02645926 5751 /* Register mappings not currenlty implemented:
02645926
AZ
5752 * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
5753 * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
5754 * USB W2FC fffb4000 - fffb47ff
5755 * Camera Interface fffb6800 - fffb6fff
02645926
AZ
5756 * USB Host fffba000 - fffba7ff
5757 * FAC fffba800 - fffbafff
5758 * HDQ/1-Wire fffbc000 - fffbc7ff
b854bc19 5759 * TIPB switches fffbc800 - fffbcfff
02645926
AZ
5760 * Mailbox fffcf000 - fffcf7ff
5761 * Local bus IF fffec100 - fffec1ff
5762 * Local bus MMU fffec200 - fffec2ff
5763 * DSP MMU fffed200 - fffed2ff
5764 */
5765
cf965d24 5766 omap_setup_dsp_mapping(omap15xx_dsp_mm);
f9d43072 5767 omap_setup_mpui_io(s);
cf965d24 5768
c3d2689d 5769 qemu_register_reset(omap_mpu_reset, s);
c3d2689d
AZ
5770
5771 return s;
5772}