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