more cleanups
[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     L4A_USBHS_OTG,
1123     L4A_USBHS_HOST,
1124     L4A_USBHS_TLL
1125 } omap3_l4_agent_info_id_t;
1126
1127 struct omap3_l4_agent_info_s {
1128     omap3_l4_agent_info_id_t agent_id;
1129     omap3_l4_region_id_t     first_region_id;
1130     int                      region_count;
1131 };
1132
1133 static const struct omap3_l4_agent_info_s omap3_l4_agent_info[] = {
1134     /* L4-Core Agents */
1135     {L4A_DSS,        L4ID_DSI,       6},
1136     /* TODO: camera */
1137     {L4A_USBHS_OTG,  L4ID_HSUSBOTG,  2},
1138     {L4A_USBHS_HOST, L4ID_HSUSBHOST, 2},
1139     {L4A_USBHS_TLL,  L4ID_USBTLL,    2},
1140     {L4A_UART1,      L4ID_UART1,     2},
1141     {L4A_UART2,      L4ID_UART2,     2},
1142     {L4A_I2C1,       L4ID_I2C1,      2},
1143     {L4A_I2C2,       L4ID_I2C2,      2},
1144     {L4A_I2C3,       L4ID_I2C3,      2},
1145     /* TODO: McBSP1 */
1146     /* TODO: McBSP5 */
1147     {L4A_GPTIMER10,  L4ID_GPTIMER10, 2},
1148     {L4A_GPTIMER11,  L4ID_GPTIMER11, 2},
1149     /* TODO: SPI1 */
1150     /* TODO: SPI2 */
1151     {L4A_MMC1,       L4ID_MMCSDIO1,  2},
1152     {L4A_MMC2,       L4ID_MMCSDIO2,  2},
1153     {L4A_MMC3,       L4ID_MMCSDIO3,  2},
1154     /* TODO: HDQ/1-Wire */
1155     /* TODO: Mailbox */
1156     /* TODO: SPI3 */
1157     /* TODO: SPI4 */
1158     /* TODO: SDMA */
1159     {L4A_CM,         L4ID_CM_A,      3},
1160     {L4A_SCM,        L4ID_SCM,       2},
1161     {L4A_TAP,        L4ID_TAP,       2},
1162     /* L4-Wakeup Agents */
1163     {L4A_GPTIMER12,  L4ID_GPTIMER12, 2},
1164     {L4A_PRM,        L4ID_PRM_A,     3},
1165     {L4A_GPIO1,      L4ID_GPIO1,     2},
1166     {L4A_WDTIMER2,   L4ID_WDTIMER2,  2},
1167     {L4A_GPTIMER1,   L4ID_GPTIMER1,  2},
1168     {L4A_32KTIMER,   L4ID_32KTIMER,  2},
1169     /* L4-Per Agents */
1170     {L4A_UART3,      L4ID_UART3,     2},
1171     /* TODO: McBSP2 */
1172     /* TODO: McBSP3 */
1173     {L4A_GPTIMER2,   L4ID_GPTIMER2,  2},
1174     {L4A_GPTIMER3,   L4ID_GPTIMER3,  2},
1175     {L4A_GPTIMER4,   L4ID_GPTIMER4,  2},
1176     {L4A_GPTIMER5,   L4ID_GPTIMER5,  2},
1177     {L4A_GPTIMER6,   L4ID_GPTIMER6,  2},
1178     {L4A_GPTIMER7,   L4ID_GPTIMER7,  2},
1179     {L4A_GPTIMER8,   L4ID_GPTIMER8,  2},
1180     {L4A_GPTIMER9,   L4ID_GPTIMER9,  2},
1181     {L4A_GPIO2,      L4ID_GPIO2,     2},
1182     {L4A_GPIO3,      L4ID_GPIO3,     2},
1183     {L4A_GPIO4,      L4ID_GPIO4,     2},
1184     {L4A_GPIO5,      L4ID_GPIO5,     2},
1185     {L4A_GPIO6,      L4ID_GPIO6,     2},
1186 };
1187
1188 static uint32_t omap3_l4ta_read(void *opaque, target_phys_addr_t addr)
1189 {
1190     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
1191     
1192     switch (addr) {
1193         case 0x00: /* COMPONENT_L */
1194             return s->component;
1195         case 0x04: /* COMPONENT_H */
1196             return 0;
1197         case 0x18: /* CORE_L */
1198             return s->component;
1199         case 0x1c: /* CORE_H */
1200             return (s->component >> 16);
1201         case 0x20: /* AGENT_CONTROL_L */
1202             return s->control;
1203         case 0x24: /* AGENT_CONTROL_H */
1204             return s->control_h;
1205         case 0x28: /* AGENT_STATUS_L */
1206             return s->status;
1207         case 0x2c: /* AGENT_STATUS_H */
1208             return 0;
1209         default:
1210             break;
1211     }
1212     
1213     OMAP_BAD_REG(s->base + addr);
1214     return 0;
1215 }
1216
1217 static void omap3_l4ta_write(void *opaque, target_phys_addr_t addr,
1218                              uint32_t value)
1219 {
1220     struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
1221     
1222     switch (addr) {
1223         case 0x00: /* COMPONENT_L */
1224         case 0x04: /* COMPONENT_H */
1225         case 0x18: /* CORE_L */
1226         case 0x1c: /* CORE_H */
1227             OMAP_RO_REG(s->base + addr);
1228             break;
1229         case 0x20: /* AGENT_CONTROL_L */
1230             s->control = value & 0x00000701;
1231             break;
1232         case 0x24: /* AGENT_CONTROL_H */
1233             s->control_h = value & 0x100; /* TODO: shouldn't this be read-only? */
1234             break;
1235         case 0x28: /* AGENT_STATUS_L */
1236             if (value & 0x100)
1237                 s->status &= ~0x100; /* REQ_TIMEOUT */
1238             break;
1239         case 0x2c: /* AGENT_STATUS_H */
1240             /* no writable bits although the register is listed as RW */
1241             break;
1242         default:
1243             OMAP_BAD_REG(s->base + addr);
1244             break;
1245     }
1246 }
1247
1248 static CPUReadMemoryFunc *omap3_l4ta_readfn[] = {
1249     omap_badwidth_read32,
1250     omap_badwidth_read32,
1251     omap3_l4ta_read,
1252 };
1253
1254 static CPUWriteMemoryFunc *omap3_l4ta_writefn[] = {
1255     omap_badwidth_write32,
1256     omap_badwidth_write32,
1257     omap3_l4ta_write,
1258 };
1259
1260 static struct omap_target_agent_s *omap3_l4ta_init(struct omap_l4_s *bus, int cs)
1261 {
1262     int i, iomemtype;
1263     struct omap_target_agent_s *ta = 0;
1264     const struct omap3_l4_agent_info_s *info = 0;
1265
1266     for (i = 0; i < bus->ta_num; i++)
1267         if (omap3_l4_agent_info[i].agent_id == cs) {
1268             ta = &bus->ta[i];
1269             info = &omap3_l4_agent_info[i];
1270             break;
1271         }
1272     if (!ta) {
1273         fprintf(stderr, "%s: invalid agent id (%i)\n", __FUNCTION__, cs);
1274         exit(-1);
1275     }
1276     if (ta->bus) {
1277         fprintf(stderr, "%s: target agent (%d) already initialized\n",
1278                 __FUNCTION__, cs);
1279         exit(-1);
1280     }
1281
1282     ta->bus = bus;
1283     ta->start = &omap3_l4_region[info->first_region_id];
1284     ta->regions = info->region_count;
1285
1286     ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
1287     ta->status = 0x00000000;
1288     ta->control = 0x00000200;
1289
1290     for (i = 0; i < info->region_count; i++)
1291         if (omap3_l4_region[info->first_region_id + i].access == L4TYPE_TA)
1292             break;
1293     if (i >= info->region_count) {
1294         fprintf(stderr, "%s: specified agent (%d) has no TA region\n",
1295                 __FUNCTION__, cs);
1296         exit(-1);
1297     }
1298     
1299     iomemtype = l4_register_io_memory(0, omap3_l4ta_readfn,
1300                                       omap3_l4ta_writefn, ta);
1301     ta->base = omap_l4_attach(ta, i, iomemtype);
1302
1303     return ta;
1304 }
1305
1306 /* common PRM domain registers */
1307 struct omap3_prm_domain_s {
1308     uint32_t rm_rstctrl;   /* 50 */
1309     uint32_t rm_rstst;     /* 58 */
1310     uint32_t pm_wken;      /* a0 */
1311     uint32_t pm_mpugrpsel; /* a4 */
1312     uint32_t pm_ivagrpsel; /* a8 */
1313     uint32_t pm_wkst;      /* b0 */
1314     uint32_t pm_wkdep;     /* c8 */
1315     uint32_t pm_pwstctrl;  /* e0 */
1316     uint32_t pm_pwstst;    /* e4 */
1317     uint32_t pm_prepwstst; /* e8 */
1318 };
1319
1320 struct omap3_prm_s {
1321     qemu_irq mpu_irq;
1322     qemu_irq iva_irq;
1323     struct omap_mpu_state_s *omap;
1324
1325     struct omap3_prm_domain_s iva2;
1326     struct omap3_prm_domain_s mpu;
1327     struct omap3_prm_domain_s core;
1328     struct omap3_prm_domain_s sgx;
1329     struct omap3_prm_domain_s wkup;
1330     struct omap3_prm_domain_s dss;
1331     struct omap3_prm_domain_s cam;
1332     struct omap3_prm_domain_s per;
1333     struct omap3_prm_domain_s emu;
1334     struct omap3_prm_domain_s neon;
1335     struct omap3_prm_domain_s usbhost;
1336
1337     uint32_t iva2_prm_irqstatus;
1338     uint32_t iva2_prm_irqenable;
1339     
1340     uint32_t mpu_pm_evgenctrl;
1341     uint32_t mpu_pm_evgenontim;
1342     uint32_t mpu_pm_evgenofftim;
1343
1344     uint32_t core_pm_wkst3;
1345     uint32_t core_pm_wken3;
1346     uint32_t core_pm_iva2grpsel3;
1347     uint32_t core_pm_mpugrpsel3;
1348
1349     uint32_t prm_revision;
1350     uint32_t prm_sysconfig;
1351     uint32_t prm_irqstatus_mpu;
1352     uint32_t prm_irqenable_mpu;
1353
1354     uint32_t prm_clksel;
1355     uint32_t prm_clkout_ctrl;
1356
1357     uint32_t prm_vc_smps_sa;
1358     uint32_t prm_vc_smps_vol_ra;
1359     uint32_t prm_vc_smps_cmd_ra;
1360     uint32_t prm_vc_cmd_val_0;
1361     uint32_t prm_vc_cmd_val_1;
1362     uint32_t prm_vc_hc_conf;
1363     uint32_t prm_vc_i2c_cfg;
1364     uint32_t prm_vc_bypass_val;
1365     uint32_t prm_rstctrl;
1366     uint32_t prm_rsttimer;
1367     uint32_t prm_rstst;
1368     uint32_t prm_voltctrl;
1369     uint32_t prm_sram_pcharge;
1370     uint32_t prm_clksrc_ctrl;
1371     uint32_t prm_obs;
1372     uint32_t prm_voltsetup1;
1373     uint32_t prm_voltoffset;
1374     uint32_t prm_clksetup;
1375     uint32_t prm_polctrl;
1376     uint32_t prm_voltsetup2;
1377 };
1378
1379 static void omap3_prm_int_update(struct omap3_prm_s *s)
1380 {
1381     qemu_set_irq(s->mpu_irq, s->prm_irqstatus_mpu & s->prm_irqenable_mpu);
1382     qemu_set_irq(s->iva_irq, s->iva2_prm_irqstatus & s->iva2_prm_irqenable);
1383 }
1384
1385 static void omap3_prm_reset(struct omap3_prm_s *s)
1386 {
1387     s->iva2.rm_rstctrl    = 0x7;
1388     s->iva2.rm_rstst      = 0x1;
1389     s->iva2.pm_wkdep      = 0xb3;
1390     s->iva2.pm_pwstctrl   = 0xff0f07;
1391     s->iva2.pm_pwstst     = 0xff7;
1392     s->iva2.pm_prepwstst  = 0x0;
1393     s->iva2_prm_irqstatus = 0x0;
1394     s->iva2_prm_irqenable = 0x0;
1395
1396     s->prm_revision      = 0x10;
1397     s->prm_sysconfig     = 0x1;
1398     s->prm_irqstatus_mpu = 0x0;
1399     s->prm_irqenable_mpu = 0x0;
1400
1401     s->mpu.rm_rstst       = 0x1;
1402     s->mpu.pm_wkdep       = 0xa5;
1403     s->mpu.pm_pwstctrl    = 0x30107;
1404     s->mpu.pm_pwstst      = 0xc7;
1405     s->mpu.pm_pwstst      = 0x0;
1406     s->mpu_pm_evgenctrl   = 0x12;
1407     s->mpu_pm_evgenontim  = 0x0;
1408     s->mpu_pm_evgenofftim = 0x0;
1409
1410     s->core.rm_rstst       = 0x1;
1411     s->core.pm_wken        = 0xc33ffe18;
1412     s->core.pm_mpugrpsel   = 0xc33ffe18;
1413     s->core.pm_ivagrpsel   = 0xc33ffe18;
1414     s->core.pm_wkst        = 0x0;
1415     s->core.pm_pwstctrl    = 0xf0307;
1416     s->core.pm_pwstst      = 0xf7;
1417     s->core.pm_prepwstst   = 0x0;
1418     s->core_pm_wkst3       = 0x0;
1419     s->core_pm_wken3       = 0x4;
1420     s->core_pm_iva2grpsel3 = 0x4;
1421     s->core_pm_mpugrpsel3  = 0x4;
1422
1423     s->sgx.rm_rstst     = 0x1;
1424     s->sgx.pm_wkdep     = 0x16;
1425     s->sgx.pm_pwstctrl  = 0x30107;
1426     s->sgx.pm_pwstst    = 0x3;
1427     s->sgx.pm_prepwstst = 0x0;
1428
1429     s->wkup.pm_wken      = 0x3cb;
1430     s->wkup.pm_mpugrpsel = 0x3cb;
1431     s->wkup.pm_ivagrpsel = 0x0;
1432     s->wkup.pm_wkst      = 0x0;
1433     s->wkup.pm_pwstst    = 0x3; /* TODO: check on real hardware */
1434
1435     s->prm_clksel      = 0x4;
1436     s->prm_clkout_ctrl = 0x80;
1437
1438     s->dss.rm_rstst     = 0x1;
1439     s->dss.pm_wken      = 0x1;
1440     s->dss.pm_wkdep     = 0x16;
1441     s->dss.pm_pwstctrl  = 0x30107;
1442     s->dss.pm_pwstst    = 0x3;
1443     s->dss.pm_prepwstst = 0x0;
1444
1445     s->cam.rm_rstst     = 0x1;
1446     s->cam.pm_wkdep     = 0x16;
1447     s->cam.pm_pwstctrl  = 0x30107;
1448     s->cam.pm_pwstst    = 0x3;
1449     s->cam.pm_prepwstst = 0x0;
1450
1451     s->per.rm_rstst     = 0x1;
1452     s->per.pm_wken      = 0x3efff;
1453     s->per.pm_mpugrpsel = 0x3efff;
1454     s->per.pm_ivagrpsel = 0x3efff;
1455     s->per.pm_wkst      = 0x0;
1456     s->per.pm_wkdep     = 0x17;
1457     s->per.pm_pwstctrl  = 0x30107;
1458     s->per.pm_pwstst    = 0x7;
1459     s->per.pm_prepwstst = 0x0;
1460
1461     s->emu.rm_rstst  = 0x1;
1462     s->emu.pm_pwstst = 0x13;
1463
1464     s->prm_vc_smps_sa     = 0x0;
1465     s->prm_vc_smps_vol_ra = 0x0;
1466     s->prm_vc_smps_cmd_ra = 0x0;
1467     s->prm_vc_cmd_val_0   = 0x0;
1468     s->prm_vc_cmd_val_1   = 0x0;
1469     s->prm_vc_hc_conf     = 0x0;
1470     s->prm_vc_i2c_cfg     = 0x18;
1471     s->prm_vc_bypass_val  = 0x0;
1472     s->prm_rstctrl        = 0x0;
1473     s->prm_rsttimer       = 0x1006;
1474     s->prm_rstst          = 0x1;
1475     s->prm_voltctrl       = 0x0;
1476     s->prm_sram_pcharge   = 0x50;
1477     s->prm_clksrc_ctrl    = 0x43;
1478     s->prm_obs            = 0x0;
1479     s->prm_voltsetup1     = 0x0;
1480     s->prm_voltoffset     = 0x0;
1481     s->prm_clksetup       = 0x0;
1482     s->prm_polctrl        = 0xa;
1483     s->prm_voltsetup2     = 0x0;
1484
1485     s->neon.rm_rstst     = 0x1;
1486     s->neon.pm_wkdep     = 0x2;
1487     s->neon.pm_pwstctrl  = 0x7;
1488     s->neon.pm_pwstst    = 0x3;
1489     s->neon.pm_prepwstst = 0x0;
1490
1491     s->usbhost.rm_rstst     = 0x1;
1492     s->usbhost.pm_wken      = 0x1;
1493     s->usbhost.pm_mpugrpsel = 0x1;
1494     s->usbhost.pm_ivagrpsel = 0x1;
1495     s->usbhost.pm_wkst      = 0x0;
1496     s->usbhost.pm_wkdep     = 0x17;
1497     s->usbhost.pm_pwstctrl  = 0x30107;
1498     s->usbhost.pm_pwstst    = 0x3;
1499     s->usbhost.pm_prepwstst = 0x0;
1500
1501     omap3_prm_int_update(s);
1502 }
1503
1504 static uint32_t omap3_prm_read(void *opaque, target_phys_addr_t addr)
1505 {
1506     struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
1507     struct omap3_prm_domain_s *d = 0;
1508
1509     TRACE("%04x", addr);
1510     
1511     /* handle common domain registers first - all domains may not
1512        have all common registers though but we're returning zeroes there */
1513     switch ((addr >> 8) & 0xff) {
1514         case 0x00: d = &s->iva2; break;
1515         case 0x09: d = &s->mpu; break;
1516         case 0x0a: d = &s->core; break;
1517         case 0x0b: d = &s->sgx; break;
1518         case 0x0c: d = &s->wkup; break;
1519         case 0x0e: d = &s->dss; break;
1520         case 0x0f: d = &s->cam; break;
1521         case 0x10: d = &s->per; break;
1522         case 0x11: d = &s->emu; break;
1523         case 0x13: d = &s->neon; break;
1524         case 0x14: d = &s->usbhost; break;
1525         default: break;
1526     }
1527     if (d)
1528         switch (addr & 0xff) {
1529             case 0x50: return d->rm_rstctrl;
1530             case 0x58: return d->rm_rstst;
1531             case 0xa0: return d->pm_wken;
1532             case 0xa4: return d->pm_mpugrpsel;
1533             case 0xa8: return d->pm_ivagrpsel;
1534             case 0xb0: return d->pm_wkst;
1535             case 0xc8: return d->pm_wkdep;
1536             case 0xe0: return d->pm_pwstctrl;
1537             case 0xe4: return d->pm_pwstst;
1538             case 0xe8: return d->pm_prepwstst;
1539             default: break;
1540         }
1541
1542     /* okay, not a common domain register so let's take a closer look */
1543     switch (addr) {
1544         case 0x00f8: return s->iva2_prm_irqstatus;
1545         case 0x00fc: return s->iva2_prm_irqenable;
1546         case 0x0804: return s->prm_revision;
1547         case 0x0814: return s->prm_sysconfig;
1548         case 0x0818: return s->prm_irqstatus_mpu;
1549         case 0x081c: return s->prm_irqenable_mpu;
1550         case 0x09d4: return s->mpu_pm_evgenctrl;
1551         case 0x09d8: return s->mpu_pm_evgenontim;
1552         case 0x09dc: return s->mpu_pm_evgenofftim;
1553         case 0x0ab8: return s->core_pm_wkst3;
1554         case 0x0af0: return s->core_pm_wken3;
1555         case 0x0af4: return s->core_pm_iva2grpsel3;
1556         case 0x0af8: return s->core_pm_mpugrpsel3;
1557         case 0x0d40: return s->prm_clksel;
1558         case 0x0d70: return s->prm_clkout_ctrl;
1559         case 0x0de4: return 0x3; /* TODO: check on real hardware */
1560         case 0x1220: return s->prm_vc_smps_sa;
1561         case 0x1224: return s->prm_vc_smps_vol_ra;
1562         case 0x1228: return s->prm_vc_smps_cmd_ra;
1563         case 0x122c: return s->prm_vc_cmd_val_0;
1564         case 0x1230: return s->prm_vc_cmd_val_1;
1565         case 0x1234: return s->prm_vc_hc_conf;
1566         case 0x1238: return s->prm_vc_i2c_cfg;
1567         case 0x123c: return s->prm_vc_bypass_val;
1568         case 0x1250: return s->prm_rstctrl;
1569         case 0x1254: return s->prm_rsttimer;
1570         case 0x1258: return s->prm_rstst;
1571         case 0x1260: return s->prm_voltctrl;
1572         case 0x1264: return s->prm_sram_pcharge;        
1573         case 0x1270: return s->prm_clksrc_ctrl;
1574         case 0x1280: return s->prm_obs;
1575         case 0x1290: return s->prm_voltsetup1;
1576         case 0x1294: return s->prm_voltoffset;
1577         case 0x1298: return s->prm_clksetup;
1578         case 0x129c: return s->prm_polctrl;
1579         case 0x12a0: return s->prm_voltsetup2;
1580         default: break;
1581     }
1582
1583     OMAP_BAD_REG(addr);
1584     return 0;
1585 }
1586
1587 static inline void omap3_prm_clksrc_ctrl_update(struct omap3_prm_s *s,
1588                                                 uint32_t value)
1589 {
1590     if ((value & 0xd0) == 0x40)
1591         omap_clk_setrate(omap_findclk(s->omap, "omap3_sys_clk"), 1, 1);
1592     else if ((value & 0xd0) == 0x80)
1593         omap_clk_setrate(omap_findclk(s->omap, "omap3_sys_clk"), 2, 1);
1594 }
1595
1596 static void omap3_prm_write(void *opaque, target_phys_addr_t addr,
1597                             uint32_t value)
1598 {
1599     struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
1600
1601     TRACE("%04x = %08x", addr, value);
1602     switch (addr) {
1603         /* IVA2_PRM */
1604         case 0x0050: s->iva2.rm_rstctrl = value & 0x7; break;
1605         case 0x0058: s->iva2.rm_rstst &= ~(value & 0x3f0f); break;
1606         case 0x00c8: s->iva2.pm_wkdep = value & 0xb3; break;
1607         case 0x00e0: s->iva2.pm_pwstctrl = 0xcff000 | (value & 0x300f0f); break;
1608         case 0x00e4: OMAP_RO_REG(addr); break;
1609         case 0x00e8: s->iva2.pm_prepwstst = value & 0xff7;
1610         case 0x00f8:
1611             s->iva2_prm_irqstatus &= ~(value & 0x7);
1612             omap3_prm_int_update(s);
1613             break;
1614         case 0x00fc:
1615             s->iva2_prm_irqenable = value & 0x7;
1616             omap3_prm_int_update(s);
1617             break;
1618         /* OCP_System_Reg_PRM */
1619         case 0x0804: OMAP_RO_REG(addr); break;
1620         case 0x0814: s->prm_sysconfig = value & 0x1; break;
1621         case 0x0818:
1622             s->prm_irqstatus_mpu &= ~(value & 0x03c003fd);
1623             omap3_prm_int_update(s);
1624             break;
1625         case 0x081c:
1626             s->prm_irqenable_mpu = value & 0x03c003fd;
1627             omap3_prm_int_update(s);
1628             break;
1629         /* MPU_PRM */
1630         case 0x0958: s->mpu.rm_rstst &= ~(value & 0x080f); break;
1631         case 0x09c8: s->mpu.pm_wkdep = value & 0xa5; break;
1632         case 0x09d4: s->mpu_pm_evgenctrl = value & 0x1f; break;
1633         case 0x09d8: s->mpu_pm_evgenontim = value; break;
1634         case 0x09dc: s->mpu_pm_evgenofftim = value; break;
1635         case 0x09e0: s->mpu.pm_pwstctrl = value & 0x3010f; break;
1636         case 0x09e4: OMAP_RO_REG(addr); break;
1637         case 0x09e8: s->mpu.pm_prepwstst = value & 0xc7; break;
1638         /* CORE_PRM */
1639         case 0x0a50: s->core.rm_rstctrl = value & 0x3; break; /* TODO: check if available on real hw */
1640         case 0x0a58: s->core.rm_rstst &= ~(value & 0x7); break;
1641         case 0x0aa0: s->core.pm_wken = 0x80000008 | (value & 0x433ffe10); break;
1642         case 0x0aa4: s->core.pm_mpugrpsel = 0x80000008 | (value & 0x433ffe10); break;
1643         case 0x0aa8: s->core.pm_ivagrpsel = 0x80000008 | (value & 0x433ffe10); break;
1644         case 0x0ab0: s->core.pm_wkst = value & 0x433ffe10; break;
1645         case 0x0ab8: s->core_pm_wkst3 &= ~(value & 0x4); break;
1646         case 0x0ae0: s->core.pm_pwstctrl = (value & 0x0f031f); break;
1647         case 0x0ae4: OMAP_RO_REG(addr); break;
1648         case 0x0ae8: s->core.pm_prepwstst = value & 0xf7; break;
1649         case 0x0af0: s->core_pm_wken3 = value & 0x4; break;
1650         case 0x0af4: s->core_pm_iva2grpsel3 = value & 0x4; break;
1651         case 0x0af8: s->core_pm_mpugrpsel3 = value & 0x4; break;
1652         /* SGX_PRM */
1653         case 0x0b58: s->sgx.rm_rstst &= ~(value & 0xf); break;
1654         case 0x0bc8: s->sgx.pm_wkdep = value & 0x16; break;
1655         case 0x0be0: s->sgx.pm_pwstctrl = 0x030104 | (value & 0x3); break;
1656         case 0x0be4: OMAP_RO_REG(addr); break;
1657         case 0x0be8: s->sgx.pm_prepwstst = value & 0x3; break;
1658         /* WKUP_PRM */
1659         case 0x0ca0: s->wkup.pm_wken = 0x2 | (value & 0x0103c9); break;
1660         case 0x0ca4: s->wkup.pm_mpugrpsel = 0x0102 | (value & 0x02c9); break;
1661         case 0x0ca8: s->wkup.pm_ivagrpsel = value & 0x03cb; break;
1662         case 0x0cb0: s->wkup.pm_wkst &= ~(value & 0x0103cb); break;
1663         /* Clock_Control_Reg_PRM */
1664         case 0x0d40: 
1665             s->prm_clksel = value & 0x7;
1666             fprintf(stderr, "%s PRM_CLKSEL = 0x%x\n", __FUNCTION__,
1667                     s->prm_clksel);
1668             /* TODO: update clocks */
1669             break;
1670         case 0x0d70:
1671             s->prm_clkout_ctrl = value & 0x80;
1672             fprintf(stderr, "%s PRM_CLKOUT_CTRL = 0x%x\n", __FUNCTION__,
1673                     s->prm_clkout_ctrl);
1674             /* TODO: update clocks */
1675             break;
1676         /* DSS_PRM */
1677         case 0x0e58: s->dss.rm_rstst &= ~(value & 0xf); break;
1678         case 0x0ea0: s->dss.pm_wken = value & 1; break;
1679         case 0x0ec8: s->dss.pm_wkdep = value & 0x16; break;
1680         case 0x0ee0: s->dss.pm_pwstctrl = 0x030104 | (value & 3); break;
1681         case 0x0ee4: OMAP_RO_REG(addr); break;
1682         case 0x0ee8: s->dss.pm_prepwstst = value & 3; break;
1683         /* CAM_PRM */
1684         case 0x0f58: s->cam.rm_rstst &= (value & 0xf); break;
1685         case 0x0fc8: s->cam.pm_wkdep = value & 0x16; break;
1686         case 0x0fe0: s->cam.pm_pwstctrl = 0x030104 | (value & 3); break;
1687         case 0x0fe4: OMAP_RO_REG(addr); break;
1688         case 0x0fe8: s->cam.pm_prepwstst = value & 0x3; break;
1689         /* PER_PRM */
1690         case 0x1058: s->per.rm_rstst &= ~(value & 0xf); break;
1691         case 0x10a0: s->per.pm_wken = value & 0x03efff; break;
1692         case 0x10a4: s->per.pm_mpugrpsel = value & 0x03efff; break;
1693         case 0x10a8: s->per.pm_ivagrpsel = value & 0x03efff; break;
1694         case 0x10b0: s->per.pm_wkst &= ~(value & 0x03efff); break;
1695         case 0x10c8: s->per.pm_wkdep = value & 0x17; break;
1696         case 0x10e0: s->per.pm_pwstctrl = 0x030100 | (value & 7); break;
1697         case 0x10e4: OMAP_RO_REG(addr); break;
1698         case 0x10e8: s->per.pm_prepwstst = value & 0x7; break;
1699         /* EMU_PRM */
1700         case 0x1158: s->emu.rm_rstst &= ~(value & 7); break;
1701         case 0x11e4: OMAP_RO_REG(addr); break;
1702         /* Global_Reg_PRM */
1703         case 0x1220: s->prm_vc_smps_sa = value & 0x7f007f; break;
1704         case 0x1224: s->prm_vc_smps_vol_ra = value & 0xff00ff; break;
1705         case 0x1228: s->prm_vc_smps_cmd_ra = value & 0xff00ff; break;
1706         case 0x122c: s->prm_vc_cmd_val_0 = value; break;
1707         case 0x1230: s->prm_vc_cmd_val_1 = value; break;
1708         case 0x1234: s->prm_vc_hc_conf = value & 0x1f001f; break;
1709         case 0x1238: s->prm_vc_i2c_cfg = value & 0x3f; break;
1710         case 0x123c: s->prm_vc_bypass_val = value & 0x01ffff7f; break;
1711         case 0x1250: s->prm_rstctrl = 0; break; /* TODO: resets */
1712         case 0x1254: s->prm_rsttimer = value & 0x1fff; break;
1713         case 0x1258: s->prm_rstst &= ~(value & 0x7fb); break;
1714         case 0x1260: s->prm_voltctrl = value & 0x1f; break;
1715         case 0x1264: s->prm_sram_pcharge = value & 0xff; break;
1716         case 0x1270:
1717             s->prm_clksrc_ctrl = value & (0xd8);
1718             omap3_prm_clksrc_ctrl_update(s, s->prm_clksrc_ctrl);
1719             /* TODO: update SYSCLKSEL bits */
1720             break;
1721         case 0x1280: OMAP_RO_REG(addr); break;
1722         case 0x1290: s->prm_voltsetup1 = value; break;
1723         case 0x1294: s->prm_voltoffset = value & 0xffff; break;
1724         case 0x1298: s->prm_clksetup = value & 0xffff; break;
1725         case 0x129c: s->prm_polctrl = value & 0xf; break;
1726         case 0x12a0: s->prm_voltsetup2 = value & 0xffff; break;
1727         /* NEON_PRM */
1728         case 0x1358: s->neon.rm_rstst &= ~(value & 0xf); break;
1729         case 0x13c8: s->neon.pm_wkdep = value & 0x2; break;
1730         case 0x13e0: s->neon.pm_pwstctrl = 0x4 | (value & 3); break;
1731         case 0x13e4: OMAP_RO_REG(addr); break;
1732         case 0x13e8: s->neon.pm_prepwstst = value & 3; break;
1733         /* USBHOST_PRM */
1734         case 0x1458: s->usbhost.rm_rstst &= ~(value & 0xf); break;
1735         case 0x14a0: s->usbhost.pm_wken = value & 1; break;
1736         case 0x14a4: s->usbhost.pm_mpugrpsel = value & 1; break;
1737         case 0x14a8: s->usbhost.pm_ivagrpsel = value & 1; break;
1738         case 0x14b0: s->usbhost.pm_wkst &= ~(value & 1); break;
1739         case 0x14c8: s->usbhost.pm_wkdep = value & 0x17; break;
1740         case 0x14e0: s->usbhost.pm_pwstctrl = 0x030104 | (value & 0x13); break;
1741         case 0x14e4: OMAP_RO_REG(addr); break;
1742         case 0x14e8: s->usbhost.pm_prepwstst = value & 3; break;
1743         default:
1744             OMAP_BAD_REGV(addr, value);
1745             break;
1746     }
1747 }
1748
1749 static CPUReadMemoryFunc *omap3_prm_readfn[] = {
1750     omap_badwidth_read32,
1751     omap_badwidth_read32,
1752     omap3_prm_read,
1753 };
1754
1755 static CPUWriteMemoryFunc *omap3_prm_writefn[] = {
1756     omap_badwidth_write32,
1757     omap_badwidth_write32,
1758     omap3_prm_write,
1759 };
1760
1761 struct omap3_prm_s *omap3_prm_init(struct omap_target_agent_s *ta,
1762                                    qemu_irq mpu_int, qemu_irq iva_int,
1763                                    struct omap_mpu_state_s *mpu)
1764 {
1765     int iomemtype;
1766     struct omap3_prm_s *s = (struct omap3_prm_s *) qemu_mallocz(sizeof(*s));
1767
1768     s->mpu_irq = mpu_int;
1769     s->iva_irq = iva_int;
1770     s->omap = mpu;
1771     omap3_prm_reset(s);
1772
1773     iomemtype = l4_register_io_memory(0, omap3_prm_readfn,
1774                                       omap3_prm_writefn, s);
1775     omap_l4_attach(ta, 0, iomemtype);
1776     omap_l4_attach(ta, 1, iomemtype);
1777
1778     return s;
1779 }
1780
1781
1782 struct omap3_cm_s
1783 {
1784     qemu_irq irq[3];
1785     struct omap_mpu_state_s *mpu;
1786
1787     /*IVA2_CM Register */
1788     uint32_t cm_fclken_iva2;    /*0x4800 4000 */
1789     uint32_t cm_clken_pll_iva2; /*0x4800 4004 */
1790     uint32_t cm_idlest_iva2;    /*0x4800 4020 */
1791     uint32_t cm_idlest_pll_iva2;        /*0x4800 4024 */
1792     uint32_t cm_autoidle_pll_iva2;      /*0x4800 4034 */
1793     uint32_t cm_clksel1_pll_iva2;       /*0x4800 4040 */
1794     uint32_t cm_clksel2_pll_iva2;       /*0x4800 4044 */
1795     uint32_t cm_clkstctrl_iva2; /*0x4800 4048 */
1796     uint32_t cm_clkstst_iva2;   /*0x4800 404c */
1797
1798     /*OCP_System_Reg_CM */
1799     uint32_t cm_revision;       /*0x4800 4800 */
1800     uint32_t cm_sysconfig;      /*0x4800 4810 */
1801
1802     /*MPU_CM Register */
1803     uint32_t cm_clken_pll_mpu;  /*0x4800 4904 */
1804     uint32_t cm_idlest_mpu;     /*0x4800 4920 */
1805     uint32_t cm_idlest_pll_mpu; /*0x4800 4924 */
1806     uint32_t cm_autoidle_pll_mpu;       /*0x4800 4934 */
1807     uint32_t cm_clksel1_pll_mpu;        /*0x4800 4940 */
1808     uint32_t cm_clksel2_pll_mpu;        /*0x4800 4944 */
1809     uint32_t cm_clkstctrl_mpu;  /*0x4800 4948 */
1810     uint32_t cm_clkstst_mpu;    /*0x4800 494c */
1811
1812     /*CORE_CM Register */
1813     uint32_t cm_fclken1_core;   /*0x4800 4a00 */
1814     uint32_t cm_fclken3_core;   /*0x4800 4a08 */
1815     uint32_t cm_iclken1_core;   /*0x4800 4a10 */
1816     uint32_t cm_iclken2_core;   /*0x4800 4a14 */
1817     uint32_t cm_iclken3_core;   /*0x4800 4a18 */
1818     uint32_t cm_idlest1_core;   /*0x4800 4a20 */
1819     uint32_t cm_idlest2_core;   /*0x4800 4a24 */
1820     uint32_t cm_idlest3_core;   /*0x4800 4a28 */
1821     uint32_t cm_autoidle1_core; /*0x4800 4a30 */
1822     uint32_t cm_autoidle2_core; /*0x4800 4a34 */
1823     uint32_t cm_autoidle3_core; /*0x4800 4a38 */
1824     uint32_t cm_clksel_core;    /*0x4800 4a40 */
1825     uint32_t cm_clkstctrl_core; /*0x4800 4a48 */
1826     uint32_t cm_clkstst_core;   /*0x4800 4a4c */
1827
1828     /*SGX_CM Register */
1829     uint32_t cm_fclken_sgx;     /*0x4800 4b00 */
1830     uint32_t cm_iclken_sgx;     /*0x4800 4b10 */
1831     uint32_t cm_idlest_sgx;     /*0x4800 4b20 */
1832     uint32_t cm_clksel_sgx;     /*0x4800 4b40 */
1833     uint32_t cm_sleepdep_sgx;   /*0x4800 4b44 */
1834     uint32_t cm_clkstctrl_sgx;  /*0x4800 4b48 */
1835     uint32_t cm_clkstst_sgx;    /*0x4800 4b4c */
1836
1837     /*WKUP_CM Register */
1838     uint32_t cm_fclken_wkup;    /*0x4800 4c00 */
1839     uint32_t cm_iclken_wkup;    /*0x4800 4c10 */
1840     uint32_t cm_idlest_wkup;    /*0x4800 4c20 */
1841     uint32_t cm_autoidle_wkup;  /*0x4800 4c30 */
1842     uint32_t cm_clksel_wkup;    /*0x4800 4c40 */
1843     uint32_t cm_c48;                  /*0x4800 4c48 */
1844
1845     /*Clock_Control_Reg_CM Register */
1846     uint32_t cm_clken_pll;      /*0x4800 4d00 */
1847     uint32_t cm_clken2_pll;     /*0x4800 4d04 */
1848     uint32_t cm_idlest_ckgen;   /*0x4800 4d20 */
1849     uint32_t cm_idlest2_ckgen;  /*0x4800 4d24 */
1850     uint32_t cm_autoidle_pll;   /*0x4800 4d30 */
1851     uint32_t cm_autoidle2_pll;  /*0x4800 4d34 */
1852     uint32_t cm_clksel1_pll;    /*0x4800 4d40 */
1853     uint32_t cm_clksel2_pll;    /*0x4800 4d44 */
1854     uint32_t cm_clksel3_pll;    /*0x4800 4d48 */
1855     uint32_t cm_clksel4_pll;    /*0x4800 4d4c */
1856     uint32_t cm_clksel5_pll;    /*0x4800 4d50 */
1857     uint32_t cm_clkout_ctrl;    /*0x4800 4d70 */
1858
1859     /*DSS_CM Register */
1860     uint32_t cm_fclken_dss;     /*0x4800 4e00 */
1861     uint32_t cm_iclken_dss;     /*0x4800 4e10 */
1862     uint32_t cm_idlest_dss;     /*0x4800 4e20 */
1863     uint32_t cm_autoidle_dss;   /*0x4800 4e30 */
1864     uint32_t cm_clksel_dss;     /*0x4800 4e40 */
1865     uint32_t cm_sleepdep_dss;   /*0x4800 4e44 */
1866     uint32_t cm_clkstctrl_dss;  /*0x4800 4e48 */
1867     uint32_t cm_clkstst_dss;    /*0x4800 4e4c */
1868
1869
1870     /*CAM_CM Register */
1871     uint32_t cm_fclken_cam;     /*0x4800 4f00 */
1872     uint32_t cm_iclken_cam;     /*0x4800 4f10 */
1873     uint32_t cm_idlest_cam;     /*0x4800 4f20 */
1874     uint32_t cm_autoidle_cam;   /*0x4800 4f30 */
1875     uint32_t cm_clksel_cam;     /*0x4800 4f40 */
1876     uint32_t cm_sleepdep_cam;   /*0x4800 4f44 */
1877     uint32_t cm_clkstctrl_cam;  /*0x4800 4f48 */
1878     uint32_t cm_clkstst_cam;    /*0x4800 4f4c */
1879
1880     /*PER_CM Register */
1881     uint32_t cm_fclken_per;     /*0x4800 5000 */
1882     uint32_t cm_iclken_per;     /*0x4800 5010 */
1883     uint32_t cm_idlest_per;     /*0x4800 5020 */
1884     uint32_t cm_autoidle_per;   /*0x4800 5030 */
1885     uint32_t cm_clksel_per;     /*0x4800 5040 */
1886     uint32_t cm_sleepdep_per;   /*0x4800 5044 */
1887     uint32_t cm_clkstctrl_per;  /*0x4800 5048 */
1888     uint32_t cm_clkstst_per;    /*0x4800 504c */
1889
1890     /*EMU_CM Register */
1891     uint32_t cm_clksel1_emu;    /*0x4800 5140 */
1892     uint32_t cm_clkstctrl_emu;  /*0x4800 5148 */
1893     uint32_t cm_clkstst_emu;    /*0x4800 514c */
1894     uint32_t cm_clksel2_emu;    /*0x4800 5150 */
1895     uint32_t cm_clksel3_emu;    /*0x4800 5154 */
1896
1897     /*Global_Reg_CM Register */
1898     uint32_t cm_polctrl;        /*0x4800 529c */
1899
1900     /*NEON_CM Register */
1901     uint32_t cm_idlest_neon;    /*0x4800 5320 */
1902     uint32_t cm_clkstctrl_neon; /*0x4800 5348 */
1903
1904     /*USBHOST_CM Register */
1905     uint32_t cm_fclken_usbhost; /*0x4800 5400 */
1906     uint32_t cm_iclken_usbhost; /*0x4800 5410 */
1907     uint32_t cm_idlest_usbhost; /*0x4800 5420 */
1908     uint32_t cm_autoidle_usbhost;       /*0x4800 5430 */
1909     uint32_t cm_sleepdep_usbhost;       /*0x4800 5444 */
1910     uint32_t cm_clkstctrl_usbhost;      /*0x4800 5448 */
1911     uint32_t cm_clkstst_usbhost;        /*0x4800 544c */
1912
1913 };
1914
1915 /*
1916 static inline void omap3_cm_fclken_wkup_update(struct omap3_cm_s *s,
1917                 uint32_t value)
1918 {
1919         
1920         if (value & 0x28)
1921         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 1);
1922     else
1923         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 0);
1924
1925     if (value &0x1)
1926         omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 1);
1927     else
1928         omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 0);
1929
1930 }
1931 static inline void omap3_cm_iclken_wkup_update(struct omap3_cm_s *s,
1932                 uint32_t value)
1933 {
1934         
1935         if (value & 0x3f)
1936         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 1);
1937     else
1938         omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 0);
1939
1940 }
1941 */
1942 static inline void omap3_cm_clksel_wkup_update(struct omap3_cm_s *s,
1943                                                uint32_t value)
1944 {
1945     omap_clk gp1_fclk = omap_findclk(s->mpu, "omap3_gp1_fclk");
1946
1947     if (value & 0x1)
1948         omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
1949     else
1950         omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
1951     /*Tell GPTIMER to generate new clk rate */
1952     omap_gp_timer_change_clk(s->mpu->gptimer[0]);
1953
1954     TRACE("omap3_gp1_fclk %lld",
1955           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp1_fclk")));
1956
1957     /*TODO:CM_USIM_CLK CLKSEL_RM */
1958 }
1959
1960 static inline void omap3_cm_mpu_update(struct omap3_cm_s *s)
1961 {
1962     uint32_t m, n, divide, m2, cm_clken_pll_mpu;
1963     uint32_t bypass = 1;
1964
1965     cm_clken_pll_mpu = s->cm_clken_pll_mpu;
1966     omap_clk mpu_clk = omap_findclk(s->mpu, "omap3_mpu_clk");
1967
1968     if ((cm_clken_pll_mpu & 0x7) == 0x5)
1969     {
1970         bypass = 1;
1971     }
1972     else if ((cm_clken_pll_mpu & 0x7) == 0x7)
1973     {
1974         m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
1975         if ((m == 0) || (m == 1))
1976             bypass = 1;
1977         else
1978             bypass = 0;
1979     }
1980     if (bypass == 1)
1981     {
1982         /*BYPASS Model */
1983         divide = (s->cm_clksel1_pll_mpu & 0x380000) >> 19;
1984         //OMAP3_DEBUG(("divide %d\n",divide));
1985         omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_core_clk"));
1986         omap_clk_setrate(mpu_clk, divide, 1);
1987
1988     }
1989     else
1990     {
1991         n = (s->cm_clksel1_pll_mpu & 0x7F);
1992         m2 = (s->cm_clksel2_pll_mpu & 0x1F);
1993         //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
1994         omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
1995         omap_clk_setrate(mpu_clk, (n + 1) * m2, m);
1996         //OMAP3_DEBUG(("mpu %d \n",omap_clk_getrate(mpu_clk)));
1997
1998     }
1999
2000 }
2001
2002 static inline void omap3_cm_iva2_update(struct omap3_cm_s *s)
2003 {
2004     uint32_t m, n, divide, m2, cm_clken_pll_iva2;
2005     uint32_t bypass = 1;
2006
2007     cm_clken_pll_iva2 = s->cm_clken_pll_iva2;
2008     omap_clk iva2_clk = omap_findclk(s->mpu, "omap3_iva2_clk");
2009
2010     if (((cm_clken_pll_iva2 & 0x7) == 0x5)
2011         || ((cm_clken_pll_iva2 & 0x7) == 0x1))
2012     {
2013         bypass = 1;
2014     }
2015     else if ((cm_clken_pll_iva2 & 0x7) == 0x7)
2016     {
2017         m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
2018         if ((m == 0) || (m == 1))
2019             bypass = 1;
2020         else
2021             bypass = 0;
2022     }
2023     if (bypass == 1)
2024     {
2025         /*BYPASS Model */
2026         divide = (s->cm_clksel1_pll_iva2 & 0x380000) >> 19;
2027         //OMAP3_DEBUG(("divide %d\n",divide));
2028         omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_core_clk"));
2029         omap_clk_setrate(iva2_clk, divide, 1);
2030
2031     }
2032     else
2033     {
2034         n = (s->cm_clksel1_pll_iva2 & 0x7F);
2035         m2 = (s->cm_clksel2_pll_iva2 & 0x1F);
2036         //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
2037         omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
2038         omap_clk_setrate(iva2_clk, (n + 1) * m2, m);
2039         //OMAP3_DEBUG(("iva2_clk %d \n",omap_clk_getrate(iva2_clk)));
2040
2041     }
2042
2043 }
2044
2045 static inline void omap3_cm_dpll3_update(struct omap3_cm_s *s)
2046 {
2047     uint32_t m, n, m2, m3, cm_clken_pll;
2048     uint32_t bypass = 1;
2049
2050     cm_clken_pll = s->cm_clken_pll;
2051
2052     /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
2053     if (((cm_clken_pll & 0x7) == 0x5) || ((cm_clken_pll & 0x7) == 0x6))
2054     {
2055         bypass = 1;
2056     }
2057     else if ((cm_clken_pll & 0x7) == 0x7)
2058     {
2059         m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
2060         if ((m == 0) || (m == 1))
2061             bypass = 1;
2062         else
2063             bypass = 0;
2064     }
2065     if (bypass == 1)
2066     {
2067         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), 1, 1);
2068         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), 1, 1);
2069         omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"), 1,
2070                          1);
2071     }
2072     else
2073     {
2074         n = (s->cm_clksel1_pll & 0x3f00) >> 8;
2075         m2 = (s->cm_clksel1_pll & 0xf8000000) >> 27;
2076         m3 = (s->cm_clksel1_emu & 0x1f0000) >> 16;
2077
2078         if (s->cm_clksel2_emu&0x80000)
2079         {
2080                 /*override control of DPLL3*/
2081                 m = (s->cm_clksel2_emu&0x7ff)>>8;
2082                 n =  s->cm_clksel2_emu&0x7f;
2083                 TRACE("DPLL3 override, m 0x%x n 0x%x",m,n);
2084         }
2085
2086         //OMAP3_DEBUG(("dpll3 cm_clksel1_pll %x m  %d n %d m2 %d  m3 %d\n",s->cm_clksel1_pll,m,n,m2,m3 ));
2087         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), (n + 1) * m2,
2088                          m);
2089         omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), (n + 1) * m2,
2090                          m * 2);
2091         omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"),
2092                          (n + 1) * m3, m * 2);
2093         TRACE("coreclk %lld",
2094               omap_clk_getrate(omap_findclk(s->mpu, "omap3_core_clk")));
2095     }
2096
2097
2098 }
2099
2100 static inline void omap3_cm_dpll4_update(struct omap3_cm_s *s)
2101 {
2102     uint32_t m, n, m2, m3, m4, m5, m6, cm_clken_pll;
2103     cm_clken_pll = s->cm_clken_pll;
2104     uint32_t bypass = 1;
2105
2106     /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
2107     /*DPLL4 */
2108     if ((cm_clken_pll & 0x70000) == 0x10000)
2109     {
2110         bypass = 1;
2111     }
2112     else if ((cm_clken_pll & 0x70000) == 0x70000)
2113     {
2114         m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
2115         if ((m == 0) || (m == 1))
2116             bypass = 1;
2117         else
2118             bypass = 0;
2119     }
2120     if (bypass == 1)
2121     {
2122         omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), 1, 1);
2123         omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), 1, 1);
2124         omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"), 1, 1);
2125         omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), 1, 1);
2126         omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"), 1, 1);
2127     }
2128     else
2129     {
2130         n = (s->cm_clksel2_pll & 0x7f);
2131         m2 = s->cm_clksel3_pll & 0x1f;
2132         m3 = (s->cm_clksel_dss & 0x1f00) >> 8;
2133         m4 = s->cm_clksel_dss & 0x1f;
2134         m5 = s->cm_clksel_cam & 0x1f;
2135         m6 = (s->cm_clksel1_emu & 0x1f000000) >> 24;
2136
2137         if (s->cm_clksel3_emu&0x80000)
2138         {
2139                 /*override control of DPLL4*/
2140                 m = (s->cm_clksel3_emu&0x7ff)>>8;
2141                 n =  s->cm_clksel3_emu&0x7f;
2142                 TRACE("DPLL4 override, m 0x%x n 0x%x",m,n);
2143         }
2144
2145
2146         //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 ));
2147         omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), (n + 1) * m2,
2148                          m * 2);
2149         omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), (n + 1) * m3,
2150                          m * 2);
2151         omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"),
2152                          (n + 1) * m4, m * 2);
2153         omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), (n + 1) * m5,
2154                          m * 2);
2155         omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"),
2156                          (n + 1) * m6, m * 2);
2157
2158         TRACE("omap3_96m_fclk %lld",
2159               omap_clk_getrate(omap_findclk(s->mpu, "omap3_96m_fclk")));
2160         TRACE("omap3_54m_fclk %lld",
2161               omap_clk_getrate(omap_findclk(s->mpu, "omap3_54m_fclk")));
2162         TRACE("omap3_dss1_alwon_fclk %lld",
2163               omap_clk_getrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk")));
2164         TRACE("omap3_cam_mclk %lld",
2165               omap_clk_getrate(omap_findclk(s->mpu, "omap3_cam_mclk")));
2166         TRACE("omap3_per_alwon_clk %lld",
2167               omap_clk_getrate(omap_findclk(s->mpu, "omap3_per_alwon_clk")));
2168         TRACE("omap3_48m_fclk %lld",
2169               omap_clk_getrate(omap_findclk(s->mpu, "omap3_48m_fclk")));
2170         TRACE("omap3_12m_fclk %lld",
2171               omap_clk_getrate(omap_findclk(s->mpu, "omap3_12m_fclk")));
2172     }
2173 }
2174
2175 static inline void omap3_cm_dpll5_update(struct omap3_cm_s *s)
2176 {
2177          uint32_t m, n, m2, cm_idlest2_ckgen;
2178     uint32_t bypass = 1;
2179
2180     cm_idlest2_ckgen = s->cm_idlest2_ckgen;;
2181
2182     /*dpll5 bypass mode */
2183     if ((cm_idlest2_ckgen & 0x1) == 0x0) 
2184     {
2185         bypass = 1;
2186     }
2187
2188     if (bypass == 1)
2189     {
2190         omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), 1, 1);
2191     }
2192     else
2193     {
2194          m = (s->cm_clksel4_pll & 0x7ff00)>>8;
2195         n = s->cm_clksel4_pll & 0x3f00;
2196         m2 = s->cm_clksel5_pll & 0x1f;
2197
2198         TRACE("dpll5 m %d n %d m2 %d",m,n,m2);
2199         omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), (n + 1) * m2,
2200                          m);
2201         TRACE("omap3_120m_fclk %lld",
2202               omap_clk_getrate(omap_findclk(s->mpu, "omap3_120m_fclk")));
2203     }
2204 }
2205
2206 static inline void omap3_cm_48m_update(struct omap3_cm_s *s)
2207 {
2208     if (s->cm_clksel1_pll & 0x8)
2209     {
2210         /*parent is sysaltclk */
2211         omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
2212                           omap_findclk(s->mpu, "omap3_sys_altclk"));
2213         omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
2214                           omap_findclk(s->mpu, "omap3_sys_altclk"));
2215         /*TODO:need to set rate ? */
2216
2217     }
2218     else
2219     {
2220         omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
2221                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2222         omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
2223                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2224         omap_clk_setrate(omap_findclk(s->mpu, "omap3_48m_fclk"), 2, 1);
2225         omap_clk_setrate(omap_findclk(s->mpu, "omap3_12m_fclk"), 8, 1);
2226
2227     }
2228
2229 }
2230
2231 static inline void omap3_cm_gp10_update(struct omap3_cm_s *s)
2232 {
2233     omap_clk gp10_fclk = omap_findclk(s->mpu, "omap3_gp10_fclk");
2234
2235     if (s->cm_clksel_core & 0x40)
2236         omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
2237     else
2238         omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
2239
2240     /*Tell GPTIMER10 to generate new clk rate */
2241     omap_gp_timer_change_clk(s->mpu->gptimer[9]);
2242     TRACE("omap3_gp10_fclk %lld",
2243           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp10_fclk")));
2244 }
2245
2246 static inline void omap3_cm_gp11_update(struct omap3_cm_s *s)
2247 {
2248     omap_clk gp11_fclk = omap_findclk(s->mpu, "omap3_gp11_fclk");
2249
2250     if (s->cm_clksel_core & 0x80)
2251         omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
2252     else
2253         omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
2254     /*Tell GPTIMER11 to generate new clk rate */
2255     omap_gp_timer_change_clk(s->mpu->gptimer[10]);
2256     TRACE("omap3_gp11_fclk %lld",
2257           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp11_fclk")));
2258 }
2259
2260 static inline void omap3_cm_l3clk_update(struct omap3_cm_s *s)
2261 {
2262     omap_clk l3_iclk = omap_findclk(s->mpu, "omap3_l3_iclk");
2263     if ((s->cm_clksel_core & 0x3) == 0x1)
2264         omap_clk_setrate(l3_iclk, 1, 1);
2265     else if ((s->cm_clksel_core & 0x3) == 0x2)
2266         omap_clk_setrate(l3_iclk, 2, 1);
2267 }
2268
2269 static inline void omap3_cm_l4clk_update(struct omap3_cm_s *s)
2270 {
2271     omap_clk l4_iclk = omap_findclk(s->mpu, "omap3_l4_iclk");
2272     if ((s->cm_clksel_core & 0xc) == 0x4)
2273         omap_clk_setrate(l4_iclk, 1, 1);
2274     else if ((s->cm_clksel_core & 0xc) == 0x8)
2275         omap_clk_setrate(l4_iclk, 2, 1);
2276 }
2277
2278 static inline void omap3_cm_per_gptimer_update(struct omap3_cm_s *s)
2279 {
2280     uint32_t cm_clksel_per = s->cm_clksel_per;
2281
2282     if (cm_clksel_per & 0x1)
2283         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
2284                           omap_findclk(s->mpu, "omap3_sys_clk"));
2285     else
2286         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
2287                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2288     omap_gp_timer_change_clk(s->mpu->gptimer[1]);
2289
2290     if (cm_clksel_per & 0x2)
2291         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
2292                           omap_findclk(s->mpu, "omap3_sys_clk"));
2293     else
2294         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
2295                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2296     omap_gp_timer_change_clk(s->mpu->gptimer[2]);
2297
2298     if (cm_clksel_per & 0x4)
2299         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
2300                           omap_findclk(s->mpu, "omap3_sys_clk"));
2301     else
2302         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
2303                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2304     omap_gp_timer_change_clk(s->mpu->gptimer[3]);
2305
2306     if (cm_clksel_per & 0x8)
2307         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
2308                           omap_findclk(s->mpu, "omap3_sys_clk"));
2309     else
2310         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
2311                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2312     omap_gp_timer_change_clk(s->mpu->gptimer[4]);
2313
2314     if (cm_clksel_per & 0x10)
2315         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
2316                           omap_findclk(s->mpu, "omap3_sys_clk"));
2317     else
2318         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
2319                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2320     omap_gp_timer_change_clk(s->mpu->gptimer[5]);
2321     
2322     if (cm_clksel_per & 0x20)
2323         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
2324                           omap_findclk(s->mpu, "omap3_sys_clk"));
2325     else
2326         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
2327                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2328     omap_gp_timer_change_clk(s->mpu->gptimer[6]);
2329
2330
2331     if (cm_clksel_per & 0x40)
2332         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
2333                           omap_findclk(s->mpu, "omap3_sys_clk"));
2334     else
2335         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
2336                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2337     omap_gp_timer_change_clk(s->mpu->gptimer[7]);
2338     
2339     if (cm_clksel_per & 0x80)
2340         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
2341                           omap_findclk(s->mpu, "omap3_sys_clk"));
2342     else
2343         omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
2344                           omap_findclk(s->mpu, "omap3_32k_fclk"));
2345     omap_gp_timer_change_clk(s->mpu->gptimer[8]);
2346
2347     /*TODO:Tell GPTIMER to generate new clk rate */
2348     TRACE("omap3_gp2_fclk %lld",
2349           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp2_fclk")));
2350     TRACE("omap3_gp3_fclk %lld",
2351           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp3_fclk")));
2352         TRACE("omap3_gp4_fclk %lld",
2353           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp4_fclk")));
2354     TRACE("omap3_gp5_fclk %lld",
2355           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp5_fclk")));
2356     TRACE("omap3_gp6_fclk %lld",
2357           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp6_fclk")));
2358     TRACE("omap3_gp7_fclk %lld",
2359           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp7_fclk")));
2360     TRACE("omap3_gp8_fclk %lld",
2361           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp8_fclk")));
2362     TRACE("omap3_gp9_fclk %lld",
2363           omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp9_fclk")));
2364 }
2365
2366 static inline void omap3_cm_clkout2_update(struct omap3_cm_s *s)
2367 {
2368         uint32 divor;
2369         
2370         if (!s->cm_clkout_ctrl&0x80)
2371                 return;
2372
2373         switch (s->cm_clkout_ctrl&0x3)
2374         {
2375                 case 0x0:
2376                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2377                           omap_findclk(s->mpu, "omap3_core_clk"));
2378                         break;
2379                 case 0x1:
2380                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2381                           omap_findclk(s->mpu, "omap3_sys_clk"));
2382                         break;
2383                 case 0x2:
2384                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2385                           omap_findclk(s->mpu, "omap3_96m_fclk"));
2386                         break;
2387                 case 0x3:
2388                         omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
2389                           omap_findclk(s->mpu, "omap3_54m_fclk"));
2390                         break;
2391         }
2392
2393         divor = (s->cm_clkout_ctrl&0x31)>>3;
2394         divor = 1<<divor;
2395         omap_clk_setrate(omap_findclk(s->mpu, "omap3_sys_clkout2"), divor, 1);
2396         
2397 }
2398
2399 static void omap3_cm_reset(struct omap3_cm_s *s)
2400 {
2401     s->cm_fclken_iva2 = 0x0;
2402     s->cm_clken_pll_iva2 = 0x11;
2403     s->cm_idlest_iva2 = 0x1;
2404     s->cm_idlest_pll_iva2 = 0x0;
2405     s->cm_autoidle_pll_iva2 = 0x0;
2406     s->cm_clksel1_pll_iva2 = 0x80000;
2407     s->cm_clksel2_pll_iva2 = 0x1;
2408     s->cm_clkstctrl_iva2 = 0x0;
2409     s->cm_clkstst_iva2 = 0x0;
2410
2411     s->cm_revision = 0x10;
2412     s->cm_sysconfig = 0x1;
2413
2414     s->cm_clken_pll_mpu = 0x15;
2415     s->cm_idlest_mpu = 0x1;
2416     s->cm_idlest_pll_mpu = 0x0;
2417     s->cm_autoidle_pll_mpu = 0x0;
2418     s->cm_clksel1_pll_mpu = 0x80000;
2419     s->cm_clksel2_pll_mpu = 0x1;
2420     s->cm_clkstctrl_mpu = 0x0;
2421     s->cm_clkstst_mpu = 0x0;
2422
2423     s->cm_fclken1_core = 0x0;
2424     s->cm_fclken3_core = 0x0;
2425     s->cm_iclken1_core = 0x42;
2426     s->cm_iclken2_core = 0x0;
2427     s->cm_iclken3_core = 0x0;
2428     /*allow access to devices*/
2429     s->cm_idlest1_core = 0x0;
2430     s->cm_idlest2_core = 0x0;
2431     /*ide status =0 */
2432     s->cm_idlest3_core = 0xa; 
2433     s->cm_autoidle1_core = 0x0;
2434     s->cm_autoidle2_core = 0x0;
2435     s->cm_autoidle3_core = 0x0;
2436     s->cm_clksel_core = 0x105;
2437     s->cm_clkstctrl_core = 0x0;
2438     s->cm_clkstst_core = 0x0;
2439
2440     s->cm_fclken_sgx = 0x0;
2441     s->cm_iclken_sgx = 0x0;
2442     s->cm_idlest_sgx = 0x1;
2443     s->cm_clksel_sgx = 0x0;
2444     s->cm_sleepdep_sgx = 0x0;
2445     s->cm_clkstctrl_sgx = 0x0;
2446     s->cm_clkstst_sgx = 0x0;
2447
2448     s->cm_fclken_wkup = 0x0;
2449     s->cm_iclken_wkup = 0x0;
2450     /*assume all clock can be accessed*/
2451     s->cm_idlest_wkup = 0x0;
2452     s->cm_autoidle_wkup = 0x0;
2453     s->cm_clksel_wkup = 0x12;
2454
2455     s->cm_clken_pll = 0x110015;
2456     s->cm_clken2_pll = 0x11;
2457     s->cm_idlest_ckgen = 0x0;
2458     s->cm_idlest2_ckgen = 0x0;
2459     s->cm_autoidle_pll = 0x0;
2460     s->cm_autoidle2_pll = 0x0;
2461     s->cm_clksel1_pll = 0x8000040;
2462     s->cm_clksel2_pll = 0x0;
2463     s->cm_clksel3_pll = 0x1;
2464     s->cm_clksel4_pll = 0x0;
2465     s->cm_clksel5_pll = 0x1;
2466     s->cm_clkout_ctrl = 0x3;
2467
2468
2469     s->cm_fclken_dss = 0x0;
2470     s->cm_iclken_dss = 0x0;
2471     /*dss can be accessed*/
2472     s->cm_idlest_dss = 0x0;
2473     s->cm_autoidle_dss = 0x0;
2474     s->cm_clksel_dss = 0x1010;
2475     s->cm_sleepdep_dss = 0x0;
2476     s->cm_clkstctrl_dss = 0x0;
2477     s->cm_clkstst_dss = 0x0;
2478
2479     s->cm_fclken_cam = 0x0;
2480     s->cm_iclken_cam = 0x0;
2481     s->cm_idlest_cam = 0x1;
2482     s->cm_autoidle_cam = 0x0;
2483     s->cm_clksel_cam = 0x10;
2484     s->cm_sleepdep_cam = 0x0;
2485     s->cm_clkstctrl_cam = 0x0;
2486     s->cm_clkstst_cam = 0x0;
2487
2488     s->cm_fclken_per = 0x0;
2489     s->cm_iclken_per = 0x0;
2490     //s->cm_idlest_per = 0x3ffff;
2491     s->cm_idlest_per = 0x0; //enable GPIO access
2492     s->cm_autoidle_per = 0x0;
2493     s->cm_clksel_per = 0x0;
2494     s->cm_sleepdep_per = 0x0;
2495     s->cm_clkstctrl_per = 0x0;
2496     s->cm_clkstst_per = 0x0;
2497
2498     s->cm_clksel1_emu = 0x10100a50;
2499     s->cm_clkstctrl_emu = 0x2;
2500     s->cm_clkstst_emu = 0x0;
2501     s->cm_clksel2_emu = 0x0;
2502     s->cm_clksel3_emu = 0x0;
2503
2504     s->cm_polctrl = 0x0;
2505
2506     s->cm_idlest_neon = 0x1;
2507     s->cm_clkstctrl_neon = 0x0;
2508
2509     s->cm_fclken_usbhost = 0x0;
2510     s->cm_iclken_usbhost = 0x0;
2511     s->cm_idlest_usbhost = 0x3;
2512     s->cm_autoidle_usbhost = 0x0;
2513     s->cm_sleepdep_usbhost = 0x0;
2514     s->cm_clkstctrl_usbhost = 0x0;
2515     s->cm_clkstst_usbhost = 0x0;
2516 }
2517
2518 static uint32_t omap3_cm_read(void *opaque, target_phys_addr_t addr)
2519 {
2520     struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
2521     uint32_t ret;
2522     uint32_t bypass = 0, m;
2523
2524     TRACE("%04x", addr);
2525     switch (addr)
2526     {
2527     case 0x0:
2528         return s->cm_fclken_iva2;
2529     case 0x04:
2530         return s->cm_clken_pll_iva2;
2531     case 0x20:
2532         return s->cm_idlest_iva2;
2533     case 0x24:
2534         if (((s->cm_clken_pll_iva2 & 0x7) == 0x5)
2535             || ((s->cm_clken_pll_iva2 & 0x7) == 0x1))
2536         {
2537             bypass = 1;
2538         }
2539         else if ((s->cm_clken_pll_iva2 & 0x7) == 0x7)
2540         {
2541             m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
2542             if ((m == 0) || (m == 1))
2543                 bypass = 1;
2544             else
2545                 bypass = 0;
2546         }
2547         if (bypass)
2548             return 0;
2549         else
2550             return 1;
2551     case 0x34:
2552         return s->cm_autoidle_pll_iva2;
2553     case 0x40:
2554         return s->cm_clksel1_pll_iva2;
2555     case 0x44:
2556         return s->cm_clksel2_pll_iva2;
2557     case 0x48:
2558         return s->cm_clkstctrl_iva2;
2559     case 0x4c:
2560         return s->cm_clkstst_iva2;
2561
2562    case 0x800:
2563                 return s->cm_revision;
2564         case 0x810:
2565                 return s->cm_sysconfig;
2566
2567         
2568     case 0x904:                /*CM_CLKEN_PLL_MPU */
2569         return s->cm_clken_pll_mpu;
2570    case 0x920:
2571                 return s->cm_idlest_mpu & 0x0;  /*MPU is active*/
2572     case 0x924:
2573         if ((s->cm_clken_pll_mpu & 0x7) == 0x5)
2574         {
2575             bypass = 1;
2576         }
2577         else if ((s->cm_clken_pll_mpu & 0x7) == 0x7)
2578         {
2579             m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
2580             if ((m == 0) || (m == 1))
2581                 bypass = 1;
2582             else
2583                 bypass = 0;
2584         }
2585         if (bypass)
2586             return 0;
2587         else
2588             return 1;
2589     case 0x934:
2590         return s->cm_autoidle_pll_mpu;
2591     case 0x940:
2592         return s->cm_clksel1_pll_mpu;
2593     case 0x944:
2594         return s->cm_clksel2_pll_mpu;
2595      case 0x948:
2596         return s->cm_clkstctrl_mpu;
2597      case 0x94c:
2598         return s->cm_clkstst_mpu;
2599
2600
2601         
2602     case 0xa00:
2603         return s->cm_fclken1_core;
2604     case 0xa08:
2605         return s->cm_fclken3_core;
2606     case 0xa10:
2607         return s->cm_iclken1_core;
2608     case 0xa14:
2609          return s->cm_iclken2_core;
2610     case 0xa20:
2611         return s->cm_idlest1_core;
2612     case 0xa24:
2613         return s->cm_idlest2_core;
2614     case 0xa28:
2615         return s->cm_idlest3_core;
2616     case 0xa30:
2617         return s->cm_autoidle1_core;
2618     case 0xa34:
2619         return s->cm_autoidle2_core;
2620     case 0xa38:
2621         return s->cm_autoidle3_core;
2622     case 0xa40:                /*CM_CLKSEL_CORE */
2623         return s->cm_clksel_core;
2624     case 0xa48:
2625          return s->cm_clkstctrl_core;
2626      case 0xa4c:
2627         return s->cm_clkstst_core;
2628
2629    case 0xb00:
2630                 return s->cm_fclken_sgx;
2631         case 0xb10:
2632                 return s->cm_iclken_sgx;
2633         case 0xb20:
2634                 return s->cm_idlest_sgx&0x0;
2635    case 0xb40:                /*CM_CLKSEL_SGX */
2636         return s->cm_clksel_sgx;
2637    case 0xb48:
2638                 return s->cm_clkstctrl_sgx;
2639         case 0xb4c:
2640                 return s->cm_clkstst_sgx;
2641
2642                 
2643     case 0xc00:                /*CM_FCLKEN_WKUP */
2644         return s->cm_fclken_wkup;
2645     case 0xc10:                /*CM_ICLKEN_WKUP */
2646         return s->cm_iclken_wkup;
2647     case 0xc20:                /*CM_IDLEST_WKUP */
2648         /*TODO: Check whether the timer can be accessed. */
2649         return 0x0;
2650     case 0xc30:
2651         return s->cm_idlest_wkup;
2652     case 0xc40:
2653         return s->cm_clksel_wkup;
2654     case 0xc48:
2655         return s->cm_c48;
2656
2657         
2658     case 0xd00:                /*CM_CLKEN_PLL */
2659         return s->cm_clken_pll;
2660     case 0xd04:
2661         return s->cm_clken2_pll;
2662     case 0xd20:
2663          /*FIXME: all clock is active. we do not care it. */
2664         ret = 0x3ffff;
2665
2666         /*DPLL3*/
2667         bypass = 0;
2668         if (((s->cm_clken_pll & 0x7) == 0x5) || ((s->cm_clken_pll & 0x7) == 0x6))
2669                 bypass = 1;
2670         else if ((s->cm_clken_pll & 0x7) == 0x7) {
2671             m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
2672             if ((m == 0) || (m == 1))
2673                 bypass = 1;
2674             else
2675                 bypass = 0;
2676         }
2677         if (bypass)
2678             ret &= 0xfffe;
2679         
2680         /*DPLL4*/
2681             bypass = 0;
2682             if ((s->cm_clken_pll & 0x70000) == 0x10000)
2683             bypass = 1;
2684         else if ((s->cm_clken_pll & 0x70000) == 0x70000) {
2685             m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
2686             if ((m == 0) || (m == 1))
2687                 bypass = 1;
2688             else
2689                 bypass = 0;
2690         }
2691         if (bypass)
2692             ret &= 0xfffd;
2693         return ret;
2694         
2695     case 0xd24:
2696         return s->cm_idlest2_ckgen;
2697     case 0xd30:
2698         return s->cm_autoidle_pll;
2699     case 0xd34:
2700         return s->cm_autoidle2_pll;
2701     case 0xd40:                /*CM_CLKSEL1_PLL */
2702         return s->cm_clksel1_pll;
2703     case 0xd44:
2704         return s->cm_clksel2_pll;
2705     case 0xd48:                /*CM_CLKSEL3_PLL */
2706         return s->cm_clksel3_pll;
2707     case 0xd4c:
2708         return s->cm_clksel4_pll;
2709     case 0xd50:                /*CM_CLKSEL5_PLL */
2710         return s->cm_clksel5_pll;
2711     case 0xd70:
2712          return s->cm_clkout_ctrl;
2713
2714          
2715     case 0xe00:
2716         return s->cm_fclken_dss;
2717         case 0xe10:
2718         return s->cm_iclken_dss;
2719     case 0xe20:
2720         return s->cm_idlest_dss;
2721     case 0xe30:
2722         return s->cm_autoidle_dss;
2723     case 0xe40:
2724         return s->cm_clksel_dss;
2725     case 0xe44:
2726         return s->cm_sleepdep_dss;
2727     case 0xe48:
2728         return s->cm_clkstctrl_dss;
2729     case 0xe4c:
2730         return s->cm_clkstst_dss;
2731
2732         
2733     case 0xf00:
2734         return s->cm_fclken_cam;
2735     case 0xf10:
2736         return s->cm_iclken_cam;
2737     case 0xf20:
2738         return s->cm_idlest_cam&0x0;
2739     case 0xf30:
2740         return s->cm_autoidle_cam;
2741     case 0xf40:
2742         return s->cm_clksel_cam;
2743     case 0xf44:
2744         return s->cm_sleepdep_cam;
2745     case 0xf48:
2746         return s->cm_clkstctrl_cam;
2747     case 0xf4c:
2748         return s->cm_clkstst_cam;
2749
2750         
2751     case 0x1000:
2752         return s->cm_fclken_per;
2753     case 0x1010:
2754         return s->cm_iclken_per;
2755     case 0x1020:
2756         return s->cm_idlest_per ;
2757     case 0x1030:
2758         return s->cm_autoidle_per;
2759     case 0x1040:
2760         return s->cm_clksel_per;
2761     case 0x1044:
2762         return s->cm_sleepdep_per;
2763     case 0x1048:
2764         return s->cm_clkstctrl_per;
2765     case 0x104c:
2766                 return s->cm_clkstst_per;
2767
2768         
2769     case 0x1140:               /*CM_CLKSEL1_EMU */
2770         return s->cm_clksel1_emu;
2771     case 0x1148:
2772          return s->cm_clkstctrl_emu;
2773     case 0x114c:
2774         return s->cm_clkstst_emu&0x0;
2775     case 0x1150:
2776         return s->cm_clksel2_emu;
2777     case 0x1154:
2778         return s->cm_clksel3_emu;
2779
2780    case 0x129c:
2781                 return s->cm_polctrl;
2782
2783         case 0x1320:
2784                 return s->cm_idlest_neon&0x0;
2785         case 0x1348:
2786                 return s->cm_clkstctrl_neon;
2787
2788         case 0x1400:
2789                 return s->cm_fclken_usbhost;
2790         case 0x1410:
2791                 return s->cm_iclken_usbhost;
2792         case 0x1420:
2793                 return s->cm_idlest_usbhost&0x0;
2794     case 0x1430:
2795         return s->cm_autoidle_usbhost;
2796     case 0x1444:
2797         return s->cm_sleepdep_usbhost;
2798     case 0x1448:
2799         return s->cm_clkstctrl_usbhost;
2800     case 0x144c:
2801         return s->cm_clkstst_usbhost;
2802
2803     default:
2804         printf("omap3_cm_read addr %x pc %x \n", addr, cpu_single_env->regs[15] );
2805         exit(-1);
2806     }
2807 }
2808
2809
2810 static void omap3_cm_write(void *opaque, target_phys_addr_t addr,
2811                            uint32_t value)
2812 {
2813     struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
2814
2815     TRACE("%04x = %08x", addr, value);
2816     switch (addr)
2817     {
2818     case 0x20:
2819     case 0x24:
2820     case 0x4c:
2821     case 0x800:
2822     case 0x920:
2823     case 0x924:
2824     case 0x94c:
2825     case 0xa20:
2826     case 0xa24:
2827     case 0xa28:
2828     case 0xa4c:
2829     case 0xb20:
2830     case 0xb4c:
2831     case 0xc20:                /*CM_IDLEST_WKUP */
2832     case 0xd20:
2833     case 0xd24:
2834     case 0xe20:
2835     case 0xe4c:
2836     case 0xf20:
2837     case 0xf4c:
2838     case 0x1020:
2839     case 0x104c:
2840     case 0x114c:
2841     case 0x1320:
2842     case 0x1420:
2843     case 0x144c:
2844         OMAP_RO_REG(addr);
2845         exit(-1);
2846         break;
2847         
2848     case 0x0:
2849         s->cm_fclken_iva2 = value & 0x1;
2850         break;
2851     case 0x4:                  /*CM_CLKEN_PLL_IVA2 */
2852         s->cm_clken_pll_iva2 = value & 0x7ff;
2853         omap3_cm_iva2_update(s);
2854         break;
2855     case 0x34:
2856         s->cm_autoidle_pll_iva2 = value & 0x7;
2857         break;
2858     case 0x40:
2859         s->cm_clksel1_pll_iva2 = value & 0x3fff7f;
2860         //printf("value %x s->cm_clksel1_pll_iva2 %x \n",value,s->cm_clksel1_pll_iva2);
2861         omap3_cm_iva2_update(s);
2862         break;
2863     case 0x44:
2864         s->cm_clksel2_pll_iva2 = value & 0x1f;
2865         omap3_cm_iva2_update(s);
2866         break;
2867     case 0x48:
2868         s->cm_clkstctrl_iva2 = value& 0x3;
2869         break;
2870
2871     case 0x810:
2872         s->cm_sysconfig = value & 0x1;
2873         break;
2874
2875         
2876     case 0x904:                /*CM_CLKEN_PLL_MPU */
2877         s->cm_clken_pll_mpu = value & 0x7ff;
2878         omap3_cm_mpu_update(s);
2879         break;
2880     case 0x934:
2881         s->cm_autoidle_pll_mpu = value & 0x7;
2882         break;
2883     case 0x940:
2884         //printf("s->cm_clksel1_pll_mpu  %x\n",s->cm_clksel1_pll_mpu );
2885         s->cm_clksel1_pll_mpu = value & 0x3fff7f;
2886         omap3_cm_mpu_update(s);
2887         break;
2888     case 0x944:
2889         s->cm_clksel2_pll_mpu = value & 0x1f;
2890         omap3_cm_mpu_update(s);
2891         break;
2892     case 0x948:
2893         s->cm_clkstctrl_mpu = value & 0x3;
2894         break;
2895
2896         
2897     case 0xa00:
2898         s->cm_fclken1_core = value & 0x43fffe00;
2899          break;
2900     case 0xa08:
2901          s->cm_fclken3_core = value & 0x7;
2902          break;
2903     case 0xa10:
2904         s->cm_iclken1_core = value & 0x637ffed2;
2905         s->cm_idlest1_core = ~s->cm_iclken1_core;
2906         /* TODO: replace code below with real implementation */
2907         s->cm_idlest1_core &= ~0x20; /* HS OTG USB idle */
2908         s->cm_idlest1_core |= 4; /* SDMA in standby */
2909         break;
2910     case 0xa14:
2911          s->cm_iclken2_core = value & 0x1f;
2912          break;
2913     case 0xa18:
2914         s->cm_iclken3_core = value & 0x4;
2915         s->cm_idlest3_core = 0xd & ~(s->cm_iclken3_core & 4);
2916         break;
2917     case 0xa30:
2918         s->cm_autoidle1_core = value & 0x7ffffed0;
2919         break;
2920     case 0xa34:
2921         s->cm_autoidle2_core = value & 0x1f;
2922         break;
2923     case 0xa38:
2924         s->cm_autoidle3_core = value & 0x2;
2925         break;
2926     case 0xa40:                /*CM_CLKSEL_CORE */
2927         s->cm_clksel_core = (value & 0xff);
2928         s->cm_clksel_core |= 0x100;
2929         omap3_cm_gp10_update(s);
2930         omap3_cm_gp11_update(s);
2931         omap3_cm_l3clk_update(s);
2932         omap3_cm_l4clk_update(s);
2933         break;
2934     case 0xa48:
2935         s->cm_clkstctrl_core = value & 0xf;
2936         break;
2937
2938     case 0xb00:
2939         s->cm_fclken_sgx = value &0x2;
2940         break;
2941     case 0xb10:
2942         s->cm_iclken_sgx = value & 0x1;
2943         break;
2944     case 0xb40:                /*CM_CLKSEL_SGX */
2945         /*TODO: SGX Clock!! */
2946         s->cm_clksel_sgx = value;
2947         break;
2948     case 0xb44:
2949         s->cm_sleepdep_sgx = value &0x2;
2950         break;
2951     case 0xb48:
2952         s->cm_clkstctrl_sgx = value & 0x3;
2953         break;
2954
2955     
2956     case 0xc00:                /*CM_FCLKEN_WKUP */
2957         s->cm_fclken_wkup = value & 0x2e9;
2958         break;
2959     case 0xc10:                /*CM_ICLKEN_WKUP */
2960         s->cm_iclken_wkup = value & 0x2ff;
2961         break;
2962     case 0xc30:
2963         s->cm_autoidle_wkup = value & 0x23f;
2964         break;
2965     case 0xc40:                /*CM_CLKSEL_WKUP */
2966         s->cm_clksel_wkup = value & 0x7f;
2967         omap3_cm_clksel_wkup_update(s, s->cm_clksel_wkup);
2968         break;
2969
2970         
2971     case 0xd00:                /*CM_CLKEN_PLL */
2972         s->cm_clken_pll = value & 0xffff17ff;
2973         omap3_cm_dpll3_update(s);
2974         omap3_cm_dpll4_update(s);
2975         break;
2976     case 0xd04:
2977         s->cm_clken2_pll = value & 0x7ff;
2978         break;
2979     case 0xd30:
2980         s->cm_autoidle_pll = value & 0x3f;
2981         break;
2982     case 0xd34:
2983         s->cm_autoidle2_pll = value & 0x7;
2984         break;
2985     case 0xd40:                /*CM_CLKSEL1_PLL */
2986         //OMAP3_DEBUG(("WD40 value %x \n",value));
2987         s->cm_clksel1_pll = value & 0xffffbffc;
2988         //OMAP3_DEBUG(("WD40 value %x \n",value));
2989         omap3_cm_dpll3_update(s);
2990         omap3_cm_48m_update(s);
2991         break;
2992     case 0xd44:
2993         s->cm_clksel2_pll = value & 0x7ff7f;
2994         omap3_cm_dpll4_update(s);
2995         break;
2996     case 0xd48:                /*CM_CLKSEL3_PLL */
2997         s->cm_clksel3_pll = value & 0x1f;
2998         omap3_cm_dpll4_update(s);
2999         break;
3000     case 0xd4c:                /*CM_CLKSEL4_PLL */  
3001         s->cm_clksel4_pll = value & 0x7ff7f;
3002         omap3_cm_dpll5_update(s);
3003         break;
3004      case 0xd50:                /*CM_CLKSEL5_PLL */
3005         s->cm_clksel5_pll = value & 0x1f;
3006         omap3_cm_dpll5_update(s);
3007         break;
3008     case 0xd70:
3009         s->cm_clkout_ctrl = value & 0xbb;
3010         omap3_cm_clkout2_update(s);
3011         break;
3012         
3013     case 0xe00:
3014         s->cm_fclken_dss = value & 0x7;
3015         break;
3016         case 0xe10:
3017         s->cm_iclken_dss = value & 0x1;
3018         break;
3019     case 0xe30:
3020         s->cm_autoidle_dss = value & 0x1;
3021         break;
3022     case 0xe40:
3023         s->cm_clksel_dss = value & 0x1f1f;
3024         omap3_cm_dpll4_update(s);
3025         break;
3026    case 0xe44:
3027                 s->cm_sleepdep_dss = value & 0x7;
3028        break;
3029    case 0xe48:
3030                 s->cm_clkstctrl_dss = value & 0x3;
3031        break;
3032         
3033     case 0xf00:
3034         s->cm_fclken_cam = value & 0x3;
3035         break;
3036     case 0xf10:
3037         s->cm_iclken_cam = value & 0x1;
3038         break;
3039     case 0xf30:
3040         s->cm_autoidle_cam = value & 0x1;
3041         break;
3042     case 0xf40:
3043         s->cm_clksel_cam = value & 0x1f;
3044         omap3_cm_dpll4_update(s);
3045         break;
3046     case 0xf44:
3047         s->cm_sleepdep_cam = value & 0x2;
3048         break;
3049     case 0xf48:
3050         s->cm_clkstctrl_cam = value & 0x3;
3051         break;
3052    
3053     case 0x1000:
3054         s->cm_fclken_per = value & 0x3ffff;
3055         break;
3056     case 0x1010:
3057         s->cm_iclken_per = value & 0x3ffff;
3058         break;
3059     
3060     case 0x1030:
3061         s->cm_autoidle_per = value &0x3ffff;
3062         break;
3063     case 0x1040:
3064         s->cm_clksel_per = value & 0xff;
3065         omap3_cm_per_gptimer_update(s);
3066         break;
3067     case 0x1044:
3068         s->cm_sleepdep_per = value & 0x6;
3069         break;
3070     case 0x1048:
3071          s->cm_clkstctrl_per = value &0x7;
3072          break;
3073          
3074     case 0x1140:               /*CM_CLKSEL1_EMU */
3075         s->cm_clksel1_emu = value & 0x1f1f3fff;
3076         //printf("cm_clksel1_emu %x\n",s->cm_clksel1_emu);
3077         omap3_cm_dpll3_update(s);
3078         omap3_cm_dpll4_update(s);
3079         break;
3080     case 0x1148:
3081         s->cm_clkstctrl_emu = value & 0x3;
3082         break;
3083          case 0x1150:
3084                  s->cm_clksel2_emu = value & 0xfff7f;
3085                  omap3_cm_dpll3_update(s);
3086         break;
3087     case 0x1154:
3088          s->cm_clksel3_emu = value & 0xfff7f;
3089                  omap3_cm_dpll4_update(s);
3090         break;
3091
3092     case 0x129c:
3093          s->cm_polctrl = value & 0x1;
3094          break;
3095
3096    case 0x1348:
3097                 s->cm_clkstctrl_neon = value & 0x3;
3098                 break;
3099
3100         case 0x1400:
3101                 s->cm_fclken_usbhost = value & 0x3;
3102                 break;
3103         case 0x1410:
3104                 s->cm_iclken_usbhost = value & 0x1;
3105                 break;
3106     case 0x1430:
3107         s->cm_autoidle_usbhost = value & 0x1;
3108         break;
3109     case 0x1444:
3110         s->cm_sleepdep_usbhost = value & 0x6;
3111         break;
3112     case 0x1448:
3113         s->cm_clkstctrl_usbhost = value & 0x3;
3114         break;
3115    
3116     default:
3117         printf("omap3_cm_write addr %x value %x pc %x\n", addr, value,cpu_single_env->regs[15] );
3118         exit(-1);
3119     }
3120 }
3121
3122
3123
3124 static CPUReadMemoryFunc *omap3_cm_readfn[] = {
3125     omap_badwidth_read32,
3126     omap_badwidth_read32,
3127     omap3_cm_read,
3128 };
3129
3130 static CPUWriteMemoryFunc *omap3_cm_writefn[] = {
3131     omap_badwidth_write32,
3132     omap_badwidth_write32,
3133     omap3_cm_write,
3134 };
3135
3136 struct omap3_cm_s *omap3_cm_init(struct omap_target_agent_s *ta,
3137                                  qemu_irq mpu_int, qemu_irq dsp_int,
3138                                  qemu_irq iva_int, struct omap_mpu_state_s *mpu)
3139 {
3140     int iomemtype;
3141     struct omap3_cm_s *s = (struct omap3_cm_s *) qemu_mallocz(sizeof(*s));
3142
3143     s->irq[0] = mpu_int;
3144     s->irq[1] = dsp_int;
3145     s->irq[2] = iva_int;
3146     s->mpu = mpu;
3147     omap3_cm_reset(s);
3148
3149     iomemtype = l4_register_io_memory(0, omap3_cm_readfn, omap3_cm_writefn, s);
3150     omap_l4_attach(ta, 0, iomemtype);
3151     omap_l4_attach(ta, 1, iomemtype);
3152
3153     return s;
3154 }
3155
3156 #define OMAP3_SEC_WDT          1
3157 #define OMAP3_MPU_WDT         2
3158 #define OMAP3_IVA2_WDT        3
3159 /*omap3 watchdog timer*/
3160 struct omap3_wdt_s
3161 {
3162     qemu_irq irq;               /*IVA2 IRQ */
3163     struct omap_mpu_state_s *mpu;
3164     omap_clk clk;
3165     QEMUTimer *timer;
3166
3167     int active;
3168     int64_t rate;
3169     int64_t time;
3170     //int64_t ticks_per_sec;
3171
3172     uint32_t wd_sysconfig;
3173     uint32_t wd_sysstatus;
3174     uint32_t wisr;
3175     uint32_t wier;
3176     uint32_t wclr;
3177     uint32_t wcrr;
3178     uint32_t wldr;
3179     uint32_t wtgr;
3180     uint32_t wwps;
3181     uint32_t wspr;
3182
3183     /*pre and ptv in wclr */
3184     uint32_t pre;
3185     uint32_t ptv;
3186     //uint32_t val;
3187
3188     uint16_t writeh;            /* LSB */
3189     uint16_t readh;             /* MSB */
3190 };
3191
3192 static inline void omap3_wdt_timer_update(struct omap3_wdt_s *wdt_timer)
3193 {
3194     int64_t expires;
3195     if (wdt_timer->active)
3196     {
3197         expires = muldiv64(0xffffffffll - wdt_timer->wcrr,
3198                            ticks_per_sec, wdt_timer->rate);
3199         qemu_mod_timer(wdt_timer->timer, wdt_timer->time + expires);
3200     }
3201     else
3202         qemu_del_timer(wdt_timer->timer);
3203 }
3204
3205 static void omap3_wdt_clk_setup(struct omap3_wdt_s *timer)
3206 {
3207     /*TODO: Add irq as user to clk */
3208 }
3209
3210 static inline uint32_t omap3_wdt_timer_read(struct omap3_wdt_s *timer)
3211 {
3212     uint64_t distance;
3213
3214     if (timer->active)
3215     {
3216         distance = qemu_get_clock(vm_clock) - timer->time;
3217         distance = muldiv64(distance, timer->rate, ticks_per_sec);
3218
3219         if (distance >= 0xffffffff - timer->wcrr)
3220             return 0xffffffff;
3221         else
3222             return timer->wcrr + distance;
3223     }
3224     else
3225         return timer->wcrr;
3226 }
3227
3228 /*
3229 static inline void omap3_wdt_timer_sync(struct omap3_wdt_s *timer)
3230 {
3231     if (timer->active) {
3232         timer->val = omap3_wdt_timer_read(timer);
3233         timer->time = qemu_get_clock(vm_clock);
3234     }
3235 }*/
3236
3237 static void omap3_wdt_reset(struct omap3_wdt_s *s, int wdt_index)
3238 {
3239     s->wd_sysconfig = 0x0;
3240     s->wd_sysstatus = 0x0;
3241     s->wisr = 0x0;
3242     s->wier = 0x0;
3243     s->wclr = 0x20;
3244     s->wcrr = 0x0;
3245     switch (wdt_index)
3246     {
3247     case OMAP3_MPU_WDT:
3248     case OMAP3_IVA2_WDT:
3249         s->wldr = 0xfffb0000;
3250         break;
3251     case OMAP3_SEC_WDT:
3252         s->wldr = 0xffa60000;
3253         break;
3254     }
3255     s->wtgr = 0x0;
3256     s->wwps = 0x0;
3257     s->wspr = 0x0;
3258
3259     switch (wdt_index)
3260     {
3261     case OMAP3_SEC_WDT:
3262     case OMAP3_MPU_WDT:
3263         s->active = 1;
3264         break;
3265     case OMAP3_IVA2_WDT:
3266         s->active = 0;
3267         break;
3268     }
3269     s->pre = s->wclr & (1 << 5);
3270     s->ptv = (s->wclr & 0x1c) >> 2;
3271     s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
3272
3273     s->active = 1;
3274     s->time = qemu_get_clock(vm_clock);
3275     omap3_wdt_timer_update(s);
3276 }
3277
3278 static uint32_t omap3_wdt_read32(void *opaque, target_phys_addr_t addr,
3279                                  int wdt_index)
3280 {
3281     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3282
3283     //uint32_t ret;
3284     //printf("omap3_wdt_read32 addr %x \n",addr);
3285     switch (addr)
3286     {
3287     case 0x10:                 /*WD_SYSCONFIG */
3288         return s->wd_sysconfig;
3289     case 0x14:                 /*WD_SYSSTATUS */
3290         return s->wd_sysstatus;
3291     case 0x18:
3292          /*WISR*/ return s->wisr & 0x1;
3293     case 0x1c:
3294          /*WIER*/ return s->wier & 0x1;
3295     case 0x24:
3296          /*WCLR*/ return s->wclr & 0x3c;
3297     case 0x28:
3298          /*WCRR*/ s->wcrr = omap3_wdt_timer_read(s);
3299         s->time = qemu_get_clock(vm_clock);
3300         return s->wcrr;
3301     case 0x2c:
3302          /*WLDR*/ return s->wldr;
3303     case 0x30:
3304          /*WTGR*/ return s->wtgr;
3305     case 0x34:
3306          /*WWPS*/ return s->wwps;
3307     case 0x48:
3308          /*WSPR*/ return s->wspr;
3309     default:
3310         printf("omap3_wdt_read32 addr %x \n", addr);
3311         exit(-1);
3312     }
3313 }
3314
3315 static uint32_t omap3_mpu_wdt_read16(void *opaque, target_phys_addr_t addr)
3316 {
3317     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3318     uint32_t ret;
3319
3320     if (addr & 2)
3321         return s->readh;
3322     else
3323     {
3324         ret = omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
3325         s->readh = ret >> 16;
3326         return ret & 0xffff;
3327     }
3328 }
3329
3330 static uint32_t omap3_mpu_wdt_read32(void *opaque, target_phys_addr_t addr)
3331 {
3332     return omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
3333 }
3334
3335 static void omap3_wdt_write32(void *opaque, target_phys_addr_t addr,
3336                               uint32_t value, int wdt_index)
3337 {
3338     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3339
3340     //printf("omap3_wdt_write32 addr %x value %x \n",addr,value);
3341     switch (addr)
3342     {
3343     case 0x14:                 /*WD_SYSSTATUS */
3344     case 0x34:
3345          /*WWPS*/ OMAP_RO_REG(addr);
3346         exit(-1);
3347         break;
3348     case 0x10:                 /*WD_SYSCONFIG */
3349         s->wd_sysconfig = value & 0x33f;
3350         break;
3351     case 0x18:
3352          /*WISR*/ s->wisr = value & 0x1;
3353         break;
3354     case 0x1c:
3355          /*WIER*/ s->wier = value & 0x1;
3356         break;
3357     case 0x24:
3358          /*WCLR*/ s->wclr = value & 0x3c;
3359         break;
3360     case 0x28:
3361          /*WCRR*/ s->wcrr = value;
3362         s->time = qemu_get_clock(vm_clock);
3363         omap3_wdt_timer_update(s);
3364         break;
3365     case 0x2c:
3366          /*WLDR*/ s->wldr = value;      /*It will take effect after next overflow */
3367         break;
3368     case 0x30:
3369          /*WTGR*/ if (value != s->wtgr)
3370         {
3371             s->wcrr = s->wldr;
3372             s->pre = s->wclr & (1 << 5);
3373             s->ptv = (s->wclr & 0x1c) >> 2;
3374             s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
3375             s->time = qemu_get_clock(vm_clock);
3376             omap3_wdt_timer_update(s);
3377         }
3378         s->wtgr = value;
3379         break;
3380     case 0x48:
3381          /*WSPR*/
3382             if (((value & 0xffff) == 0x5555) && ((s->wspr & 0xffff) == 0xaaaa))
3383         {
3384             s->active = 0;
3385             s->wcrr = omap3_wdt_timer_read(s);
3386             omap3_wdt_timer_update(s);
3387         }
3388         if (((value & 0xffff) == 0x4444) && ((s->wspr & 0xffff) == 0xbbbb))
3389         {
3390             s->active = 1;
3391             s->time = qemu_get_clock(vm_clock);
3392             omap3_wdt_timer_update(s);
3393         }
3394         s->wspr = value;
3395         break;
3396     default:
3397         printf("omap3_wdt_write32 addr %x \n", addr);
3398         exit(-1);
3399     }
3400 }
3401
3402 static void omap3_mpu_wdt_write16(void *opaque, target_phys_addr_t addr,
3403                                   uint32_t value)
3404 {
3405     struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
3406
3407     if (addr & 2)
3408         return omap3_wdt_write32(opaque, addr, (value << 16) | s->writeh,
3409                                  OMAP3_MPU_WDT);
3410     else
3411         s->writeh = (uint16_t) value;
3412 }
3413
3414 static void omap3_mpu_wdt_write32(void *opaque, target_phys_addr_t addr,
3415                                   uint32_t value)
3416 {
3417     omap3_wdt_write32(opaque, addr, value, OMAP3_MPU_WDT);
3418 }
3419
3420 static CPUReadMemoryFunc *omap3_mpu_wdt_readfn[] = {
3421     omap_badwidth_read32,
3422     omap3_mpu_wdt_read16,
3423     omap3_mpu_wdt_read32,
3424 };
3425
3426 static CPUWriteMemoryFunc *omap3_mpu_wdt_writefn[] = {
3427     omap_badwidth_write32,
3428     omap3_mpu_wdt_write16,
3429     omap3_mpu_wdt_write32,
3430 };
3431
3432 static void omap3_mpu_wdt_timer_tick(void *opaque)
3433 {
3434     struct omap3_wdt_s *wdt_timer = (struct omap3_wdt_s *) opaque;
3435
3436     /*TODO:Sent reset pulse to PRCM */
3437     wdt_timer->wcrr = wdt_timer->wldr;
3438
3439     /*after overflow, generate the new wdt_timer->rate */
3440     wdt_timer->pre = wdt_timer->wclr & (1 << 5);
3441     wdt_timer->ptv = (wdt_timer->wclr & 0x1c) >> 2;
3442     wdt_timer->rate =
3443         omap_clk_getrate(wdt_timer->clk) >> (wdt_timer->pre ? wdt_timer->
3444                                              ptv : 0);
3445
3446     wdt_timer->time = qemu_get_clock(vm_clock);
3447     omap3_wdt_timer_update(wdt_timer);
3448 }
3449
3450 static struct omap3_wdt_s *omap3_mpu_wdt_init(struct omap_target_agent_s *ta,
3451                                               qemu_irq irq, omap_clk fclk,
3452                                               omap_clk iclk,
3453                                               struct omap_mpu_state_s *mpu)
3454 {
3455     int iomemtype;
3456     struct omap3_wdt_s *s = (struct omap3_wdt_s *) qemu_mallocz(sizeof(*s));
3457
3458     s->irq = irq;
3459     s->clk = fclk;
3460     s->timer = qemu_new_timer(vm_clock, omap3_mpu_wdt_timer_tick, s);
3461
3462     omap3_wdt_reset(s, OMAP3_MPU_WDT);
3463     if (irq != NULL)
3464         omap3_wdt_clk_setup(s);
3465
3466     iomemtype = l4_register_io_memory(0, omap3_mpu_wdt_readfn,
3467                                       omap3_mpu_wdt_writefn, s);
3468     omap_l4_attach(ta, 0, iomemtype);
3469
3470     return s;
3471
3472 }
3473
3474 struct omap3_scm_s {
3475     struct omap_mpu_state_s *mpu;
3476
3477         uint8 interface[48];     /*0x4800 2000*/
3478         uint8 padconfs[576];     /*0x4800 2030*/
3479         uint32 general[228];     /*0x4800 2270*/
3480         uint8 mem_wkup[1024];    /*0x4800 2600*/
3481         uint8 padconfs_wkup[84]; /*0x4800 2a00*/
3482         uint32 general_wkup[8];  /*0x4800 2a60*/
3483 };
3484
3485 #define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
3486                                                 inputenable0,inputenable1,pupd0,pupd1,muxmode0,muxmode1,offset) \
3487         do { \
3488                  *(padconfs+offset/4) = (wakeup0 <<14)|(offmode0<<9)|(inputenable0<<8)|(pupd0<<3)|(muxmode0); \
3489                  *(padconfs+offset/4) |= (wakeup1 <<30)|(offmode1<<25)|(inputenable1<<24)|(pupd1<<19)|(muxmode1<<16); \
3490 } while (0)
3491
3492
3493 static void omap3_scm_reset(struct omap3_scm_s *s)
3494 {
3495     uint32 * padconfs;
3496     padconfs = (uint32 *)(s->padconfs);
3497     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x0);
3498     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3499     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x8);
3500     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3501     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3502     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3503     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x18);
3504     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x1c);
3505     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x20);
3506     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x24);
3507     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x28);
3508     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x2c);
3509     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x30);
3510     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x34);
3511     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x38);
3512     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x3c);
3513     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x40);
3514     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x44);
3515     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,7,0x48);
3516     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x4c);
3517     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x50);
3518     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x54);
3519     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x58);
3520     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,0,0x5c);
3521     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x60);
3522     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x64);
3523     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x68);
3524     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x6c);
3525     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x70);
3526     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x74);
3527     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x78);
3528     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x7c);
3529     PADCONFS_VALUE(0,0,0,0,1,1,0,3,0,7,0x80);
3530     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x84);
3531     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x88);
3532     PADCONFS_VALUE(0,0,0,0,1,1,3,0,7,0,0x8c);
3533     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x90);
3534     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x94);
3535     PADCONFS_VALUE(0,0,0,0,1,1,1,0,7,0,0x98);
3536     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,7,0x9c);
3537     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa0);
3538     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa4);
3539     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0xa8);
3540     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xac);
3541     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb0);
3542     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb4);
3543     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb8);
3544     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xbc);
3545     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc0);
3546     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc4);
3547     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc8);
3548     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xcc);
3549     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd0);
3550     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd4);
3551     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd8);
3552     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xdc);
3553     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe0);
3554     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe4);
3555     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe8);
3556     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xec);
3557     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf0);
3558     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf4);
3559     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf8);
3560     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xfc);
3561     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x100);
3562     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x104);
3563     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x108);
3564     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x10c);
3565     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x110);
3566     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x114);
3567     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x118);
3568     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x11c);
3569     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x120);
3570     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x124);
3571     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x128);
3572     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x12c);
3573     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x130);
3574     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x134);
3575     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x138);
3576     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x13c);
3577     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x140);
3578     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x144);
3579     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x148);
3580     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x14c);
3581     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x150);
3582     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x154);
3583     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x158);
3584     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x15c);
3585     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x160);
3586     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x164);
3587     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x168);
3588     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x16c);
3589     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x170);
3590     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x174);
3591     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x178);
3592     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x17c);
3593     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x180);
3594     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x184);
3595     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x188);
3596     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x18c);
3597     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x190);
3598     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x194);
3599     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x198);
3600     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x19c);
3601     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x1a0);
3602     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1a4);
3603     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x1a8);
3604     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1ac);
3605     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1b0);
3606     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b4);
3607     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b8);
3608     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1bc);
3609     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c0);
3610     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c4);
3611     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c8);
3612     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1cc);
3613     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d0);
3614     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d4);
3615     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d8);
3616     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1dc);
3617     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e0);
3618     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e4);
3619     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e8);
3620     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1ec);
3621     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f0);
3622     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f4);
3623     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f8);
3624     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1fc);
3625     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x200);
3626     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x204);
3627     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x208);
3628     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x20c);
3629     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x210);
3630     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x214);
3631     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x218);
3632     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x21c);
3633     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x220);
3634     PADCONFS_VALUE(0,0,0,0,1,1,3,1,0,0,0x224);
3635     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x228);
3636     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x22c);
3637     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x230);
3638     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x234);
3639
3640         padconfs = (uint32 *)(s->general);
3641     memset(s->general, 0, sizeof(s->general));
3642         s->general[0x01] = 0x4000000;  /* CONTROL_DEVCONF_0 */
3643         s->general[0x1c] = 0x1;        /* 0x480022e0?? */
3644     s->general[0x20] = 0x30f;      /* CONTROL_STATUS:
3645                                     * - device type = GP Device
3646                                     * - sys_boot = NAND, USB, UART3, MMC1 */
3647         s->general[0x75] = 0x7fc0;     /* CONTROL_PROG_IO0 */
3648         s->general[0x76] = 0xaa;       /* CONTROL_PROG_IO1 */
3649         s->general[0x7c] = 0x2700;     /* CONTROL_SDRC_SHARING */
3650         s->general[0x7d] = 0x300000;   /* CONTROL_SDRC_MCFG0 */
3651         s->general[0x7e] = 0x300000;   /* CONTROL_SDRC_MCFG1 */
3652         s->general[0x81] = 0xffff;     /* CONTROL_MODEM_GPMC_DT_FW_REQ_INFO */
3653         s->general[0x82] = 0xffff;     /* CONTROL_MODEM_GPMC_DT_FW_RD */
3654         s->general[0x83] = 0xffff;     /* CONTROL_MODEM_GPMC_DT_FW_WR */
3655         s->general[0x84] = 0x6;        /* CONTROL_MODEM_GPMC_BOOT_CODE */
3656         s->general[0x85] = 0xffffffff; /* CONTROL_MODEM_SMS_RG_ATT1 */
3657         s->general[0x86] = 0xffff;     /* CONTROL_MODEM_SMS_RG_RDPERM1 */
3658         s->general[0x87] = 0xffff;     /* CONTROL_MODEM_SMS_RG_WRPERM1 */
3659         s->general[0x88] = 0x1;        /* CONTROL_MODEM_D2D_FW_DEBUG_MODE */
3660         s->general[0x8b] = 0xffffffff; /* CONTROL_DPF_OCM_RAM_FW_REQINFO */
3661         s->general[0x8c] = 0xffff;     /* CONTROL_DPF_OCM_RAM_FW_WR */
3662         s->general[0x8e] = 0xffff;     /* CONTROL_DPF_REGION4_GPMC_FW_REQINFO */
3663         s->general[0x8f] = 0xffff;     /* CONTROL_DPF_REGION4_GPMC_FW_WR */
3664         s->general[0x91] = 0xffff;     /* CONTROL_DPF_REGION1_IVA2_FW_REQINFO */
3665         s->general[0x92] = 0xffff;     /* CONTROL_DPF_REGION1_IVA2_FW_WR */
3666         s->general[0xac] = 0x109;      /* CONTROL_PBIAS_LITE */
3667         s->general[0xb2] = 0xffff;     /* CONTROL_DPF_MAD2D_FW_ADDR_MATCH */
3668         s->general[0xb3] = 0xffff;     /* CONTROL_DPF_MAD2D_FW_REQINFO */
3669         s->general[0xb4] = 0xffff;     /* CONTROL_DPF_MAD2D_FW_WR */
3670         PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x368); /* PADCONF_ETK_CLK */
3671     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x36c); /* PADCONF_ETK_D0 */
3672     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x370); /* PADCONF_ETK_D2 */
3673     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x374); /* PADCONF_ETK_D4 */
3674     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x378); /* PADCONF_ETK_D6 */
3675     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x37c); /* PADCONF_ETK_D8 */
3676     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x380); /* PADCONF_ETK_D10 */
3677     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x384); /* PADCONF_ETK_D12 */
3678     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x388); /* PADCONF_ETK_D14 */
3679
3680         padconfs = (uint32 *)(s->padconfs_wkup);
3681         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x0);
3682         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3683         PADCONFS_VALUE(0,0,0,0,1,1,3,0,0,0,0x8);
3684         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3685         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3686         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3687         PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x18);
3688         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c);
3689         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x20);
3690         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x24);
3691         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x2c);
3692
3693         s->general_wkup[0] = 0x66ff; /* 0x48002A60?? */
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 struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
4164                                            const char *core)
4165 {
4166     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4167         qemu_mallocz(sizeof(struct omap_mpu_state_s));
4168     ram_addr_t sram_base, q2_base;
4169     qemu_irq *cpu_irq;
4170     qemu_irq dma_irqs[4];
4171     int i;
4172
4173     s->mpu_model = omap3530;
4174     s->env = cpu_init("cortex-a8-r2");
4175     if (!s->env) {
4176         fprintf(stderr, "Unable to find CPU definition\n");
4177         exit(1);
4178     }
4179     s->sdram_size = sdram_size;
4180     s->sram_size = OMAP3530_SRAM_SIZE;
4181
4182     /* Clocks */
4183     omap_clk_init(s);
4184
4185     /* Memory-mapped stuff */
4186
4187     q2_base = qemu_ram_alloc(s->sdram_size);
4188     cpu_register_physical_memory(OMAP3_Q2_BASE, s->sdram_size,
4189                                  (q2_base | IO_MEM_RAM));
4190     sram_base = qemu_ram_alloc(s->sram_size);
4191     cpu_register_physical_memory(OMAP3_SRAM_BASE, s->sram_size,
4192                                  (sram_base | IO_MEM_RAM));
4193
4194     s->l4 = omap_l4_init(OMAP3_L4_BASE, 
4195                          sizeof(omap3_l4_agent_info) 
4196                          / sizeof(struct omap3_l4_agent_info_s));
4197
4198     cpu_irq = arm_pic_init_cpu(s->env);
4199     s->ih[0] = omap2_inth_init(s, 0x48200000, 0x1000, 3, &s->irq[0],
4200                                cpu_irq[ARM_PIC_CPU_IRQ],
4201                                cpu_irq[ARM_PIC_CPU_FIQ], 
4202                                omap_findclk(s, "omap3_mpu_intc_fclk"),
4203                                omap_findclk(s, "omap3_mpu_intc_iclk"));
4204
4205     for (i = 0; i < 4; i++)
4206         dma_irqs[i] =
4207             s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
4208     s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
4209                             omap_findclk(s, "omap3_sdma_fclk"),
4210                             omap_findclk(s, "omap3_sdma_iclk"));
4211     s->port->addr_valid = omap3_validate_addr;
4212
4213     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
4214     soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
4215     soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
4216
4217
4218     s->omap3_cm = omap3_cm_init(omap3_l4ta_init(s->l4, L4A_CM), NULL, NULL, NULL, s);
4219
4220     s->omap3_prm = omap3_prm_init(omap3_l4ta_init(s->l4, L4A_PRM),
4221                                   s->irq[0][OMAP_INT_35XX_PRCM_MPU_IRQ],
4222                                   NULL, s);
4223
4224     s->omap3_mpu_wdt = omap3_mpu_wdt_init(omap3_l4ta_init(s->l4, L4A_WDTIMER2),
4225                                           NULL,
4226                                           omap_findclk(s, "omap3_wkup_32k_fclk"),
4227                                           omap_findclk(s, "omap3_wkup_l4_iclk"),
4228                                           s);
4229
4230     s->omap3_l3 = omap3_l3_init(OMAP3_L3_BASE, 
4231                                 omap3_l3_region,
4232                                 sizeof(omap3_l3_region)
4233                                 / sizeof(struct omap_l3_region_s));
4234     s->omap3_scm = omap3_scm_init(omap3_l4ta_init(s->l4, L4A_SCM), s);
4235
4236     s->omap3_sms = omap3_sms_init(s);
4237
4238     s->gptimer[0] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER1),
4239                                        s->irq[0][OMAP_INT_35XX_GPT1_IRQ],
4240                                        omap_findclk(s, "omap3_gp1_fclk"),
4241                                        omap_findclk(s, "omap3_wkup_l4_iclk"));
4242     s->gptimer[1] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER2),
4243                                        s->irq[0][OMAP_INT_35XX_GPT2_IRQ],
4244                                        omap_findclk(s, "omap3_gp2_fclk"),
4245                                        omap_findclk(s, "omap3_per_l4_iclk"));
4246     s->gptimer[2] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER3),
4247                                        s->irq[0][OMAP_INT_35XX_GPT3_IRQ],
4248                                        omap_findclk(s, "omap3_gp3_fclk"),
4249                                        omap_findclk(s, "omap3_per_l4_iclk"));
4250     s->gptimer[3] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER4),
4251                                        s->irq[0][OMAP_INT_35XX_GPT4_IRQ],
4252                                        omap_findclk(s, "omap3_gp4_fclk"),
4253                                        omap_findclk(s, "omap3_per_l4_iclk"));
4254     s->gptimer[4] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER5),
4255                                        s->irq[0][OMAP_INT_35XX_GPT5_IRQ],
4256                                        omap_findclk(s, "omap3_gp5_fclk"),
4257                                        omap_findclk(s, "omap3_per_l4_iclk"));
4258     s->gptimer[5] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER6),
4259                                        s->irq[0][OMAP_INT_35XX_GPT6_IRQ],
4260                                        omap_findclk(s, "omap3_gp6_fclk"),
4261                                        omap_findclk(s, "omap3_per_l4_iclk"));
4262     s->gptimer[6] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER7),
4263                                        s->irq[0][OMAP_INT_35XX_GPT7_IRQ],
4264                                        omap_findclk(s, "omap3_gp7_fclk"),
4265                                        omap_findclk(s, "omap3_per_l4_iclk"));
4266     s->gptimer[7] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER8),
4267                                        s->irq[0][OMAP_INT_35XX_GPT8_IRQ],
4268                                        omap_findclk(s, "omap3_gp8_fclk"),
4269                                        omap_findclk(s, "omap3_per_l4_iclk"));
4270     s->gptimer[8] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER9),
4271                                        s->irq[0][OMAP_INT_35XX_GPT9_IRQ],
4272                                        omap_findclk(s, "omap3_gp9_fclk"),
4273                                        omap_findclk(s, "omap3_per_l4_iclk"));
4274     s->gptimer[9] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER10),
4275                                        s->irq[0][OMAP_INT_35XX_GPT10_IRQ],
4276                                        omap_findclk(s, "omap3_gp10_fclk"),
4277                                        omap_findclk(s, "omap3_core_l4_iclk"));
4278     s->gptimer[10] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER11),
4279                                        s->irq[0][OMAP_INT_35XX_GPT11_IRQ],
4280                                        omap_findclk(s, "omap3_gp12_fclk"),
4281                                        omap_findclk(s, "omap3_core_l4_iclk"));
4282     s->gptimer[11] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER12),
4283                                         s->irq[0][OMAP_INT_35XX_GPT12_IRQ],
4284                                         omap_findclk(s, "omap3_gp12_fclk"),
4285                                         omap_findclk(s, "omap3_wkup_l4_iclk"));
4286     
4287         
4288     omap_synctimer_init(omap3_l4ta_init(s->l4, L4A_32KTIMER), s,
4289                         omap_findclk(s, "omap3_sys_32k"), NULL);
4290
4291     s->sdrc = omap_sdrc_init(0x6d000000);
4292     
4293     s->gpmc = omap_gpmc_init(s, 0x6e000000, s->irq[0][OMAP_INT_35XX_GPMC_IRQ]);
4294     
4295
4296     s->uart[0] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART1),
4297                                  s->irq[0][OMAP_INT_35XX_UART1_IRQ],
4298                                  omap_findclk(s, "omap3_uart1_fclk"),
4299                                  omap_findclk(s, "omap3_uart1_iclk"),
4300                                  s->drq[OMAP35XX_DMA_UART1_TX],
4301                                  s->drq[OMAP35XX_DMA_UART1_RX], 0);
4302     s->uart[1] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART2),
4303                                  s->irq[0][OMAP_INT_35XX_UART2_IRQ],
4304                                  omap_findclk(s, "omap3_uart2_fclk"),
4305                                  omap_findclk(s, "omap3_uart2_iclk"),
4306                                  s->drq[OMAP35XX_DMA_UART2_TX],
4307                                  s->drq[OMAP35XX_DMA_UART2_RX], 0);
4308     s->uart[2] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART3),
4309                                  s->irq[0][OMAP_INT_35XX_UART3_IRQ],
4310                                  omap_findclk(s, "omap3_uart2_fclk"),
4311                                  omap_findclk(s, "omap3_uart3_iclk"),
4312                                  s->drq[OMAP35XX_DMA_UART3_TX],
4313                                  s->drq[OMAP35XX_DMA_UART3_RX], 0);
4314     
4315     s->dss = omap_dss_init(s, omap3_l4ta_init(s->l4, L4A_DSS), 
4316                     s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
4317                    NULL,NULL,NULL,NULL,NULL);
4318
4319     s->gpif = omap3_gpif_init();
4320     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO1),
4321                     &s->irq[0][OMAP_INT_35XX_GPIO1_MPU_IRQ], 
4322                     NULL,NULL,0);
4323     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO2),
4324                     &s->irq[0][OMAP_INT_35XX_GPIO2_MPU_IRQ], 
4325                     NULL,NULL,1);
4326     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO3),
4327                     &s->irq[0][OMAP_INT_35XX_GPIO3_MPU_IRQ], 
4328                     NULL,NULL,2);
4329     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO4),
4330                     &s->irq[0][OMAP_INT_35XX_GPIO4_MPU_IRQ], 
4331                     NULL,NULL,3);
4332     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO5),
4333                     &s->irq[0][OMAP_INT_35XX_GPIO5_MPU_IRQ], 
4334                     NULL,NULL,4);
4335     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO6),
4336                     &s->irq[0][OMAP_INT_35XX_GPIO6_MPU_IRQ], 
4337                     NULL,NULL,5);
4338
4339     omap_tap_init(omap3_l4ta_init(s->l4, L4A_TAP), s);
4340
4341     s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC1),
4342                                      s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
4343                                      &s->drq[OMAP35XX_DMA_MMC1_TX],
4344                                      omap_findclk(s, "omap3_mmc1_fclk"),
4345                                      omap_findclk(s, "omap3_mmc1_iclk"));
4346
4347     s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC2),
4348                                      s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
4349                                      &s->drq[OMAP35XX_DMA_MMC2_TX],
4350                                      omap_findclk(s, "omap3_mmc2_fclk"),
4351                                      omap_findclk(s, "omap3_mmc2_iclk"));
4352
4353     s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC3),
4354                                      s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
4355                                      &s->drq[OMAP35XX_DMA_MMC3_TX],
4356                                      omap_findclk(s, "omap3_mmc3_fclk"),
4357                                      omap_findclk(s, "omap3_mmc3_iclk"));
4358
4359     s->i2c[0] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C1),
4360                                s->irq[0][OMAP_INT_35XX_I2C1_IRQ],
4361                                &s->drq[OMAP35XX_DMA_I2C1_TX],
4362                                omap_findclk(s, "omap3_i2c1_fclk"),
4363                                omap_findclk(s, "omap3_i2c1_iclk"),
4364                                8);
4365     s->i2c[1] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C2),
4366                                s->irq[0][OMAP_INT_35XX_I2C2_IRQ],
4367                                &s->drq[OMAP35XX_DMA_I2C2_TX],
4368                                omap_findclk(s, "omap3_i2c2_fclk"),
4369                                omap_findclk(s, "omap3_i2c2_iclk"),
4370                                8);
4371     s->i2c[2] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C3),
4372                                s->irq[0][OMAP_INT_35XX_I2C3_IRQ],
4373                                &s->drq[OMAP35XX_DMA_I2C3_TX],
4374                                omap_findclk(s, "omap3_i2c3_fclk"),
4375                                omap_findclk(s, "omap3_i2c3_iclk"),
4376                                64);
4377
4378     s->omap3_usb = omap3_hsusb_init(omap3_l4ta_init(s->l4, L4A_USBHS_OTG),
4379                                     omap3_l4ta_init(s->l4, L4A_USBHS_HOST),
4380                                     omap3_l4ta_init(s->l4, L4A_USBHS_TLL),
4381                                     s->irq[0][OMAP_INT_35XX_HSUSB_MC],
4382                                     s->irq[0][OMAP_INT_35XX_HSUSB_DMA],
4383                                     s->irq[0][OMAP_INT_35XX_OHCI_IRQ],
4384                                     s->irq[0][OMAP_INT_35XX_EHCI_IRQ],
4385                                     s->irq[0][OMAP_INT_35XX_TLL_IRQ]);
4386     return s;
4387 }
4388
4389
4390 static inline uint32_t omap3_get_le32(const void *p)
4391 {
4392     const uint8_t *q = (const uint8_t *)p;
4393     uint32_t v;
4394     v = q[3]; v <<= 8;
4395     v |= q[2]; v <<= 8;
4396     v |= q[1]; v <<= 8;
4397     v |= q[0];
4398     return v;
4399 }
4400
4401 static inline uint32_t omap3_get_le16(const void *p)
4402 {
4403     const uint8_t *q = (const uint8_t *)p;
4404     uint32_t v;
4405     v = q[1]; v <<= 8;
4406     v |= q[0];
4407     return v;
4408 }
4409
4410 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
4411 {
4412     uint8_t x[4];
4413     
4414     cpu_physical_memory_read(addr, x, 4);
4415     x[0] = lsb & 0xff;
4416     x[1] = (lsb >> 8) & 0xff;
4417     cpu_physical_memory_write(addr, x, 4);
4418 }
4419
4420 struct omap3_boot_s {
4421     struct omap_mpu_state_s *mpu;
4422     enum {
4423         undefined = 0,
4424         confighdr,
4425         chdone,
4426         imagehdr,
4427         copy,
4428         done
4429     } state;
4430     target_phys_addr_t addr;
4431     uint32_t count;
4432 };
4433
4434 static struct omap3_boot_s *omap3_boot_init(const uint8_t *data,
4435                                             uint32_t data_len,
4436                                             struct omap_mpu_state_s *mpu)
4437 {
4438     struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
4439     s->mpu = mpu;
4440     s->state = imagehdr;
4441     if (data_len >= 512) {
4442         if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
4443             || !strncasecmp((char *)(data + 0x14), "chram", 5)
4444             || !strncasecmp((char *)(data + 0x14), "chflash", 7)
4445             || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
4446             s->state = confighdr;
4447     }
4448     return s;
4449 }
4450
4451 static void omap3_boot_chsettings(const uint8_t *chtoc)
4452 {
4453     uint32_t flags, x;
4454     
4455     if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
4456         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4457         return;
4458     }
4459     if (!chtoc[4]) { /* section disabled? */
4460         return;
4461     }
4462     if (omap3_get_le16(chtoc + 5) != 0x0001) {
4463         fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
4464                 omap3_get_le16(chtoc));
4465         return;
4466     }
4467     flags = omap3_get_le32(chtoc + 8);
4468     chtoc += 12;
4469     if (flags & 1) {
4470         cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
4471         cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
4472         cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
4473         if (flags & (1 << 2)) { /* clock configuration */
4474             cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
4475             cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
4476         }
4477         if (flags & (1 << 5)) { /* DPLL3 CORE */
4478             if (flags & (1 << 8)) { /* enable DPLL3 bypass */
4479                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4480                 x &= ~7; x |= 5; /* set DPLL3 bypass */
4481                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4482             }
4483             cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
4484             cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
4485             cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
4486         }
4487         if (flags & (1 << 3)) { /* DPLL4 PER */
4488             if (flags & (1 << 6)) { /* enable DPLL4 bypass */
4489                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4490                 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
4491                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4492             }
4493             cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
4494             cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
4495             cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
4496             cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
4497         }
4498         if (flags & (1 << 3)) { /* DPLL1 MPU */
4499             if (flags & (1 << 7)) { /* enable DPLL1 bypass */
4500                 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
4501                 x &= ~7; x |= 5; /* set DPLL1 bypass */
4502                 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
4503             }
4504             cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
4505             cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
4506             cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
4507             cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
4508             cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
4509         }
4510         switch ((flags >> 24) & 0xff) {
4511             case 0x01: x = 0; break; /* 12MHz */
4512             case 0x02: x = 1; break; /* 13MHz */
4513             case 0x03: x = 5; break; /* 16.8MHz */
4514             case 0x04: x = 2; break; /* 19.2MHz */
4515             case 0x05: x = 3; break; /* 26MHz */
4516             case 0x06: x = 4; break; /* 38.4MHz */
4517             default:
4518                 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
4519                 x = 1;
4520                 break;
4521         }
4522         if (x != omap3_get_le32(chtoc + 0x04)) {
4523             fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
4524         }
4525     }
4526 }
4527
4528 static void omap3_boot_chram(const uint8_t *chtoc)
4529 {
4530     if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
4531         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4532         return;
4533     }
4534     if (!chtoc[4]) { /* section disabled? */
4535         return;
4536     }
4537     omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
4538     omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
4539     cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
4540
4541     cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
4542     omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
4543     omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
4544     omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
4545     omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
4546     cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
4547     cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
4548     cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
4549     
4550     cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
4551     omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
4552     omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
4553     omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
4554     omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
4555     cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
4556     cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
4557     cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
4558 }
4559
4560 static void omap3_boot_chflash(const uint8_t *chtoc)
4561 {
4562     if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
4563         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4564         return;
4565     }
4566     if (!chtoc[4]) { /* section disabled? */
4567         return;
4568     }
4569     omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
4570     omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
4571     omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
4572     omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
4573     cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
4574     cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
4575     cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
4576     cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
4577     cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
4578     cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
4579     cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
4580     cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
4581     omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
4582     omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
4583     /* TODO: ECC config registers. The TRM spec is not clear on these */
4584 }
4585
4586 static void omap3_boot_chmmcsd(const uint8_t *chtoc)
4587 {
4588     if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
4589         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4590         return;
4591     }
4592     if (!chtoc[4]) { /* section disabled? */
4593         return;
4594     }
4595     /* TODO: MMCHS registers */
4596 }
4597
4598 /* returns non-zero if more blocks are needed */
4599 static uint32_t omap3_boot_block(const uint8_t *data,
4600                                  uint32_t data_len,
4601                                  struct omap3_boot_s *s)
4602 {
4603     const uint8_t *p = 0;
4604     uint32_t i = 0;
4605     
4606     switch (s->state) {
4607         case confighdr:
4608             i = data_len;
4609             for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
4610                 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
4611                     omap3_boot_chsettings(p + omap3_get_le32(p));
4612                 else if (!strcasecmp((char *)(p + 0x14), "chram"))
4613                     omap3_boot_chram(p + omap3_get_le32(p));
4614                 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
4615                     omap3_boot_chflash(p + omap3_get_le32(p));
4616                 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
4617                     omap3_boot_chmmcsd(p + omap3_get_le32(p));
4618                 else
4619                     fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
4620                             __FUNCTION__, (char *)(p + 0x14));
4621             }
4622             data += 512;
4623             data_len -= 512;
4624             s->state = chdone;
4625             /* fallthrough */
4626         case chdone:
4627             s->state = imagehdr;
4628             /* fallthrough */
4629         case imagehdr:
4630             if (!data_len)
4631                 return 1;
4632             if (data_len < 8)
4633                 break;
4634             s->count = omap3_get_le32(data);
4635             s->addr = omap3_get_le32(data + 4);
4636             if (!s->count || !s->addr || s->addr == 0xffffffff)
4637                 break;
4638             s->mpu->env->regs[15] = s->addr;
4639             data += 8;
4640             data_len -= 8;
4641             s->state = copy;
4642             /* fallthrough */
4643         case copy:
4644             i = (s->count >= data_len) ? data_len : s->count;
4645             cpu_physical_memory_write(s->addr, data, i);
4646             s->addr += i;
4647             s->count -= i;
4648             if (!s->count)
4649                 s->state = done;
4650             return s->count;
4651         default:
4652             break;
4653     }
4654     return 0;
4655 }
4656
4657 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
4658 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
4659 {
4660     int i;
4661     
4662     /* there are 0x10 items with 0x20 bytes per item */
4663     for (i = 0x10; i--; s += 0x20) {
4664         if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
4665         if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
4666     }
4667     return 0;
4668 }
4669
4670 struct omap3_fat_drv_s {
4671     BlockDriverState *bs;
4672     uint8_t ptype; /* 12, 16, 32 */
4673     uint64_t c0;   /* physical byte offset for data cluster 0 */
4674     uint64_t fat;  /* physical byte offset for used FAT sector 0 */
4675     uint32_t spc;  /* sectors per cluster */
4676 };
4677
4678 /* returns cluster data in the buffer and next cluster chain number
4679    or 0 if unsuccessful */
4680 static uint32_t omap3_read_fat_cluster(uint8_t *data,
4681                                        struct omap3_fat_drv_s *drv,
4682                                        uint32_t cl)
4683 {
4684     uint8_t buf[ 4 ];
4685     uint32_t len = drv->spc * 0x200; /* number of bytes to read */
4686     
4687     switch (drv->ptype) { /* check for EOF */
4688         case 12: if (cl > 0xff0) return 0; break;
4689         case 16: if (cl > 0xfff0) return 0; break;
4690         case 32: if (cl > 0x0ffffff0) return 0; break;
4691         default: return 0;
4692     }
4693     
4694     if (bdrv_pread(drv->bs, 
4695                    drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
4696                    data, len) != len)
4697         return 0;
4698     
4699     switch (drv->ptype) { /* determine next cluster # */
4700         case 12:
4701             fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
4702                     __FUNCTION__);
4703             break;
4704         case 16:
4705             return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
4706             ? 0 : omap3_get_le16(buf);
4707         case 32:
4708             return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
4709             ? 0 : omap3_get_le32(buf) & 0x0fffffff;
4710         default:
4711             break;
4712     }
4713     return 0;
4714 }
4715
4716 static int omap3_mmc_fat_boot(BlockDriverState *bs,
4717                               uint8_t *sector,
4718                               uint32_t pstart,
4719                               struct omap_mpu_state_s *mpu)
4720 {
4721     struct omap3_fat_drv_s drv;
4722     struct omap3_boot_s *boot;
4723     uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
4724     const uint8_t *p, *q;
4725     uint8_t *cluster;
4726     int result = 0;
4727     
4728     /* determine FAT type */
4729     
4730     drv.bs = bs;
4731     fatsize = omap3_get_le16(sector + 0x16);
4732     if (!fatsize) 
4733         fatsize = omap3_get_le32(sector + 0x24);
4734     bootsize = omap3_get_le16(sector + 0x0e);
4735     cluster0 = bootsize + fatsize * sector[0x10];
4736     rootsize = omap3_get_le16(sector + 0x11);
4737     if (rootsize & 0x0f)
4738         rootsize += 0x10;
4739     rootsize >>= 4;
4740     drv.spc = sector[0x0d];
4741     i = omap3_get_le16(sector + 0x13);
4742     if (!i)
4743         i = omap3_get_le32(sector + 0x20);
4744     i = (i - (cluster0 + rootsize)) / drv.spc;
4745     drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
4746     
4747     /* search for boot loader file */
4748     
4749     drv.fat = (bootsize + pstart) * 0x200;
4750     drv.c0 = (cluster0 + pstart) * 0x200;
4751     if (drv.ptype == 32) {
4752         i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
4753         j = omap3_get_le16(sector + 0x28);
4754         if (j & 0x80)
4755             drv.fat += (j & 0x0f) * fatsize * 0x200;
4756         cluster = qemu_mallocz(drv.spc * 0x200);
4757         for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
4758             for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
4759                 p = omap3_scan_fat_dir_sector(q);
4760             if (p) 
4761                 memcpy(sector, q - 0x200, 0x200); /* save the sector */
4762         }
4763         free(cluster);
4764     } else { /* FAT12/16 */
4765         for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
4766             if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
4767                 break;
4768             p = omap3_scan_fat_dir_sector(sector);
4769         }
4770     }
4771     
4772     if (p && *p) { /* did we indeed find the file? */
4773         i = omap3_get_le16(p + 0x14);
4774         i <<= 16;
4775         i |= omap3_get_le16(p + 0x1a);
4776         j = drv.spc * 0x200;
4777         uint8 *data = qemu_mallocz(j);
4778         if ((i = omap3_read_fat_cluster(data, &drv, i))) {
4779             boot = omap3_boot_init(data, j, mpu);
4780             boot->state = imagehdr; /* override CH detection */
4781             while (omap3_boot_block(data, j, boot))
4782                 i = omap3_read_fat_cluster(data, &drv, i);
4783             result = (boot->state == done);
4784             free(boot);
4785         } else
4786             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
4787                     __FUNCTION__);
4788         free(data);
4789     } else
4790         fprintf(stderr, "%s: MLO file not found in the root directory\n",
4791                 __FUNCTION__);
4792
4793     return result;
4794 }
4795
4796 static int omap3_mmc_raw_boot(BlockDriverState *bs,
4797                               uint8_t *sector,
4798                               struct omap_mpu_state_s *mpu)
4799 {
4800     struct omap3_boot_s *boot;
4801     uint32_t i = 0;
4802     int result = 0;
4803     
4804     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4805         boot = omap3_boot_init(sector, 0x200, mpu);
4806         if (boot->state == confighdr) { /* CH must be present for raw boot */
4807             while (omap3_boot_block(sector, 0x200, boot)) {
4808                 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
4809                     fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
4810                             __FUNCTION__, i);
4811                     break;
4812                 }
4813             }
4814         }
4815         result = (boot->state == done);
4816         free(boot);
4817     }
4818     return result;
4819 }
4820
4821 /* returns non-zero if successful, zero if unsuccessful */
4822 int omap3_mmc_boot(struct omap_mpu_state_s *s)
4823 {
4824     BlockDriverState *bs;
4825     int sdindex = drive_get_index(IF_SD, 0, 0);
4826     uint8_t *sector, *p;
4827     uint32_t pstart, i;
4828     int result = 0;
4829     
4830     /* very simple implementation for GP device boot,
4831        supports only two modes:
4832        1. MBR partition table with an active FAT partition
4833           and boot loader file (MLO) in its root directory, or
4834        2. CH sector located on first sector, followed by boot loader image */
4835     if (sdindex >= 0) {
4836         bs = drives_table[sdindex].bdrv;
4837         sector = qemu_mallocz(0x200);
4838         if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4839             for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
4840                 if (p[0] == 0x80) break;
4841             if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
4842                 && i < 4 /* active partition exists */
4843                 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
4844                     || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
4845                 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
4846                               sector, 0x200) == 0x200
4847                 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
4848                 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
4849             else
4850                 result = omap3_mmc_raw_boot(bs, sector, s);
4851         }
4852         free(sector);
4853     }
4854     return result;
4855 }
4856
4857 /* returns non-zero if successful, zero if unsuccessful */
4858 int omap3_nand_boot(struct omap_mpu_state_s *mpu,
4859                     struct nand_flash_s *nand,
4860                     void (*nand_pread_f)(struct nand_flash_s *nand,
4861                                          uint64_t address,
4862                                          uint8_t *data,
4863                                          uint32_t len))
4864 {
4865     struct omap3_boot_s *boot;
4866     uint8_t *data;
4867     uint64_t addr = 0;
4868     int result = 0;
4869     
4870     data = qemu_mallocz(0x1000);
4871     nand_pread_f(nand, 0, data, 0x1000);
4872     boot = omap3_boot_init(data, 0x1000, mpu);
4873     while (omap3_boot_block(data, 0x1000, boot)) {
4874         addr += 0x1000;
4875         nand_pread_f(nand, addr, data, 0x1000);
4876     }
4877     result = (boot->state == done);
4878     free(boot);
4879     free(data);
4880     return result;
4881 }