improve OMAP3 boot CH support
[qemu] / hw / omap3.c
1 /*
2  * TI OMAP3 processors emulation.
3  *
4  * Copyright (C) 2008 yajin <yajin@vm-kernel.org>
5  * Copyright (C) 2009 Nokia Corporation
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 or
10  * (at your option) version 3 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include "hw.h"
24 #include "arm-misc.h"
25 #include "omap.h"
26 #include "sysemu.h"
27 #include "qemu-timer.h"
28 #include "qemu-char.h"
29 #include "flash.h"
30 #include "soc_dma.h"
31 #include "audio/audio.h"
32 #include "block.h"
33
34 //#define OMAP3_DEBUG_
35
36 #ifdef OMAP3_DEBUG_
37 #define TRACE(fmt, ...) fprintf(stderr, "%s " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
38 #else
39 #define TRACE(...) 
40 #endif
41
42 typedef enum {
43     /* 68000000-680003FF */ L3ID_L3RT = 0,
44     /* 68000400-680007FF */ L3ID_L3SI,
45     /* 68000800-680013FF */
46     /* 68001400-680017FF */ L3ID_MPUSS_IA,
47     /* 68001800-68001BFF */ L3ID_IVASS_IA,
48     /* 68001C00-68001FFF */ L3ID_SGXSS_IA,
49     /* 68002000-680023FF */ L3ID_SMS_TA,
50     /* 68002400-680027FF */ L3ID_GPMC_TA,
51     /* 68002800-68002BFF */ L3ID_OCM_RAM_TA,
52     /* 68002C00-68002FFF */ L3ID_OCM_ROM_TA,
53     /* 68003000-680033FF */ L3ID_D2D_IA,
54     /* 68003400-680037FF */ L3ID_D2D_TA,
55     /* 68003800-68003FFF */
56     /* 68004000-680043FF */ L3ID_HSUSB_HOST_IA,
57     /* 68004400-680047FF */ L3ID_HSUSB_OTG_IA,
58     /* 68004800-68004BFF */
59     /* 68004C00-68004FFF */ L3ID_SDMA_RD_IA,
60     /* 68005000-680053FF */ L3ID_SDMA_WR_IA,
61     /* 68005400-680057FF */ L3ID_DSS_IA,
62     /* 68005800-68005BFF */ L3ID_CAMISP_IA,
63     /* 68005C00-68005FFF */ L3ID_DAP_IA,
64     /* 68006000-680063FF */ L3ID_IVASS_TA,
65     /* 68006400-680067FF */ L3ID_SGXSS_TA,
66     /* 68006800-68006BFF */ L3ID_L4_CORE_TA,
67     /* 68006C00-68006FFF */ L3ID_L4_PER_TA,
68     /* 68007000-680073FF */ L3ID_L4_EMU_TA,
69     /* 68007400-6800FFFF */
70     /* 68010000-680103FF */ L3ID_RT_PM,
71     /* 68010400-680123FF */
72     /* 68012400-680127FF */ L3ID_GPMC_PM,
73     /* 68012800-68012BFF */ L3ID_OCM_RAM_PM,
74     /* 68012C00-68012FFF */ L3ID_OCM_ROM_PM,
75     /* 68013000-680133FF */ L3ID_D2D_PM,
76     /* 68013400-68013FFF */
77     /* 68014000-680143FF */ L3ID_IVA_PM,
78     /* 68014400-68FFFFFF */
79 } omap3_l3_region_id_t;
80
81 struct omap_l3_region_s {
82     target_phys_addr_t offset;
83     size_t size;
84     enum {
85         L3TYPE_GENERIC = 0, /* needs to be mapped separately */
86         L3TYPE_IA,          /* initiator agent */
87         L3TYPE_TA,          /* target agent */
88         L3TYPE_PM,          /* protection mechanism */
89         L3TYPE_UNDEFINED,   /* every access will emit an error message */
90     } type;
91 };
92
93 struct omap3_l3_initiator_agent_s {
94     target_phys_addr_t base;
95     
96     uint32_t component;
97     uint32_t control;
98     uint32_t status;
99 };
100
101 struct omap3_l3pm_s {
102     target_phys_addr_t base;
103     
104     uint32_t error_log;
105     uint8_t  control;
106     uint16_t req_info_permission[8];
107     uint16_t read_permission[8];
108     uint16_t write_permission[8];
109     uint32_t addr_match[7];
110 };
111
112 union omap3_l3_port_s {
113     struct omap_target_agent_s ta;
114     struct omap3_l3_initiator_agent_s ia;
115     struct omap3_l3pm_s pm;
116 };
117
118 struct omap_l3_s {
119     target_phys_addr_t base;
120     int region_count;
121     union omap3_l3_port_s region[0];
122 };
123
124 static struct omap_l3_region_s omap3_l3_region[] = {
125     [L3ID_L3RT         ] = {0x00000000, 0x0400, L3TYPE_UNDEFINED},
126     [L3ID_L3SI         ] = {0x00000400, 0x0400, L3TYPE_UNDEFINED},
127     [L3ID_MPUSS_IA     ] = {0x00001400, 0x0400, L3TYPE_IA},
128     [L3ID_IVASS_IA     ] = {0x00001800, 0x0400, L3TYPE_IA},
129     [L3ID_SGXSS_IA     ] = {0x00001c00, 0x0400, L3TYPE_IA},
130     [L3ID_SMS_TA       ] = {0x00002000, 0x0400, L3TYPE_TA},
131     [L3ID_GPMC_TA      ] = {0x00002400, 0x0400, L3TYPE_TA},
132     [L3ID_OCM_RAM_TA   ] = {0x00002800, 0x0400, L3TYPE_TA},
133     [L3ID_OCM_ROM_TA   ] = {0x00002c00, 0x0400, L3TYPE_TA},
134     [L3ID_D2D_IA       ] = {0x00003000, 0x0400, L3TYPE_IA},
135     [L3ID_D2D_TA       ] = {0x00003400, 0x0400, L3TYPE_TA},
136     [L3ID_HSUSB_HOST_IA] = {0x00004000, 0x0400, L3TYPE_IA},
137     [L3ID_HSUSB_OTG_IA ] = {0x00004400, 0x0400, L3TYPE_IA},
138     [L3ID_SDMA_RD_IA   ] = {0x00004c00, 0x0400, L3TYPE_IA},
139     [L3ID_SDMA_WR_IA   ] = {0x00005000, 0x0400, L3TYPE_IA},
140     [L3ID_DSS_IA       ] = {0x00005400, 0x0400, L3TYPE_IA},
141     [L3ID_CAMISP_IA    ] = {0x00005800, 0x0400, L3TYPE_IA},
142     [L3ID_DAP_IA       ] = {0x00005c00, 0x0400, L3TYPE_IA},
143     [L3ID_IVASS_TA     ] = {0x00006000, 0x0400, L3TYPE_TA},
144     [L3ID_SGXSS_TA     ] = {0x00006400, 0x0400, L3TYPE_TA},
145     [L3ID_L4_CORE_TA   ] = {0x00006800, 0x0400, L3TYPE_TA},
146     [L3ID_L4_PER_TA    ] = {0x00006c00, 0x0400, L3TYPE_TA},
147     [L3ID_L4_EMU_TA    ] = {0x00007000, 0x0400, L3TYPE_TA},
148     [L3ID_RT_PM        ] = {0x00010000, 0x0400, L3TYPE_PM},
149     [L3ID_GPMC_PM      ] = {0x00012400, 0x0400, L3TYPE_PM},
150     [L3ID_OCM_RAM_PM   ] = {0x00012800, 0x0400, L3TYPE_PM},
151     [L3ID_OCM_ROM_PM   ] = {0x00012c00, 0x0400, L3TYPE_PM},
152     [L3ID_D2D_PM       ] = {0x00013000, 0x0400, L3TYPE_PM},
153     [L3ID_IVA_PM       ] = {0x00014000, 0x0400, L3TYPE_PM},
154 };
155
156 static uint32_t omap3_l3ia_read(void *opaque, target_phys_addr_t addr)
157 {
158     struct omap3_l3_initiator_agent_s *s = (struct omap3_l3_initiator_agent_s *)opaque;
159     
160     switch (addr) {
161         case 0x00: /* COMPONENT_L */
162             return s->component;
163         case 0x04: /* COMPONENT_H */
164             return 0;
165         case 0x18: /* CORE_L */
166             return s->component;
167         case 0x1c: /* CORE_H */
168             return (s->component >> 16);
169         case 0x20: /* AGENT_CONTROL_L */
170             return s->control;
171         case 0x24: /* AGENT_CONTROL_H */
172             return 0;
173         case 0x28: /* AGENT_STATUS_L */
174             return s->status;
175         case 0x2c: /* AGENT_STATUS_H */
176             return 0;
177         case 0x58: /* ERROR_LOG_L */
178             return 0;
179         case 0x5c: /* ERROR_LOG_H */
180             return 0;
181         case 0x60: /* ERROR_LOG_ADDR_L */
182             return 0;
183         case 0x64: /* ERROR_LOG_ADDR_H */
184             return 0;
185         default:
186             break;
187     }
188     
189     OMAP_BAD_REG(s->base + addr);
190     return 0;
191 }
192
193 static void omap3_l3ia_write(void *opaque, target_phys_addr_t addr,
194                              uint32_t value)
195 {
196     struct omap3_l3_initiator_agent_s *s = (struct omap3_l3_initiator_agent_s *)opaque;
197     
198     switch (addr) {
199         case 0x00: /* COMPONENT_L */
200         case 0x04: /* COMPONENT_H */
201         case 0x18: /* CORE_L */
202         case 0x1c: /* CORE_H */
203         case 0x60: /* ERROR_LOG_ADDR_L */
204         case 0x64: /* ERROR_LOG_ADDR_H */
205             OMAP_RO_REG(s->base + addr);
206             break;
207         case 0x24: /* AGENT_CONTROL_H */
208         case 0x2c: /* AGENT_STATUS_H */
209         case 0x5c: /* ERROR_LOG_H */
210             /* RW register but all bits are reserved/read-only */
211             break;
212         case 0x20: /* AGENT_CONTROL_L */
213             s->control = value & 0x3e070711;
214             /* TODO: some bits are reserved for some IA instances */
215             break;
216         case 0x28: /* AGENT_STATUS_L */
217             s->status &= ~(value & 0x30000000);
218             break;
219         case 0x58: /* ERROR_LOG_L */
220             /* error logging is not implemented, so ignore */
221             break;
222         default:
223             OMAP_BAD_REG(s->base + addr);
224             break;
225     }
226 }
227
228 static void omap3_l3ia_init(struct omap3_l3_initiator_agent_s *s)
229 {
230     s->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
231     s->control = 0x3e000000;
232     s->status = 0;
233 }
234
235 static CPUReadMemoryFunc *omap3_l3ia_readfn[] = {
236     omap_badwidth_read32,
237     omap_badwidth_read32,
238     omap3_l3ia_read,
239 };
240
241 static CPUWriteMemoryFunc *omap3_l3ia_writefn[] = {
242     omap_badwidth_write32,
243     omap_badwidth_write32,
244     omap3_l3ia_write,
245 };
246
247 static uint32_t omap3_l3ta_read(void *opaque, target_phys_addr_t addr)
248 {
249     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
250     
251     switch (addr) {
252         case 0x00: /* COMPONENT_L */
253             return s->component;
254         case 0x04: /* COMPONENT_H */
255             return 0;
256         case 0x18: /* CORE_L */
257             return s->component;
258         case 0x1c: /* CORE_H */
259             return (s->component >> 16);
260         case 0x20: /* AGENT_CONTROL_L */
261             return s->control;
262         case 0x24: /* AGENT_CONTROL_H */
263             return s->control_h;
264         case 0x28: /* AGENT_STATUS_L */
265             return s->status;
266         case 0x2c: /* AGENT_STATUS_H */
267             return 0;
268         case 0x58: /* ERROR_LOG_L */
269             return 0;
270         case 0x5c: /* ERROR_LOG_H */
271             return 0;
272         case 0x60: /* ERROR_LOG_ADDR_L */
273             return 0;
274         case 0x64: /* ERROR_LOG_ADDR_H */
275             return 0;
276         default:
277             break;
278     }
279     
280     OMAP_BAD_REG(s->base + addr);
281     return 0;
282 }
283
284 static void omap3_l3ta_write(void *opaque, target_phys_addr_t addr,
285                              uint32_t value)
286 {
287     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
288     
289     switch (addr) {
290         case 0x00: /* COMPONENT_L */
291         case 0x04: /* COMPONENT_H */
292         case 0x18: /* CORE_L */
293         case 0x1c: /* CORE_H */
294         case 0x60: /* ERROR_LOG_ADDR_L */
295         case 0x64: /* ERROR_LOG_ADDR_H */
296             OMAP_RO_REG(s->base + addr);
297             break;
298         case 0x24: /* AGENT_CONTROL_H */
299         case 0x5c: /* ERROR_LOG_H */
300             /* RW register but all bits are reserved/read-only */
301             break;
302         case 0x20: /* AGENT_CONTROL_L */
303             s->control = value & 0x03000711;
304             break;
305         case 0x28: /* AGENT_STATUS_L */
306             if (s->base == OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_CORE_TA].offset
307                 || s->base == OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_PER_TA].offset
308                 || s->base == OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_EMU_TA].offset) {
309                 s->status &= ~(value & (1 << 24));
310             } else
311                 OMAP_RO_REG(s->base + addr);
312             break;
313         case 0x2c: /* AGENT_STATUS_H */
314             if (s->base != OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_CORE_TA].offset
315                 && s->base != OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_PER_TA].offset
316                 && s->base != OMAP3_L3_BASE + omap3_l3_region[L3ID_L4_EMU_TA].offset)
317                 OMAP_RO_REG(s->base + addr);
318             /* for L4 core, per, emu TAs this is RW reg */
319             break;
320         case 0x58: /* ERROR_LOG_L */
321             /* error logging is not implemented, so ignore */
322             break;
323         default:
324             OMAP_BAD_REG(s->base + addr);
325             break;
326     }
327 }
328
329 static void omap3_l3ta_init(struct omap_target_agent_s *s)
330 {
331     s->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
332     s->control = 0x03000000;
333     s->status = 0;
334 }
335
336 static CPUReadMemoryFunc *omap3_l3ta_readfn[] = {
337     omap_badwidth_read32,
338     omap_badwidth_read32,
339     omap3_l3ta_read,
340 };
341
342 static CPUWriteMemoryFunc *omap3_l3ta_writefn[] = {
343     omap_badwidth_write32,
344     omap_badwidth_write32,
345     omap3_l3ta_write,
346 };
347
348 static uint32_t omap3_l3pm_read8(void *opaque, target_phys_addr_t addr)
349 {
350     struct omap3_l3pm_s *s = (struct omap3_l3pm_s *)opaque;
351     int i;
352     
353     switch (addr) {
354         case 0x00 ... 0x1f:
355         case 0x40 ... 0x47:
356             OMAP_BAD_REG(s->base + addr);
357             return 0;
358         /* ERROR_LOG */
359         case 0x20: return s->error_log & 0xff;
360         case 0x21: return (s->error_log >> 8) & 0xff;
361         case 0x22: return (s->error_log >> 16) & 0xff;
362         case 0x23: return (s->error_log >> 24) & 0xff;
363         case 0x24 ... 0x27: return 0;
364         /* CONTROL */
365         case 0x28 ... 0x2a: return 0;
366         case 0x2b: return s->control;
367         case 0x2c ... 0x2f: return 0;
368         /* ERROR_CLEAR_SINGLE */
369         case 0x30: return 0; /* TODO: clear single error from log */
370         case 0x31 ... 0x37: return 0;
371         /* ERROR_CLEAR_MULTI */
372         case 0x38: return 0; /* TODO: clear multiple errors from log */
373         case 0x39 ... 0x3f: return 0;
374         default:
375             break;
376     }
377     
378     i = (addr - 0x48) / 0x20;
379     addr -= i * 0x20;
380     if (i < 7 || (i < 8 && addr < 0x60)) 
381         switch (addr) {
382             /* REQ_INFO_PERMISSION_i */
383             case 0x48: return s->req_info_permission[i] & 0xff;
384             case 0x49: return (s->req_info_permission[i] >> 8) & 0xff;
385             case 0x4a ... 0x4f: return 0;
386             /* READ_PERMISSION_i */
387             case 0x50: return s->read_permission[i] & 0xff;
388             case 0x51: return (s->read_permission[i] >> 8) & 0xff;
389             case 0x52 ... 0x57: return 0;
390             /* WRITE_PERMISSION_i */
391             case 0x58: return s->write_permission[i] & 0xff;
392             case 0x59: return (s->write_permission[i] >> 8) & 0xff;
393             case 0x5a ... 0x5f: return 0;
394             /* ADDR_MATCH_i */
395             case 0x60: return s->addr_match[i] & 0xff;
396             case 0x61: return (s->addr_match[i] >> 8) & 0xff;
397             case 0x62: return (s->addr_match[i] >> 16) & 0xff;
398             case 0x63 ... 0x67: return 0;
399             default:
400                 break;
401         }
402
403     OMAP_BAD_REG(s->base + addr);
404     return 0;
405 }
406
407 static uint32_t omap3_l3pm_read16(void *opaque, target_phys_addr_t addr)
408 {
409     return omap3_l3pm_read8(opaque, addr)
410         | (omap3_l3pm_read8(opaque, addr + 1) << 8);
411 }
412
413 static uint32_t omap3_l3pm_read32(void *opaque, target_phys_addr_t addr)
414 {
415     return omap3_l3pm_read16(opaque, addr)
416         | (omap3_l3pm_read16(opaque, addr + 2) << 16);
417 }
418
419 static void omap3_l3pm_write8(void *opaque, target_phys_addr_t addr,
420                               uint32_t value)
421 {
422     struct omap3_l3pm_s *s = (struct omap3_l3pm_s *)opaque;
423     int i;
424     
425     switch (addr) {
426         case 0x00 ... 0x1f:
427         case 0x40 ... 0x47:
428             OMAP_BAD_REGV(s->base + addr, value);
429             return;
430         /* ERROR_LOG */
431         case 0x23:
432             s->error_log &= ~((value & 0xcf) << 24);
433         case 0x20 ... 0x22:
434         case 0x24 ... 0x27:
435             return;
436         /* CONTROL */
437         case 0x2b:
438             s->control = value & 3;
439         case 0x28 ... 0x2a:
440         case 0x2c ... 0x2f:
441             return;
442         /* ERROR_CLEAR_SINGLE / ERROR_CLEAR_MULTI */
443         case 0x30 ... 0x3f:
444             OMAP_RO_REGV(s->base + addr, value);
445             return;
446         default:
447             break;
448     }
449     
450     i = (addr - 0x48) / 0x20;
451     addr -= i * 0x20;
452     if (i < 7 || (i < 8 && addr < 0x60)) 
453         switch (addr) {
454             /* REQ_INFO_PERMISSION_i */
455             case 0x48:
456                 s->req_info_permission[i] =
457                     (s->req_info_permission[i] & ~0xff) | (value & 0xff);
458                 return;
459             case 0x49:
460                 s->req_info_permission[i] =
461                     (s->req_info_permission[i] & ~0xff00) | ((value & 0xff) << 8);
462                 return;
463             case 0x4a ... 0x4f:
464                 return;
465             /* READ_PERMISSION_i */
466             case 0x50:
467                 s->read_permission[i] =
468                     (s->read_permission[i] & ~0xff) | (value & 0x3e);
469                 return;
470             case 0x51:
471                 s->read_permission[i] =
472                     (s->read_permission[i] & ~0xff00) | ((value & 0x5f) << 8);
473                 return;
474             case 0x52 ... 0x57:
475                 return;
476             /* WRITE_PERMISSION_i */
477             case 0x58:
478                 s->write_permission[i] =
479                     (s->write_permission[i] & ~0xff) | (value & 0x3e);
480                 return;
481             case 0x59:
482                 s->write_permission[i] =
483                     (s->write_permission[i] & ~0xff00) | ((value & 0x5f) << 8);
484                 return;
485             case 0x5a ... 0x5f:
486                 return;
487             /* ADDR_MATCH_i */
488             case 0x60:
489                 s->addr_match[i] = (s->addr_match[i] & ~0xff) | (value & 0xff);
490                 return;
491             case 0x61:
492                 s->addr_match[i] =
493                     (s->addr_match[i] & ~0xfe00) | ((value & 0xfe) << 8);
494                 return;
495             case 0x62:
496                 s->addr_match[i] =
497                     (s->addr_match[i] & ~0x0f0000) | ((value & 0x0f) << 16);
498                 return;
499             case 0x63 ... 0x67:
500                 return;
501             default:
502                 break;
503         }
504     
505     OMAP_BAD_REGV(s->base + addr, value);
506 }
507
508 static void omap3_l3pm_write16(void *opaque, target_phys_addr_t addr,
509                                uint32_t value)
510 {
511     omap3_l3pm_write8(opaque, addr + 0, value & 0xff);
512     omap3_l3pm_write8(opaque, addr + 1, (value >> 8) & 0xff);
513 }
514
515 static void omap3_l3pm_write32(void *opaque, target_phys_addr_t addr,
516                                uint32_t value)
517 {
518     omap3_l3pm_write16(opaque, addr + 0, value & 0xffff);
519     omap3_l3pm_write16(opaque, addr + 2, (value >> 16) & 0xffff);
520 }
521
522 static void omap3_l3pm_init(struct omap3_l3pm_s *s)
523 {
524     int i;
525     
526     s->error_log = 0;
527     s->control = 0x03;
528     switch (s->base) {
529         case 0x68010000: /* PM_RT */
530             s->req_info_permission[0] = 0xffff;
531             s->req_info_permission[1] = 0;
532             for (i = 0; i < 2; i++)
533                 s->read_permission[i] = s->write_permission[i] = 0x1406;
534             s->addr_match[0] = 0x10230;
535             break;
536         case 0x68012400: /* PM_GPMC */
537             s->req_info_permission[0] = 0;
538             for (i = 3; i < 8; i++)
539                 s->req_info_permission[i] = 0xffff;
540             for (i = 0; i < 8; i++)
541                 s->read_permission[i] = s->write_permission[i] = 0x563e;
542             s->addr_match[0] = 0x00098;
543             break;
544         case 0x68012800: /* PM_OCM_RAM */
545             s->req_info_permission[0] = 0;
546             for (i = 1; i < 8; i++)
547                 s->req_info_permission[i] = 0xffff;
548             for (i = 0; i < 8; i++)
549                 s->read_permission[i] = s->write_permission[i] = 0x5f3e;
550             s->addr_match[1] = 0x0f810;
551             break;
552         case 0x68012C00: /* PM_OCM_ROM */
553             s->req_info_permission[1] = 0xffff;
554             for (i = 0; i < 2; i++) {
555                 s->read_permission[i] = 0x1002;
556                 s->write_permission[i] = 0;
557             }
558             s->addr_match[0] = 0x14028;
559             break;
560         case 0x68013000: /* PM_MAD2D */
561             s->req_info_permission[0] = 0;
562             for (i = 1; i < 8; i++)
563                 s->req_info_permission[i] = 0xffff;
564             for (i = 0; i < 8; i++)
565                 s->read_permission[i] = s->write_permission[i] = 0x5f1e;
566             break;
567         case 0x68014000: /* PM_IVA2.2 */
568             s->req_info_permission[0] = 0;
569             for (i = 1; i < 4; i++)
570                 s->req_info_permission[i] = 0xffff;
571             for (i = 0; i < 4; i++)
572                 s->read_permission[i] = s->write_permission[i] = 0x140e;
573             break;
574         default:
575             fprintf(stderr, "%s: unknown PM region (0x%08x)\n",
576                     __FUNCTION__, s->base);
577             exit(-1);
578             break;
579     }
580 }
581
582 static CPUReadMemoryFunc *omap3_l3pm_readfn[] = {
583     omap3_l3pm_read8,
584     omap3_l3pm_read16,
585     omap3_l3pm_read32,
586 };
587
588 static CPUWriteMemoryFunc *omap3_l3pm_writefn[] = {
589     omap3_l3pm_write8,
590     omap3_l3pm_write16,
591     omap3_l3pm_write32,
592 };
593
594 static uint32_t omap3_l3undef_read8(void *opaque, target_phys_addr_t addr)
595 {
596     fprintf(stderr, "%s: unsupported register at %08x\n",
597             __FUNCTION__, addr);
598     return 0;
599 }
600
601 static uint32_t omap3_l3undef_read16(void *opaque, target_phys_addr_t addr)
602 {
603     fprintf(stderr, "%s: unsupported register at %08x\n",
604             __FUNCTION__, addr);
605     return 0;
606 }
607
608 static uint32_t omap3_l3undef_read32(void *opaque, target_phys_addr_t addr)
609 {
610     fprintf(stderr, "%s: unsupported register at %08x\n",
611             __FUNCTION__, addr);
612     return 0;
613 }
614
615 static void omap3_l3undef_write8(void *opaque, target_phys_addr_t addr,
616                                uint32_t value)
617 {
618     fprintf(stderr, "%s: unsupported register at %08x, value %02x\n",
619             __FUNCTION__, addr, value);
620 }
621
622 static void omap3_l3undef_write16(void *opaque, target_phys_addr_t addr,
623                                 uint32_t value)
624 {
625     fprintf(stderr, "%s: unsupported register at %08x, value %04x\n",
626             __FUNCTION__, addr, value);
627 }
628
629 static void omap3_l3undef_write32(void *opaque, target_phys_addr_t addr,
630                                 uint32_t value)
631 {
632     fprintf(stderr, "%s: unsupported register at %08x, value %08x\n",
633             __FUNCTION__, addr, value);
634 }
635
636 static CPUReadMemoryFunc *omap3_l3undef_readfn[] = {
637     omap3_l3undef_read8,
638     omap3_l3undef_read16,
639     omap3_l3undef_read32,
640 };
641
642 static CPUWriteMemoryFunc *omap3_l3undef_writefn[] = {
643     omap3_l3undef_write8,
644     omap3_l3undef_write16,
645     omap3_l3undef_write32,
646 };
647
648 static struct omap_l3_s *omap3_l3_init(target_phys_addr_t base,
649                                        struct omap_l3_region_s *regions,
650                                        int n)
651 {
652     int i, iomemtype = 0;
653     
654     struct omap_l3_s *bus = qemu_mallocz(sizeof(*bus) + n * sizeof(*bus->region));
655     bus->region_count = n;
656     bus->base = base;
657     
658     for (i = 0; i < n; i++) {
659         switch (regions[i].type) {
660             case L3TYPE_GENERIC:
661                 /* not mapped for now, mapping will be done later by
662                    specialized code */
663                 break;
664             case L3TYPE_IA:
665                 iomemtype = cpu_register_io_memory(0, omap3_l3ia_readfn,
666                                                    omap3_l3ia_writefn,
667                                                    &bus->region[i].ia);
668                 bus->region[i].ia.base = base + regions[i].offset;
669                 omap3_l3ia_init(&bus->region[i].ia);
670                 break;
671             case L3TYPE_TA:
672                 iomemtype = cpu_register_io_memory(0, omap3_l3ta_readfn,
673                                                    omap3_l3ta_writefn,
674                                                    &bus->region[i].ta);
675                 bus->region[i].ta.base = base + regions[i].offset;
676                 omap3_l3ta_init(&bus->region[i].ta);
677                 break;
678             case L3TYPE_PM:
679                 iomemtype = cpu_register_io_memory(0, omap3_l3pm_readfn,
680                                                    omap3_l3pm_writefn,
681                                                    &bus->region[i].pm);
682                 bus->region[i].pm.base = base + regions[i].offset;
683                 omap3_l3pm_init(&bus->region[i].pm);
684                 break;
685             case L3TYPE_UNDEFINED:
686                 iomemtype = cpu_register_io_memory(0, omap3_l3undef_readfn,
687                                                    omap3_l3undef_writefn,
688                                                    &bus->region[i]);
689                 break;
690             default:
691                 fprintf(stderr, "%s: unknown L3 region type: %d\n",
692                         __FUNCTION__, regions[i].type);
693                 exit(-1);
694                 break;
695         }
696         cpu_register_physical_memory(base + regions[i].offset,
697                                      regions[i].size,
698                                      iomemtype);
699     }
700     
701     return bus;
702 }
703
704 typedef enum {
705     /* 48000000-48001FFF */
706     /* 48002000-48002FFF */ L4ID_SCM = 0,
707     /* 48003000-48003FFF */ L4ID_SCM_TA,
708     /* 48004000-48005FFF */ L4ID_CM_A,
709     /* 48006000-480067FF */ L4ID_CM_B,
710     /* 48006800-48006FFF */
711     /* 48007000-48007FFF */ L4ID_CM_TA,
712     /* 48008000-48023FFF */
713     /* 48024000-48024FFF */
714     /* 48025000-48025FFF */
715     /* 48026000-4803FFFF */
716     /* 48040000-480407FF */ L4ID_CORE_AP,
717     /* 48040800-48040FFF */ L4ID_CORE_IP,
718     /* 48041000-48041FFF */ L4ID_CORE_LA,
719     /* 48042000-4804FBFF */
720     /* 4804FC00-4804FFFF */ L4ID_DSI,
721     /* 48050000-480503FF */ L4ID_DSS,
722     /* 48050400-480507FF */ L4ID_DISPC,
723     /* 48050800-48050BFF */ L4ID_RFBI,
724     /* 48050C00-48050FFF */ L4ID_VENC,
725     /* 48051000-48051FFF */ L4ID_DSS_TA,
726     /* 48052000-48055FFF */
727     /* 48056000-48056FFF */ L4ID_SDMA,
728     /* 48057000-48057FFF */ L4ID_SDMA_TA,
729     /* 48058000-4805FFFF */
730     /* 48060000-48060FFF */ L4ID_I2C3,
731     /* 48061000-48061FFF */ L4ID_I2C3_TA,
732     /* 48062000-48062FFF */ L4ID_USBTLL,
733     /* 48063000-48063FFF */ L4ID_USBTLL_TA,
734     /* 48064000-48064FFF */ L4ID_HSUSBHOST,
735     /* 48065000-48065FFF */ L4ID_HSUSBHOST_TA,
736     /* 48066000-48069FFF */
737     /* 4806A000-4806AFFF */ L4ID_UART1,
738     /* 4806B000-4806BFFF */ L4ID_UART1_TA,
739     /* 4806C000-4806CFFF */ L4ID_UART2,
740     /* 4806D000-4806DFFF */ L4ID_UART2_TA,
741     /* 4806E000-4806FFFF */
742     /* 48070000-48070FFF */ L4ID_I2C1,
743     /* 48071000-48071FFF */ L4ID_I2C1_TA,
744     /* 48072000-48072FFF */ L4ID_I2C2,
745     /* 48073000-48073FFF */ L4ID_I2C2_TA,
746     /* 48074000-48074FFF */ L4ID_MCBSP1,
747     /* 48075000-48075FFF */ L4ID_MCBSP1_TA,
748     /* 48076000-48085FFF */
749     /* 48086000-48086FFF */ L4ID_GPTIMER10,
750     /* 48087000-48087FFF */ L4ID_GPTIMER10_TA,
751     /* 48088000-48088FFF */ L4ID_GPTIMER11,
752     /* 48089000-48089FFF */ L4ID_GPTIMER11_TA,
753     /* 4808A000-4808AFFF */
754     /* 4808B000-4808BFFF */
755     /* 4808C000-48093FFF */
756     /* 48094000-48094FFF */ L4ID_MAILBOX,
757     /* 48095000-48095FFF */ L4ID_MAILBOX_TA,
758     /* 48096000-48096FFF */ L4ID_MCBSP5,
759     /* 48097000-48097FFF */ L4ID_MCBSP5_TA,
760     /* 48098000-48098FFF */ L4ID_MCSPI1,
761     /* 48099000-48099FFF */ L4ID_MCSPI1_TA,
762     /* 4809A000-4809AFFF */ L4ID_MCSPI2,
763     /* 4809B000-4809BFFF */ L4ID_MCSPI2_TA,
764     /* 4809C000-4809CFFF */ L4ID_MMCSDIO1,
765     /* 4809D000-4809DFFF */ L4ID_MMCSDIO1_TA,
766     /* 4809E000-4809EFFF */ L4ID_MSPRO,
767     /* 4809F000-4809FFFF */ L4ID_MSPRO_TA,
768     /* 480A0000-480AAFFF */
769     /* 480AB000-480ABFFF */ L4ID_HSUSBOTG,
770     /* 480AC000-480ACFFF */ L4ID_HSUSBOTG_TA,
771     /* 480AD000-480ADFFF */ L4ID_MMCSDIO3,
772     /* 480AE000-480AEFFF */ L4ID_MMCSDIO3_TA,
773     /* 480AF000-480AFFFF */
774     /* 480B0000-480B0FFF */
775     /* 480B1000-480B1FFF */
776     /* 480B2000-480B2FFF */ L4ID_HDQ1WIRE,
777     /* 480B3000-480B2FFF */ L4ID_HDQ1WIRE_TA,
778     /* 480B4000-480B4FFF */ L4ID_MMCSDIO2,
779     /* 480B5000-480B5FFF */ L4ID_MMCSDIO2_TA,
780     /* 480B6000-480B6FFF */ L4ID_ICRMPU,
781     /* 480B7000-480B7FFF */ L4ID_ICRMPU_TA,
782     /* 480B8000-480B8FFF */ L4ID_MCSPI3,
783     /* 480B9000-480B9FFF */ L4ID_MCSPI3_TA,
784     /* 480BA000-480BAFFF */ L4ID_MCSPI4,
785     /* 480BB000-480BBFFF */ L4ID_MCSPI4_TA,
786     /* 480BC000-480BFFFF */ L4ID_CAMERAISP,
787     /* 480C0000-480C0FFF */ L4ID_CAMERAISP_TA,
788     /* 480C1000-480CCFFF */
789     /* 480CD000-480CDFFF */ L4ID_ICRMODEM,
790     /* 480CE000-480CEFFF */ L4ID_ICRMODEM_TA,
791     /* 480CF000-482FFFFF */
792     /* 48300000-48303FFF */
793     /* 48304000-48304FFF */ L4ID_GPTIMER12,
794     /* 48305000-48305FFF */ L4ID_GPTIMER12_TA,
795     /* 48306000-48307FFF */ L4ID_PRM_A,
796     /* 48308000-483087FF */ L4ID_PRM_B,
797     /* 48308800-48308FFF */
798     /* 48309000-48309FFF */ L4ID_PRM_TA,
799     /* 4830A000-4830AFFF */ L4ID_TAP,
800     /* 4830B000-4830BFFF */ L4ID_TAP_TA,
801     /* 4830C000-4830FFFF */
802     /* 48310000-48310FFF */ L4ID_GPIO1,
803     /* 48311000-48311FFF */ L4ID_GPIO1_TA,
804     /* 48312000-48313FFF */
805     /* 48314000-48314FFF */ L4ID_WDTIMER2,
806     /* 48315000-48315FFF */ L4ID_WDTIMER2_TA,
807     /* 48316000-48317FFF */
808     /* 48318000-48318FFF */ L4ID_GPTIMER1,
809     /* 48319000-48319FFF */ L4ID_GPTIMER1_TA,
810     /* 4831A000-4831FFFF */
811     /* 48320000-48320FFF */ L4ID_32KTIMER,
812     /* 48321000-48321FFF */ L4ID_32KTIMER_TA,
813     /* 48322000-48327FFF */
814     /* 48328000-483287FF */ L4ID_WAKEUP_AP,
815     /* 48328800-48328FFF */ L4ID_WAKEUP_C_IP,
816     /* 48329000-48329FFF */ L4ID_WAKEUP_LA,
817     /* 4832A000-4832A7FF */ L4ID_WAKEUP_E_IP,
818     /* 4832A800-4833FFFF */
819     /* 48340000-48340FFF */
820     /* 48341000-48FFFFFF */
821     /* 49000000-490007FF */ L4ID_PER_AP,
822     /* 49000800-49000FFF */ L4ID_PER_IP,
823     /* 49001000-49001FFF */ L4ID_PER_LA,
824     /* 49002000-4901FFFF */
825     /* 49020000-49020FFF */ L4ID_UART3,
826     /* 49021000-49021FFF */ L4ID_UART3_TA,
827     /* 49022000-49022FFF */ L4ID_MCBSP2,
828     /* 49023000-49023FFF */ L4ID_MCBSP2_TA,
829     /* 49024000-49024FFF */ L4ID_MCBSP3,
830     /* 49025000-49025FFF */ L4ID_MCBSP3_TA,
831     /* 49026000-49026FFF */ L4ID_MCBSP4,
832     /* 49027000-49027FFF */ L4ID_MCBSP4_TA,
833     /* 49028000-49028FFF */ L4ID_MCBSP2S,
834     /* 49029000-49029FFF */ L4ID_MCBSP2S_TA,
835     /* 4902A000-4902AFFF */ L4ID_MCBSP3S,
836     /* 4902B000-4902BFFF */ L4ID_MCBSP3S_TA,
837     /* 4902C000-4902FFFF */
838     /* 49030000-49030FFF */ L4ID_WDTIMER3,
839     /* 49031000-49031FFF */ L4ID_WDTIMER3_TA,
840     /* 49032000-49032FFF */ L4ID_GPTIMER2,
841     /* 49033000-49033FFF */ L4ID_GPTIMER2_TA,
842     /* 49034000-49034FFF */ L4ID_GPTIMER3,
843     /* 49035000-49035FFF */ L4ID_GPTIMER3_TA,
844     /* 49036000-49036FFF */ L4ID_GPTIMER4,
845     /* 49037000-49037FFF */ L4ID_GPTIMER4_TA,
846     /* 49038000-49038FFF */ L4ID_GPTIMER5,
847     /* 49039000-49039FFF */ L4ID_GPTIMER5_TA,
848     /* 4903A000-4903AFFF */ L4ID_GPTIMER6,
849     /* 4903B000-4903BFFF */ L4ID_GPTIMER6_TA,
850     /* 4903C000-4903CFFF */ L4ID_GPTIMER7,
851     /* 4903D000-4903DFFF */ L4ID_GPTIMER7_TA,
852     /* 4903E000-4903EFFF */ L4ID_GPTIMER8,
853     /* 4903F000-4903FFFF */ L4ID_GPTIMER8_TA,
854     /* 49040000-49040FFF */ L4ID_GPTIMER9,
855     /* 49041000-49041FFF */ L4ID_GPTIMER9_TA,
856     /* 49042000-4904FFFF */
857     /* 49050000-49050FFF */ L4ID_GPIO2,
858     /* 49051000-49051FFF */ L4ID_GPIO2_TA,
859     /* 49052000-49052FFF */ L4ID_GPIO3,
860     /* 49053000-49053FFF */ L4ID_GPIO3_TA,
861     /* 49054000-49054FFF */ L4ID_GPIO4,
862     /* 49055000-49055FFF */ L4ID_GPIO4_TA,
863     /* 49056000-49056FFF */ L4ID_GPIO5,
864     /* 49057000-49057FFF */ L4ID_GPIO5_TA,
865     /* 49058000-49058FFF */ L4ID_GPIO6,
866     /* 49059000-49059FFF */ L4ID_GPIO6_TA,
867     /* 4905A000-490FFFFF */
868     /* 54000000-54003FFF */
869     /* 54004000-54005FFF */
870     /* 54006000-540067FF */ L4ID_EMU_AP,
871     /* 54006800-54006FFF */ L4ID_EMU_IP_C,
872     /* 54007000-54007FFF */ L4ID_EMU_LA,
873     /* 54008000-540087FF */ L4ID_EMU_IP_DAP,
874     /* 54008800-5400FFFF */
875     /* 54010000-54017FFF */ L4ID_MPUEMU,
876     /* 54018000-54018FFF */ L4ID_MPUEMU_TA,
877     /* 54019000-54019FFF */ L4ID_TPIU,
878     /* 5401A000-5401AFFF */ L4ID_TPIU_TA,
879     /* 5401B000-5401BFFF */ L4ID_ETB,
880     /* 5401C000-5401CFFF */ L4ID_ETB_TA,
881     /* 5401D000-5401DFFF */ L4ID_DAPCTL,
882     /* 5401E000-5401EFFF */ L4ID_DAPCTL_TA,
883     /* 5401F000-5401FFFF */ L4ID_SDTI_TA,
884     /* 54020000-544FFFFF */
885     /* 54500000-5450FFFF */ L4ID_SDTI_CFG,
886     /* 54510000-545FFFFF */
887     /* 54600000-546FFFFF */ L4ID_SDTI,
888     /* 54700000-54705FFF */
889     /* 54706000-54707FFF */ L4ID_EMU_PRM_A,
890     /* 54708000-547087FF */ L4ID_EMU_PRM_B,
891     /* 54708800-54708FFF */
892     /* 54709000-54709FFF */ L4ID_EMU_PRM_TA,
893     /* 5470A000-5470FFFF */
894     /* 54710000-54710FFF */ L4ID_EMU_GPIO1,
895     /* 54711000-54711FFF */ L4ID_EMU_GPIO1_TA,
896     /* 54712000-54713FFF */
897     /* 54714000-54714FFF */ L4ID_EMU_WDTM2,
898     /* 54715000-54715FFF */ L4ID_EMU_WDTM2_TA,
899     /* 54716000-54717FFF */
900     /* 54718000-54718FFF */ L4ID_EMU_GPTM1,
901     /* 54719000-54719FFF */ L4ID_EMU_GPTM1_TA,
902     /* 5471A000-5471FFFF */
903     /* 54720000-54720FFF */ L4ID_EMU_32KTM,
904     /* 54721000-54721FFF */ L4ID_EMU_32KTM_TA,
905     /* 54722000-54727FFF */
906     /* 54728000-547287FF */ L4ID_EMU_WKUP_AP,
907     /* 54728800-54728FFF */ L4ID_EMU_WKUP_IPC,
908     /* 54729000-54729FFF */ L4ID_EMU_WKUP_LA,
909     /* 5472A000-5472A7FF */ L4ID_EMU_WKUP_IPE,
910     /* 5472A800-547FFFFF */
911 } omap3_l4_region_id_t;
912
913 typedef enum {
914     L4TYPE_GENERIC = 0, /* not mapped by default, must be mapped separately */
915     L4TYPE_IA,          /* initiator agent */
916     L4TYPE_TA,          /* target agent */
917     L4TYPE_LA,          /* link register agent */
918     L4TYPE_AP           /* address protection */
919 } omap3_l4_region_type_t;
920
921 /* we reuse the "access" member for defining region type -- the original
922    omap_l4_region_s "access" member is not used anywhere else anyway! */
923 static struct omap_l4_region_s omap3_l4_region[] = {
924     /* L4-Core */
925     [L4ID_SCM         ] = {0x00002000, 0x1000, L4TYPE_GENERIC},
926     [L4ID_SCM_TA      ] = {0x00003000, 0x1000, L4TYPE_TA},
927     [L4ID_CM_A        ] = {0x00004000, 0x2000, L4TYPE_GENERIC},
928     [L4ID_CM_B        ] = {0x00006000, 0x0800, L4TYPE_GENERIC},
929     [L4ID_CM_TA       ] = {0x00007000, 0x1000, L4TYPE_TA},
930     [L4ID_CORE_AP     ] = {0x00040000, 0x0800, L4TYPE_AP},
931     [L4ID_CORE_IP     ] = {0x00040800, 0x0800, L4TYPE_IA},
932     [L4ID_CORE_LA     ] = {0x00041000, 0x1000, L4TYPE_LA},
933     [L4ID_DSI         ] = {0x0004fc00, 0x0400, L4TYPE_GENERIC},
934     [L4ID_DSS         ] = {0x00050000, 0x0400, L4TYPE_GENERIC},
935     [L4ID_DISPC       ] = {0x00050400, 0x0400, L4TYPE_GENERIC},
936     [L4ID_RFBI        ] = {0x00050800, 0x0400, L4TYPE_GENERIC},
937     [L4ID_VENC        ] = {0x00050c00, 0x0400, L4TYPE_GENERIC},
938     [L4ID_DSS_TA      ] = {0x00051000, 0x1000, L4TYPE_TA},
939     [L4ID_SDMA        ] = {0x00056000, 0x1000, L4TYPE_GENERIC},
940     [L4ID_SDMA_TA     ] = {0x00057000, 0x1000, L4TYPE_TA},
941     [L4ID_I2C3        ] = {0x00060000, 0x1000, L4TYPE_GENERIC},
942     [L4ID_I2C3_TA     ] = {0x00061000, 0x1000, L4TYPE_TA},
943     [L4ID_USBTLL      ] = {0x00062000, 0x1000, L4TYPE_GENERIC},
944     [L4ID_USBTLL_TA   ] = {0x00063000, 0x1000, L4TYPE_TA},
945     [L4ID_HSUSBHOST   ] = {0x00064000, 0x1000, L4TYPE_GENERIC},
946     [L4ID_HSUSBHOST_TA] = {0x00065000, 0x1000, L4TYPE_TA},
947     [L4ID_UART1       ] = {0x0006a000, 0x1000, L4TYPE_GENERIC},
948     [L4ID_UART1_TA    ] = {0x0006b000, 0x1000, L4TYPE_TA},
949     [L4ID_UART2       ] = {0x0006c000, 0x1000, L4TYPE_GENERIC},
950     [L4ID_UART2_TA    ] = {0x0006d000, 0x1000, L4TYPE_TA},
951     [L4ID_I2C1        ] = {0x00070000, 0x1000, L4TYPE_GENERIC},
952     [L4ID_I2C1_TA     ] = {0x00071000, 0x1000, L4TYPE_TA},
953     [L4ID_I2C2        ] = {0x00072000, 0x1000, L4TYPE_GENERIC},
954     [L4ID_I2C2_TA     ] = {0x00073000, 0x1000, L4TYPE_TA},
955     [L4ID_MCBSP1      ] = {0x00074000, 0x1000, L4TYPE_GENERIC},
956     [L4ID_MCBSP1_TA   ] = {0x00075000, 0x1000, L4TYPE_TA},
957     [L4ID_GPTIMER10   ] = {0x00086000, 0x1000, L4TYPE_GENERIC},
958     [L4ID_GPTIMER10_TA] = {0x00087000, 0x1000, L4TYPE_TA},
959     [L4ID_GPTIMER11   ] = {0x00088000, 0x1000, L4TYPE_GENERIC},
960     [L4ID_GPTIMER11_TA] = {0x00089000, 0x1000, L4TYPE_TA},
961     [L4ID_MAILBOX     ] = {0x00094000, 0x1000, L4TYPE_GENERIC},
962     [L4ID_MAILBOX_TA  ] = {0x00095000, 0x1000, L4TYPE_TA},
963     [L4ID_MCBSP5      ] = {0x00096000, 0x1000, L4TYPE_GENERIC},
964     [L4ID_MCBSP5_TA   ] = {0x00097000, 0x1000, L4TYPE_TA},
965     [L4ID_MCSPI1      ] = {0x00098000, 0x1000, L4TYPE_GENERIC},
966     [L4ID_MCSPI1_TA   ] = {0x00099000, 0x1000, L4TYPE_TA},
967     [L4ID_MCSPI2      ] = {0x0009a000, 0x1000, L4TYPE_GENERIC},
968     [L4ID_MCSPI2_TA   ] = {0x0009b000, 0x1000, L4TYPE_TA},
969     [L4ID_MMCSDIO1    ] = {0x0009c000, 0x1000, L4TYPE_GENERIC},
970     [L4ID_MMCSDIO1_TA ] = {0x0009d000, 0x1000, L4TYPE_TA},
971     [L4ID_MSPRO       ] = {0x0009e000, 0x1000, L4TYPE_GENERIC},
972     [L4ID_MSPRO_TA    ] = {0x0009f000, 0x1000, L4TYPE_TA},
973     [L4ID_HSUSBOTG    ] = {0x000ab000, 0x1000, L4TYPE_GENERIC},
974     [L4ID_HSUSBOTG_TA ] = {0x000ac000, 0x1000, L4TYPE_TA},
975     [L4ID_MMCSDIO3    ] = {0x000ad000, 0x1000, L4TYPE_GENERIC},
976     [L4ID_MMCSDIO3_TA ] = {0x000ae000, 0x1000, L4TYPE_TA},
977     [L4ID_HDQ1WIRE    ] = {0x000b2000, 0x1000, L4TYPE_GENERIC},
978     [L4ID_HDQ1WIRE_TA ] = {0x000b3000, 0x1000, L4TYPE_TA},
979     [L4ID_MMCSDIO2    ] = {0x000b4000, 0x1000, L4TYPE_GENERIC},
980     [L4ID_MMCSDIO2_TA ] = {0x000b5000, 0x1000, L4TYPE_TA},
981     [L4ID_ICRMPU      ] = {0x000b6000, 0x1000, L4TYPE_GENERIC},
982     [L4ID_ICRMPU_TA   ] = {0x000b7000, 0x1000, L4TYPE_TA},
983     [L4ID_MCSPI3      ] = {0x000b8000, 0x1000, L4TYPE_GENERIC},
984     [L4ID_MCSPI3_TA   ] = {0x000b9000, 0x1000, L4TYPE_TA},
985     [L4ID_MCSPI4      ] = {0x000ba000, 0x1000, L4TYPE_GENERIC},
986     [L4ID_MCSPI4_TA   ] = {0x000bb000, 0x1000, L4TYPE_TA},
987     [L4ID_CAMERAISP   ] = {0x000bc000, 0x4000, L4TYPE_GENERIC},
988     [L4ID_CAMERAISP_TA] = {0x000c0000, 0x1000, L4TYPE_TA},
989     [L4ID_ICRMODEM    ] = {0x000cd000, 0x1000, L4TYPE_GENERIC},
990     [L4ID_ICRMODEM_TA ] = {0x000ce000, 0x1000, L4TYPE_TA},
991     /* L4-Wakeup interconnect region A */
992     [L4ID_GPTIMER12   ] = {0x00304000, 0x1000, L4TYPE_GENERIC},
993     [L4ID_GPTIMER12_TA] = {0x00305000, 0x1000, L4TYPE_TA},
994     [L4ID_PRM_A       ] = {0x00306000, 0x2000, L4TYPE_GENERIC},
995     [L4ID_PRM_B       ] = {0x00308000, 0x0800, L4TYPE_GENERIC},
996     [L4ID_PRM_TA      ] = {0x00309000, 0x1000, L4TYPE_TA},
997     /* L4-Core */
998     [L4ID_TAP         ] = {0x0030a000, 0x1000, L4TYPE_GENERIC},
999     [L4ID_TAP_TA      ] = {0x0030b000, 0x1000, L4TYPE_TA},
1000     /* L4-Wakeup interconnect region B */
1001     [L4ID_GPIO1       ] = {0x00310000, 0x1000, L4TYPE_GENERIC},
1002     [L4ID_GPIO1_TA    ] = {0x00311000, 0x1000, L4TYPE_TA},
1003     [L4ID_WDTIMER2    ] = {0x00314000, 0x1000, L4TYPE_GENERIC},
1004     [L4ID_WDTIMER2_TA ] = {0x00315000, 0x1000, L4TYPE_TA},
1005     [L4ID_GPTIMER1    ] = {0x00318000, 0x1000, L4TYPE_GENERIC},
1006     [L4ID_GPTIMER1_TA ] = {0x00319000, 0x1000, L4TYPE_TA},
1007     [L4ID_32KTIMER    ] = {0x00320000, 0x1000, L4TYPE_GENERIC},
1008     [L4ID_32KTIMER_TA ] = {0x00321000, 0x1000, L4TYPE_TA},
1009     [L4ID_WAKEUP_AP   ] = {0x00328000, 0x0800, L4TYPE_AP},
1010     [L4ID_WAKEUP_C_IP ] = {0x00328800, 0x0800, L4TYPE_IA},
1011     [L4ID_WAKEUP_LA   ] = {0x00329000, 0x1000, L4TYPE_LA},
1012     [L4ID_WAKEUP_E_IP ] = {0x0032a000, 0x0800, L4TYPE_IA},
1013     /* L4-Per */
1014     [L4ID_PER_AP      ] = {0x01000000, 0x0800, L4TYPE_AP},
1015     [L4ID_PER_IP      ] = {0x01000800, 0x0800, L4TYPE_IA},
1016     [L4ID_PER_LA      ] = {0x01001000, 0x1000, L4TYPE_LA},
1017     [L4ID_UART3       ] = {0x01020000, 0x1000, L4TYPE_GENERIC},
1018     [L4ID_UART3_TA    ] = {0x01021000, 0x1000, L4TYPE_TA},
1019     [L4ID_MCBSP2      ] = {0x01022000, 0x1000, L4TYPE_GENERIC},
1020     [L4ID_MCBSP2_TA   ] = {0x01023000, 0x1000, L4TYPE_TA},
1021     [L4ID_MCBSP3      ] = {0x01024000, 0x1000, L4TYPE_GENERIC},
1022     [L4ID_MCBSP3_TA   ] = {0x01025000, 0x1000, L4TYPE_TA},
1023     [L4ID_MCBSP4      ] = {0x01026000, 0x1000, L4TYPE_GENERIC},
1024     [L4ID_MCBSP4_TA   ] = {0x01027000, 0x1000, L4TYPE_TA},
1025     [L4ID_MCBSP2S     ] = {0x01028000, 0x1000, L4TYPE_GENERIC},
1026     [L4ID_MCBSP2S_TA  ] = {0x01029000, 0x1000, L4TYPE_TA},
1027     [L4ID_MCBSP3S     ] = {0x0102a000, 0x1000, L4TYPE_GENERIC},
1028     [L4ID_MCBSP3S_TA  ] = {0x0102b000, 0x1000, L4TYPE_TA},
1029     [L4ID_WDTIMER3    ] = {0x01030000, 0x1000, L4TYPE_GENERIC},
1030     [L4ID_WDTIMER3_TA ] = {0x01031000, 0x1000, L4TYPE_TA},
1031     [L4ID_GPTIMER2    ] = {0x01032000, 0x1000, L4TYPE_GENERIC},
1032     [L4ID_GPTIMER2_TA ] = {0x01033000, 0x1000, L4TYPE_TA},
1033     [L4ID_GPTIMER3    ] = {0x01034000, 0x1000, L4TYPE_GENERIC},
1034     [L4ID_GPTIMER3_TA ] = {0x01035000, 0x1000, L4TYPE_TA},
1035     [L4ID_GPTIMER4    ] = {0x01036000, 0x1000, L4TYPE_GENERIC},
1036     [L4ID_GPTIMER4_TA ] = {0x01037000, 0x1000, L4TYPE_TA},
1037     [L4ID_GPTIMER5    ] = {0x01038000, 0x1000, L4TYPE_GENERIC},
1038     [L4ID_GPTIMER5_TA ] = {0x01039000, 0x1000, L4TYPE_TA},
1039     [L4ID_GPTIMER6    ] = {0x0103a000, 0x1000, L4TYPE_GENERIC},
1040     [L4ID_GPTIMER6_TA ] = {0x0103b000, 0x1000, L4TYPE_TA},
1041     [L4ID_GPTIMER7    ] = {0x0103c000, 0x1000, L4TYPE_GENERIC},
1042     [L4ID_GPTIMER7_TA ] = {0x0103d000, 0x1000, L4TYPE_TA},
1043     [L4ID_GPTIMER8    ] = {0x0103e000, 0x1000, L4TYPE_GENERIC},
1044     [L4ID_GPTIMER8_TA ] = {0x0103f000, 0x1000, L4TYPE_TA},
1045     [L4ID_GPTIMER9    ] = {0x01040000, 0x1000, L4TYPE_GENERIC},
1046     [L4ID_GPTIMER9_TA ] = {0x01041000, 0x1000, L4TYPE_TA},
1047     [L4ID_GPIO2       ] = {0x01050000, 0x1000, L4TYPE_GENERIC},
1048     [L4ID_GPIO2_TA    ] = {0x01051000, 0x1000, L4TYPE_TA},
1049     [L4ID_GPIO3       ] = {0x01052000, 0x1000, L4TYPE_GENERIC},
1050     [L4ID_GPIO3_TA    ] = {0x01053000, 0x1000, L4TYPE_TA},
1051     [L4ID_GPIO4       ] = {0x01054000, 0x1000, L4TYPE_GENERIC},
1052     [L4ID_GPIO4_TA    ] = {0x01055000, 0x1000, L4TYPE_TA},
1053     [L4ID_GPIO5       ] = {0x01056000, 0x1000, L4TYPE_GENERIC},
1054     [L4ID_GPIO5_TA    ] = {0x01057000, 0x1000, L4TYPE_TA},
1055     [L4ID_GPIO6       ] = {0x01058000, 0x1000, L4TYPE_GENERIC},
1056     [L4ID_GPIO6_TA    ] = {0x01059000, 0x1000, L4TYPE_TA},
1057     /* L4-Emu */
1058     [L4ID_EMU_AP      ] = {0x0c006000, 0x0800, L4TYPE_AP},
1059     [L4ID_EMU_IP_C    ] = {0x0c006800, 0x0800, L4TYPE_IA},
1060     [L4ID_EMU_LA      ] = {0x0c007000, 0x1000, L4TYPE_LA},
1061     [L4ID_EMU_IP_DAP  ] = {0x0c008000, 0x0800, L4TYPE_IA},
1062     [L4ID_MPUEMU      ] = {0x0c010000, 0x8000, L4TYPE_GENERIC},
1063     [L4ID_MPUEMU_TA   ] = {0x0c018000, 0x1000, L4TYPE_TA},
1064     [L4ID_TPIU        ] = {0x0c019000, 0x1000, L4TYPE_GENERIC},
1065     [L4ID_TPIU_TA     ] = {0x0c01a000, 0x1000, L4TYPE_TA},
1066     [L4ID_ETB         ] = {0x0c01b000, 0x1000, L4TYPE_GENERIC},
1067     [L4ID_ETB_TA      ] = {0x0c01c000, 0x1000, L4TYPE_TA},
1068     [L4ID_DAPCTL      ] = {0x0c01d000, 0x1000, L4TYPE_GENERIC},
1069     [L4ID_DAPCTL_TA   ] = {0x0c01e000, 0x1000, L4TYPE_TA},
1070     [L4ID_EMU_PRM_A   ] = {0x0c706000, 0x2000, L4TYPE_GENERIC},
1071     [L4ID_EMU_PRM_B   ] = {0x0c706800, 0x0800, L4TYPE_GENERIC},
1072     [L4ID_EMU_PRM_TA  ] = {0x0c709000, 0x1000, L4TYPE_TA},
1073     [L4ID_EMU_GPIO1   ] = {0x0c710000, 0x1000, L4TYPE_GENERIC},
1074     [L4ID_EMU_GPIO1_TA] = {0x0c711000, 0x1000, L4TYPE_TA},
1075     [L4ID_EMU_WDTM2   ] = {0x0c714000, 0x1000, L4TYPE_GENERIC},
1076     [L4ID_EMU_WDTM2_TA] = {0x0c715000, 0x1000, L4TYPE_TA},
1077     [L4ID_EMU_GPTM1   ] = {0x0c718000, 0x1000, L4TYPE_GENERIC},
1078     [L4ID_EMU_GPTM1_TA] = {0x0c719000, 0x1000, L4TYPE_TA},
1079     [L4ID_EMU_32KTM   ] = {0x0c720000, 0x1000, L4TYPE_GENERIC},
1080     [L4ID_EMU_32KTM_TA] = {0x0c721000, 0x1000, L4TYPE_TA},
1081     [L4ID_EMU_WKUP_AP ] = {0x0c728000, 0x0800, L4TYPE_AP},
1082     [L4ID_EMU_WKUP_IPC] = {0x0c728800, 0x0800, L4TYPE_IA},
1083     [L4ID_EMU_WKUP_LA ] = {0x0c729000, 0x1000, L4TYPE_LA},
1084     [L4ID_EMU_WKUP_IPE] = {0x0c72a000, 0x0800, L4TYPE_IA},
1085 };
1086
1087 typedef enum {
1088     L4A_SCM = 0,
1089     L4A_CM,
1090     L4A_PRM,
1091     L4A_GPTIMER1,
1092     L4A_GPTIMER2,
1093     L4A_GPTIMER3,
1094     L4A_GPTIMER4,
1095     L4A_GPTIMER5,
1096     L4A_GPTIMER6,
1097     L4A_GPTIMER7,
1098     L4A_GPTIMER8,
1099     L4A_GPTIMER9,
1100     L4A_GPTIMER10,
1101     L4A_GPTIMER11,
1102     L4A_GPTIMER12,
1103     L4A_WDTIMER2,
1104     L4A_32KTIMER,
1105     L4A_UART1,
1106     L4A_UART2,
1107     L4A_UART3,
1108     L4A_DSS,
1109     L4A_GPIO1,
1110     L4A_GPIO2,
1111     L4A_GPIO3,
1112     L4A_GPIO4,
1113     L4A_GPIO5,
1114     L4A_GPIO6,
1115     L4A_MMC1,
1116     L4A_MMC2,
1117     L4A_MMC3,
1118     L4A_I2C1,
1119     L4A_I2C2,
1120     L4A_I2C3,
1121     L4A_TAP
1122 } omap3_l4_agent_info_id_t;
1123
1124 struct omap3_l4_agent_info_s {
1125     omap3_l4_agent_info_id_t agent_id;
1126     omap3_l4_region_id_t     first_region_id;
1127     int                      region_count;
1128 };
1129
1130 static const struct omap3_l4_agent_info_s omap3_l4_agent_info[] = {
1131     /* L4-Core Agents */
1132     {L4A_DSS,       L4ID_DSI,       6},
1133     /* TODO: camera */
1134     /* TODO: USBHS OTG */
1135     /* TODO: USBHS host */
1136     /* TODO: USBTLL */
1137     {L4A_UART1,     L4ID_UART1,     2},
1138     {L4A_UART2,     L4ID_UART2,     2},
1139     {L4A_I2C1,      L4ID_I2C1,      2},
1140     {L4A_I2C2,      L4ID_I2C2,      2},
1141     {L4A_I2C3,      L4ID_I2C3,      2},
1142     /* TODO: McBSP1 */
1143     /* TODO: McBSP5 */
1144     {L4A_GPTIMER10, L4ID_GPTIMER10, 2},
1145     {L4A_GPTIMER11, L4ID_GPTIMER11, 2},
1146     /* TODO: SPI1 */
1147     /* TODO: SPI2 */
1148     {L4A_MMC1,      L4ID_MMCSDIO1,  2},
1149     {L4A_MMC2,      L4ID_MMCSDIO2,  2},
1150     {L4A_MMC3,      L4ID_MMCSDIO3,  2},
1151     /* TODO: HDQ/1-Wire */
1152     /* TODO: Mailbox */
1153     /* TODO: SPI3 */
1154     /* TODO: SPI4 */
1155     /* TODO: SDMA */
1156     {L4A_CM,        L4ID_CM_A,      3},
1157     {L4A_SCM,       L4ID_SCM,       2},
1158     {L4A_TAP,       L4ID_TAP,       2},
1159     /* L4-Wakeup Agents */
1160     {L4A_GPTIMER12, L4ID_GPTIMER12, 2},
1161     {L4A_PRM,       L4ID_PRM_A,     3},
1162     {L4A_GPIO1,     L4ID_GPIO1,     2},
1163     {L4A_WDTIMER2,  L4ID_WDTIMER2,  2},
1164     {L4A_GPTIMER1,  L4ID_GPTIMER1,  2},
1165     {L4A_32KTIMER,  L4ID_32KTIMER,  2},
1166     /* L4-Per Agents */
1167     {L4A_UART3,     L4ID_UART3,     2},
1168     /* TODO: McBSP2 */
1169     /* TODO: McBSP3 */
1170     {L4A_GPTIMER2,  L4ID_GPTIMER2,  2},
1171     {L4A_GPTIMER3,  L4ID_GPTIMER3,  2},
1172     {L4A_GPTIMER4,  L4ID_GPTIMER4,  2},
1173     {L4A_GPTIMER5,  L4ID_GPTIMER5,  2},
1174     {L4A_GPTIMER6,  L4ID_GPTIMER6,  2},
1175     {L4A_GPTIMER7,  L4ID_GPTIMER7,  2},
1176     {L4A_GPTIMER8,  L4ID_GPTIMER8,  2},
1177     {L4A_GPTIMER9,  L4ID_GPTIMER9,  2},
1178     {L4A_GPIO2,     L4ID_GPIO2,     2},
1179     {L4A_GPIO3,     L4ID_GPIO3,     2},
1180     {L4A_GPIO4,     L4ID_GPIO4,     2},
1181     {L4A_GPIO5,     L4ID_GPIO5,     2},
1182     {L4A_GPIO6,     L4ID_GPIO6,     2},
1183 };
1184
1185 static uint32_t omap3_l4ta_read(void *opaque, target_phys_addr_t addr)
1186 {
1187     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
1188     
1189     switch (addr) {
1190         case 0x00: /* COMPONENT_L */
1191             return s->component;
1192         case 0x04: /* COMPONENT_H */
1193             return 0;
1194         case 0x18: /* CORE_L */
1195             return s->component;
1196         case 0x1c: /* CORE_H */
1197             return (s->component >> 16);
1198         case 0x20: /* AGENT_CONTROL_L */
1199             return s->control;
1200         case 0x24: /* AGENT_CONTROL_H */
1201             return s->control_h;
1202         case 0x28: /* AGENT_STATUS_L */
1203             return s->status;
1204         case 0x2c: /* AGENT_STATUS_H */
1205             return 0;
1206         default:
1207             break;
1208     }
1209     
1210     OMAP_BAD_REG(s->base + addr);
1211     return 0;
1212 }
1213
1214 static void omap3_l4ta_write(void *opaque, target_phys_addr_t addr,
1215                              uint32_t value)
1216 {
1217     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
1218     
1219     switch (addr) {
1220         case 0x00: /* COMPONENT_L */
1221         case 0x04: /* COMPONENT_H */
1222         case 0x18: /* CORE_L */
1223         case 0x1c: /* CORE_H */
1224             OMAP_RO_REG(s->base + addr);
1225             break;
1226         case 0x20: /* AGENT_CONTROL_L */
1227             s->control = value & 0x00000701;
1228             break;
1229         case 0x24: /* AGENT_CONTROL_H */
1230             s->control_h = value & 0x100; /* TODO: shouldn't this be read-only? */
1231             break;
1232         case 0x28: /* AGENT_STATUS_L */
1233             if (value & 0x100)
1234                 s->status &= ~0x100; /* REQ_TIMEOUT */
1235             break;
1236         case 0x2c: /* AGENT_STATUS_H */
1237             /* no writable bits although the register is listed as RW */
1238             break;
1239         default:
1240             OMAP_BAD_REG(s->base + addr);
1241             break;
1242     }
1243 }
1244
1245 static CPUReadMemoryFunc *omap3_l4ta_readfn[] = {
1246     omap_badwidth_read32,
1247     omap_badwidth_read32,
1248     omap3_l4ta_read,
1249 };
1250
1251 static CPUWriteMemoryFunc *omap3_l4ta_writefn[] = {
1252     omap_badwidth_write32,
1253     omap_badwidth_write32,
1254     omap3_l4ta_write,
1255 };
1256
1257 static struct omap_target_agent_s *omap3_l4ta_init(struct omap_l4_s *bus, int cs)
1258 {
1259     int i, iomemtype;
1260     struct omap_target_agent_s *ta = 0;
1261     const struct omap3_l4_agent_info_s *info = 0;
1262
1263     for (i = 0; i < bus->ta_num; i++)
1264         if (omap3_l4_agent_info[i].agent_id == cs) {
1265             ta = &bus->ta[i];
1266             info = &omap3_l4_agent_info[i];
1267             break;
1268         }
1269     if (!ta) {
1270         fprintf(stderr, "%s: invalid agent id (%i)\n", __FUNCTION__, cs);
1271         exit(-1);
1272     }
1273     if (ta->bus) {
1274         fprintf(stderr, "%s: target agent (%d) already initialized\n",
1275                 __FUNCTION__, cs);
1276         exit(-1);
1277     }
1278
1279     ta->bus = bus;
1280     ta->start = &omap3_l4_region[info->first_region_id];
1281     ta->regions = info->region_count;
1282
1283     ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
1284     ta->status = 0x00000000;
1285     ta->control = 0x00000200;
1286
1287     for (i = 0; i < info->region_count; i++)
1288         if (omap3_l4_region[info->first_region_id + i].access == L4TYPE_TA)
1289             break;
1290     if (i >= info->region_count) {
1291         fprintf(stderr, "%s: specified agent (%d) has no TA region\n",
1292                 __FUNCTION__, cs);
1293         exit(-1);
1294     }
1295     
1296     iomemtype = l4_register_io_memory(0, omap3_l4ta_readfn,
1297                                       omap3_l4ta_writefn, ta);
1298     ta->base = omap_l4_attach(ta, i, iomemtype);
1299
1300     return ta;
1301 }
1302
1303 /* common PRM domain registers */
1304 struct omap3_prm_domain_s {
1305     uint32_t rm_rstctrl;   /* 50 */
1306     uint32_t rm_rstst;     /* 58 */
1307     uint32_t pm_wken;      /* a0 */
1308     uint32_t pm_mpugrpsel; /* a4 */
1309     uint32_t pm_ivagrpsel; /* a8 */
1310     uint32_t pm_wkst;      /* b0 */
1311     uint32_t pm_wkdep;     /* c8 */
1312     uint32_t pm_pwstctrl;  /* e0 */
1313     uint32_t pm_pwstst;    /* e4 */
1314     uint32_t pm_prepwstst; /* e8 */
1315 };
1316
1317 struct omap3_prm_s {
1318     qemu_irq mpu_irq;
1319     qemu_irq iva_irq;
1320     struct omap_mpu_state_s *omap;
1321
1322     struct omap3_prm_domain_s iva2;
1323     struct omap3_prm_domain_s mpu;
1324     struct omap3_prm_domain_s core;
1325     struct omap3_prm_domain_s sgx;
1326     struct omap3_prm_domain_s wkup;
1327     struct omap3_prm_domain_s dss;
1328     struct omap3_prm_domain_s cam;
1329     struct omap3_prm_domain_s per;
1330     struct omap3_prm_domain_s emu;
1331     struct omap3_prm_domain_s neon;
1332     struct omap3_prm_domain_s usbhost;
1333
1334     uint32_t iva2_prm_irqstatus;
1335     uint32_t iva2_prm_irqenable;
1336     
1337     uint32_t mpu_pm_evgenctrl;
1338     uint32_t mpu_pm_evgenontim;
1339     uint32_t mpu_pm_evgenofftim;
1340
1341     uint32_t core_pm_wkst3;
1342     uint32_t core_pm_wken3;
1343     uint32_t core_pm_iva2grpsel3;
1344     uint32_t core_pm_mpugrpsel3;
1345
1346     uint32_t prm_revision;
1347     uint32_t prm_sysconfig;
1348     uint32_t prm_irqstatus_mpu;
1349     uint32_t prm_irqenable_mpu;
1350
1351     uint32_t prm_clksel;
1352     uint32_t prm_clkout_ctrl;
1353
1354     uint32_t prm_vc_smps_sa;
1355     uint32_t prm_vc_smps_vol_ra;
1356     uint32_t prm_vc_smps_cmd_ra;
1357     uint32_t prm_vc_cmd_val_0;
1358     uint32_t prm_vc_cmd_val_1;
1359     uint32_t prm_vc_hc_conf;
1360     uint32_t prm_vc_i2c_cfg;
1361     uint32_t prm_vc_bypass_val;
1362     uint32_t prm_rstctrl;
1363     uint32_t prm_rsttimer;
1364     uint32_t prm_rstst;
1365     uint32_t prm_voltctrl;
1366     uint32_t prm_sram_pcharge;
1367     uint32_t prm_clksrc_ctrl;
1368     uint32_t prm_obs;
1369     uint32_t prm_voltsetup1;
1370     uint32_t prm_voltoffset;
1371     uint32_t prm_clksetup;
1372     uint32_t prm_polctrl;
1373     uint32_t prm_voltsetup2;
1374 };
1375
1376 static void omap3_prm_int_update(struct omap3_prm_s *s)
1377 {
1378     qemu_set_irq(s->mpu_irq, s->prm_irqstatus_mpu & s->prm_irqenable_mpu);
1379     qemu_set_irq(s->iva_irq, s->iva2_prm_irqstatus & s->iva2_prm_irqenable);
1380 }
1381
1382 static void omap3_prm_reset(struct omap3_prm_s *s)
1383 {
1384     s->iva2.rm_rstctrl    = 0x7;
1385     s->iva2.rm_rstst      = 0x1;
1386     s->iva2.pm_wkdep      = 0xb3;
1387     s->iva2.pm_pwstctrl   = 0xff0f07;
1388     s->iva2.pm_pwstst     = 0xff7;
1389     s->iva2.pm_prepwstst  = 0x0;
1390     s->iva2_prm_irqstatus = 0x0;
1391     s->iva2_prm_irqenable = 0x0;
1392
1393     s->prm_revision      = 0x10;
1394     s->prm_sysconfig     = 0x1;
1395     s->prm_irqstatus_mpu = 0x0;
1396     s->prm_irqenable_mpu = 0x0;
1397
1398     s->mpu.rm_rstst       = 0x1;
1399     s->mpu.pm_wkdep       = 0xa5;
1400     s->mpu.pm_pwstctrl    = 0x30107;
1401     s->mpu.pm_pwstst      = 0xc7;
1402     s->mpu.pm_pwstst      = 0x0;
1403     s->mpu_pm_evgenctrl   = 0x12;
1404     s->mpu_pm_evgenontim  = 0x0;
1405     s->mpu_pm_evgenofftim = 0x0;
1406
1407     s->core.rm_rstst       = 0x1;
1408     s->core.pm_wken        = 0xc33ffe18;
1409     s->core.pm_mpugrpsel   = 0xc33ffe18;
1410     s->core.pm_ivagrpsel   = 0xc33ffe18;
1411     s->core.pm_wkst        = 0x0;
1412     s->core.pm_pwstctrl    = 0xf0307;
1413     s->core.pm_pwstst      = 0xf7;
1414     s->core.pm_prepwstst   = 0x0;
1415     s->core_pm_wkst3       = 0x0;
1416     s->core_pm_wken3       = 0x4;
1417     s->core_pm_iva2grpsel3 = 0x4;
1418     s->core_pm_mpugrpsel3  = 0x4;
1419
1420     s->sgx.rm_rstst     = 0x1;
1421     s->sgx.pm_wkdep     = 0x16;
1422     s->sgx.pm_pwstctrl  = 0x30107;
1423     s->sgx.pm_pwstst    = 0x3;
1424     s->sgx.pm_prepwstst = 0x0;
1425
1426     s->wkup.pm_wken      = 0x3cb;
1427     s->wkup.pm_mpugrpsel = 0x3cb;
1428     s->wkup.pm_ivagrpsel = 0x0;
1429     s->wkup.pm_wkst      = 0x0;
1430     s->wkup.pm_pwstst    = 0x3; /* TODO: check on real hardware */
1431
1432     s->prm_clksel      = 0x4;
1433     s->prm_clkout_ctrl = 0x80;
1434
1435     s->dss.rm_rstst     = 0x1;
1436     s->dss.pm_wken      = 0x1;
1437     s->dss.pm_wkdep     = 0x16;
1438     s->dss.pm_pwstctrl  = 0x30107;
1439     s->dss.pm_pwstst    = 0x3;
1440     s->dss.pm_prepwstst = 0x0;
1441
1442     s->cam.rm_rstst     = 0x1;
1443     s->cam.pm_wkdep     = 0x16;
1444     s->cam.pm_pwstctrl  = 0x30107;
1445     s->cam.pm_pwstst    = 0x3;
1446     s->cam.pm_prepwstst = 0x0;
1447
1448     s->per.rm_rstst     = 0x1;
1449     s->per.pm_wken      = 0x3efff;
1450     s->per.pm_mpugrpsel = 0x3efff;
1451     s->per.pm_ivagrpsel = 0x3efff;
1452     s->per.pm_wkst      = 0x0;
1453     s->per.pm_wkdep     = 0x17;
1454     s->per.pm_pwstctrl  = 0x30107;
1455     s->per.pm_pwstst    = 0x7;
1456     s->per.pm_prepwstst = 0x0;
1457
1458     s->emu.rm_rstst  = 0x1;
1459     s->emu.pm_pwstst = 0x13;
1460
1461     s->prm_vc_smps_sa     = 0x0;
1462     s->prm_vc_smps_vol_ra = 0x0;
1463     s->prm_vc_smps_cmd_ra = 0x0;
1464     s->prm_vc_cmd_val_0   = 0x0;
1465     s->prm_vc_cmd_val_1   = 0x0;
1466     s->prm_vc_hc_conf     = 0x0;
1467     s->prm_vc_i2c_cfg     = 0x18;
1468     s->prm_vc_bypass_val  = 0x0;
1469     s->prm_rstctrl        = 0x0;
1470     s->prm_rsttimer       = 0x1006;
1471     s->prm_rstst          = 0x1;
1472     s->prm_voltctrl       = 0x0;
1473     s->prm_sram_pcharge   = 0x50;
1474     s->prm_clksrc_ctrl    = 0x43;
1475     s->prm_obs            = 0x0;
1476     s->prm_voltsetup1     = 0x0;
1477     s->prm_voltoffset     = 0x0;
1478     s->prm_clksetup       = 0x0;
1479     s->prm_polctrl        = 0xa;
1480     s->prm_voltsetup2     = 0x0;
1481
1482     s->neon.rm_rstst     = 0x1;
1483     s->neon.pm_wkdep     = 0x2;
1484     s->neon.pm_pwstctrl  = 0x7;
1485     s->neon.pm_pwstst    = 0x3;
1486     s->neon.pm_prepwstst = 0x0;
1487
1488     s->usbhost.rm_rstst     = 0x1;
1489     s->usbhost.pm_wken      = 0x1;
1490     s->usbhost.pm_mpugrpsel = 0x1;
1491     s->usbhost.pm_ivagrpsel = 0x1;
1492     s->usbhost.pm_wkst      = 0x0;
1493     s->usbhost.pm_wkdep     = 0x17;
1494     s->usbhost.pm_pwstctrl  = 0x30107;
1495     s->usbhost.pm_pwstst    = 0x3;
1496     s->usbhost.pm_prepwstst = 0x0;
1497
1498     omap3_prm_int_update(s);
1499 }
1500
1501 static uint32_t omap3_prm_read(void *opaque, target_phys_addr_t addr)
1502 {
1503     struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
1504     struct omap3_prm_domain_s *d = 0;
1505
1506     TRACE("%04x", addr);
1507     
1508     /* handle common domain registers first - all domains may not
1509        have all common registers though but we're returning zeroes there */
1510     switch ((addr >> 8) & 0xff) {
1511         case 0x00: d = &s->iva2; break;
1512         case 0x09: d = &s->mpu; break;
1513         case 0x0a: d = &s->core; break;
1514         case 0x0b: d = &s->sgx; break;
1515         case 0x0c: d = &s->wkup; break;
1516         case 0x0e: d = &s->dss; break;
1517         case 0x0f: d = &s->cam; break;
1518         case 0x10: d = &s->per; break;
1519         case 0x11: d = &s->emu; break;
1520         case 0x13: d = &s->neon; break;
1521         case 0x14: d = &s->usbhost; break;
1522         default: break;
1523     }
1524     if (d)
1525         switch (addr & 0xff) {
1526             case 0x50: return d->rm_rstctrl;
1527             case 0x58: return d->rm_rstst;
1528             case 0xa0: return d->pm_wken;
1529             case 0xa4: return d->pm_mpugrpsel;
1530             case 0xa8: return d->pm_ivagrpsel;
1531             case 0xb0: return d->pm_wkst;
1532             case 0xc8: return d->pm_wkdep;
1533             case 0xe0: return d->pm_pwstctrl;
1534             case 0xe4: return d->pm_pwstst;
1535             case 0xe8: return d->pm_prepwstst;
1536             default: break;
1537         }
1538
1539     /* okay, not a common domain register so let's take a closer look */
1540     switch (addr) {
1541         case 0x00f8: return s->iva2_prm_irqstatus;
1542         case 0x00fc: return s->iva2_prm_irqenable;
1543         case 0x0804: return s->prm_revision;
1544         case 0x0814: return s->prm_sysconfig;
1545         case 0x0818: return s->prm_irqstatus_mpu;
1546         case 0x081c: return s->prm_irqenable_mpu;
1547         case 0x09d4: return s->mpu_pm_evgenctrl;
1548         case 0x09d8: return s->mpu_pm_evgenontim;
1549         case 0x09dc: return s->mpu_pm_evgenofftim;
1550         case 0x0ab8: return s->core_pm_wkst3;
1551         case 0x0af0: return s->core_pm_wken3;
1552         case 0x0af4: return s->core_pm_iva2grpsel3;
1553         case 0x0af8: return s->core_pm_mpugrpsel3;
1554         case 0x0d40: return s->prm_clksel;
1555         case 0x0d70: return s->prm_clkout_ctrl;
1556         case 0x0de4: return 0x3; /* TODO: check on real hardware */
1557         case 0x1220: return s->prm_vc_smps_sa;
1558         case 0x1224: return s->prm_vc_smps_vol_ra;
1559         case 0x1228: return s->prm_vc_smps_cmd_ra;
1560         case 0x122c: return s->prm_vc_cmd_val_0;
1561         case 0x1230: return s->prm_vc_cmd_val_1;
1562         case 0x1234: return s->prm_vc_hc_conf;
1563         case 0x1238: return s->prm_vc_i2c_cfg;
1564         case 0x123c: return s->prm_vc_bypass_val;
1565         case 0x1250: return s->prm_rstctrl;
1566         case 0x1254: return s->prm_rsttimer;
1567         case 0x1258: return s->prm_rstst;
1568         case 0x1260: return s->prm_voltctrl;
1569         case 0x1264: return s->prm_sram_pcharge;        
1570         case 0x1270: return s->prm_clksrc_ctrl;
1571         case 0x1280: return s->prm_obs;
1572         case 0x1290: return s->prm_voltsetup1;
1573         case 0x1294: return s->prm_voltoffset;
1574         case 0x1298: return s->prm_clksetup;
1575         case 0x129c: return s->prm_polctrl;
1576         case 0x12a0: return s->prm_voltsetup2;
1577         default: break;
1578     }
1579
1580     OMAP_BAD_REG(addr);
1581     return 0;
1582 }
1583
1584 static inline void omap3_prm_clksrc_ctrl_update(struct omap3_prm_s *s,
1585                                                 uint32_t value)
1586 {
1587     if ((value & 0xd0) == 0x40)
1588         omap_clk_setrate(omap_findclk(s->omap, "omap3_sys_clk"), 1, 1);
1589     else if ((value & 0xd0) == 0x80)
1590         omap_clk_setrate(omap_findclk(s->omap, "omap3_sys_clk"), 2, 1);
1591 }
1592
1593 static void omap3_prm_write(void *opaque, target_phys_addr_t addr,
1594                             uint32_t value)
1595 {
1596     struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
1597
1598     TRACE("%04x = %08x", addr, value);
1599     switch (addr) {
1600         /* IVA2_PRM */
1601         case 0x0050: s->iva2.rm_rstctrl = value & 0x7; break;
1602         case 0x0058: s->iva2.rm_rstst &= ~(value & 0x3f0f); break;
1603         case 0x00c8: s->iva2.pm_wkdep = value & 0xb3; break;
1604         case 0x00e0: s->iva2.pm_pwstctrl = 0xcff000 | (value & 0x300f0f); break;
1605         case 0x00e4: OMAP_RO_REG(addr); break;
1606         case 0x00e8: s->iva2.pm_prepwstst = value & 0xff7;
1607         case 0x00f8:
1608             s->iva2_prm_irqstatus &= ~(value & 0x7);
1609             omap3_prm_int_update(s);
1610             break;
1611         case 0x00fc:
1612             s->iva2_prm_irqenable = value & 0x7;
1613             omap3_prm_int_update(s);
1614             break;
1615         /* OCP_System_Reg_PRM */
1616         case 0x0804: OMAP_RO_REG(addr); break;
1617         case 0x0814: s->prm_sysconfig = value & 0x1; break;
1618         case 0x0818:
1619             s->prm_irqstatus_mpu &= ~(value & 0x03c003fd);
1620             omap3_prm_int_update(s);
1621             break;
1622         case 0x081c:
1623             s->prm_irqenable_mpu = value & 0x03c003fd;
1624             omap3_prm_int_update(s);
1625             break;
1626         /* MPU_PRM */
1627         case 0x0958: s->mpu.rm_rstst &= ~(value & 0x080f); break;
1628         case 0x09c8: s->mpu.pm_wkdep = value & 0xa5; break;
1629         case 0x09d4: s->mpu_pm_evgenctrl = value & 0x1f; break;
1630         case 0x09d8: s->mpu_pm_evgenontim = value; break;
1631         case 0x09dc: s->mpu_pm_evgenofftim = value; break;
1632         case 0x09e0: s->mpu.pm_pwstctrl = value & 0x3010f; break;
1633         case 0x09e4: OMAP_RO_REG(addr); break;
1634         case 0x09e8: s->mpu.pm_prepwstst = value & 0xc7; break;
1635         /* CORE_PRM */
1636         case 0x0a50: s->core.rm_rstctrl = value & 0x3; break; /* TODO: check if available on real hw */
1637         case 0x0a58: s->core.rm_rstst &= ~(value & 0x7); break;
1638         case 0x0aa0: s->core.pm_wken = 0x80000008 | (value & 0x433ffe10); break;
1639         case 0x0aa4: s->core.pm_mpugrpsel = 0x80000008 | (value & 0x433ffe10); break;
1640         case 0x0aa8: s->core.pm_ivagrpsel = 0x80000008 | (value & 0x433ffe10); break;
1641         case 0x0ab0: s->core.pm_wkst = value & 0x433ffe10; break;
1642         case 0x0ab8: s->core_pm_wkst3 &= ~(value & 0x4); break;
1643         case 0x0ae0: s->core.pm_pwstctrl = (value & 0x0f031f); break;
1644         case 0x0ae4: OMAP_RO_REG(addr); break;
1645         case 0x0ae8: s->core.pm_prepwstst = value & 0xf7; break;
1646         case 0x0af0: s->core_pm_wken3 = value & 0x4; break;
1647         case 0x0af4: s->core_pm_iva2grpsel3 = value & 0x4; break;
1648         case 0x0af8: s->core_pm_mpugrpsel3 = value & 0x4; break;
1649         /* SGX_PRM */
1650         case 0x0b58: s->sgx.rm_rstst &= ~(value & 0xf); break;
1651         case 0x0bc8: s->sgx.pm_wkdep = value & 0x16; break;
1652         case 0x0be0: s->sgx.pm_pwstctrl = 0x030104 | (value & 0x3); break;
1653         case 0x0be4: OMAP_RO_REG(addr); break;
1654         case 0x0be8: s->sgx.pm_prepwstst = value & 0x3; break;
1655         /* WKUP_PRM */
1656         case 0x0ca0: s->wkup.pm_wken = 0x2 | (value & 0x0103c9); break;
1657         case 0x0ca4: s->wkup.pm_mpugrpsel = 0x0102 | (value & 0x02c9); break;
1658         case 0x0ca8: s->wkup.pm_ivagrpsel = value & 0x03cb; break;
1659         case 0x0cb0: s->wkup.pm_wkst &= ~(value & 0x0103cb); break;
1660         /* Clock_Control_Reg_PRM */
1661         case 0x0d40: 
1662             s->prm_clksel = value & 0x7;
1663             fprintf(stderr, "%s PRM_CLKSEL = 0x%x\n", __FUNCTION__,
1664                     s->prm_clksel);
1665             /* TODO: update clocks */
1666             break;
1667         case 0x0d70:
1668             s->prm_clkout_ctrl = value & 0x80;
1669             fprintf(stderr, "%s PRM_CLKOUT_CTRL = 0x%x\n", __FUNCTION__,
1670                     s->prm_clkout_ctrl);
1671             /* TODO: update clocks */
1672             break;
1673         /* DSS_PRM */
1674         case 0x0e58: s->dss.rm_rstst &= ~(value & 0xf); break;
1675         case 0x0ea0: s->dss.pm_wken = value & 1; break;
1676         case 0x0ec8: s->dss.pm_wkdep = value & 0x16; break;
1677         case 0x0ee0: s->dss.pm_pwstctrl = 0x030104 | (value & 3); break;
1678         case 0x0ee4: OMAP_RO_REG(addr); break;
1679         case 0x0ee8: s->dss.pm_prepwstst = value & 3; break;
1680         /* CAM_PRM */
1681         case 0x0f58: s->cam.rm_rstst &= (value & 0xf); break;
1682         case 0x0fc8: s->cam.pm_wkdep = value & 0x16; break;
1683         case 0x0fe0: s->cam.pm_pwstctrl = 0x030104 | (value & 3); break;
1684         case 0x0fe4: OMAP_RO_REG(addr); break;
1685         case 0x0fe8: s->cam.pm_prepwstst = value & 0x3; break;
1686         /* PER_PRM */
1687         case 0x1058: s->per.rm_rstst &= ~(value & 0xf); break;
1688         case 0x10a0: s->per.pm_wken = value & 0x03efff; break;
1689         case 0x10a4: s->per.pm_mpugrpsel = value & 0x03efff; break;
1690         case 0x10a8: s->per.pm_ivagrpsel = value & 0x03efff; break;
1691         case 0x10b0: s->per.pm_wkst &= ~(value & 0x03efff); break;
1692         case 0x10c8: s->per.pm_wkdep = value & 0x17; break;
1693         case 0x10e0: s->per.pm_pwstctrl = 0x030100 | (value & 7); break;
1694         case 0x10e4: OMAP_RO_REG(addr); break;
1695         case 0x10e8: s->per.pm_prepwstst = value & 0x7; break;
1696         /* EMU_PRM */
1697         case 0x1158: s->emu.rm_rstst &= ~(value & 7); break;
1698         case 0x11e4: OMAP_RO_REG(addr); break;
1699         /* Global_Reg_PRM */
1700         case 0x1220: s->prm_vc_smps_sa = value & 0x7f007f; break;
1701         case 0x1224: s->prm_vc_smps_vol_ra = value & 0xff00ff; break;
1702         case 0x1228: s->prm_vc_smps_cmd_ra = value & 0xff00ff; break;
1703         case 0x122c: s->prm_vc_cmd_val_0 = value; break;
1704         case 0x1230: s->prm_vc_cmd_val_1 = value; break;
1705         case 0x1234: s->prm_vc_hc_conf = value & 0x1f001f; break;
1706         case 0x1238: s->prm_vc_i2c_cfg = value & 0x3f; break;
1707         case 0x123c: s->prm_vc_bypass_val = value & 0x01ffff7f; break;
1708         case 0x1250: s->prm_rstctrl = 0; break; /* TODO: resets */
1709         case 0x1254: s->prm_rsttimer = value & 0x1fff; break;
1710         case 0x1258: s->prm_rstst &= ~(value & 0x7fb); break;
1711         case 0x1260: s->prm_voltctrl = value & 0x1f; break;
1712         case 0x1264: s->prm_sram_pcharge = value & 0xff; break;
1713         case 0x1270:
1714             s->prm_clksrc_ctrl = value & (0xd8);
1715             omap3_prm_clksrc_ctrl_update(s, s->prm_clksrc_ctrl);
1716             /* TODO: update SYSCLKSEL bits */
1717             break;
1718         case 0x1280: OMAP_RO_REG(addr); break;
1719         case 0x1290: s->prm_voltsetup1 = value; break;
1720         case 0x1294: s->prm_voltoffset = value & 0xffff; break;
1721         case 0x1298: s->prm_clksetup = value & 0xffff; break;
1722         case 0x129c: s->prm_polctrl = value & 0xf; break;
1723         case 0x12a0: s->prm_voltsetup2 = value & 0xffff; break;
1724         /* NEON_PRM */
1725         case 0x1358: s->neon.rm_rstst &= ~(value & 0xf); break;
1726         case 0x13c8: s->neon.pm_wkdep = value & 0x2; break;
1727         case 0x13e0: s->neon.pm_pwstctrl = 0x4 | (value & 3); break;
1728         case 0x13e4: OMAP_RO_REG(addr); break;
1729         case 0x13e8: s->neon.pm_prepwstst = value & 3; break;
1730         /* USBHOST_PRM */
1731         case 0x1458: s->usbhost.rm_rstst &= ~(value & 0xf); break;
1732         case 0x14a0: s->usbhost.pm_wken = value & 1; break;
1733         case 0x14a4: s->usbhost.pm_mpugrpsel = value & 1; break;
1734         case 0x14a8: s->usbhost.pm_ivagrpsel = value & 1; break;
1735         case 0x14b0: s->usbhost.pm_wkst &= ~(value & 1); break;
1736         case 0x14c8: s->usbhost.pm_wkdep = value & 0x17; break;
1737         case 0x14e0: s->usbhost.pm_pwstctrl = 0x030104 | (value & 0x13); break;
1738         case 0x14e4: OMAP_RO_REG(addr); break;
1739         case 0x14e8: s->usbhost.pm_prepwstst = value & 3; break;
1740         default:
1741             OMAP_BAD_REGV(addr, value);
1742             break;
1743     }
1744 }
1745
1746 static CPUReadMemoryFunc *omap3_prm_readfn[] = {
1747     omap_badwidth_read32,
1748     omap_badwidth_read32,
1749     omap3_prm_read,
1750 };
1751
1752 static CPUWriteMemoryFunc *omap3_prm_writefn[] = {
1753     omap_badwidth_write32,
1754     omap_badwidth_write32,
1755     omap3_prm_write,
1756 };
1757
1758 struct omap3_prm_s *omap3_prm_init(struct omap_target_agent_s *ta,
1759                                    qemu_irq mpu_int, qemu_irq iva_int,
1760                                    struct omap_mpu_state_s *mpu)
1761 {
1762     int iomemtype;
1763     struct omap3_prm_s *s = (struct omap3_prm_s *) qemu_mallocz(sizeof(*s));
1764
1765     s->mpu_irq = mpu_int;
1766     s->iva_irq = iva_int;
1767     s->omap = mpu;
1768     omap3_prm_reset(s);
1769
1770     iomemtype = l4_register_io_memory(0, omap3_prm_readfn,
1771                                       omap3_prm_writefn, s);
1772     omap_l4_attach(ta, 0, iomemtype);
1773     omap_l4_attach(ta, 1, iomemtype);
1774
1775     return s;
1776 }
1777
1778
1779 struct omap3_cm_s
1780 {
1781     qemu_irq irq[3];
1782     struct omap_mpu_state_s *mpu;
1783
1784     /*IVA2_CM Register */
1785     uint32_t cm_fclken_iva2;    /*0x4800 4000 */
1786     uint32_t cm_clken_pll_iva2; /*0x4800 4004 */
1787     uint32_t cm_idlest_iva2;    /*0x4800 4020 */
1788     uint32_t cm_idlest_pll_iva2;        /*0x4800 4024 */
1789     uint32_t cm_autoidle_pll_iva2;      /*0x4800 4034 */
1790     uint32_t cm_clksel1_pll_iva2;       /*0x4800 4040 */
1791     uint32_t cm_clksel2_pll_iva2;       /*0x4800 4044 */
1792     uint32_t cm_clkstctrl_iva2; /*0x4800 4048 */
1793     uint32_t cm_clkstst_iva2;   /*0x4800 404c */
1794
1795     /*OCP_System_Reg_CM */
1796     uint32_t cm_revision;       /*0x4800 4800 */
1797     uint32_t cm_sysconfig;      /*0x4800 4810 */
1798
1799     /*MPU_CM Register */
1800     uint32_t cm_clken_pll_mpu;  /*0x4800 4904 */
1801     uint32_t cm_idlest_mpu;     /*0x4800 4920 */
1802     uint32_t cm_idlest_pll_mpu; /*0x4800 4924 */
1803     uint32_t cm_autoidle_pll_mpu;       /*0x4800 4934 */
1804     uint32_t cm_clksel1_pll_mpu;        /*0x4800 4940 */
1805     uint32_t cm_clksel2_pll_mpu;        /*0x4800 4944 */
1806     uint32_t cm_clkstctrl_mpu;  /*0x4800 4948 */
1807     uint32_t cm_clkstst_mpu;    /*0x4800 494c */
1808
1809     /*CORE_CM Register */
1810     uint32_t cm_fclken1_core;   /*0x4800 4a00 */
1811     uint32_t cm_fclken3_core;   /*0x4800 4a08 */
1812     uint32_t cm_iclken1_core;   /*0x4800 4a10 */
1813     uint32_t cm_iclken2_core;   /*0x4800 4a14 */
1814     uint32_t cm_iclken3_core;   /*0x4800 4a18 */
1815     uint32_t cm_idlest1_core;   /*0x4800 4a20 */
1816     uint32_t cm_idlest2_core;   /*0x4800 4a24 */
1817     uint32_t cm_idlest3_core;   /*0x4800 4a28 */
1818     uint32_t cm_autoidle1_core; /*0x4800 4a30 */
1819     uint32_t cm_autoidle2_core; /*0x4800 4a34 */
1820     uint32_t cm_autoidle3_core; /*0x4800 4a38 */
1821     uint32_t cm_clksel_core;    /*0x4800 4a40 */
1822     uint32_t cm_clkstctrl_core; /*0x4800 4a48 */
1823     uint32_t cm_clkstst_core;   /*0x4800 4a4c */
1824
1825     /*SGX_CM Register */
1826     uint32_t cm_fclken_sgx;     /*0x4800 4b00 */
1827     uint32_t cm_iclken_sgx;     /*0x4800 4b10 */
1828     uint32_t cm_idlest_sgx;     /*0x4800 4b20 */
1829     uint32_t cm_clksel_sgx;     /*0x4800 4b40 */
1830     uint32_t cm_sleepdep_sgx;   /*0x4800 4b44 */
1831     uint32_t cm_clkstctrl_sgx;  /*0x4800 4b48 */
1832     uint32_t cm_clkstst_sgx;    /*0x4800 4b4c */
1833
1834     /*WKUP_CM Register */
1835     uint32_t cm_fclken_wkup;    /*0x4800 4c00 */
1836     uint32_t cm_iclken_wkup;    /*0x4800 4c10 */
1837     uint32_t cm_idlest_wkup;    /*0x4800 4c20 */
1838     uint32_t cm_autoidle_wkup;  /*0x4800 4c30 */
1839     uint32_t cm_clksel_wkup;    /*0x4800 4c40 */
1840     uint32_t cm_c48;                  /*0x4800 4c48 */
1841
1842     /*Clock_Control_Reg_CM Register */
1843     uint32_t cm_clken_pll;      /*0x4800 4d00 */
1844     uint32_t cm_clken2_pll;     /*0x4800 4d04 */
1845     uint32_t cm_idlest_ckgen;   /*0x4800 4d20 */
1846     uint32_t cm_idlest2_ckgen;  /*0x4800 4d24 */
1847     uint32_t cm_autoidle_pll;   /*0x4800 4d30 */
1848     uint32_t cm_autoidle2_pll;  /*0x4800 4d34 */
1849     uint32_t cm_clksel1_pll;    /*0x4800 4d40 */
1850     uint32_t cm_clksel2_pll;    /*0x4800 4d44 */
1851     uint32_t cm_clksel3_pll;    /*0x4800 4d48 */
1852     uint32_t cm_clksel4_pll;    /*0x4800 4d4c */
1853     uint32_t cm_clksel5_pll;    /*0x4800 4d50 */
1854     uint32_t cm_clkout_ctrl;    /*0x4800 4d70 */
1855
1856     /*DSS_CM Register */
1857     uint32_t cm_fclken_dss;     /*0x4800 4e00 */
1858     uint32_t cm_iclken_dss;     /*0x4800 4e10 */
1859     uint32_t cm_idlest_dss;     /*0x4800 4e20 */
1860     uint32_t cm_autoidle_dss;   /*0x4800 4e30 */
1861     uint32_t cm_clksel_dss;     /*0x4800 4e40 */
1862     uint32_t cm_sleepdep_dss;   /*0x4800 4e44 */
1863     uint32_t cm_clkstctrl_dss;  /*0x4800 4e48 */
1864     uint32_t cm_clkstst_dss;    /*0x4800 4e4c */
1865
1866
1867     /*CAM_CM Register */
1868     uint32_t cm_fclken_cam;     /*0x4800 4f00 */
1869     uint32_t cm_iclken_cam;     /*0x4800 4f10 */
1870     uint32_t cm_idlest_cam;     /*0x4800 4f20 */
1871     uint32_t cm_autoidle_cam;   /*0x4800 4f30 */
1872     uint32_t cm_clksel_cam;     /*0x4800 4f40 */
1873     uint32_t cm_sleepdep_cam;   /*0x4800 4f44 */
1874     uint32_t cm_clkstctrl_cam;  /*0x4800 4f48 */
1875     uint32_t cm_clkstst_cam;    /*0x4800 4f4c */
1876
1877     /*PER_CM Register */
1878     uint32_t cm_fclken_per;     /*0x4800 5000 */
1879     uint32_t cm_iclken_per;     /*0x4800 5010 */
1880     uint32_t cm_idlest_per;     /*0x4800 5020 */
1881     uint32_t cm_autoidle_per;   /*0x4800 5030 */
1882     uint32_t cm_clksel_per;     /*0x4800 5040 */
1883     uint32_t cm_sleepdep_per;   /*0x4800 5044 */
1884     uint32_t cm_clkstctrl_per;  /*0x4800 5048 */
1885     uint32_t cm_clkstst_per;    /*0x4800 504c */
1886
1887     /*EMU_CM Register */
1888     uint32_t cm_clksel1_emu;    /*0x4800 5140 */
1889     uint32_t cm_clkstctrl_emu;  /*0x4800 5148 */
1890     uint32_t cm_clkstst_emu;    /*0x4800 514c */
1891     uint32_t cm_clksel2_emu;    /*0x4800 5150 */
1892     uint32_t cm_clksel3_emu;    /*0x4800 5154 */
1893
1894     /*Global_Reg_CM Register */
1895     uint32_t cm_polctrl;        /*0x4800 529c */
1896
1897     /*NEON_CM Register */
1898     uint32_t cm_idlest_neon;    /*0x4800 5320 */
1899     uint32_t cm_clkstctrl_neon; /*0x4800 5348 */
1900
1901     /*USBHOST_CM Register */
1902     uint32_t cm_fclken_usbhost; /*0x4800 5400 */
1903     uint32_t cm_iclken_usbhost; /*0x4800 5410 */
1904     uint32_t cm_idlest_usbhost; /*0x4800 5420 */
1905     uint32_t cm_autoidle_usbhost;       /*0x4800 5430 */
1906     uint32_t cm_sleepdep_usbhost;       /*0x4800 5444 */
1907     uint32_t cm_clkstctrl_usbhost;      /*0x4800 5448 */
1908     uint32_t cm_clkstst_usbhost;        /*0x4800 544c */
1909
1910 };
1911
1912 /*
1913 static inline void omap3_cm_fclken_wkup_update(struct omap3_cm_s *s,
1914                 uint32_t value)
1915 {
1916         
1917         if (value & 0x28)
1918         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 1);
1919     else
1920         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 0);
1921
1922     if (value &0x1)
1923         omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 1);
1924     else
1925         omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 0);
1926
1927 }
1928 static inline void omap3_cm_iclken_wkup_update(struct omap3_cm_s *s,
1929                 uint32_t value)
1930 {
1931         
1932         if (value & 0x3f)
1933         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 1);
1934     else
1935         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 0);
1936
1937 }
1938 */
1939 static inline void omap3_cm_clksel_wkup_update(struct omap3_cm_s *s,
1940                                                uint32_t value)
1941 {
1942     omap_clk gp1_fclk = omap_findclk(s->mpu, "omap3_gp1_fclk");
1943
1944     if (value & 0x1)
1945         omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
1946     else
1947         omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
1948     /*Tell GPTIMER to generate new clk rate */
1949     omap_gp_timer_change_clk(s->mpu->gptimer[0]);
1950
1951     TRACE("omap3_gp1_fclk %lld",
1952           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp1_fclk")));
1953
1954     /*TODO:CM_USIM_CLK CLKSEL_RM */
1955 }
1956
1957 static inline void omap3_cm_mpu_update(struct omap3_cm_s *s)
1958 {
1959     uint32_t m, n, divide, m2, cm_clken_pll_mpu;
1960     uint32_t bypass = 1;
1961
1962     cm_clken_pll_mpu = s->cm_clken_pll_mpu;
1963     omap_clk mpu_clk = omap_findclk(s->mpu, "omap3_mpu_clk");
1964
1965     if ((cm_clken_pll_mpu & 0x7) == 0x5)
1966     {
1967         bypass = 1;
1968     }
1969     else if ((cm_clken_pll_mpu & 0x7) == 0x7)
1970     {
1971         m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
1972         if ((m == 0) || (m == 1))
1973             bypass = 1;
1974         else
1975             bypass = 0;
1976     }
1977     if (bypass == 1)
1978     {
1979         /*BYPASS Model */
1980         divide = (s->cm_clksel1_pll_mpu & 0x380000) >> 19;
1981         //OMAP3_DEBUG(("divide %d\n",divide));
1982         omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_core_clk"));
1983         omap_clk_setrate(mpu_clk, divide, 1);
1984
1985     }
1986     else
1987     {
1988         n = (s->cm_clksel1_pll_mpu & 0x7F);
1989         m2 = (s->cm_clksel2_pll_mpu & 0x1F);
1990         //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
1991         omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
1992         omap_clk_setrate(mpu_clk, (n + 1) * m2, m);
1993         //OMAP3_DEBUG(("mpu %d \n",omap_clk_getrate(mpu_clk)));
1994
1995     }
1996
1997 }
1998
1999 static inline void omap3_cm_iva2_update(struct omap3_cm_s *s)
2000 {
2001     uint32_t m, n, divide, m2, cm_clken_pll_iva2;
2002     uint32_t bypass = 1;
2003
2004     cm_clken_pll_iva2 = s->cm_clken_pll_iva2;
2005     omap_clk iva2_clk = omap_findclk(s->mpu, "omap3_iva2_clk");
2006
2007     if (((cm_clken_pll_iva2 & 0x7) == 0x5)
2008         || ((cm_clken_pll_iva2 & 0x7) == 0x1))
2009     {
2010         bypass = 1;
2011     }
2012     else if ((cm_clken_pll_iva2 & 0x7) == 0x7)
2013     {
2014         m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
2015         if ((m == 0) || (m == 1))
2016             bypass = 1;
2017         else
2018             bypass = 0;
2019     }
2020     if (bypass == 1)
2021     {
2022         /*BYPASS Model */
2023         divide = (s->cm_clksel1_pll_iva2 & 0x380000) >> 19;
2024         //OMAP3_DEBUG(("divide %d\n",divide));
2025         omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_core_clk"));
2026         omap_clk_setrate(iva2_clk, divide, 1);
2027
2028     }
2029     else
2030     {
2031         n = (s->cm_clksel1_pll_iva2 & 0x7F);
2032         m2 = (s->cm_clksel2_pll_iva2 & 0x1F);
2033         //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
2034         omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
2035         omap_clk_setrate(iva2_clk, (n + 1) * m2, m);
2036         //OMAP3_DEBUG(("iva2_clk %d \n",omap_clk_getrate(iva2_clk)));
2037
2038     }
2039
2040 }
2041
2042 static inline void omap3_cm_dpll3_update(struct omap3_cm_s *s)
2043 {
2044     uint32_t m, n, m2, m3, cm_clken_pll;
2045     uint32_t bypass = 1;
2046
2047     cm_clken_pll = s->cm_clken_pll;
2048
2049     /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
2050     if (((cm_clken_pll & 0x7) == 0x5) || ((cm_clken_pll & 0x7) == 0x6))
2051     {
2052         bypass = 1;
2053     }
2054     else if ((cm_clken_pll & 0x7) == 0x7)
2055     {
2056         m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
2057         if ((m == 0) || (m == 1))
2058             bypass = 1;
2059         else
2060             bypass = 0;
2061     }
2062     if (bypass == 1)
2063     {
2064         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), 1, 1);
2065         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), 1, 1);
2066         omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"), 1,
2067                          1);
2068     }
2069     else
2070     {
2071         n = (s->cm_clksel1_pll & 0x3f00) >> 8;
2072         m2 = (s->cm_clksel1_pll & 0xf8000000) >> 27;
2073         m3 = (s->cm_clksel1_emu & 0x1f0000) >> 16;
2074
2075         if (s->cm_clksel2_emu&0x80000)
2076         {
2077                 /*override control of DPLL3*/
2078                 m = (s->cm_clksel2_emu&0x7ff)>>8;
2079                 n =  s->cm_clksel2_emu&0x7f;
2080                 TRACE("DPLL3 override, m 0x%x n 0x%x",m,n);
2081         }
2082
2083         //OMAP3_DEBUG(("dpll3 cm_clksel1_pll %x m  %d n %d m2 %d  m3 %d\n",s->cm_clksel1_pll,m,n,m2,m3 ));
2084         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), (n + 1) * m2,
2085                          m);
2086         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), (n + 1) * m2,
2087                          m * 2);
2088         omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"),
2089                          (n + 1) * m3, m * 2);
2090         TRACE("coreclk %lld",
2091               omap_clk_getrate(omap_findclk(s->mpu, "omap3_core_clk")));
2092     }
2093
2094
2095 }
2096
2097 static inline void omap3_cm_dpll4_update(struct omap3_cm_s *s)
2098 {
2099     uint32_t m, n, m2, m3, m4, m5, m6, cm_clken_pll;
2100     cm_clken_pll = s->cm_clken_pll;
2101     uint32_t bypass = 1;
2102
2103     /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
2104     /*DPLL4 */
2105     if ((cm_clken_pll & 0x70000) == 0x10000)
2106     {
2107         bypass = 1;
2108     }
2109     else if ((cm_clken_pll & 0x70000) == 0x70000)
2110     {
2111         m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
2112         if ((m == 0) || (m == 1))
2113             bypass = 1;
2114         else
2115             bypass = 0;
2116     }
2117     if (bypass == 1)
2118     {
2119         omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), 1, 1);
2120         omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), 1, 1);
2121         omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"), 1, 1);
2122         omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), 1, 1);
2123         omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"), 1, 1);
2124     }
2125     else
2126     {
2127         n = (s->cm_clksel2_pll & 0x7f);
2128         m2 = s->cm_clksel3_pll & 0x1f;
2129         m3 = (s->cm_clksel_dss & 0x1f00) >> 8;
2130         m4 = s->cm_clksel_dss & 0x1f;
2131         m5 = s->cm_clksel_cam & 0x1f;
2132         m6 = (s->cm_clksel1_emu & 0x1f000000) >> 24;
2133
2134         if (s->cm_clksel3_emu&0x80000)
2135         {
2136                 /*override control of DPLL4*/
2137                 m = (s->cm_clksel3_emu&0x7ff)>>8;
2138                 n =  s->cm_clksel3_emu&0x7f;
2139                 TRACE("DPLL4 override, m 0x%x n 0x%x",m,n);
2140         }
2141
2142
2143         //OMAP3_DEBUG(("dpll4 m  %d n %d m2 %d  m3 %d m4 %d m5 %d m6 %d \n",m,n,m2,m3,m4,m5,m6 ));
2144         omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), (n + 1) * m2,
2145                          m * 2);
2146         omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), (n + 1) * m3,
2147                          m * 2);
2148         omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"),
2149                          (n + 1) * m4, m * 2);
2150         omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), (n + 1) * m5,
2151                          m * 2);
2152         omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"),
2153                          (n + 1) * m6, m * 2);
2154
2155         TRACE("omap3_96m_fclk %lld",
2156               omap_clk_getrate(omap_findclk(s->mpu, "omap3_96m_fclk")));
2157         TRACE("omap3_54m_fclk %lld",
2158               omap_clk_getrate(omap_findclk(s->mpu, "omap3_54m_fclk")));
2159         TRACE("omap3_dss1_alwon_fclk %lld",
2160               omap_clk_getrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk")));
2161         TRACE("omap3_cam_mclk %lld",
2162               omap_clk_getrate(omap_findclk(s->mpu, "omap3_cam_mclk")));
2163         TRACE("omap3_per_alwon_clk %lld",
2164               omap_clk_getrate(omap_findclk(s->mpu, "omap3_per_alwon_clk")));
2165         TRACE("omap3_48m_fclk %lld",
2166               omap_clk_getrate(omap_findclk(s->mpu, "omap3_48m_fclk")));
2167         TRACE("omap3_12m_fclk %lld",
2168               omap_clk_getrate(omap_findclk(s->mpu, "omap3_12m_fclk")));
2169     }
2170 }
2171
2172 static inline void omap3_cm_dpll5_update(struct omap3_cm_s *s)
2173 {
2174          uint32_t m, n, m2, cm_idlest2_ckgen;
2175     uint32_t bypass = 1;
2176
2177     cm_idlest2_ckgen = s->cm_idlest2_ckgen;;
2178
2179     /*dpll5 bypass mode */
2180     if ((cm_idlest2_ckgen & 0x1) == 0x0) 
2181     {
2182         bypass = 1;
2183     }
2184
2185     if (bypass == 1)
2186     {
2187         omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), 1, 1);
2188     }
2189     else
2190     {
2191          m = (s->cm_clksel4_pll & 0x7ff00)>>8;
2192         n = s->cm_clksel4_pll & 0x3f00;
2193         m2 = s->cm_clksel5_pll & 0x1f;
2194
2195         TRACE("dpll5 m %d n %d m2 %d",m,n,m2);
2196         omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), (n + 1) * m2,
2197                          m);
2198         TRACE("omap3_120m_fclk %lld",
2199               omap_clk_getrate(omap_findclk(s->mpu, "omap3_120m_fclk")));
2200     }
2201 }
2202
2203 static inline void omap3_cm_48m_update(struct omap3_cm_s *s)
2204 {
2205     if (s->cm_clksel1_pll & 0x8)
2206     {
2207         /*parent is sysaltclk */
2208         omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
2209                           omap_findclk(s->mpu, "omap3_sys_altclk"));
2210         omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
2211                           omap_findclk(s->mpu, "omap3_sys_altclk"));
2212         /*TODO:need to set rate ? */
2213
2214     }
2215     else
2216     {
2217         omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
2218                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2219         omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
2220                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2221         omap_clk_setrate(omap_findclk(s->mpu, "omap3_48m_fclk"), 2, 1);
2222         omap_clk_setrate(omap_findclk(s->mpu, "omap3_12m_fclk"), 8, 1);
2223
2224     }
2225
2226 }
2227
2228 static inline void omap3_cm_gp10_update(struct omap3_cm_s *s)
2229 {
2230     omap_clk gp10_fclk = omap_findclk(s->mpu, "omap3_gp10_fclk");
2231
2232     if (s->cm_clksel_core & 0x40)
2233         omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
2234     else
2235         omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
2236
2237     /*Tell GPTIMER10 to generate new clk rate */
2238     omap_gp_timer_change_clk(s->mpu->gptimer[9]);
2239     TRACE("omap3_gp10_fclk %lld",
2240           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp10_fclk")));
2241 }
2242
2243 static inline void omap3_cm_gp11_update(struct omap3_cm_s *s)
2244 {
2245     omap_clk gp11_fclk = omap_findclk(s->mpu, "omap3_gp11_fclk");
2246
2247     if (s->cm_clksel_core & 0x80)
2248         omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
2249     else
2250         omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
2251     /*Tell GPTIMER11 to generate new clk rate */
2252     omap_gp_timer_change_clk(s->mpu->gptimer[10]);
2253     TRACE("omap3_gp11_fclk %lld",
2254           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp11_fclk")));
2255 }
2256
2257 static inline void omap3_cm_l3clk_update(struct omap3_cm_s *s)
2258 {
2259     omap_clk l3_iclk = omap_findclk(s->mpu, "omap3_l3_iclk");
2260     if ((s->cm_clksel_core & 0x3) == 0x1)
2261         omap_clk_setrate(l3_iclk, 1, 1);
2262     else if ((s->cm_clksel_core & 0x3) == 0x2)
2263         omap_clk_setrate(l3_iclk, 2, 1);
2264 }
2265
2266 static inline void omap3_cm_l4clk_update(struct omap3_cm_s *s)
2267 {
2268     omap_clk l4_iclk = omap_findclk(s->mpu, "omap3_l4_iclk");
2269     if ((s->cm_clksel_core & 0xc) == 0x4)
2270         omap_clk_setrate(l4_iclk, 1, 1);
2271     else if ((s->cm_clksel_core & 0xc) == 0x8)
2272         omap_clk_setrate(l4_iclk, 2, 1);
2273 }
2274
2275 static inline void omap3_cm_per_gptimer_update(struct omap3_cm_s *s)
2276 {
2277     uint32_t cm_clksel_per = s->cm_clksel_per;
2278
2279     if (cm_clksel_per & 0x1)
2280         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
2281                           omap_findclk(s->mpu, "omap3_sys_clk"));
2282     else
2283         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
2284                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2285     omap_gp_timer_change_clk(s->mpu->gptimer[1]);
2286
2287     if (cm_clksel_per & 0x2)
2288         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
2289                           omap_findclk(s->mpu, "omap3_sys_clk"));
2290     else
2291         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
2292                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2293     omap_gp_timer_change_clk(s->mpu->gptimer[2]);
2294
2295     if (cm_clksel_per & 0x4)
2296         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
2297                           omap_findclk(s->mpu, "omap3_sys_clk"));
2298     else
2299         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
2300                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2301     omap_gp_timer_change_clk(s->mpu->gptimer[3]);
2302
2303     if (cm_clksel_per & 0x8)
2304         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
2305                           omap_findclk(s->mpu, "omap3_sys_clk"));
2306     else
2307         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
2308                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2309     omap_gp_timer_change_clk(s->mpu->gptimer[4]);
2310
2311     if (cm_clksel_per & 0x10)
2312         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
2313                           omap_findclk(s->mpu, "omap3_sys_clk"));
2314     else
2315         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
2316                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2317     omap_gp_timer_change_clk(s->mpu->gptimer[5]);
2318     
2319     if (cm_clksel_per & 0x20)
2320         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
2321                           omap_findclk(s->mpu, "omap3_sys_clk"));
2322     else
2323         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
2324                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2325     omap_gp_timer_change_clk(s->mpu->gptimer[6]);
2326
2327
2328     if (cm_clksel_per & 0x40)
2329         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
2330                           omap_findclk(s->mpu, "omap3_sys_clk"));
2331     else
2332         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
2333                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2334     omap_gp_timer_change_clk(s->mpu->gptimer[7]);
2335     
2336     if (cm_clksel_per & 0x80)
2337         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
2338                           omap_findclk(s->mpu, "omap3_sys_clk"));
2339     else
2340         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
2341                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2342     omap_gp_timer_change_clk(s->mpu->gptimer[8]);
2343
2344     /*TODO:Tell GPTIMER to generate new clk rate */
2345     TRACE("omap3_gp2_fclk %lld",
2346           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp2_fclk")));
2347     TRACE("omap3_gp3_fclk %lld",
2348           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp3_fclk")));
2349         TRACE("omap3_gp4_fclk %lld",
2350           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp4_fclk")));
2351     TRACE("omap3_gp5_fclk %lld",
2352           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp5_fclk")));
2353     TRACE("omap3_gp6_fclk %lld",
2354           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp6_fclk")));
2355     TRACE("omap3_gp7_fclk %lld",
2356           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp7_fclk")));
2357     TRACE("omap3_gp8_fclk %lld",
2358           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp8_fclk")));
2359     TRACE("omap3_gp9_fclk %lld",
2360           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp9_fclk")));
2361 }
2362
2363 static inline void omap3_cm_clkout2_update(struct omap3_cm_s *s)
2364 {
2365         uint32 divor;
2366         
2367         if (!s->cm_clkout_ctrl&0x80)
2368                 return;
2369
2370         switch (s->cm_clkout_ctrl&0x3)
2371         {
2372                 case 0x0:
2373                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2374                           omap_findclk(s->mpu, "omap3_core_clk"));
2375                         break;
2376                 case 0x1:
2377                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2378                           omap_findclk(s->mpu, "omap3_sys_clk"));
2379                         break;
2380                 case 0x2:
2381                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2382                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2383                         break;
2384                 case 0x3:
2385                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2386                           omap_findclk(s->mpu, "omap3_54m_fclk"));
2387                         break;
2388         }
2389
2390         divor = (s->cm_clkout_ctrl&0x31)>>3;
2391         divor = 1<<divor;
2392         omap_clk_setrate(omap_findclk(s->mpu, "omap3_sys_clkout2"), divor, 1);
2393         
2394 }
2395
2396 static void omap3_cm_reset(struct omap3_cm_s *s)
2397 {
2398     s->cm_fclken_iva2 = 0x0;
2399     s->cm_clken_pll_iva2 = 0x11;
2400     s->cm_idlest_iva2 = 0x1;
2401     s->cm_idlest_pll_iva2 = 0x0;
2402     s->cm_autoidle_pll_iva2 = 0x0;
2403     s->cm_clksel1_pll_iva2 = 0x80000;
2404     s->cm_clksel2_pll_iva2 = 0x1;
2405     s->cm_clkstctrl_iva2 = 0x0;
2406     s->cm_clkstst_iva2 = 0x0;
2407
2408     s->cm_revision = 0x10;
2409     s->cm_sysconfig = 0x1;
2410
2411     s->cm_clken_pll_mpu = 0x15;
2412     s->cm_idlest_mpu = 0x1;
2413     s->cm_idlest_pll_mpu = 0x0;
2414     s->cm_autoidle_pll_mpu = 0x0;
2415     s->cm_clksel1_pll_mpu = 0x80000;
2416     s->cm_clksel2_pll_mpu = 0x1;
2417     s->cm_clkstctrl_mpu = 0x0;
2418     s->cm_clkstst_mpu = 0x0;
2419
2420     s->cm_fclken1_core = 0x0;
2421     s->cm_fclken3_core = 0x0;
2422     s->cm_iclken1_core = 0x42;
2423     s->cm_iclken2_core = 0x0;
2424     s->cm_iclken3_core = 0x0;
2425     /*allow access to devices*/
2426     s->cm_idlest1_core = 0x0;
2427     s->cm_idlest2_core = 0x0;
2428     /*ide status =0 */
2429     s->cm_idlest3_core = 0xa; 
2430     s->cm_autoidle1_core = 0x0;
2431     s->cm_autoidle2_core = 0x0;
2432     s->cm_autoidle3_core = 0x0;
2433     s->cm_clksel_core = 0x105;
2434     s->cm_clkstctrl_core = 0x0;
2435     s->cm_clkstst_core = 0x0;
2436
2437     s->cm_fclken_sgx = 0x0;
2438     s->cm_iclken_sgx = 0x0;
2439     s->cm_idlest_sgx = 0x1;
2440     s->cm_clksel_sgx = 0x0;
2441     s->cm_sleepdep_sgx = 0x0;
2442     s->cm_clkstctrl_sgx = 0x0;
2443     s->cm_clkstst_sgx = 0x0;
2444
2445     s->cm_fclken_wkup = 0x0;
2446     s->cm_iclken_wkup = 0x0;
2447     /*assume all clock can be accessed*/
2448     s->cm_idlest_wkup = 0x0;
2449     s->cm_autoidle_wkup = 0x0;
2450     s->cm_clksel_wkup = 0x12;
2451
2452     s->cm_clken_pll = 0x110015;
2453     s->cm_clken2_pll = 0x11;
2454     s->cm_idlest_ckgen = 0x0;
2455     s->cm_idlest2_ckgen = 0x0;
2456     s->cm_autoidle_pll = 0x0;
2457     s->cm_autoidle2_pll = 0x0;
2458     s->cm_clksel1_pll = 0x8000040;
2459     s->cm_clksel2_pll = 0x0;
2460     s->cm_clksel3_pll = 0x1;
2461     s->cm_clksel4_pll = 0x0;
2462     s->cm_clksel5_pll = 0x1;
2463     s->cm_clkout_ctrl = 0x3;
2464
2465
2466     s->cm_fclken_dss = 0x0;
2467     s->cm_iclken_dss = 0x0;
2468     /*dss can be accessed*/
2469     s->cm_idlest_dss = 0x0;
2470     s->cm_autoidle_dss = 0x0;
2471     s->cm_clksel_dss = 0x1010;
2472     s->cm_sleepdep_dss = 0x0;
2473     s->cm_clkstctrl_dss = 0x0;
2474     s->cm_clkstst_dss = 0x0;
2475
2476     s->cm_fclken_cam = 0x0;
2477     s->cm_iclken_cam = 0x0;
2478     s->cm_idlest_cam = 0x1;
2479     s->cm_autoidle_cam = 0x0;
2480     s->cm_clksel_cam = 0x10;
2481     s->cm_sleepdep_cam = 0x0;
2482     s->cm_clkstctrl_cam = 0x0;
2483     s->cm_clkstst_cam = 0x0;
2484
2485     s->cm_fclken_per = 0x0;
2486     s->cm_iclken_per = 0x0;
2487     //s->cm_idlest_per = 0x3ffff;
2488     s->cm_idlest_per = 0x0; //enable GPIO access
2489     s->cm_autoidle_per = 0x0;
2490     s->cm_clksel_per = 0x0;
2491     s->cm_sleepdep_per = 0x0;
2492     s->cm_clkstctrl_per = 0x0;
2493     s->cm_clkstst_per = 0x0;
2494
2495     s->cm_clksel1_emu = 0x10100a50;
2496     s->cm_clkstctrl_emu = 0x2;
2497     s->cm_clkstst_emu = 0x0;
2498     s->cm_clksel2_emu = 0x0;
2499     s->cm_clksel3_emu = 0x0;
2500
2501     s->cm_polctrl = 0x0;
2502
2503     s->cm_idlest_neon = 0x1;
2504     s->cm_clkstctrl_neon = 0x0;
2505
2506     s->cm_fclken_usbhost = 0x0;
2507     s->cm_iclken_usbhost = 0x0;
2508     s->cm_idlest_usbhost = 0x3;
2509     s->cm_autoidle_usbhost = 0x0;
2510     s->cm_sleepdep_usbhost = 0x0;
2511     s->cm_clkstctrl_usbhost = 0x0;
2512     s->cm_clkstst_usbhost = 0x0;
2513 }
2514
2515 static uint32_t omap3_cm_read(void *opaque, target_phys_addr_t addr)
2516 {
2517     struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
2518     uint32_t ret;
2519     uint32_t bypass = 0, m;
2520
2521     TRACE("%04x", addr);
2522     switch (addr)
2523     {
2524     case 0x0:
2525         return s->cm_fclken_iva2;
2526     case 0x04:
2527         return s->cm_clken_pll_iva2;
2528     case 0x20:
2529         return s->cm_idlest_iva2;
2530     case 0x24:
2531         if (((s->cm_clken_pll_iva2 & 0x7) == 0x5)
2532             || ((s->cm_clken_pll_iva2 & 0x7) == 0x1))
2533         {
2534             bypass = 1;
2535         }
2536         else if ((s->cm_clken_pll_iva2 & 0x7) == 0x7)
2537         {
2538             m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
2539             if ((m == 0) || (m == 1))
2540                 bypass = 1;
2541             else
2542                 bypass = 0;
2543         }
2544         if (bypass)
2545             return 0;
2546         else
2547             return 1;
2548     case 0x34:
2549         return s->cm_autoidle_pll_iva2;
2550     case 0x40:
2551         return s->cm_clksel1_pll_iva2;
2552     case 0x44:
2553         return s->cm_clksel2_pll_iva2;
2554     case 0x48:
2555         return s->cm_clkstctrl_iva2;
2556     case 0x4c:
2557         return s->cm_clkstst_iva2;
2558
2559    case 0x800:
2560                 return s->cm_revision;
2561         case 0x810:
2562                 return s->cm_sysconfig;
2563
2564         
2565     case 0x904:                /*CM_CLKEN_PLL_MPU */
2566         return s->cm_clken_pll_mpu;
2567    case 0x920:
2568                 return s->cm_idlest_mpu & 0x0;  /*MPU is active*/
2569     case 0x924:
2570         if ((s->cm_clken_pll_mpu & 0x7) == 0x5)
2571         {
2572             bypass = 1;
2573         }
2574         else if ((s->cm_clken_pll_mpu & 0x7) == 0x7)
2575         {
2576             m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
2577             if ((m == 0) || (m == 1))
2578                 bypass = 1;
2579             else
2580                 bypass = 0;
2581         }
2582         if (bypass)
2583             return 0;
2584         else
2585             return 1;
2586     case 0x934:
2587         return s->cm_autoidle_pll_mpu;
2588     case 0x940:
2589         return s->cm_clksel1_pll_mpu;
2590     case 0x944:
2591         return s->cm_clksel2_pll_mpu;
2592      case 0x948:
2593         return s->cm_clkstctrl_mpu;
2594      case 0x94c:
2595         return s->cm_clkstst_mpu;
2596
2597
2598         
2599     case 0xa00:
2600         return s->cm_fclken1_core;
2601     case 0xa08:
2602         return s->cm_fclken3_core;
2603     case 0xa10:
2604         return s->cm_iclken1_core;
2605     case 0xa14:
2606          return s->cm_iclken2_core;
2607     case 0xa20:
2608         return s->cm_idlest1_core;
2609     case 0xa24:
2610         return s->cm_idlest2_core;
2611     case 0xa28:
2612         return s->cm_idlest3_core;
2613     case 0xa30:
2614         return s->cm_autoidle1_core;
2615     case 0xa34:
2616         return s->cm_autoidle2_core;
2617     case 0xa38:
2618         return s->cm_autoidle3_core;
2619     case 0xa40:                /*CM_CLKSEL_CORE */
2620         return s->cm_clksel_core;
2621     case 0xa48:
2622          return s->cm_clkstctrl_core;
2623      case 0xa4c:
2624         return s->cm_clkstst_core;
2625
2626    case 0xb00:
2627                 return s->cm_fclken_sgx;
2628         case 0xb10:
2629                 return s->cm_iclken_sgx;
2630         case 0xb20:
2631                 return s->cm_idlest_sgx&0x0;
2632    case 0xb40:                /*CM_CLKSEL_SGX */
2633         return s->cm_clksel_sgx;
2634    case 0xb48:
2635                 return s->cm_clkstctrl_sgx;
2636         case 0xb4c:
2637                 return s->cm_clkstst_sgx;
2638
2639                 
2640     case 0xc00:                /*CM_FCLKEN_WKUP */
2641         return s->cm_fclken_wkup;
2642     case 0xc10:                /*CM_ICLKEN_WKUP */
2643         return s->cm_iclken_wkup;
2644     case 0xc20:                /*CM_IDLEST_WKUP */
2645         /*TODO: Check whether the timer can be accessed. */
2646         return 0x0;
2647     case 0xc30:
2648         return s->cm_idlest_wkup;
2649     case 0xc40:
2650         return s->cm_clksel_wkup;
2651     case 0xc48:
2652         return s->cm_c48;
2653
2654         
2655     case 0xd00:                /*CM_CLKEN_PLL */
2656         return s->cm_clken_pll;
2657     case 0xd04:
2658         return s->cm_clken2_pll;
2659     case 0xd20:
2660          /*FIXME: all clock is active. we do not care it. */
2661         ret = 0x3ffff;
2662
2663         /*DPLL3*/
2664         bypass = 0;
2665         if (((s->cm_clken_pll & 0x7) == 0x5) || ((s->cm_clken_pll & 0x7) == 0x6))
2666                 bypass = 1;
2667         else if ((s->cm_clken_pll & 0x7) == 0x7) {
2668             m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
2669             if ((m == 0) || (m == 1))
2670                 bypass = 1;
2671             else
2672                 bypass = 0;
2673         }
2674         if (bypass)
2675             ret &= 0xfffe;
2676         
2677         /*DPLL4*/
2678             bypass = 0;
2679             if ((s->cm_clken_pll & 0x70000) == 0x10000)
2680             bypass = 1;
2681         else if ((s->cm_clken_pll & 0x70000) == 0x70000) {
2682             m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
2683             if ((m == 0) || (m == 1))
2684                 bypass = 1;
2685             else
2686                 bypass = 0;
2687         }
2688         if (bypass)
2689             ret &= 0xfffd;
2690         return ret;
2691         
2692     case 0xd24:
2693         return s->cm_idlest2_ckgen;
2694     case 0xd30:
2695         return s->cm_autoidle_pll;
2696     case 0xd34:
2697         return s->cm_autoidle2_pll;
2698     case 0xd40:                /*CM_CLKSEL1_PLL */
2699         return s->cm_clksel1_pll;
2700     case 0xd44:
2701         return s->cm_clksel2_pll;
2702     case 0xd48:                /*CM_CLKSEL3_PLL */
2703         return s->cm_clksel3_pll;
2704     case 0xd4c:
2705         return s->cm_clksel4_pll;
2706     case 0xd50:                /*CM_CLKSEL5_PLL */
2707         return s->cm_clksel5_pll;
2708     case 0xd70:
2709          return s->cm_clkout_ctrl;
2710
2711          
2712     case 0xe00:
2713         return s->cm_fclken_dss;
2714         case 0xe10:
2715         return s->cm_iclken_dss;
2716     case 0xe20:
2717         return s->cm_idlest_dss;
2718     case 0xe30:
2719         return s->cm_autoidle_dss;
2720     case 0xe40:
2721         return s->cm_clksel_dss;
2722     case 0xe44:
2723         return s->cm_sleepdep_dss;
2724     case 0xe48:
2725         return s->cm_clkstctrl_dss;
2726     case 0xe4c:
2727         return s->cm_clkstst_dss;
2728
2729         
2730     case 0xf00:
2731         return s->cm_fclken_cam;
2732     case 0xf10:
2733         return s->cm_iclken_cam;
2734     case 0xf20:
2735         return s->cm_idlest_cam&0x0;
2736     case 0xf30:
2737         return s->cm_autoidle_cam;
2738     case 0xf40:
2739         return s->cm_clksel_cam;
2740     case 0xf44:
2741         return s->cm_sleepdep_cam;
2742     case 0xf48:
2743         return s->cm_clkstctrl_cam;
2744     case 0xf4c:
2745         return s->cm_clkstst_cam;
2746
2747         
2748     case 0x1000:
2749         return s->cm_fclken_per;
2750     case 0x1010:
2751         return s->cm_iclken_per;
2752     case 0x1020:
2753         return s->cm_idlest_per ;
2754     case 0x1030:
2755         return s->cm_autoidle_per;
2756     case 0x1040:
2757         return s->cm_clksel_per;
2758     case 0x1044:
2759         return s->cm_sleepdep_per;
2760     case 0x1048:
2761         return s->cm_clkstctrl_per;
2762     case 0x104c:
2763                 return s->cm_clkstst_per;
2764
2765         
2766     case 0x1140:               /*CM_CLKSEL1_EMU */
2767         return s->cm_clksel1_emu;
2768     case 0x1148:
2769          return s->cm_clkstctrl_emu;
2770     case 0x114c:
2771         return s->cm_clkstst_emu&0x0;
2772     case 0x1150:
2773         return s->cm_clksel2_emu;
2774     case 0x1154:
2775         return s->cm_clksel3_emu;
2776
2777    case 0x129c:
2778                 return s->cm_polctrl;
2779
2780         case 0x1320:
2781                 return s->cm_idlest_neon&0x0;
2782         case 0x1348:
2783                 return s->cm_clkstctrl_neon;
2784
2785         case 0x1400:
2786                 return s->cm_fclken_usbhost;
2787         case 0x1410:
2788                 return s->cm_iclken_usbhost;
2789         case 0x1420:
2790                 return s->cm_idlest_usbhost&0x0;
2791     case 0x1430:
2792         return s->cm_autoidle_usbhost;
2793     case 0x1444:
2794         return s->cm_sleepdep_usbhost;
2795     case 0x1448:
2796         return s->cm_clkstctrl_usbhost;
2797     case 0x144c:
2798         return s->cm_clkstst_usbhost;
2799
2800     default:
2801         printf("omap3_cm_read addr %x pc %x \n", addr, cpu_single_env->regs[15] );
2802         exit(-1);
2803     }
2804 }
2805
2806
2807 static void omap3_cm_write(void *opaque, target_phys_addr_t addr,
2808                            uint32_t value)
2809 {
2810     struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
2811
2812     TRACE("%04x = %08x", addr, value);
2813     switch (addr)
2814     {
2815     case 0x20:
2816     case 0x24:
2817     case 0x4c:
2818     case 0x800:
2819     case 0x920:
2820     case 0x924:
2821     case 0x94c:
2822     case 0xa20:
2823     case 0xa24:
2824     case 0xa28:
2825     case 0xa4c:
2826     case 0xb20:
2827     case 0xb4c:
2828     case 0xc20:                /*CM_IDLEST_WKUP */
2829     case 0xd20:
2830     case 0xd24:
2831     case 0xe20:
2832     case 0xe4c:
2833     case 0xf20:
2834     case 0xf4c:
2835     case 0x1020:
2836     case 0x104c:
2837     case 0x114c:
2838     case 0x1320:
2839     case 0x1420:
2840     case 0x144c:
2841         OMAP_RO_REG(addr);
2842         exit(-1);
2843         break;
2844         
2845     case 0x0:
2846         s->cm_fclken_iva2 = value & 0x1;
2847         break;
2848     case 0x4:                  /*CM_CLKEN_PLL_IVA2 */
2849         s->cm_clken_pll_iva2 = value & 0x7ff;
2850         omap3_cm_iva2_update(s);
2851         break;
2852     case 0x34:
2853         s->cm_autoidle_pll_iva2 = value & 0x7;
2854         break;
2855     case 0x40:
2856         s->cm_clksel1_pll_iva2 = value & 0x3fff7f;
2857         //printf("value %x s->cm_clksel1_pll_iva2 %x \n",value,s->cm_clksel1_pll_iva2);
2858         omap3_cm_iva2_update(s);
2859         break;
2860     case 0x44:
2861         s->cm_clksel2_pll_iva2 = value & 0x1f;
2862         omap3_cm_iva2_update(s);
2863         break;
2864     case 0x48:
2865         s->cm_clkstctrl_iva2 = value& 0x3;
2866         break;
2867
2868     case 0x810:
2869         s->cm_sysconfig = value & 0x1;
2870         break;
2871
2872         
2873     case 0x904:                /*CM_CLKEN_PLL_MPU */
2874         s->cm_clken_pll_mpu = value & 0x7ff;
2875         omap3_cm_mpu_update(s);
2876         break;
2877     case 0x934:
2878         s->cm_autoidle_pll_mpu = value & 0x7;
2879         break;
2880     case 0x940:
2881         //printf("s->cm_clksel1_pll_mpu  %x\n",s->cm_clksel1_pll_mpu );
2882         s->cm_clksel1_pll_mpu = value & 0x3fff7f;
2883         omap3_cm_mpu_update(s);
2884         break;
2885     case 0x944:
2886         s->cm_clksel2_pll_mpu = value & 0x1f;
2887         omap3_cm_mpu_update(s);
2888         break;
2889     case 0x948:
2890         s->cm_clkstctrl_mpu = value & 0x3;
2891         break;
2892
2893         
2894     case 0xa00:
2895         s->cm_fclken1_core = value & 0x43fffe00;
2896          break;
2897     case 0xa08:
2898          s->cm_fclken3_core = value & 0x7;
2899          break;
2900     case 0xa10:
2901         s->cm_iclken1_core = value & 0x637ffed2;
2902         s->cm_idlest1_core = ~s->cm_iclken1_core;
2903         /* TODO: replace code below with real implementation */
2904         s->cm_idlest1_core &= ~0x20; /* HS OTG USB idle */
2905         s->cm_idlest1_core |= 4; /* SDMA in standby */
2906         break;
2907     case 0xa14:
2908          s->cm_iclken2_core = value & 0x1f;
2909          break;
2910     case 0xa18:
2911         s->cm_iclken3_core = value & 0x4;
2912         s->cm_idlest3_core = 0xd & ~(s->cm_iclken3_core & 4);
2913         break;
2914     case 0xa30:
2915         s->cm_autoidle1_core = value & 0x7ffffed0;
2916         break;
2917     case 0xa34:
2918         s->cm_autoidle2_core = value & 0x1f;
2919         break;
2920     case 0xa38:
2921         s->cm_autoidle3_core = value & 0x2;
2922         break;
2923     case 0xa40:                /*CM_CLKSEL_CORE */
2924         s->cm_clksel_core = (value & 0xff);
2925         s->cm_clksel_core |= 0x100;
2926         omap3_cm_gp10_update(s);
2927         omap3_cm_gp11_update(s);
2928         omap3_cm_l3clk_update(s);
2929         omap3_cm_l4clk_update(s);
2930         break;
2931     case 0xa48:
2932         s->cm_clkstctrl_core = value & 0xf;
2933         break;
2934
2935     case 0xb00:
2936         s->cm_fclken_sgx = value &0x2;
2937         break;
2938     case 0xb10:
2939         s->cm_iclken_sgx = value & 0x1;
2940         break;
2941     case 0xb40:                /*CM_CLKSEL_SGX */
2942         /*TODO: SGX Clock!! */
2943         s->cm_clksel_sgx = value;
2944         break;
2945     case 0xb44:
2946         s->cm_sleepdep_sgx = value &0x2;
2947         break;
2948     case 0xb48:
2949         s->cm_clkstctrl_sgx = value & 0x3;
2950         break;
2951
2952     
2953     case 0xc00:                /*CM_FCLKEN_WKUP */
2954         s->cm_fclken_wkup = value & 0x2e9;
2955         break;
2956     case 0xc10:                /*CM_ICLKEN_WKUP */
2957         s->cm_iclken_wkup = value & 0x2ff;
2958         break;
2959     case 0xc30:
2960         s->cm_autoidle_wkup = value & 0x23f;
2961         break;
2962     case 0xc40:                /*CM_CLKSEL_WKUP */
2963         s->cm_clksel_wkup = value & 0x7f;
2964         omap3_cm_clksel_wkup_update(s, s->cm_clksel_wkup);
2965         break;
2966
2967         
2968     case 0xd00:                /*CM_CLKEN_PLL */
2969         s->cm_clken_pll = value & 0xffff17ff;
2970         omap3_cm_dpll3_update(s);
2971         omap3_cm_dpll4_update(s);
2972         break;
2973     case 0xd04:
2974         s->cm_clken2_pll = value & 0x7ff;
2975         break;
2976     case 0xd30:
2977         s->cm_autoidle_pll = value & 0x3f;
2978         break;
2979     case 0xd34:
2980         s->cm_autoidle2_pll = value & 0x7;
2981         break;
2982     case 0xd40:                /*CM_CLKSEL1_PLL */
2983         //OMAP3_DEBUG(("WD40 value %x \n",value));
2984         s->cm_clksel1_pll = value & 0xffffbffc;
2985         //OMAP3_DEBUG(("WD40 value %x \n",value));
2986         omap3_cm_dpll3_update(s);
2987         omap3_cm_48m_update(s);
2988         break;
2989     case 0xd44:
2990         s->cm_clksel2_pll = value & 0x7ff7f;
2991         omap3_cm_dpll4_update(s);
2992         break;
2993     case 0xd48:                /*CM_CLKSEL3_PLL */
2994         s->cm_clksel3_pll = value & 0x1f;
2995         omap3_cm_dpll4_update(s);
2996         break;
2997     case 0xd4c:                /*CM_CLKSEL4_PLL */  
2998         s->cm_clksel4_pll = value & 0x7ff7f;
2999         omap3_cm_dpll5_update(s);
3000         break;
3001      case 0xd50:                /*CM_CLKSEL5_PLL */
3002         s->cm_clksel5_pll = value & 0x1f;
3003         omap3_cm_dpll5_update(s);
3004         break;
3005     case 0xd70:
3006         s->cm_clkout_ctrl = value & 0xbb;
3007         omap3_cm_clkout2_update(s);
3008         break;
3009         
3010     case 0xe00:
3011         s->cm_fclken_dss = value & 0x7;
3012         break;
3013         case 0xe10:
3014         s->cm_iclken_dss = value & 0x1;
3015         break;
3016     case 0xe30:
3017         s->cm_autoidle_dss = value & 0x1;
3018         break;
3019     case 0xe40:
3020         s->cm_clksel_dss = value & 0x1f1f;
3021         omap3_cm_dpll4_update(s);
3022         break;
3023    case 0xe44:
3024                 s->cm_sleepdep_dss = value & 0x7;
3025        break;
3026    case 0xe48:
3027                 s->cm_clkstctrl_dss = value & 0x3;
3028        break;
3029         
3030     case 0xf00:
3031         s->cm_fclken_cam = value & 0x3;
3032         break;
3033     case 0xf10:
3034         s->cm_iclken_cam = value & 0x1;
3035         break;
3036     case 0xf30:
3037         s->cm_autoidle_cam = value & 0x1;
3038         break;
3039     case 0xf40:
3040         s->cm_clksel_cam = value & 0x1f;
3041         omap3_cm_dpll4_update(s);
3042         break;
3043     case 0xf44:
3044         s->cm_sleepdep_cam = value & 0x2;
3045         break;
3046     case 0xf48:
3047         s->cm_clkstctrl_cam = value & 0x3;
3048         break;
3049    
3050     case 0x1000:
3051         s->cm_fclken_per = value & 0x3ffff;
3052         break;
3053     case 0x1010:
3054         s->cm_iclken_per = value & 0x3ffff;
3055         break;
3056     
3057     case 0x1030:
3058         s->cm_autoidle_per = value &0x3ffff;
3059         break;
3060     case 0x1040:
3061         s->cm_clksel_per = value & 0xff;
3062         omap3_cm_per_gptimer_update(s);
3063         break;
3064     case 0x1044:
3065         s->cm_sleepdep_per = value & 0x6;
3066         break;
3067     case 0x1048:
3068          s->cm_clkstctrl_per = value &0x7;
3069          break;
3070          
3071     case 0x1140:               /*CM_CLKSEL1_EMU */
3072         s->cm_clksel1_emu = value & 0x1f1f3fff;
3073         //printf("cm_clksel1_emu %x\n",s->cm_clksel1_emu);
3074         omap3_cm_dpll3_update(s);
3075         omap3_cm_dpll4_update(s);
3076         break;
3077     case 0x1148:
3078         s->cm_clkstctrl_emu = value & 0x3;
3079         break;
3080          case 0x1150:
3081                  s->cm_clksel2_emu = value & 0xfff7f;
3082                  omap3_cm_dpll3_update(s);
3083         break;
3084     case 0x1154:
3085          s->cm_clksel3_emu = value & 0xfff7f;
3086                  omap3_cm_dpll4_update(s);
3087         break;
3088
3089     case 0x129c:
3090          s->cm_polctrl = value & 0x1;
3091          break;
3092
3093    case 0x1348:
3094                 s->cm_clkstctrl_neon = value & 0x3;
3095                 break;
3096
3097         case 0x1400:
3098                 s->cm_fclken_usbhost = value & 0x3;
3099                 break;
3100         case 0x1410:
3101                 s->cm_iclken_usbhost = value & 0x1;
3102                 break;
3103     case 0x1430:
3104         s->cm_autoidle_usbhost = value & 0x1;
3105         break;
3106     case 0x1444:
3107         s->cm_sleepdep_usbhost = value & 0x6;
3108         break;
3109     case 0x1448:
3110         s->cm_clkstctrl_usbhost = value & 0x3;
3111         break;
3112    
3113     default:
3114         printf("omap3_cm_write addr %x value %x pc %x\n", addr, value,cpu_single_env->regs[15] );
3115         exit(-1);
3116     }
3117 }
3118
3119
3120
3121 static CPUReadMemoryFunc *omap3_cm_readfn[] = {
3122     omap_badwidth_read32,
3123     omap_badwidth_read32,
3124     omap3_cm_read,
3125 };
3126
3127 static CPUWriteMemoryFunc *omap3_cm_writefn[] = {
3128     omap_badwidth_write32,
3129     omap_badwidth_write32,
3130     omap3_cm_write,
3131 };
3132
3133 struct omap3_cm_s *omap3_cm_init(struct omap_target_agent_s *ta,
3134                                  qemu_irq mpu_int, qemu_irq dsp_int,
3135                                  qemu_irq iva_int, struct omap_mpu_state_s *mpu)
3136 {
3137     int iomemtype;
3138     struct omap3_cm_s *s = (struct omap3_cm_s *) qemu_mallocz(sizeof(*s));
3139
3140     s->irq[0] = mpu_int;
3141     s->irq[1] = dsp_int;
3142     s->irq[2] = iva_int;
3143     s->mpu = mpu;
3144     omap3_cm_reset(s);
3145
3146     iomemtype = l4_register_io_memory(0, omap3_cm_readfn, omap3_cm_writefn, s);
3147     omap_l4_attach(ta, 0, iomemtype);
3148     omap_l4_attach(ta, 1, iomemtype);
3149
3150     return s;
3151 }
3152
3153 #define OMAP3_SEC_WDT          1
3154 #define OMAP3_MPU_WDT         2
3155 #define OMAP3_IVA2_WDT        3
3156 /*omap3 watchdog timer*/
3157 struct omap3_wdt_s
3158 {
3159     qemu_irq irq;               /*IVA2 IRQ */
3160     struct omap_mpu_state_s *mpu;
3161     omap_clk clk;
3162     QEMUTimer *timer;
3163
3164     int active;
3165     int64_t rate;
3166     int64_t time;
3167     //int64_t ticks_per_sec;
3168
3169     uint32_t wd_sysconfig;
3170     uint32_t wd_sysstatus;
3171     uint32_t wisr;
3172     uint32_t wier;
3173     uint32_t wclr;
3174     uint32_t wcrr;
3175     uint32_t wldr;
3176     uint32_t wtgr;
3177     uint32_t wwps;
3178     uint32_t wspr;
3179
3180     /*pre and ptv in wclr */
3181     uint32_t pre;
3182     uint32_t ptv;
3183     //uint32_t val;
3184
3185     uint16_t writeh;            /* LSB */
3186     uint16_t readh;             /* MSB */
3187 };
3188
3189 static inline void omap3_wdt_timer_update(struct omap3_wdt_s *wdt_timer)
3190 {
3191     int64_t expires;
3192     if (wdt_timer->active)
3193     {
3194         expires = muldiv64(0xffffffffll - wdt_timer->wcrr,
3195                            ticks_per_sec, wdt_timer->rate);
3196         qemu_mod_timer(wdt_timer->timer, wdt_timer->time + expires);
3197     }
3198     else
3199         qemu_del_timer(wdt_timer->timer);
3200 }
3201
3202 static void omap3_wdt_clk_setup(struct omap3_wdt_s *timer)
3203 {
3204     /*TODO: Add irq as user to clk */
3205 }
3206
3207 static inline uint32_t omap3_wdt_timer_read(struct omap3_wdt_s *timer)
3208 {
3209     uint64_t distance;
3210
3211     if (timer->active)
3212     {
3213         distance = qemu_get_clock(vm_clock) - timer->time;
3214         distance = muldiv64(distance, timer->rate, ticks_per_sec);
3215
3216         if (distance >= 0xffffffff - timer->wcrr)
3217             return 0xffffffff;
3218         else
3219             return timer->wcrr + distance;
3220     }
3221     else
3222         return timer->wcrr;
3223 }
3224
3225 /*
3226 static inline void omap3_wdt_timer_sync(struct omap3_wdt_s *timer)
3227 {
3228     if (timer->active) {
3229         timer->val = omap3_wdt_timer_read(timer);
3230         timer->time = qemu_get_clock(vm_clock);
3231     }
3232 }*/
3233
3234 static void omap3_wdt_reset(struct omap3_wdt_s *s, int wdt_index)
3235 {
3236     s->wd_sysconfig = 0x0;
3237     s->wd_sysstatus = 0x0;
3238     s->wisr = 0x0;
3239     s->wier = 0x0;
3240     s->wclr = 0x20;
3241     s->wcrr = 0x0;
3242     switch (wdt_index)
3243     {
3244     case OMAP3_MPU_WDT:
3245     case OMAP3_IVA2_WDT:
3246         s->wldr = 0xfffb0000;
3247         break;
3248     case OMAP3_SEC_WDT:
3249         s->wldr = 0xffa60000;
3250         break;
3251     }
3252     s->wtgr = 0x0;
3253     s->wwps = 0x0;
3254     s->wspr = 0x0;
3255
3256     switch (wdt_index)
3257     {
3258     case OMAP3_SEC_WDT:
3259     case OMAP3_MPU_WDT:
3260         s->active = 1;
3261         break;
3262     case OMAP3_IVA2_WDT:
3263         s->active = 0;
3264         break;
3265     }
3266     s->pre = s->wclr & (1 << 5);
3267     s->ptv = (s->wclr & 0x1c) >> 2;
3268     s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
3269
3270     s->active = 1;
3271     s->time = qemu_get_clock(vm_clock);
3272     omap3_wdt_timer_update(s);
3273 }
3274
3275 static uint32_t omap3_wdt_read32(void *opaque, target_phys_addr_t addr,
3276                                  int wdt_index)
3277 {
3278     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3279
3280     //uint32_t ret;
3281     //printf("omap3_wdt_read32 addr %x \n",addr);
3282     switch (addr)
3283     {
3284     case 0x10:                 /*WD_SYSCONFIG */
3285         return s->wd_sysconfig;
3286     case 0x14:                 /*WD_SYSSTATUS */
3287         return s->wd_sysstatus;
3288     case 0x18:
3289          /*WISR*/ return s->wisr & 0x1;
3290     case 0x1c:
3291          /*WIER*/ return s->wier & 0x1;
3292     case 0x24:
3293          /*WCLR*/ return s->wclr & 0x3c;
3294     case 0x28:
3295          /*WCRR*/ s->wcrr = omap3_wdt_timer_read(s);
3296         s->time = qemu_get_clock(vm_clock);
3297         return s->wcrr;
3298     case 0x2c:
3299          /*WLDR*/ return s->wldr;
3300     case 0x30:
3301          /*WTGR*/ return s->wtgr;
3302     case 0x34:
3303          /*WWPS*/ return s->wwps;
3304     case 0x48:
3305          /*WSPR*/ return s->wspr;
3306     default:
3307         printf("omap3_wdt_read32 addr %x \n", addr);
3308         exit(-1);
3309     }
3310 }
3311
3312 static uint32_t omap3_mpu_wdt_read16(void *opaque, target_phys_addr_t addr)
3313 {
3314     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3315     uint32_t ret;
3316
3317     if (addr & 2)
3318         return s->readh;
3319     else
3320     {
3321         ret = omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
3322         s->readh = ret >> 16;
3323         return ret & 0xffff;
3324     }
3325 }
3326
3327 static uint32_t omap3_mpu_wdt_read32(void *opaque, target_phys_addr_t addr)
3328 {
3329     return omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
3330 }
3331
3332 static void omap3_wdt_write32(void *opaque, target_phys_addr_t addr,
3333                               uint32_t value, int wdt_index)
3334 {
3335     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3336
3337     //printf("omap3_wdt_write32 addr %x value %x \n",addr,value);
3338     switch (addr)
3339     {
3340     case 0x14:                 /*WD_SYSSTATUS */
3341     case 0x34:
3342          /*WWPS*/ OMAP_RO_REG(addr);
3343         exit(-1);
3344         break;
3345     case 0x10:                 /*WD_SYSCONFIG */
3346         s->wd_sysconfig = value & 0x33f;
3347         break;
3348     case 0x18:
3349          /*WISR*/ s->wisr = value & 0x1;
3350         break;
3351     case 0x1c:
3352          /*WIER*/ s->wier = value & 0x1;
3353         break;
3354     case 0x24:
3355          /*WCLR*/ s->wclr = value & 0x3c;
3356         break;
3357     case 0x28:
3358          /*WCRR*/ s->wcrr = value;
3359         s->time = qemu_get_clock(vm_clock);
3360         omap3_wdt_timer_update(s);
3361         break;
3362     case 0x2c:
3363          /*WLDR*/ s->wldr = value;      /*It will take effect after next overflow */
3364         break;
3365     case 0x30:
3366          /*WTGR*/ if (value != s->wtgr)
3367         {
3368             s->wcrr = s->wldr;
3369             s->pre = s->wclr & (1 << 5);
3370             s->ptv = (s->wclr & 0x1c) >> 2;
3371             s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
3372             s->time = qemu_get_clock(vm_clock);
3373             omap3_wdt_timer_update(s);
3374         }
3375         s->wtgr = value;
3376         break;
3377     case 0x48:
3378          /*WSPR*/
3379             if (((value & 0xffff) == 0x5555) && ((s->wspr & 0xffff) == 0xaaaa))
3380         {
3381             s->active = 0;
3382             s->wcrr = omap3_wdt_timer_read(s);
3383             omap3_wdt_timer_update(s);
3384         }
3385         if (((value & 0xffff) == 0x4444) && ((s->wspr & 0xffff) == 0xbbbb))
3386         {
3387             s->active = 1;
3388             s->time = qemu_get_clock(vm_clock);
3389             omap3_wdt_timer_update(s);
3390         }
3391         s->wspr = value;
3392         break;
3393     default:
3394         printf("omap3_wdt_write32 addr %x \n", addr);
3395         exit(-1);
3396     }
3397 }
3398
3399 static void omap3_mpu_wdt_write16(void *opaque, target_phys_addr_t addr,
3400                                   uint32_t value)
3401 {
3402     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3403
3404     if (addr & 2)
3405         return omap3_wdt_write32(opaque, addr, (value << 16) | s->writeh,
3406                                  OMAP3_MPU_WDT);
3407     else
3408         s->writeh = (uint16_t) value;
3409 }
3410
3411 static void omap3_mpu_wdt_write32(void *opaque, target_phys_addr_t addr,
3412                                   uint32_t value)
3413 {
3414     omap3_wdt_write32(opaque, addr, value, OMAP3_MPU_WDT);
3415 }
3416
3417 static CPUReadMemoryFunc *omap3_mpu_wdt_readfn[] = {
3418     omap_badwidth_read32,
3419     omap3_mpu_wdt_read16,
3420     omap3_mpu_wdt_read32,
3421 };
3422
3423 static CPUWriteMemoryFunc *omap3_mpu_wdt_writefn[] = {
3424     omap_badwidth_write32,
3425     omap3_mpu_wdt_write16,
3426     omap3_mpu_wdt_write32,
3427 };
3428
3429 static void omap3_mpu_wdt_timer_tick(void *opaque)
3430 {
3431     struct omap3_wdt_s *wdt_timer = (struct omap3_wdt_s *) opaque;
3432
3433     /*TODO:Sent reset pulse to PRCM */
3434     wdt_timer->wcrr = wdt_timer->wldr;
3435
3436     /*after overflow, generate the new wdt_timer->rate */
3437     wdt_timer->pre = wdt_timer->wclr & (1 << 5);
3438     wdt_timer->ptv = (wdt_timer->wclr & 0x1c) >> 2;
3439     wdt_timer->rate =
3440         omap_clk_getrate(wdt_timer->clk) >> (wdt_timer->pre ? wdt_timer->
3441                                              ptv : 0);
3442
3443     wdt_timer->time = qemu_get_clock(vm_clock);
3444     omap3_wdt_timer_update(wdt_timer);
3445 }
3446
3447 static struct omap3_wdt_s *omap3_mpu_wdt_init(struct omap_target_agent_s *ta,
3448                                               qemu_irq irq, omap_clk fclk,
3449                                               omap_clk iclk,
3450                                               struct omap_mpu_state_s *mpu)
3451 {
3452     int iomemtype;
3453     struct omap3_wdt_s *s = (struct omap3_wdt_s *) qemu_mallocz(sizeof(*s));
3454
3455     s->irq = irq;
3456     s->clk = fclk;
3457     s->timer = qemu_new_timer(vm_clock, omap3_mpu_wdt_timer_tick, s);
3458
3459     omap3_wdt_reset(s, OMAP3_MPU_WDT);
3460     if (irq != NULL)
3461         omap3_wdt_clk_setup(s);
3462
3463     iomemtype = l4_register_io_memory(0, omap3_mpu_wdt_readfn,
3464                                       omap3_mpu_wdt_writefn, s);
3465     omap_l4_attach(ta, 0, iomemtype);
3466
3467     return s;
3468
3469 }
3470
3471 /*dummy system control module*/
3472 struct omap3_scm_s
3473 {
3474     struct omap_mpu_state_s *mpu;
3475
3476         uint8 interface[48];           /*0x4800 2000*/
3477         uint8 padconfs[576];         /*0x4800 2030*/
3478         uint32 general[228];            /*0x4800 2270*/
3479         uint8 mem_wkup[1024];     /*0x4800 2600*/
3480         uint8 padconfs_wkup[84]; /*0x4800 2a00*/
3481         uint32 general_wkup[8];    /*0x4800 2a60*/
3482 };
3483
3484 #define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
3485                                                 inputenable0,inputenable1,pupd0,pupd1,muxmode0,muxmode1,offset) \
3486         do { \
3487                  *(padconfs+offset/4) = (wakeup0 <<14)|(offmode0<<9)|(inputenable0<<8)|(pupd0<<3)|(muxmode0); \
3488                  *(padconfs+offset/4) |= (wakeup1 <<30)|(offmode1<<25)|(inputenable1<<24)|(pupd1<<19)|(muxmode1<<16); \
3489 } while (0)
3490
3491
3492 static void omap3_scm_reset(struct omap3_scm_s *s)
3493 {
3494          uint32 * padconfs;
3495     padconfs = (uint32 *)(s->padconfs);
3496     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x0);
3497     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3498     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x8);
3499     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3500     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3501     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3502     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x18);
3503     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x1c);
3504     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x20);
3505     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x24);
3506     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x28);
3507     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x2c);
3508     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x30);
3509     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x34);
3510     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x38);
3511     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x3c);
3512     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x40);
3513     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x44);
3514     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,7,0x48);
3515     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x4c);
3516     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x50);
3517     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x54);
3518     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x58);
3519     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,0,0x5c);
3520     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x60);
3521     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x64);
3522     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x68);
3523     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x6c);
3524     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x70);
3525     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x74);
3526     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x78);
3527     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x7c);
3528     PADCONFS_VALUE(0,0,0,0,1,1,0,3,0,7,0x80);
3529     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x84);
3530     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x88);
3531     PADCONFS_VALUE(0,0,0,0,1,1,3,0,7,0,0x8c);
3532     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x90);
3533     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x94);
3534     PADCONFS_VALUE(0,0,0,0,1,1,1,0,7,0,0x98);
3535     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,7,0x9c);
3536     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa0);
3537     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa4);
3538     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0xa8);
3539     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xac);
3540     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb0);
3541     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb4);
3542     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb8);
3543     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xbc);
3544     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc0);
3545     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc4);
3546     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc8);
3547     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xcc);
3548     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd0);
3549     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd4);
3550     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd8);
3551     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xdc);
3552     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe0);
3553     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe4);
3554     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe8);
3555     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xec);
3556     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf0);
3557     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf4);
3558     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf8);
3559     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xfc);
3560     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x100);
3561     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x104);
3562     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x108);
3563     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x10c);
3564     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x110);
3565     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x114);
3566     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x118);
3567     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x11c);
3568     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x120);
3569     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x124);
3570     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x128);
3571     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x12c);
3572     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x130);
3573     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x134);
3574     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x138);
3575     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x13c);
3576     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x140);
3577     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x144);
3578     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x148);
3579     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x14c);
3580     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x150);
3581     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x154);
3582     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x158);
3583     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x15c);
3584     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x160);
3585     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x164);
3586     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x168);
3587     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x16c);
3588     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x170);
3589     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x174);
3590     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x178);
3591     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x17c);
3592     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x180);
3593     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x184);
3594     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x188);
3595     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x18c);
3596     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x190);
3597     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x194);
3598     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x198);
3599     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x19c);
3600     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x1a0);
3601     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1a4);
3602     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x1a8);
3603     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1ac);
3604     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1b0);
3605     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b4);
3606     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b8);
3607     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1bc);
3608     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c0);
3609     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c4);
3610     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c8);
3611     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1cc);
3612     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d0);
3613     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d4);
3614     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d8);
3615     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1dc);
3616     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e0);
3617     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e4);
3618     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e8);
3619     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1ec);
3620     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f0);
3621     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f4);
3622     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f8);
3623     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1fc);
3624     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x200);
3625     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x204);
3626     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x208);
3627     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x20c);
3628     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x210);
3629     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x214);
3630     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x218);
3631     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x21c);
3632     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x220);
3633     PADCONFS_VALUE(0,0,0,0,1,1,3,1,0,0,0x224);
3634     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x228);
3635     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x22c);
3636     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x230);
3637     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x234);
3638
3639
3640         padconfs = (uint32 *)(s->general);
3641         s->general[1] = 0x4000000;  /*0x4800 2274*/
3642         s->general[0x1c] = 0x1;  /*0x4800 22e0*/
3643         s->general[0x75] = 0x7fc0;  /*0x4800 2444*/
3644         s->general[0x76] = 0xaa;  /*0x4800 2448*/
3645         s->general[0x7c] = 0x2700;  /*0x4800 2460*/
3646         s->general[0x7d] = 0x300000;  /*0x4800 2464*/
3647         s->general[0x7e] = 0x300000;  /*0x4800 2468*/
3648         s->general[0x81] = 0xffff;  /*0x4800 2474*/
3649         s->general[0x82] = 0xffff;  /*0x4800 2478*/
3650         s->general[0x83] = 0xffff;  /*0x4800 247c*/
3651         s->general[0x84] = 0x6;  /*0x4800 2480*/
3652         s->general[0x85] = 0xffffffff;  /*0x4800 2484*/
3653         s->general[0x86] = 0xffff;  /*0x4800 2488*/
3654         s->general[0x87] = 0xffff;  /*0x4800 248c*/
3655         s->general[0x88] = 0x1;  /*0x4800 2490*/
3656         s->general[0x8b] = 0xffffffff;  /*0x4800 249c*/
3657         s->general[0x8c] = 0xffff;  /*0x4800 24a0*/
3658         s->general[0x8e] = 0xffff;  /*0x4800 24a8*/
3659         s->general[0x8f] = 0xffff;  /*0x4800 24ac*/
3660         s->general[0x91] = 0xffff;  /*0x4800 24b4*/
3661         s->general[0x92] = 0xffff;  /*0x4800 24b8*/
3662         s->general[0xac] = 0x109;  /*0x4800 2520*/
3663         s->general[0xb2] = 0xffff;  /*0x4800 2538*/
3664         s->general[0xb3] = 0xffff;  /*0x4800 253c*/
3665         s->general[0xb4] = 0xffff;  /*0x4800 2540*/
3666         PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x368);
3667     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x36c);
3668     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x370);
3669     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x374);
3670     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x378);
3671     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x37c);
3672     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x380);
3673     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x384);
3674     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x388);
3675
3676     
3677
3678         padconfs = (uint32 *)(s->padconfs_wkup);
3679         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x0);
3680         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3681         PADCONFS_VALUE(0,0,0,0,1,1,3,0,0,0,0x8);
3682         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3683         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3684         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3685         PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x18);
3686         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c);
3687         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x20);
3688         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x24);
3689         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x2c);
3690
3691
3692         s->general_wkup[0] = 0x66ff; /*0x4800 2A60*/
3693             
3694 }
3695
3696 static uint32_t omap3_scm_read8(void *opaque, target_phys_addr_t addr)
3697 {
3698     struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
3699     uint8_t* temp;
3700         
3701     switch (addr) {
3702     case 0x00 ... 0x2f:
3703         return s->interface[addr];
3704     case 0x30 ... 0x26f:
3705         return s->padconfs[addr-0x30];
3706     case 0x270 ... 0x5ff:
3707         temp = (uint8_t *)s->general;
3708         return temp[addr-0x270];
3709     case 0x600 ... 0x9ff:
3710         return s->mem_wkup[addr-0x600];
3711     case 0xa00 ... 0xa5f:
3712         return s->padconfs_wkup[addr-0xa00];
3713     case 0xa60 ... 0xa7f:
3714         temp = (uint8_t *)s->general_wkup;
3715         return temp[addr-0xa60];
3716     default:
3717         break;
3718     }
3719     printf("omap3_scm_read8 addr %x pc %x  \n", addr,cpu_single_env->regs[15] );
3720     return 0;
3721 }
3722
3723 static uint32_t omap3_scm_read16(void *opaque, target_phys_addr_t addr)
3724 {
3725     uint32_t v;
3726     v = omap3_scm_read8(opaque, addr);
3727     v |= omap3_scm_read8(opaque, addr + 1) << 8;
3728     return v;
3729 }
3730
3731 static uint32_t omap3_scm_read32(void *opaque, target_phys_addr_t addr)
3732 {
3733     uint32_t v;
3734     v = omap3_scm_read8(opaque, addr);
3735     v |= omap3_scm_read8(opaque, addr + 1) << 8;
3736     v |= omap3_scm_read8(opaque, addr + 2) << 16;
3737     v |= omap3_scm_read8(opaque, addr + 3) << 24;
3738     return v;
3739 }
3740
3741 static void omap3_scm_write8(void *opaque, target_phys_addr_t addr,
3742                              uint32_t value)
3743 {
3744     struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
3745     uint8_t* temp;
3746
3747     switch (addr)
3748     {
3749     case 0x00 ... 0x2f:
3750         s->interface[addr] = value;
3751         break;
3752     case 0x30 ... 0x26f:
3753         s->padconfs[addr-0x30] = value;
3754         break;
3755     case 0x270 ... 0x5ff:
3756         temp = (uint8_t *)s->general;
3757         temp[addr-0x270] = value;
3758         break;
3759     case 0x600 ... 0x9ff:
3760         s->mem_wkup[addr-0x600] = value;
3761         break;
3762     case 0xa00 ... 0xa5f:
3763         s->padconfs_wkup[addr-0xa00] = value;
3764         break;
3765     case 0xa60 ... 0xa7f:
3766         temp = (uint8_t *)s->general_wkup;
3767         temp[addr-0xa60] = value;
3768         break;
3769     default:
3770         /*we do not care scm write*/
3771         printf("omap3_scm_write8 addr %x pc %x \n \n", addr,
3772                cpu_single_env->regs[15] - 0x80008000 + 0x80e80000);
3773         exit(1);
3774         //break;
3775     }
3776 }
3777
3778 static void omap3_scm_write16(void *opaque, target_phys_addr_t addr,
3779                               uint32_t value)
3780 {
3781     omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
3782     omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
3783 }
3784
3785 static void omap3_scm_write32(void *opaque, target_phys_addr_t addr,
3786                               uint32_t value)
3787 {
3788     omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
3789     omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
3790     omap3_scm_write8(opaque, addr + 2, (value >> 16) & 0xff);
3791     omap3_scm_write8(opaque, addr + 3, (value >> 24) & 0xff);
3792 }
3793
3794 static CPUReadMemoryFunc *omap3_scm_readfn[] = {
3795     omap3_scm_read8,
3796     omap3_scm_read16,
3797     omap3_scm_read32,
3798 };
3799
3800 static CPUWriteMemoryFunc *omap3_scm_writefn[] = {
3801     omap3_scm_write8,
3802     omap3_scm_write16,
3803     omap3_scm_write32,
3804 };
3805
3806 static struct omap3_scm_s *omap3_scm_init(struct omap_target_agent_s *ta,
3807                                           struct omap_mpu_state_s *mpu)
3808 {
3809     int iomemtype;
3810     struct omap3_scm_s *s = (struct omap3_scm_s *) qemu_mallocz(sizeof(*s));
3811
3812     s->mpu = mpu;
3813
3814     omap3_scm_reset(s);
3815
3816     iomemtype = l4_register_io_memory(0, omap3_scm_readfn,
3817                                       omap3_scm_writefn, s);
3818     omap_l4_attach(ta, 0, iomemtype);
3819     
3820     return s;
3821 }
3822
3823 /*dummy SDRAM Memory Scheduler emulation*/
3824 struct omap3_sms_s
3825 {
3826     struct omap_mpu_state_s *mpu;
3827
3828     uint32 sms_sysconfig;
3829     uint32 sms_sysstatus;
3830     uint32 sms_rg_att[8];
3831     uint32 sms_rg_rdperm[8];
3832     uint32 sms_rg_wrperm[8];
3833     uint32 sms_rg_start[7];
3834     uint32 sms_rg_end[7];
3835     uint32 sms_security_control;
3836     uint32 sms_class_arbiter0;
3837     uint32 sms_class_arbiter1;
3838     uint32 sms_class_arbiter2;
3839     uint32 sms_interclass_arbiter;
3840     uint32 sms_class_rotation[3];
3841     uint32 sms_err_addr;
3842     uint32 sms_err_type;
3843     uint32 sms_pow_ctrl;
3844     uint32 sms_rot_control[12];
3845     uint32 sms_rot_size[12];
3846     uint32 sms_rot_physical_ba[12];
3847 };
3848
3849 static uint32_t omap3_sms_read32(void *opaque, target_phys_addr_t addr)
3850 {
3851     struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
3852
3853     switch (addr)
3854     {
3855     case 0x10:
3856         return s->sms_sysconfig;
3857     case 0x14:
3858         return s->sms_sysstatus;
3859     case 0x48:
3860     case 0x68:
3861     case 0x88:
3862     case 0xa8:
3863     case 0xc8:
3864     case 0xe8:
3865     case 0x108:
3866     case 0x128:
3867         return s->sms_rg_att[(addr-0x48)/0x20];
3868     case 0x50:
3869     case 0x70:
3870     case 0x90:
3871     case 0xb0:
3872     case 0xd0:
3873     case 0xf0:
3874     case 0x110:
3875     case 0x130:
3876         return s->sms_rg_rdperm[(addr-0x50)/0x20];
3877     case 0x58:
3878     case 0x78:
3879     case 0x98:
3880     case 0xb8:
3881     case 0xd8:
3882     case 0xf8:
3883     case 0x118:
3884         return s->sms_rg_wrperm[(addr-0x58)/0x20];
3885     case 0x60:
3886     case 0x80:
3887     case 0xa0:
3888     case 0xc0:
3889     case 0xe0:
3890     case 0x100:
3891     case 0x120:
3892         return s->sms_rg_start[(addr-0x60)/0x20];
3893
3894     case 0x64:
3895     case 0x84:
3896     case 0xa4:
3897     case 0xc4:
3898     case 0xe4:
3899     case 0x104:
3900     case 0x124:
3901         return s->sms_rg_end[(addr-0x64)/0x20];
3902     case 0x140:
3903         return s->sms_security_control;
3904     case 0x150:
3905         return s->sms_class_arbiter0;
3906         case 0x154:
3907                 return s->sms_class_arbiter1;
3908         case 0x158:
3909                 return s->sms_class_arbiter2;
3910         case 0x160:
3911                 return s->sms_interclass_arbiter;
3912         case 0x164:
3913         case 0x168:
3914         case 0x16c:
3915                 return s->sms_class_rotation[(addr-0x164)/4];
3916         case 0x170:
3917                 return s->sms_err_addr;
3918         case 0x174:
3919                 return s->sms_err_type;
3920         case 0x178:
3921                 return s->sms_pow_ctrl;
3922         case 0x180:
3923         case 0x190:
3924         case 0x1a0:
3925         case 0x1b0:
3926         case 0x1c0:
3927         case 0x1d0:
3928         case 0x1e0:
3929         case 0x1f0:
3930         case 0x200:
3931         case 0x210:
3932         case 0x220:
3933         case 0x230:
3934                 return s->sms_rot_control[(addr-0x180)/0x10];
3935         case 0x184:
3936         case 0x194:
3937         case 0x1a4:
3938         case 0x1b4:
3939         case 0x1c4:
3940         case 0x1d4:
3941         case 0x1e4:
3942         case 0x1f4:
3943         case 0x204:
3944         case 0x214:
3945         case 0x224:
3946         case 0x234:
3947                 return s->sms_rot_size[(addr-0x184)/0x10];
3948
3949         case 0x188:
3950         case 0x198:
3951         case 0x1a8:
3952         case 0x1b8:
3953         case 0x1c8:
3954         case 0x1d8:
3955         case 0x1e8:
3956         case 0x1f8:
3957         case 0x208:
3958         case 0x218:
3959         case 0x228:
3960         case 0x238:
3961                 return s->sms_rot_size[(addr-0x188)/0x10];
3962
3963     default:
3964         printf("omap3_sms_read32 addr %x \n", addr);
3965         exit(-1);
3966     }
3967 }
3968
3969 static void omap3_sms_write32(void *opaque, target_phys_addr_t addr,
3970                               uint32_t value)
3971 {
3972     struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
3973     //int i;
3974
3975     switch (addr)
3976     {
3977     case 0x14:
3978         OMAP_RO_REG(addr);
3979         return;
3980     case 0x10:
3981         s->sms_sysconfig = value & 0x1f;
3982         break;
3983     
3984     case 0x48:
3985     case 0x68:
3986     case 0x88:
3987     case 0xa8:
3988     case 0xc8:
3989     case 0xe8:
3990     case 0x108:
3991     case 0x128:
3992         s->sms_rg_att[(addr-0x48)/0x20] = value;
3993         break;
3994     case 0x50:
3995     case 0x70:
3996     case 0x90:
3997     case 0xb0:
3998     case 0xd0:
3999     case 0xf0:
4000     case 0x110:
4001     case 0x130:
4002         s->sms_rg_rdperm[(addr-0x50)/0x20] = value&0xffff;
4003         break;
4004     case 0x58:
4005     case 0x78:
4006     case 0x98:
4007     case 0xb8:
4008     case 0xd8:
4009     case 0xf8:
4010     case 0x118:
4011         s->sms_rg_wrperm[(addr-0x58)/0x20] = value&0xffff;
4012         break;          
4013     case 0x60:
4014     case 0x80:
4015     case 0xa0:
4016     case 0xc0:
4017     case 0xe0:
4018     case 0x100:
4019     case 0x120:
4020         s->sms_rg_start[(addr-0x60)/0x20] = value;
4021         break;
4022     case 0x64:
4023     case 0x84:
4024     case 0xa4:
4025     case 0xc4:
4026     case 0xe4:
4027     case 0x104:
4028     case 0x124:
4029         s->sms_rg_end[(addr-0x64)/0x20] = value;
4030         break;
4031     case 0x140:
4032         s->sms_security_control = value &0xfffffff;
4033         break;
4034     case 0x150:
4035         s->sms_class_arbiter0 = value;
4036         break;
4037         case 0x154:
4038                 s->sms_class_arbiter1 = value;
4039                 break;
4040         case 0x158:
4041                 s->sms_class_arbiter2 = value;
4042                 break;
4043         case 0x160:
4044                 s->sms_interclass_arbiter = value;
4045                 break;
4046         case 0x164:
4047         case 0x168:
4048         case 0x16c:
4049                 s->sms_class_rotation[(addr-0x164)/4] = value;
4050                 break;
4051         case 0x170:
4052                 s->sms_err_addr = value;
4053                 break;
4054         case 0x174:
4055                 s->sms_err_type = value;
4056                 break;
4057         case 0x178:
4058                 s->sms_pow_ctrl = value;
4059                 break;
4060         case 0x180:
4061         case 0x190:
4062         case 0x1a0:
4063         case 0x1b0:
4064         case 0x1c0:
4065         case 0x1d0:
4066         case 0x1e0:
4067         case 0x1f0:
4068         case 0x200:
4069         case 0x210:
4070         case 0x220:
4071         case 0x230:
4072                 s->sms_rot_control[(addr-0x180)/0x10] = value;
4073                 break;
4074         case 0x184:
4075         case 0x194:
4076         case 0x1a4:
4077         case 0x1b4:
4078         case 0x1c4:
4079         case 0x1d4:
4080         case 0x1e4:
4081         case 0x1f4:
4082         case 0x204:
4083         case 0x214:
4084         case 0x224:
4085         case 0x234:
4086                 s->sms_rot_size[(addr-0x184)/0x10] = value;
4087                 break;
4088
4089         case 0x188:
4090         case 0x198:
4091         case 0x1a8:
4092         case 0x1b8:
4093         case 0x1c8:
4094         case 0x1d8:
4095         case 0x1e8:
4096         case 0x1f8:
4097         case 0x208:
4098         case 0x218:
4099         case 0x228:
4100         case 0x238:
4101                 s->sms_rot_size[(addr-0x188)/0x10] = value;   
4102                 break;
4103         default:
4104         printf("omap3_sms_write32 addr %x\n", addr);
4105         exit(-1);
4106     }
4107 }
4108
4109 static CPUReadMemoryFunc *omap3_sms_readfn[] = {
4110     omap_badwidth_read32,
4111     omap_badwidth_read32,
4112     omap3_sms_read32,
4113 };
4114
4115 static CPUWriteMemoryFunc *omap3_sms_writefn[] = {
4116     omap_badwidth_write32,
4117     omap_badwidth_write32,
4118     omap3_sms_write32,
4119 };
4120
4121 static void omap3_sms_reset(struct omap3_sms_s *s)
4122 {
4123         s->sms_sysconfig = 0x1;
4124         s->sms_class_arbiter0 = 0x500000;
4125         s->sms_class_arbiter1 = 0x500;
4126         s->sms_class_arbiter2 = 0x55000;
4127         s->sms_interclass_arbiter = 0x400040;
4128         s->sms_class_rotation[0] = 0x1;
4129         s->sms_class_rotation[1] = 0x1;
4130         s->sms_class_rotation[2] = 0x1;
4131         s->sms_pow_ctrl = 0x80;
4132 }
4133
4134 static struct omap3_sms_s *omap3_sms_init(struct omap_mpu_state_s *mpu)
4135 {
4136     int iomemtype;
4137     struct omap3_sms_s *s = (struct omap3_sms_s *) qemu_mallocz(sizeof(*s));
4138
4139     s->mpu = mpu;
4140
4141     omap3_sms_reset(s);
4142     
4143     iomemtype = cpu_register_io_memory(0, omap3_sms_readfn,
4144                                        omap3_sms_writefn, s);
4145     cpu_register_physical_memory(0x6c000000, 0x10000, iomemtype);
4146
4147     return s;
4148 }
4149
4150 static const struct dma_irq_map omap3_dma_irq_map[] = {
4151     {0, OMAP_INT_35XX_SDMA_IRQ0},
4152     {0, OMAP_INT_35XX_SDMA_IRQ1},
4153     {0, OMAP_INT_35XX_SDMA_IRQ2},
4154     {0, OMAP_INT_35XX_SDMA_IRQ3},
4155 };
4156
4157 static int omap3_validate_addr(struct omap_mpu_state_s *s,
4158                                target_phys_addr_t addr)
4159 {
4160     return 1;
4161 }
4162
4163 /*
4164   set the kind of memory connected to GPMC that we are trying to boot form.
4165   Uses SYS BOOT settings.
4166 */
4167 void omap3_set_mem_type(struct omap_mpu_state_s *s,int bootfrom)
4168 {
4169         switch (bootfrom)
4170         {
4171                 case 0x0: /*GPMC_NOR*/
4172                         s->omap3_scm->general[32] |= 7;
4173                         break;
4174                 case 0x1: /*GPMC_NAND*/
4175                         s->omap3_scm->general[32] |= 1;
4176                         break;
4177                 case 0x2:
4178                         s->omap3_scm->general[32] |= 8;
4179                         break;
4180                 case 0x3:
4181                         s->omap3_scm->general[32] |= 0;
4182                         break;
4183                 case 0x4:
4184                         s->omap3_scm->general[32] |= 17;
4185                         break;
4186                 case 0x5:
4187                         s->omap3_scm->general[32] |= 3;
4188                         break;
4189         }
4190 }
4191
4192 void omap3_set_device_type(struct omap_mpu_state_s *s,int device_type)
4193 {
4194         s->omap3_scm->general[32] |= (device_type & 0x7) << 8;
4195 }
4196
4197 struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
4198                                            const char *core)
4199 {
4200     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4201         qemu_mallocz(sizeof(struct omap_mpu_state_s));
4202     ram_addr_t sram_base, q2_base;
4203     qemu_irq *cpu_irq;
4204     qemu_irq dma_irqs[4];
4205     int i;
4206     int sdindex;
4207     //omap_clk gpio_clks[4];
4208
4209     s->mpu_model = omap3530;
4210     s->env = cpu_init("cortex-a8-r2");
4211     if (!s->env) {
4212         fprintf(stderr, "Unable to find CPU definition\n");
4213         exit(1);
4214     }
4215     s->sdram_size = sdram_size;
4216     s->sram_size = OMAP3530_SRAM_SIZE;
4217
4218     sdindex = drive_get_index(IF_SD, 0, 0);
4219     if (sdindex == -1) {
4220         fprintf(stderr, "qemu: missing SecureDigital device\n");
4221         exit(1);
4222     }
4223
4224     /* Clocks */
4225     omap_clk_init(s);
4226
4227     /* Memory-mapped stuff */
4228
4229     q2_base = qemu_ram_alloc(s->sdram_size);
4230     cpu_register_physical_memory(OMAP3_Q2_BASE, s->sdram_size,
4231                                  (q2_base | IO_MEM_RAM));
4232     sram_base = qemu_ram_alloc(s->sram_size);
4233     cpu_register_physical_memory(OMAP3_SRAM_BASE, s->sram_size,
4234                                  (sram_base | IO_MEM_RAM));
4235
4236     s->l4 = omap_l4_init(OMAP3_L4_BASE, 
4237                          sizeof(omap3_l4_agent_info) 
4238                          / sizeof(struct omap3_l4_agent_info_s));
4239
4240     cpu_irq = arm_pic_init_cpu(s->env);
4241     s->ih[0] = omap2_inth_init(s, 0x48200000, 0x1000, 3, &s->irq[0],
4242                                cpu_irq[ARM_PIC_CPU_IRQ],
4243                                cpu_irq[ARM_PIC_CPU_FIQ], 
4244                                omap_findclk(s, "omap3_mpu_intc_fclk"),
4245                                omap_findclk(s, "omap3_mpu_intc_iclk"));
4246
4247     for (i = 0; i < 4; i++)
4248         dma_irqs[i] =
4249             s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
4250     s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
4251                             omap_findclk(s, "omap3_sdma_fclk"),
4252                             omap_findclk(s, "omap3_sdma_iclk"));
4253     s->port->addr_valid = omap3_validate_addr;
4254
4255
4256     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
4257     soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
4258     soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
4259
4260
4261     s->omap3_cm = omap3_cm_init(omap3_l4ta_init(s->l4, L4A_CM), NULL, NULL, NULL, s);
4262
4263     s->omap3_prm = omap3_prm_init(omap3_l4ta_init(s->l4, L4A_PRM),
4264                                   s->irq[0][OMAP_INT_35XX_PRCM_MPU_IRQ],
4265                                   NULL, s);
4266
4267     s->omap3_mpu_wdt = omap3_mpu_wdt_init(omap3_l4ta_init(s->l4, L4A_WDTIMER2),
4268                                           NULL,
4269                                           omap_findclk(s, "omap3_wkup_32k_fclk"),
4270                                           omap_findclk(s, "omap3_wkup_l4_iclk"),
4271                                           s);
4272
4273     s->omap3_l3 = omap3_l3_init(OMAP3_L3_BASE, 
4274                                 omap3_l3_region,
4275                                 sizeof(omap3_l3_region)
4276                                 / sizeof(struct omap_l3_region_s));
4277     s->omap3_scm = omap3_scm_init(omap3_l4ta_init(s->l4, L4A_SCM), s);
4278
4279     s->omap3_sms = omap3_sms_init(s);
4280
4281     s->gptimer[0] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER1),
4282                                        s->irq[0][OMAP_INT_35XX_GPTIMER1],
4283                                        omap_findclk(s, "omap3_gp1_fclk"),
4284                                        omap_findclk(s, "omap3_wkup_l4_iclk"));
4285     s->gptimer[1] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER2),
4286                                        s->irq[0][OMAP_INT_35XX_GPTIMER2],
4287                                        omap_findclk(s, "omap3_gp2_fclk"),
4288                                        omap_findclk(s, "omap3_per_l4_iclk"));
4289     s->gptimer[2] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER3),
4290                                        s->irq[0][OMAP_INT_35XX_GPTIMER3],
4291                                        omap_findclk(s, "omap3_gp3_fclk"),
4292                                        omap_findclk(s, "omap3_per_l4_iclk"));
4293     s->gptimer[3] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER4),
4294                                        s->irq[0][OMAP_INT_35XX_GPTIMER4],
4295                                        omap_findclk(s, "omap3_gp4_fclk"),
4296                                        omap_findclk(s, "omap3_per_l4_iclk"));
4297     s->gptimer[4] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER5),
4298                                        s->irq[0][OMAP_INT_35XX_GPTIMER5],
4299                                        omap_findclk(s, "omap3_gp5_fclk"),
4300                                        omap_findclk(s, "omap3_per_l4_iclk"));
4301     s->gptimer[5] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER6),
4302                                        s->irq[0][OMAP_INT_35XX_GPTIMER6],
4303                                        omap_findclk(s, "omap3_gp6_fclk"),
4304                                        omap_findclk(s, "omap3_per_l4_iclk"));
4305     s->gptimer[6] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER7),
4306                                        s->irq[0][OMAP_INT_35XX_GPTIMER7],
4307                                        omap_findclk(s, "omap3_gp7_fclk"),
4308                                        omap_findclk(s, "omap3_per_l4_iclk"));
4309     s->gptimer[7] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER8),
4310                                        s->irq[0][OMAP_INT_35XX_GPTIMER8],
4311                                        omap_findclk(s, "omap3_gp8_fclk"),
4312                                        omap_findclk(s, "omap3_per_l4_iclk"));
4313     s->gptimer[8] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER9),
4314                                        s->irq[0][OMAP_INT_35XX_GPTIMER9],
4315                                        omap_findclk(s, "omap3_gp9_fclk"),
4316                                        omap_findclk(s, "omap3_per_l4_iclk"));
4317     s->gptimer[9] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER10),
4318                                        s->irq[0][OMAP_INT_35XX_GPTIMER10],
4319                                        omap_findclk(s, "omap3_gp10_fclk"),
4320                                        omap_findclk(s, "omap3_core_l4_iclk"));
4321     s->gptimer[10] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER11),
4322                                        s->irq[0][OMAP_INT_35XX_GPTIMER11],
4323                                        omap_findclk(s, "omap3_gp12_fclk"),
4324                                        omap_findclk(s, "omap3_core_l4_iclk"));
4325     s->gptimer[11] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER12),
4326                                         s->irq[0][OMAP_INT_35XX_GPTIMER12],
4327                                         omap_findclk(s, "omap3_gp12_fclk"),
4328                                         omap_findclk(s, "omap3_wkup_l4_iclk"));
4329     
4330         
4331     omap_synctimer_init(omap3_l4ta_init(s->l4, L4A_32KTIMER), s,
4332                         omap_findclk(s, "omap3_sys_32k"), NULL);
4333
4334     s->sdrc = omap_sdrc_init(0x6d000000);
4335     
4336     s->gpmc = omap_gpmc_init(s, 0x6e000000, s->irq[0][OMAP_INT_35XX_GPMC_IRQ]);
4337     
4338
4339     s->uart[0] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART1),
4340                                  s->irq[0][OMAP_INT_35XX_UART1_IRQ],
4341                                  omap_findclk(s, "omap3_uart1_fclk"),
4342                                  omap_findclk(s, "omap3_uart1_iclk"),
4343                                  s->drq[OMAP35XX_DMA_UART1_TX],
4344                                  s->drq[OMAP35XX_DMA_UART1_RX], serial_hds[0]);
4345     s->uart[1] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART2),
4346                                  s->irq[0][OMAP_INT_35XX_UART2_IRQ],
4347                                  omap_findclk(s, "omap3_uart2_fclk"),
4348                                  omap_findclk(s, "omap3_uart2_iclk"),
4349                                  s->drq[OMAP35XX_DMA_UART2_TX],
4350                                  s->drq[OMAP35XX_DMA_UART2_RX],
4351                                  serial_hds[0] ? serial_hds[1] : 0);
4352     s->uart[2] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART3),
4353                                  s->irq[0][OMAP_INT_35XX_UART3_IRQ],
4354                                  omap_findclk(s, "omap3_uart2_fclk"),
4355                                  omap_findclk(s, "omap3_uart3_iclk"),
4356                                  s->drq[OMAP35XX_DMA_UART3_TX],
4357                                  s->drq[OMAP35XX_DMA_UART3_RX],
4358                                  serial_hds[0]
4359                                  && serial_hds[1] ? serial_hds[2] : 0);
4360     
4361     /*attach serial[0] to uart 2 for beagle board */
4362     omap_uart_attach(s->uart[2], serial_hds[0]);
4363
4364     s->dss = omap_dss_init(s, omap3_l4ta_init(s->l4, L4A_DSS), 
4365                     s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
4366                    NULL,NULL,NULL,NULL,NULL);
4367
4368     //gpio_clks[0] = NULL;
4369     //gpio_clks[1] = NULL;
4370     //gpio_clks[2] = NULL;
4371     //gpio_clks[3] = NULL;
4372
4373     s->gpif = omap3_gpif_init();
4374     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO1),
4375                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK1], 
4376                     NULL,NULL,0);
4377     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO2),
4378                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK2], 
4379                     NULL,NULL,1);
4380     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO3),
4381                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK3], 
4382                     NULL,NULL,2);
4383     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO4),
4384                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK4], 
4385                     NULL,NULL,3);
4386     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO5),
4387                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK5], 
4388                     NULL,NULL,4);
4389     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO6),
4390                     &s->irq[0][OMAP_INT_35XX_GPIO_BANK6], 
4391                     NULL,NULL,5);
4392
4393     omap_tap_init(omap3_l4ta_init(s->l4, L4A_TAP), s);
4394
4395     s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC1),
4396                                      drives_table[sdindex].bdrv,
4397                                      s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
4398                                      &s->drq[OMAP35XX_DMA_MMC1_TX],
4399                                      omap_findclk(s, "omap3_mmc1_fclk"),
4400                                      omap_findclk(s, "omap3_mmc1_iclk"));
4401
4402     s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC2),
4403                                      NULL,
4404                                      s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
4405                                      &s->drq[OMAP35XX_DMA_MMC2_TX],
4406                                      omap_findclk(s, "omap3_mmc2_fclk"),
4407                                      omap_findclk(s, "omap3_mmc2_iclk"));
4408
4409     s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC3),
4410                                      NULL,
4411                                      s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
4412                                      &s->drq[OMAP35XX_DMA_MMC3_TX],
4413                                      omap_findclk(s, "omap3_mmc3_fclk"),
4414                                      omap_findclk(s, "omap3_mmc3_iclk"));
4415
4416     s->i2c[0] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C1),
4417                                s->irq[0][OMAP_INT_35XX_I2C1_IRQ],
4418                                &s->drq[OMAP35XX_DMA_I2C1_TX],
4419                                omap_findclk(s, "omap3_i2c1_fclk"),
4420                                omap_findclk(s, "omap3_i2c1_iclk"),
4421                                8);
4422     s->i2c[1] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C2),
4423                                s->irq[0][OMAP_INT_35XX_I2C2_IRQ],
4424                                &s->drq[OMAP35XX_DMA_I2C2_TX],
4425                                omap_findclk(s, "omap3_i2c2_fclk"),
4426                                omap_findclk(s, "omap3_i2c2_iclk"),
4427                                8);
4428     s->i2c[2] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C3),
4429                                s->irq[0][OMAP_INT_35XX_I2C3_IRQ],
4430                                &s->drq[OMAP35XX_DMA_I2C3_TX],
4431                                omap_findclk(s, "omap3_i2c3_fclk"),
4432                                omap_findclk(s, "omap3_i2c3_iclk"),
4433                                64);
4434
4435     return s;
4436 }
4437
4438
4439 static inline uint32_t omap3_get_le32(const void *p)
4440 {
4441     const uint8_t *q = (const uint8_t *)p;
4442     uint32_t v;
4443     v = q[3]; v <<= 8;
4444     v |= q[2]; v <<= 8;
4445     v |= q[1]; v <<= 8;
4446     v |= q[0];
4447     return v;
4448 }
4449
4450 static inline uint32_t omap3_get_le16(const void *p)
4451 {
4452     const uint8_t *q = (const uint8_t *)p;
4453     uint32_t v;
4454     v = q[1]; v <<= 8;
4455     v |= q[0];
4456     return v;
4457 }
4458
4459 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
4460 {
4461     uint8_t x[4];
4462     
4463     cpu_physical_memory_read(addr, x, 4);
4464     x[0] = lsb & 0xff;
4465     x[1] = (lsb >> 8) & 0xff;
4466     cpu_physical_memory_write(addr, x, 4);
4467 }
4468
4469 struct omap3_boot_s {
4470     struct omap_mpu_state_s *mpu;
4471     enum {
4472         undefined = 0,
4473         confighdr,
4474         chdone,
4475         imagehdr,
4476         copy,
4477         done
4478     } state;
4479     target_phys_addr_t addr;
4480     uint32_t count;
4481 };
4482
4483 static struct omap3_boot_s *omap3_boot_init(const uint8_t *data,
4484                                             uint32_t data_len,
4485                                             struct omap_mpu_state_s *mpu)
4486 {
4487     struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
4488     s->mpu = mpu;
4489     s->state = imagehdr;
4490     if (data_len >= 512) {
4491         if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
4492             || !strncasecmp((char *)(data + 0x14), "chram", 5)
4493             || !strncasecmp((char *)(data + 0x14), "chflash", 7)
4494             || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
4495             s->state = confighdr;
4496     }
4497     return s;
4498 }
4499
4500 static void omap3_boot_chsettings(const uint8_t *chtoc)
4501 {
4502     uint32_t flags, x;
4503     
4504     if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
4505         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4506         return;
4507     }
4508     if (!chtoc[4]) { /* section disabled? */
4509         return;
4510     }
4511     if (omap3_get_le16(chtoc + 5) != 0x0001) {
4512         fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
4513                 omap3_get_le16(chtoc));
4514         return;
4515     }
4516     flags = omap3_get_le32(chtoc + 8);
4517     chtoc += 12;
4518     if (flags & 1) {
4519         cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
4520         cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
4521         cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
4522         if (flags & (1 << 2)) { /* clock configuration */
4523             cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
4524             cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
4525         }
4526         if (flags & (1 << 5)) { /* DPLL3 CORE */
4527             if (flags & (1 << 8)) { /* enable DPLL3 bypass */
4528                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4529                 x &= ~7; x |= 5; /* set DPLL3 bypass */
4530                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4531             }
4532             cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
4533             cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
4534             cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
4535         }
4536         if (flags & (1 << 3)) { /* DPLL4 PER */
4537             if (flags & (1 << 6)) { /* enable DPLL4 bypass */
4538                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4539                 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
4540                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4541             }
4542             cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
4543             cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
4544             cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
4545             cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
4546         }
4547         if (flags & (1 << 3)) { /* DPLL1 MPU */
4548             if (flags & (1 << 7)) { /* enable DPLL1 bypass */
4549                 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
4550                 x &= ~7; x |= 5; /* set DPLL1 bypass */
4551                 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
4552             }
4553             cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
4554             cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
4555             cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
4556             cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
4557             cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
4558         }
4559         switch ((flags >> 24) & 0xff) {
4560             case 0x01: x = 0; break; /* 12MHz */
4561             case 0x02: x = 1; break; /* 13MHz */
4562             case 0x03: x = 5; break; /* 16.8MHz */
4563             case 0x04: x = 2; break; /* 19.2MHz */
4564             case 0x05: x = 3; break; /* 26MHz */
4565             case 0x06: x = 4; break; /* 38.4MHz */
4566             default:
4567                 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
4568                 x = 1;
4569                 break;
4570         }
4571         if (x != omap3_get_le32(chtoc + 0x04)) {
4572             fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
4573         }
4574     }
4575 }
4576
4577 static void omap3_boot_chram(const uint8_t *chtoc)
4578 {
4579     if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
4580         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4581         return;
4582     }
4583     if (!chtoc[4]) { /* section disabled? */
4584         return;
4585     }
4586     omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
4587     omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
4588     cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
4589
4590     cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
4591     omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
4592     omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
4593     omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
4594     omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
4595     cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
4596     cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
4597     cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
4598     
4599     cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
4600     omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
4601     omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
4602     omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
4603     omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
4604     cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
4605     cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
4606     cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
4607 }
4608
4609 static void omap3_boot_chflash(const uint8_t *chtoc)
4610 {
4611     if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
4612         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4613         return;
4614     }
4615     if (!chtoc[4]) { /* section disabled? */
4616         return;
4617     }
4618     omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
4619     omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
4620     omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
4621     omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
4622     cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
4623     cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
4624     cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
4625     cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
4626     cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
4627     cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
4628     cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
4629     cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
4630     omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
4631     omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
4632     /* TODO: ECC config registers. The TRM spec is not clear on these */
4633 }
4634
4635 static void omap3_boot_chmmcsd(const uint8_t *chtoc)
4636 {
4637     if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
4638         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4639         return;
4640     }
4641     if (!chtoc[4]) { /* section disabled? */
4642         return;
4643     }
4644     /* TODO: MMCHS registers */
4645 }
4646
4647 /* returns non-zero if more blocks are needed */
4648 static uint32_t omap3_boot_block(const uint8_t *data,
4649                                  uint32_t data_len,
4650                                  struct omap3_boot_s *s)
4651 {
4652     const uint8_t *p = 0;
4653     uint32_t i = 0;
4654     
4655     switch (s->state) {
4656         case confighdr:
4657             i = data_len;
4658             for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
4659                 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
4660                     omap3_boot_chsettings(p + omap3_get_le32(p));
4661                 else if (!strcasecmp((char *)(p + 0x14), "chram"))
4662                     omap3_boot_chram(p + omap3_get_le32(p));
4663                 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
4664                     omap3_boot_chflash(p + omap3_get_le32(p));
4665                 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
4666                     omap3_boot_chmmcsd(p + omap3_get_le32(p));
4667                 else
4668                     fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
4669                             __FUNCTION__, (char *)(p + 0x14));
4670             }
4671             data += 512;
4672             data_len -= 512;
4673             s->state = chdone;
4674             /* fallthrough */
4675         case chdone:
4676             s->state = imagehdr;
4677             /* fallthrough */
4678         case imagehdr:
4679             if (data_len < 8)
4680                 break;
4681             s->count = omap3_get_le32(data);
4682             s->addr = omap3_get_le32(data + 4);
4683             s->mpu->env->regs[15] = s->addr;
4684             data += 8;
4685             data_len -= 8;
4686             s->state = copy;
4687             /* fallthrough */
4688         case copy:
4689             i = (s->count >= data_len) ? data_len : s->count;
4690             cpu_physical_memory_write(s->addr, data, i);
4691             s->addr += i;
4692             s->count -= i;
4693            if (!s->count)
4694                 s->state = done;
4695             return s->count;
4696         default:
4697             break;
4698     }
4699     return 0;
4700 }
4701
4702 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
4703 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
4704 {
4705     int i;
4706     
4707     /* there are 0x10 items with 0x20 bytes per item */
4708     for (i = 0x10; i--; s += 0x20) {
4709         if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
4710         if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
4711     }
4712     return 0;
4713 }
4714
4715 struct omap3_fat_drv_s {
4716     BlockDriverState *bs;
4717     uint8_t ptype; /* 12, 16, 32 */
4718     uint64_t c0;   /* physical byte offset for data cluster 0 */
4719     uint64_t fat;  /* physical byte offset for used FAT sector 0 */
4720     uint32_t spc;  /* sectors per cluster */
4721 };
4722
4723 /* returns cluster data in the buffer and next cluster chain number
4724    or 0 if unsuccessful */
4725 static uint32_t omap3_read_fat_cluster(uint8_t *data,
4726                                        struct omap3_fat_drv_s *drv,
4727                                        uint32_t cl)
4728 {
4729     uint8_t buf[ 4 ];
4730     uint32_t len = drv->spc * 0x200; /* number of bytes to read */
4731     
4732     switch (drv->ptype) { /* check for EOF */
4733         case 12: if (cl > 0xff0) return 0; break;
4734         case 16: if (cl > 0xfff0) return 0; break;
4735         case 32: if (cl > 0x0ffffff0) return 0; break;
4736         default: return 0;
4737     }
4738     
4739     if (bdrv_pread(drv->bs, 
4740                    drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
4741                    data, len) != len)
4742         return 0;
4743     
4744     switch (drv->ptype) { /* determine next cluster # */
4745         case 12:
4746             fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
4747                     __FUNCTION__);
4748             break;
4749         case 16:
4750             return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
4751             ? 0 : omap3_get_le16(buf);
4752         case 32:
4753             return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
4754             ? 0 : omap3_get_le32(buf) & 0x0fffffff;
4755         default:
4756             break;
4757     }
4758     return 0;
4759 }
4760
4761 static int omap3_mmc_fat_boot(BlockDriverState *bs,
4762                               uint8_t *sector,
4763                               uint32_t pstart,
4764                               struct omap_mpu_state_s *mpu)
4765 {
4766     struct omap3_fat_drv_s drv;
4767     struct omap3_boot_s *boot;
4768     uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
4769     const uint8_t *p, *q;
4770     uint8_t *cluster;
4771     int result = 0;
4772     
4773     /* determine FAT type */
4774     
4775     drv.bs = bs;
4776     fatsize = omap3_get_le16(sector + 0x16);
4777     if (!fatsize) 
4778         fatsize = omap3_get_le32(sector + 0x24);
4779     bootsize = omap3_get_le16(sector + 0x0e);
4780     cluster0 = bootsize + fatsize * sector[0x10];
4781     rootsize = omap3_get_le16(sector + 0x11);
4782     if (rootsize & 0x0f)
4783         rootsize += 0x10;
4784     rootsize >>= 4;
4785     drv.spc = sector[0x0d];
4786     i = omap3_get_le16(sector + 0x13);
4787     if (!i)
4788         i = omap3_get_le32(sector + 0x20);
4789     i = (i - (cluster0 + rootsize)) / drv.spc;
4790     drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
4791     
4792     /* search for boot loader file */
4793     
4794     drv.fat = (bootsize + pstart) * 0x200;
4795     drv.c0 = (cluster0 + pstart) * 0x200;
4796     if (drv.ptype == 32) {
4797         i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
4798         j = omap3_get_le16(sector + 0x28);
4799         if (j & 0x80)
4800             drv.fat += (j & 0x0f) * fatsize * 0x200;
4801         cluster = qemu_mallocz(drv.spc * 0x200);
4802         for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
4803             for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
4804                 p = omap3_scan_fat_dir_sector(q);
4805             if (p) 
4806                 memcpy(sector, q - 0x200, 0x200); /* save the sector */
4807         }
4808         free(cluster);
4809     } else { /* FAT12/16 */
4810         for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
4811             if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
4812                 break;
4813             p = omap3_scan_fat_dir_sector(sector);
4814         }
4815     }
4816     
4817     if (p && *p) { /* did we indeed find the file? */
4818         i = omap3_get_le16(p + 0x14);
4819         i <<= 16;
4820         i |= omap3_get_le16(p + 0x1a);
4821         j = drv.spc * 0x200;
4822         uint8 *data = qemu_mallocz(j);
4823         if ((i = omap3_read_fat_cluster(data, &drv, i))) {
4824             boot = omap3_boot_init(data, j, mpu);
4825             boot->state = imagehdr; /* override CH detection */
4826             while (omap3_boot_block(data, j, boot))
4827                 i = omap3_read_fat_cluster(data, &drv, i);
4828             free(boot);
4829             result = 1;
4830         } else
4831             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
4832                     __FUNCTION__);
4833         free(data);
4834     } else
4835         fprintf(stderr, "%s: MLO file not found in the root directory\n",
4836                 __FUNCTION__);
4837
4838     return result;
4839 }
4840
4841 static int omap3_mmc_raw_boot(BlockDriverState *bs,
4842                               uint8_t *sector,
4843                               struct omap_mpu_state_s *mpu)
4844 {
4845     struct omap3_boot_s *boot;
4846     uint32_t i = 0;
4847     
4848     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4849         boot = omap3_boot_init(sector, 0x200, mpu);
4850         if (boot->state == confighdr) { /* CH must be present for raw boot */
4851             while (omap3_boot_block(sector, 0x200, boot)) {
4852                 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
4853                     fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
4854                             __FUNCTION__, i);
4855                     break;
4856                 }
4857             }
4858         }
4859         free(boot);
4860     }
4861     return 0;
4862 }
4863
4864 /* returns non-zero if successful, zero if unsuccessful */
4865 int omap3_mmc_boot(struct omap_mpu_state_s *s)
4866 {
4867     BlockDriverState *bs;
4868     int sdindex = drive_get_index(IF_SD, 0, 0);
4869     uint8_t *sector, *p;
4870     uint32_t pstart, i;
4871     int result = 0;
4872     
4873     /* very simple implementation for GP device boot,
4874        supports only two modes:
4875        1. MBR partition table with an active FAT partition
4876           and boot loader file (MLO) in its root directory, or
4877        2. CH sector or boot loader located on first sector */
4878     if (sdindex >= 0) {
4879         bs = drives_table[sdindex].bdrv;
4880         sector = qemu_mallocz(0x200);
4881         if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4882             for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
4883                 if (p[0] == 0x80) break;
4884             if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
4885                 && i < 4 /* active partition exists */
4886                 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
4887                     || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
4888                 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
4889                               sector, 0x200) == 0x200
4890                 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
4891                 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
4892             else
4893                 result = omap3_mmc_raw_boot(bs, sector, s);
4894         }
4895         free(sector);
4896     }
4897     return result;
4898 }
4899