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