misc clean-ups
[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 /*dummy system control module*/
3475 struct omap3_scm_s
3476 {
3477     struct omap_mpu_state_s *mpu;
3478
3479         uint8 interface[48];           /*0x4800 2000*/
3480         uint8 padconfs[576];         /*0x4800 2030*/
3481         uint32 general[228];            /*0x4800 2270*/
3482         uint8 mem_wkup[1024];     /*0x4800 2600*/
3483         uint8 padconfs_wkup[84]; /*0x4800 2a00*/
3484         uint32 general_wkup[8];    /*0x4800 2a60*/
3485 };
3486
3487 #define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
3488                                                 inputenable0,inputenable1,pupd0,pupd1,muxmode0,muxmode1,offset) \
3489         do { \
3490                  *(padconfs+offset/4) = (wakeup0 <<14)|(offmode0<<9)|(inputenable0<<8)|(pupd0<<3)|(muxmode0); \
3491                  *(padconfs+offset/4) |= (wakeup1 <<30)|(offmode1<<25)|(inputenable1<<24)|(pupd1<<19)|(muxmode1<<16); \
3492 } while (0)
3493
3494
3495 static void omap3_scm_reset(struct omap3_scm_s *s)
3496 {
3497          uint32 * padconfs;
3498     padconfs = (uint32 *)(s->padconfs);
3499     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x0);
3500     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3501     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x8);
3502     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3503     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3504     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3505     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x18);
3506     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x1c);
3507     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x20);
3508     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x24);
3509     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x28);
3510     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x2c);
3511     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x30);
3512     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x34);
3513     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x38);
3514     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x3c);
3515     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x40);
3516     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x44);
3517     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,7,0x48);
3518     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x4c);
3519     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x50);
3520     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x54);
3521     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x58);
3522     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,0,0x5c);
3523     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x60);
3524     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x64);
3525     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x68);
3526     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x6c);
3527     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x70);
3528     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x74);
3529     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x78);
3530     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x7c);
3531     PADCONFS_VALUE(0,0,0,0,1,1,0,3,0,7,0x80);
3532     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x84);
3533     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x88);
3534     PADCONFS_VALUE(0,0,0,0,1,1,3,0,7,0,0x8c);
3535     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x90);
3536     PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x94);
3537     PADCONFS_VALUE(0,0,0,0,1,1,1,0,7,0,0x98);
3538     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,7,0x9c);
3539     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa0);
3540     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa4);
3541     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0xa8);
3542     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xac);
3543     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb0);
3544     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb4);
3545     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb8);
3546     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xbc);
3547     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc0);
3548     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc4);
3549     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc8);
3550     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xcc);
3551     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd0);
3552     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd4);
3553     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd8);
3554     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xdc);
3555     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe0);
3556     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe4);
3557     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe8);
3558     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xec);
3559     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf0);
3560     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf4);
3561     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf8);
3562     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xfc);
3563     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x100);
3564     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x104);
3565     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x108);
3566     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x10c);
3567     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x110);
3568     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x114);
3569     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x118);
3570     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x11c);
3571     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x120);
3572     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x124);
3573     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x128);
3574     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x12c);
3575     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x130);
3576     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x134);
3577     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x138);
3578     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x13c);
3579     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x140);
3580     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x144);
3581     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x148);
3582     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x14c);
3583     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x150);
3584     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x154);
3585     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x158);
3586     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x15c);
3587     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x160);
3588     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x164);
3589     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x168);
3590     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x16c);
3591     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x170);
3592     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x174);
3593     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x178);
3594     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x17c);
3595     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x180);
3596     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x184);
3597     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x188);
3598     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x18c);
3599     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x190);
3600     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x194);
3601     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x198);
3602     PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x19c);
3603     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x1a0);
3604     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1a4);
3605     PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x1a8);
3606     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1ac);
3607     PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1b0);
3608     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b4);
3609     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b8);
3610     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1bc);
3611     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c0);
3612     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c4);
3613     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c8);
3614     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1cc);
3615     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d0);
3616     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d4);
3617     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d8);
3618     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1dc);
3619     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e0);
3620     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e4);
3621     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e8);
3622     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1ec);
3623     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f0);
3624     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f4);
3625     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f8);
3626     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1fc);
3627     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x200);
3628     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x204);
3629     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x208);
3630     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x20c);
3631     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x210);
3632     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x214);
3633     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x218);
3634     PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x21c);
3635     PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x220);
3636     PADCONFS_VALUE(0,0,0,0,1,1,3,1,0,0,0x224);
3637     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x228);
3638     PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x22c);
3639     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x230);
3640     PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x234);
3641
3642
3643         padconfs = (uint32 *)(s->general);
3644         s->general[1] = 0x4000000;  /*0x4800 2274*/
3645         s->general[0x1c] = 0x1;  /*0x4800 22e0*/
3646         s->general[0x75] = 0x7fc0;  /*0x4800 2444*/
3647         s->general[0x76] = 0xaa;  /*0x4800 2448*/
3648         s->general[0x7c] = 0x2700;  /*0x4800 2460*/
3649         s->general[0x7d] = 0x300000;  /*0x4800 2464*/
3650         s->general[0x7e] = 0x300000;  /*0x4800 2468*/
3651         s->general[0x81] = 0xffff;  /*0x4800 2474*/
3652         s->general[0x82] = 0xffff;  /*0x4800 2478*/
3653         s->general[0x83] = 0xffff;  /*0x4800 247c*/
3654         s->general[0x84] = 0x6;  /*0x4800 2480*/
3655         s->general[0x85] = 0xffffffff;  /*0x4800 2484*/
3656         s->general[0x86] = 0xffff;  /*0x4800 2488*/
3657         s->general[0x87] = 0xffff;  /*0x4800 248c*/
3658         s->general[0x88] = 0x1;  /*0x4800 2490*/
3659         s->general[0x8b] = 0xffffffff;  /*0x4800 249c*/
3660         s->general[0x8c] = 0xffff;  /*0x4800 24a0*/
3661         s->general[0x8e] = 0xffff;  /*0x4800 24a8*/
3662         s->general[0x8f] = 0xffff;  /*0x4800 24ac*/
3663         s->general[0x91] = 0xffff;  /*0x4800 24b4*/
3664         s->general[0x92] = 0xffff;  /*0x4800 24b8*/
3665         s->general[0xac] = 0x109;  /*0x4800 2520*/
3666         s->general[0xb2] = 0xffff;  /*0x4800 2538*/
3667         s->general[0xb3] = 0xffff;  /*0x4800 253c*/
3668         s->general[0xb4] = 0xffff;  /*0x4800 2540*/
3669         PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x368);
3670     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x36c);
3671     PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x370);
3672     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x374);
3673     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x378);
3674     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x37c);
3675     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x380);
3676     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x384);
3677     PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x388);
3678
3679     
3680
3681         padconfs = (uint32 *)(s->padconfs_wkup);
3682         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x0);
3683         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
3684         PADCONFS_VALUE(0,0,0,0,1,1,3,0,0,0,0x8);
3685         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
3686         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
3687         PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
3688         PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x18);
3689         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c);
3690         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x20);
3691         PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x24);
3692         PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x2c);
3693
3694
3695         s->general_wkup[0] = 0x66ff; /*0x4800 2A60*/
3696             
3697 }
3698
3699 static uint32_t omap3_scm_read8(void *opaque, target_phys_addr_t addr)
3700 {
3701     struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
3702     uint8_t* temp;
3703         
3704     switch (addr) {
3705     case 0x00 ... 0x2f:
3706         return s->interface[addr];
3707     case 0x30 ... 0x26f:
3708         return s->padconfs[addr-0x30];
3709     case 0x270 ... 0x5ff:
3710         temp = (uint8_t *)s->general;
3711         return temp[addr-0x270];
3712     case 0x600 ... 0x9ff:
3713         return s->mem_wkup[addr-0x600];
3714     case 0xa00 ... 0xa5f:
3715         return s->padconfs_wkup[addr-0xa00];
3716     case 0xa60 ... 0xa7f:
3717         temp = (uint8_t *)s->general_wkup;
3718         return temp[addr-0xa60];
3719     default:
3720         break;
3721     }
3722     printf("omap3_scm_read8 addr %x pc %x  \n", addr,cpu_single_env->regs[15] );
3723     return 0;
3724 }
3725
3726 static uint32_t omap3_scm_read16(void *opaque, target_phys_addr_t addr)
3727 {
3728     uint32_t v;
3729     v = omap3_scm_read8(opaque, addr);
3730     v |= omap3_scm_read8(opaque, addr + 1) << 8;
3731     return v;
3732 }
3733
3734 static uint32_t omap3_scm_read32(void *opaque, target_phys_addr_t addr)
3735 {
3736     uint32_t v;
3737     v = omap3_scm_read8(opaque, addr);
3738     v |= omap3_scm_read8(opaque, addr + 1) << 8;
3739     v |= omap3_scm_read8(opaque, addr + 2) << 16;
3740     v |= omap3_scm_read8(opaque, addr + 3) << 24;
3741     return v;
3742 }
3743
3744 static void omap3_scm_write8(void *opaque, target_phys_addr_t addr,
3745                              uint32_t value)
3746 {
3747     struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
3748     uint8_t* temp;
3749
3750     switch (addr)
3751     {
3752     case 0x00 ... 0x2f:
3753         s->interface[addr] = value;
3754         break;
3755     case 0x30 ... 0x26f:
3756         s->padconfs[addr-0x30] = value;
3757         break;
3758     case 0x270 ... 0x5ff:
3759         temp = (uint8_t *)s->general;
3760         temp[addr-0x270] = value;
3761         break;
3762     case 0x600 ... 0x9ff:
3763         s->mem_wkup[addr-0x600] = value;
3764         break;
3765     case 0xa00 ... 0xa5f:
3766         s->padconfs_wkup[addr-0xa00] = value;
3767         break;
3768     case 0xa60 ... 0xa7f:
3769         temp = (uint8_t *)s->general_wkup;
3770         temp[addr-0xa60] = value;
3771         break;
3772     default:
3773         /*we do not care scm write*/
3774         printf("omap3_scm_write8 addr %x pc %x \n \n", addr,
3775                cpu_single_env->regs[15] - 0x80008000 + 0x80e80000);
3776         exit(1);
3777         //break;
3778     }
3779 }
3780
3781 static void omap3_scm_write16(void *opaque, target_phys_addr_t addr,
3782                               uint32_t value)
3783 {
3784     omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
3785     omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
3786 }
3787
3788 static void omap3_scm_write32(void *opaque, target_phys_addr_t addr,
3789                               uint32_t value)
3790 {
3791     omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
3792     omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
3793     omap3_scm_write8(opaque, addr + 2, (value >> 16) & 0xff);
3794     omap3_scm_write8(opaque, addr + 3, (value >> 24) & 0xff);
3795 }
3796
3797 static CPUReadMemoryFunc *omap3_scm_readfn[] = {
3798     omap3_scm_read8,
3799     omap3_scm_read16,
3800     omap3_scm_read32,
3801 };
3802
3803 static CPUWriteMemoryFunc *omap3_scm_writefn[] = {
3804     omap3_scm_write8,
3805     omap3_scm_write16,
3806     omap3_scm_write32,
3807 };
3808
3809 static struct omap3_scm_s *omap3_scm_init(struct omap_target_agent_s *ta,
3810                                           struct omap_mpu_state_s *mpu)
3811 {
3812     int iomemtype;
3813     struct omap3_scm_s *s = (struct omap3_scm_s *) qemu_mallocz(sizeof(*s));
3814
3815     s->mpu = mpu;
3816
3817     omap3_scm_reset(s);
3818
3819     iomemtype = l4_register_io_memory(0, omap3_scm_readfn,
3820                                       omap3_scm_writefn, s);
3821     omap_l4_attach(ta, 0, iomemtype);
3822     
3823     return s;
3824 }
3825
3826 /*dummy SDRAM Memory Scheduler emulation*/
3827 struct omap3_sms_s
3828 {
3829     struct omap_mpu_state_s *mpu;
3830
3831     uint32 sms_sysconfig;
3832     uint32 sms_sysstatus;
3833     uint32 sms_rg_att[8];
3834     uint32 sms_rg_rdperm[8];
3835     uint32 sms_rg_wrperm[8];
3836     uint32 sms_rg_start[7];
3837     uint32 sms_rg_end[7];
3838     uint32 sms_security_control;
3839     uint32 sms_class_arbiter0;
3840     uint32 sms_class_arbiter1;
3841     uint32 sms_class_arbiter2;
3842     uint32 sms_interclass_arbiter;
3843     uint32 sms_class_rotation[3];
3844     uint32 sms_err_addr;
3845     uint32 sms_err_type;
3846     uint32 sms_pow_ctrl;
3847     uint32 sms_rot_control[12];
3848     uint32 sms_rot_size[12];
3849     uint32 sms_rot_physical_ba[12];
3850 };
3851
3852 static uint32_t omap3_sms_read32(void *opaque, target_phys_addr_t addr)
3853 {
3854     struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
3855
3856     switch (addr)
3857     {
3858     case 0x10:
3859         return s->sms_sysconfig;
3860     case 0x14:
3861         return s->sms_sysstatus;
3862     case 0x48:
3863     case 0x68:
3864     case 0x88:
3865     case 0xa8:
3866     case 0xc8:
3867     case 0xe8:
3868     case 0x108:
3869     case 0x128:
3870         return s->sms_rg_att[(addr-0x48)/0x20];
3871     case 0x50:
3872     case 0x70:
3873     case 0x90:
3874     case 0xb0:
3875     case 0xd0:
3876     case 0xf0:
3877     case 0x110:
3878     case 0x130:
3879         return s->sms_rg_rdperm[(addr-0x50)/0x20];
3880     case 0x58:
3881     case 0x78:
3882     case 0x98:
3883     case 0xb8:
3884     case 0xd8:
3885     case 0xf8:
3886     case 0x118:
3887         return s->sms_rg_wrperm[(addr-0x58)/0x20];
3888     case 0x60:
3889     case 0x80:
3890     case 0xa0:
3891     case 0xc0:
3892     case 0xe0:
3893     case 0x100:
3894     case 0x120:
3895         return s->sms_rg_start[(addr-0x60)/0x20];
3896
3897     case 0x64:
3898     case 0x84:
3899     case 0xa4:
3900     case 0xc4:
3901     case 0xe4:
3902     case 0x104:
3903     case 0x124:
3904         return s->sms_rg_end[(addr-0x64)/0x20];
3905     case 0x140:
3906         return s->sms_security_control;
3907     case 0x150:
3908         return s->sms_class_arbiter0;
3909         case 0x154:
3910                 return s->sms_class_arbiter1;
3911         case 0x158:
3912                 return s->sms_class_arbiter2;
3913         case 0x160:
3914                 return s->sms_interclass_arbiter;
3915         case 0x164:
3916         case 0x168:
3917         case 0x16c:
3918                 return s->sms_class_rotation[(addr-0x164)/4];
3919         case 0x170:
3920                 return s->sms_err_addr;
3921         case 0x174:
3922                 return s->sms_err_type;
3923         case 0x178:
3924                 return s->sms_pow_ctrl;
3925         case 0x180:
3926         case 0x190:
3927         case 0x1a0:
3928         case 0x1b0:
3929         case 0x1c0:
3930         case 0x1d0:
3931         case 0x1e0:
3932         case 0x1f0:
3933         case 0x200:
3934         case 0x210:
3935         case 0x220:
3936         case 0x230:
3937                 return s->sms_rot_control[(addr-0x180)/0x10];
3938         case 0x184:
3939         case 0x194:
3940         case 0x1a4:
3941         case 0x1b4:
3942         case 0x1c4:
3943         case 0x1d4:
3944         case 0x1e4:
3945         case 0x1f4:
3946         case 0x204:
3947         case 0x214:
3948         case 0x224:
3949         case 0x234:
3950                 return s->sms_rot_size[(addr-0x184)/0x10];
3951
3952         case 0x188:
3953         case 0x198:
3954         case 0x1a8:
3955         case 0x1b8:
3956         case 0x1c8:
3957         case 0x1d8:
3958         case 0x1e8:
3959         case 0x1f8:
3960         case 0x208:
3961         case 0x218:
3962         case 0x228:
3963         case 0x238:
3964                 return s->sms_rot_size[(addr-0x188)/0x10];
3965
3966     default:
3967         printf("omap3_sms_read32 addr %x \n", addr);
3968         exit(-1);
3969     }
3970 }
3971
3972 static void omap3_sms_write32(void *opaque, target_phys_addr_t addr,
3973                               uint32_t value)
3974 {
3975     struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
3976     //int i;
3977
3978     switch (addr)
3979     {
3980     case 0x14:
3981         OMAP_RO_REG(addr);
3982         return;
3983     case 0x10:
3984         s->sms_sysconfig = value & 0x1f;
3985         break;
3986     
3987     case 0x48:
3988     case 0x68:
3989     case 0x88:
3990     case 0xa8:
3991     case 0xc8:
3992     case 0xe8:
3993     case 0x108:
3994     case 0x128:
3995         s->sms_rg_att[(addr-0x48)/0x20] = value;
3996         break;
3997     case 0x50:
3998     case 0x70:
3999     case 0x90:
4000     case 0xb0:
4001     case 0xd0:
4002     case 0xf0:
4003     case 0x110:
4004     case 0x130:
4005         s->sms_rg_rdperm[(addr-0x50)/0x20] = value&0xffff;
4006         break;
4007     case 0x58:
4008     case 0x78:
4009     case 0x98:
4010     case 0xb8:
4011     case 0xd8:
4012     case 0xf8:
4013     case 0x118:
4014         s->sms_rg_wrperm[(addr-0x58)/0x20] = value&0xffff;
4015         break;          
4016     case 0x60:
4017     case 0x80:
4018     case 0xa0:
4019     case 0xc0:
4020     case 0xe0:
4021     case 0x100:
4022     case 0x120:
4023         s->sms_rg_start[(addr-0x60)/0x20] = value;
4024         break;
4025     case 0x64:
4026     case 0x84:
4027     case 0xa4:
4028     case 0xc4:
4029     case 0xe4:
4030     case 0x104:
4031     case 0x124:
4032         s->sms_rg_end[(addr-0x64)/0x20] = value;
4033         break;
4034     case 0x140:
4035         s->sms_security_control = value &0xfffffff;
4036         break;
4037     case 0x150:
4038         s->sms_class_arbiter0 = value;
4039         break;
4040         case 0x154:
4041                 s->sms_class_arbiter1 = value;
4042                 break;
4043         case 0x158:
4044                 s->sms_class_arbiter2 = value;
4045                 break;
4046         case 0x160:
4047                 s->sms_interclass_arbiter = value;
4048                 break;
4049         case 0x164:
4050         case 0x168:
4051         case 0x16c:
4052                 s->sms_class_rotation[(addr-0x164)/4] = value;
4053                 break;
4054         case 0x170:
4055                 s->sms_err_addr = value;
4056                 break;
4057         case 0x174:
4058                 s->sms_err_type = value;
4059                 break;
4060         case 0x178:
4061                 s->sms_pow_ctrl = value;
4062                 break;
4063         case 0x180:
4064         case 0x190:
4065         case 0x1a0:
4066         case 0x1b0:
4067         case 0x1c0:
4068         case 0x1d0:
4069         case 0x1e0:
4070         case 0x1f0:
4071         case 0x200:
4072         case 0x210:
4073         case 0x220:
4074         case 0x230:
4075                 s->sms_rot_control[(addr-0x180)/0x10] = value;
4076                 break;
4077         case 0x184:
4078         case 0x194:
4079         case 0x1a4:
4080         case 0x1b4:
4081         case 0x1c4:
4082         case 0x1d4:
4083         case 0x1e4:
4084         case 0x1f4:
4085         case 0x204:
4086         case 0x214:
4087         case 0x224:
4088         case 0x234:
4089                 s->sms_rot_size[(addr-0x184)/0x10] = value;
4090                 break;
4091
4092         case 0x188:
4093         case 0x198:
4094         case 0x1a8:
4095         case 0x1b8:
4096         case 0x1c8:
4097         case 0x1d8:
4098         case 0x1e8:
4099         case 0x1f8:
4100         case 0x208:
4101         case 0x218:
4102         case 0x228:
4103         case 0x238:
4104                 s->sms_rot_size[(addr-0x188)/0x10] = value;   
4105                 break;
4106         default:
4107         printf("omap3_sms_write32 addr %x\n", addr);
4108         exit(-1);
4109     }
4110 }
4111
4112 static CPUReadMemoryFunc *omap3_sms_readfn[] = {
4113     omap_badwidth_read32,
4114     omap_badwidth_read32,
4115     omap3_sms_read32,
4116 };
4117
4118 static CPUWriteMemoryFunc *omap3_sms_writefn[] = {
4119     omap_badwidth_write32,
4120     omap_badwidth_write32,
4121     omap3_sms_write32,
4122 };
4123
4124 static void omap3_sms_reset(struct omap3_sms_s *s)
4125 {
4126         s->sms_sysconfig = 0x1;
4127         s->sms_class_arbiter0 = 0x500000;
4128         s->sms_class_arbiter1 = 0x500;
4129         s->sms_class_arbiter2 = 0x55000;
4130         s->sms_interclass_arbiter = 0x400040;
4131         s->sms_class_rotation[0] = 0x1;
4132         s->sms_class_rotation[1] = 0x1;
4133         s->sms_class_rotation[2] = 0x1;
4134         s->sms_pow_ctrl = 0x80;
4135 }
4136
4137 static struct omap3_sms_s *omap3_sms_init(struct omap_mpu_state_s *mpu)
4138 {
4139     int iomemtype;
4140     struct omap3_sms_s *s = (struct omap3_sms_s *) qemu_mallocz(sizeof(*s));
4141
4142     s->mpu = mpu;
4143
4144     omap3_sms_reset(s);
4145     
4146     iomemtype = cpu_register_io_memory(0, omap3_sms_readfn,
4147                                        omap3_sms_writefn, s);
4148     cpu_register_physical_memory(0x6c000000, 0x10000, iomemtype);
4149
4150     return s;
4151 }
4152
4153 static const struct dma_irq_map omap3_dma_irq_map[] = {
4154     {0, OMAP_INT_35XX_SDMA_IRQ0},
4155     {0, OMAP_INT_35XX_SDMA_IRQ1},
4156     {0, OMAP_INT_35XX_SDMA_IRQ2},
4157     {0, OMAP_INT_35XX_SDMA_IRQ3},
4158 };
4159
4160 static int omap3_validate_addr(struct omap_mpu_state_s *s,
4161                                target_phys_addr_t addr)
4162 {
4163     return 1;
4164 }
4165
4166 /*
4167   set the kind of memory connected to GPMC that we are trying to boot form.
4168   Uses SYS BOOT settings.
4169 */
4170 void omap3_set_mem_type(struct omap_mpu_state_s *s,int bootfrom)
4171 {
4172     s->omap3_scm->general[32] &= ~0x3f;
4173         switch (bootfrom) {
4174                 case 0x0: /*GPMC_NOR*/
4175                         s->omap3_scm->general[32] |= 7;
4176                         break;
4177                 case 0x1: /*GPMC_NAND*/
4178                         s->omap3_scm->general[32] |= 1;
4179                         break;
4180                 case 0x2:
4181                         s->omap3_scm->general[32] |= 8;
4182                         break;
4183                 case 0x3:
4184                         s->omap3_scm->general[32] |= 0;
4185                         break;
4186                 case 0x4:
4187                         s->omap3_scm->general[32] |= 17;
4188                         break;
4189                 case 0x5:
4190                         s->omap3_scm->general[32] |= 3;
4191                         break;
4192         }
4193 }
4194
4195 void omap3_set_device_type(struct omap_mpu_state_s *s,int device_type)
4196 {
4197     s->omap3_scm->general[32] &= ~(0x7 << 8);
4198         s->omap3_scm->general[32] |= (device_type & 0x7) << 8;
4199 }
4200
4201 struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
4202                                            const char *core)
4203 {
4204     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4205         qemu_mallocz(sizeof(struct omap_mpu_state_s));
4206     ram_addr_t sram_base, q2_base;
4207     qemu_irq *cpu_irq;
4208     qemu_irq dma_irqs[4];
4209     int i;
4210
4211     s->mpu_model = omap3530;
4212     s->env = cpu_init("cortex-a8-r2");
4213     if (!s->env) {
4214         fprintf(stderr, "Unable to find CPU definition\n");
4215         exit(1);
4216     }
4217     s->sdram_size = sdram_size;
4218     s->sram_size = OMAP3530_SRAM_SIZE;
4219
4220     /* Clocks */
4221     omap_clk_init(s);
4222
4223     /* Memory-mapped stuff */
4224
4225     q2_base = qemu_ram_alloc(s->sdram_size);
4226     cpu_register_physical_memory(OMAP3_Q2_BASE, s->sdram_size,
4227                                  (q2_base | IO_MEM_RAM));
4228     sram_base = qemu_ram_alloc(s->sram_size);
4229     cpu_register_physical_memory(OMAP3_SRAM_BASE, s->sram_size,
4230                                  (sram_base | IO_MEM_RAM));
4231
4232     s->l4 = omap_l4_init(OMAP3_L4_BASE, 
4233                          sizeof(omap3_l4_agent_info) 
4234                          / sizeof(struct omap3_l4_agent_info_s));
4235
4236     cpu_irq = arm_pic_init_cpu(s->env);
4237     s->ih[0] = omap2_inth_init(s, 0x48200000, 0x1000, 3, &s->irq[0],
4238                                cpu_irq[ARM_PIC_CPU_IRQ],
4239                                cpu_irq[ARM_PIC_CPU_FIQ], 
4240                                omap_findclk(s, "omap3_mpu_intc_fclk"),
4241                                omap_findclk(s, "omap3_mpu_intc_iclk"));
4242
4243     for (i = 0; i < 4; i++)
4244         dma_irqs[i] =
4245             s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
4246     s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
4247                             omap_findclk(s, "omap3_sdma_fclk"),
4248                             omap_findclk(s, "omap3_sdma_iclk"));
4249     s->port->addr_valid = omap3_validate_addr;
4250
4251     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
4252     soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
4253     soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
4254
4255
4256     s->omap3_cm = omap3_cm_init(omap3_l4ta_init(s->l4, L4A_CM), NULL, NULL, NULL, s);
4257
4258     s->omap3_prm = omap3_prm_init(omap3_l4ta_init(s->l4, L4A_PRM),
4259                                   s->irq[0][OMAP_INT_35XX_PRCM_MPU_IRQ],
4260                                   NULL, s);
4261
4262     s->omap3_mpu_wdt = omap3_mpu_wdt_init(omap3_l4ta_init(s->l4, L4A_WDTIMER2),
4263                                           NULL,
4264                                           omap_findclk(s, "omap3_wkup_32k_fclk"),
4265                                           omap_findclk(s, "omap3_wkup_l4_iclk"),
4266                                           s);
4267
4268     s->omap3_l3 = omap3_l3_init(OMAP3_L3_BASE, 
4269                                 omap3_l3_region,
4270                                 sizeof(omap3_l3_region)
4271                                 / sizeof(struct omap_l3_region_s));
4272     s->omap3_scm = omap3_scm_init(omap3_l4ta_init(s->l4, L4A_SCM), s);
4273
4274     s->omap3_sms = omap3_sms_init(s);
4275
4276     s->gptimer[0] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER1),
4277                                        s->irq[0][OMAP_INT_35XX_GPT1_IRQ],
4278                                        omap_findclk(s, "omap3_gp1_fclk"),
4279                                        omap_findclk(s, "omap3_wkup_l4_iclk"));
4280     s->gptimer[1] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER2),
4281                                        s->irq[0][OMAP_INT_35XX_GPT2_IRQ],
4282                                        omap_findclk(s, "omap3_gp2_fclk"),
4283                                        omap_findclk(s, "omap3_per_l4_iclk"));
4284     s->gptimer[2] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER3),
4285                                        s->irq[0][OMAP_INT_35XX_GPT3_IRQ],
4286                                        omap_findclk(s, "omap3_gp3_fclk"),
4287                                        omap_findclk(s, "omap3_per_l4_iclk"));
4288     s->gptimer[3] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER4),
4289                                        s->irq[0][OMAP_INT_35XX_GPT4_IRQ],
4290                                        omap_findclk(s, "omap3_gp4_fclk"),
4291                                        omap_findclk(s, "omap3_per_l4_iclk"));
4292     s->gptimer[4] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER5),
4293                                        s->irq[0][OMAP_INT_35XX_GPT5_IRQ],
4294                                        omap_findclk(s, "omap3_gp5_fclk"),
4295                                        omap_findclk(s, "omap3_per_l4_iclk"));
4296     s->gptimer[5] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER6),
4297                                        s->irq[0][OMAP_INT_35XX_GPT6_IRQ],
4298                                        omap_findclk(s, "omap3_gp6_fclk"),
4299                                        omap_findclk(s, "omap3_per_l4_iclk"));
4300     s->gptimer[6] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER7),
4301                                        s->irq[0][OMAP_INT_35XX_GPT7_IRQ],
4302                                        omap_findclk(s, "omap3_gp7_fclk"),
4303                                        omap_findclk(s, "omap3_per_l4_iclk"));
4304     s->gptimer[7] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER8),
4305                                        s->irq[0][OMAP_INT_35XX_GPT8_IRQ],
4306                                        omap_findclk(s, "omap3_gp8_fclk"),
4307                                        omap_findclk(s, "omap3_per_l4_iclk"));
4308     s->gptimer[8] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER9),
4309                                        s->irq[0][OMAP_INT_35XX_GPT9_IRQ],
4310                                        omap_findclk(s, "omap3_gp9_fclk"),
4311                                        omap_findclk(s, "omap3_per_l4_iclk"));
4312     s->gptimer[9] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER10),
4313                                        s->irq[0][OMAP_INT_35XX_GPT10_IRQ],
4314                                        omap_findclk(s, "omap3_gp10_fclk"),
4315                                        omap_findclk(s, "omap3_core_l4_iclk"));
4316     s->gptimer[10] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER11),
4317                                        s->irq[0][OMAP_INT_35XX_GPT11_IRQ],
4318                                        omap_findclk(s, "omap3_gp12_fclk"),
4319                                        omap_findclk(s, "omap3_core_l4_iclk"));
4320     s->gptimer[11] = omap_gp_timer_init(omap3_l4ta_init(s->l4, L4A_GPTIMER12),
4321                                         s->irq[0][OMAP_INT_35XX_GPT12_IRQ],
4322                                         omap_findclk(s, "omap3_gp12_fclk"),
4323                                         omap_findclk(s, "omap3_wkup_l4_iclk"));
4324     
4325         
4326     omap_synctimer_init(omap3_l4ta_init(s->l4, L4A_32KTIMER), s,
4327                         omap_findclk(s, "omap3_sys_32k"), NULL);
4328
4329     s->sdrc = omap_sdrc_init(0x6d000000);
4330     
4331     s->gpmc = omap_gpmc_init(s, 0x6e000000, s->irq[0][OMAP_INT_35XX_GPMC_IRQ]);
4332     
4333
4334     s->uart[0] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART1),
4335                                  s->irq[0][OMAP_INT_35XX_UART1_IRQ],
4336                                  omap_findclk(s, "omap3_uart1_fclk"),
4337                                  omap_findclk(s, "omap3_uart1_iclk"),
4338                                  s->drq[OMAP35XX_DMA_UART1_TX],
4339                                  s->drq[OMAP35XX_DMA_UART1_RX], 0);
4340     s->uart[1] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART2),
4341                                  s->irq[0][OMAP_INT_35XX_UART2_IRQ],
4342                                  omap_findclk(s, "omap3_uart2_fclk"),
4343                                  omap_findclk(s, "omap3_uart2_iclk"),
4344                                  s->drq[OMAP35XX_DMA_UART2_TX],
4345                                  s->drq[OMAP35XX_DMA_UART2_RX], 0);
4346     s->uart[2] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART3),
4347                                  s->irq[0][OMAP_INT_35XX_UART3_IRQ],
4348                                  omap_findclk(s, "omap3_uart2_fclk"),
4349                                  omap_findclk(s, "omap3_uart3_iclk"),
4350                                  s->drq[OMAP35XX_DMA_UART3_TX],
4351                                  s->drq[OMAP35XX_DMA_UART3_RX], 0);
4352     
4353     s->dss = omap_dss_init(s, omap3_l4ta_init(s->l4, L4A_DSS), 
4354                     s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
4355                    NULL,NULL,NULL,NULL,NULL);
4356
4357     s->gpif = omap3_gpif_init();
4358     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO1),
4359                     &s->irq[0][OMAP_INT_35XX_GPIO1_MPU_IRQ], 
4360                     NULL,NULL,0);
4361     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO2),
4362                     &s->irq[0][OMAP_INT_35XX_GPIO2_MPU_IRQ], 
4363                     NULL,NULL,1);
4364     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO3),
4365                     &s->irq[0][OMAP_INT_35XX_GPIO3_MPU_IRQ], 
4366                     NULL,NULL,2);
4367     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO4),
4368                     &s->irq[0][OMAP_INT_35XX_GPIO4_MPU_IRQ], 
4369                     NULL,NULL,3);
4370     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO5),
4371                     &s->irq[0][OMAP_INT_35XX_GPIO5_MPU_IRQ], 
4372                     NULL,NULL,4);
4373     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO6),
4374                     &s->irq[0][OMAP_INT_35XX_GPIO6_MPU_IRQ], 
4375                     NULL,NULL,5);
4376
4377     omap_tap_init(omap3_l4ta_init(s->l4, L4A_TAP), s);
4378
4379     s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC1),
4380                                      s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
4381                                      &s->drq[OMAP35XX_DMA_MMC1_TX],
4382                                      omap_findclk(s, "omap3_mmc1_fclk"),
4383                                      omap_findclk(s, "omap3_mmc1_iclk"));
4384
4385     s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC2),
4386                                      s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
4387                                      &s->drq[OMAP35XX_DMA_MMC2_TX],
4388                                      omap_findclk(s, "omap3_mmc2_fclk"),
4389                                      omap_findclk(s, "omap3_mmc2_iclk"));
4390
4391     s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC3),
4392                                      s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
4393                                      &s->drq[OMAP35XX_DMA_MMC3_TX],
4394                                      omap_findclk(s, "omap3_mmc3_fclk"),
4395                                      omap_findclk(s, "omap3_mmc3_iclk"));
4396
4397     s->i2c[0] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C1),
4398                                s->irq[0][OMAP_INT_35XX_I2C1_IRQ],
4399                                &s->drq[OMAP35XX_DMA_I2C1_TX],
4400                                omap_findclk(s, "omap3_i2c1_fclk"),
4401                                omap_findclk(s, "omap3_i2c1_iclk"),
4402                                8);
4403     s->i2c[1] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C2),
4404                                s->irq[0][OMAP_INT_35XX_I2C2_IRQ],
4405                                &s->drq[OMAP35XX_DMA_I2C2_TX],
4406                                omap_findclk(s, "omap3_i2c2_fclk"),
4407                                omap_findclk(s, "omap3_i2c2_iclk"),
4408                                8);
4409     s->i2c[2] = omap3_i2c_init(omap3_l4ta_init(s->l4, L4A_I2C3),
4410                                s->irq[0][OMAP_INT_35XX_I2C3_IRQ],
4411                                &s->drq[OMAP35XX_DMA_I2C3_TX],
4412                                omap_findclk(s, "omap3_i2c3_fclk"),
4413                                omap_findclk(s, "omap3_i2c3_iclk"),
4414                                64);
4415
4416     s->omap3_usb = omap3_hsusb_init(omap3_l4ta_init(s->l4, L4A_USBHS_OTG),
4417                                     omap3_l4ta_init(s->l4, L4A_USBHS_HOST),
4418                                     omap3_l4ta_init(s->l4, L4A_USBHS_TLL),
4419                                     s->irq[0][OMAP_INT_35XX_HSUSB_MC],
4420                                     s->irq[0][OMAP_INT_35XX_HSUSB_DMA],
4421                                     s->irq[0][OMAP_INT_35XX_OHCI_IRQ],
4422                                     s->irq[0][OMAP_INT_35XX_EHCI_IRQ],
4423                                     s->irq[0][OMAP_INT_35XX_TLL_IRQ]);
4424     return s;
4425 }
4426
4427
4428 static inline uint32_t omap3_get_le32(const void *p)
4429 {
4430     const uint8_t *q = (const uint8_t *)p;
4431     uint32_t v;
4432     v = q[3]; v <<= 8;
4433     v |= q[2]; v <<= 8;
4434     v |= q[1]; v <<= 8;
4435     v |= q[0];
4436     return v;
4437 }
4438
4439 static inline uint32_t omap3_get_le16(const void *p)
4440 {
4441     const uint8_t *q = (const uint8_t *)p;
4442     uint32_t v;
4443     v = q[1]; v <<= 8;
4444     v |= q[0];
4445     return v;
4446 }
4447
4448 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
4449 {
4450     uint8_t x[4];
4451     
4452     cpu_physical_memory_read(addr, x, 4);
4453     x[0] = lsb & 0xff;
4454     x[1] = (lsb >> 8) & 0xff;
4455     cpu_physical_memory_write(addr, x, 4);
4456 }
4457
4458 struct omap3_boot_s {
4459     struct omap_mpu_state_s *mpu;
4460     enum {
4461         undefined = 0,
4462         confighdr,
4463         chdone,
4464         imagehdr,
4465         copy,
4466         done
4467     } state;
4468     target_phys_addr_t addr;
4469     uint32_t count;
4470 };
4471
4472 static struct omap3_boot_s *omap3_boot_init(const uint8_t *data,
4473                                             uint32_t data_len,
4474                                             struct omap_mpu_state_s *mpu)
4475 {
4476     struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
4477     s->mpu = mpu;
4478     s->state = imagehdr;
4479     if (data_len >= 512) {
4480         if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
4481             || !strncasecmp((char *)(data + 0x14), "chram", 5)
4482             || !strncasecmp((char *)(data + 0x14), "chflash", 7)
4483             || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
4484             s->state = confighdr;
4485     }
4486     return s;
4487 }
4488
4489 static void omap3_boot_chsettings(const uint8_t *chtoc)
4490 {
4491     uint32_t flags, x;
4492     
4493     if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
4494         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4495         return;
4496     }
4497     if (!chtoc[4]) { /* section disabled? */
4498         return;
4499     }
4500     if (omap3_get_le16(chtoc + 5) != 0x0001) {
4501         fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
4502                 omap3_get_le16(chtoc));
4503         return;
4504     }
4505     flags = omap3_get_le32(chtoc + 8);
4506     chtoc += 12;
4507     if (flags & 1) {
4508         cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
4509         cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
4510         cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
4511         if (flags & (1 << 2)) { /* clock configuration */
4512             cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
4513             cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
4514         }
4515         if (flags & (1 << 5)) { /* DPLL3 CORE */
4516             if (flags & (1 << 8)) { /* enable DPLL3 bypass */
4517                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4518                 x &= ~7; x |= 5; /* set DPLL3 bypass */
4519                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4520             }
4521             cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
4522             cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
4523             cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
4524         }
4525         if (flags & (1 << 3)) { /* DPLL4 PER */
4526             if (flags & (1 << 6)) { /* enable DPLL4 bypass */
4527                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
4528                 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
4529                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
4530             }
4531             cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
4532             cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
4533             cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
4534             cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
4535         }
4536         if (flags & (1 << 3)) { /* DPLL1 MPU */
4537             if (flags & (1 << 7)) { /* enable DPLL1 bypass */
4538                 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
4539                 x &= ~7; x |= 5; /* set DPLL1 bypass */
4540                 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
4541             }
4542             cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
4543             cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
4544             cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
4545             cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
4546             cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
4547         }
4548         switch ((flags >> 24) & 0xff) {
4549             case 0x01: x = 0; break; /* 12MHz */
4550             case 0x02: x = 1; break; /* 13MHz */
4551             case 0x03: x = 5; break; /* 16.8MHz */
4552             case 0x04: x = 2; break; /* 19.2MHz */
4553             case 0x05: x = 3; break; /* 26MHz */
4554             case 0x06: x = 4; break; /* 38.4MHz */
4555             default:
4556                 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
4557                 x = 1;
4558                 break;
4559         }
4560         if (x != omap3_get_le32(chtoc + 0x04)) {
4561             fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
4562         }
4563     }
4564 }
4565
4566 static void omap3_boot_chram(const uint8_t *chtoc)
4567 {
4568     if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
4569         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4570         return;
4571     }
4572     if (!chtoc[4]) { /* section disabled? */
4573         return;
4574     }
4575     omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
4576     omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
4577     cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
4578
4579     cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
4580     omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
4581     omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
4582     omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
4583     omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
4584     cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
4585     cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
4586     cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
4587     
4588     cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
4589     omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
4590     omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
4591     omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
4592     omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
4593     cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
4594     cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
4595     cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
4596 }
4597
4598 static void omap3_boot_chflash(const uint8_t *chtoc)
4599 {
4600     if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
4601         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4602         return;
4603     }
4604     if (!chtoc[4]) { /* section disabled? */
4605         return;
4606     }
4607     omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
4608     omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
4609     omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
4610     omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
4611     cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
4612     cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
4613     cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
4614     cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
4615     cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
4616     cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
4617     cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
4618     cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
4619     omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
4620     omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
4621     /* TODO: ECC config registers. The TRM spec is not clear on these */
4622 }
4623
4624 static void omap3_boot_chmmcsd(const uint8_t *chtoc)
4625 {
4626     if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
4627         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
4628         return;
4629     }
4630     if (!chtoc[4]) { /* section disabled? */
4631         return;
4632     }
4633     /* TODO: MMCHS registers */
4634 }
4635
4636 /* returns non-zero if more blocks are needed */
4637 static uint32_t omap3_boot_block(const uint8_t *data,
4638                                  uint32_t data_len,
4639                                  struct omap3_boot_s *s)
4640 {
4641     const uint8_t *p = 0;
4642     uint32_t i = 0;
4643     
4644     switch (s->state) {
4645         case confighdr:
4646             i = data_len;
4647             for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
4648                 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
4649                     omap3_boot_chsettings(p + omap3_get_le32(p));
4650                 else if (!strcasecmp((char *)(p + 0x14), "chram"))
4651                     omap3_boot_chram(p + omap3_get_le32(p));
4652                 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
4653                     omap3_boot_chflash(p + omap3_get_le32(p));
4654                 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
4655                     omap3_boot_chmmcsd(p + omap3_get_le32(p));
4656                 else
4657                     fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
4658                             __FUNCTION__, (char *)(p + 0x14));
4659             }
4660             data += 512;
4661             data_len -= 512;
4662             s->state = chdone;
4663             /* fallthrough */
4664         case chdone:
4665             s->state = imagehdr;
4666             /* fallthrough */
4667         case imagehdr:
4668             if (!data_len)
4669                 return 1;
4670             if (data_len < 8)
4671                 break;
4672             s->count = omap3_get_le32(data);
4673             s->addr = omap3_get_le32(data + 4);
4674             if (!s->count || !s->addr || s->addr == 0xffffffff)
4675                 break;
4676             s->mpu->env->regs[15] = s->addr;
4677             data += 8;
4678             data_len -= 8;
4679             s->state = copy;
4680             /* fallthrough */
4681         case copy:
4682             i = (s->count >= data_len) ? data_len : s->count;
4683             cpu_physical_memory_write(s->addr, data, i);
4684             s->addr += i;
4685             s->count -= i;
4686             if (!s->count)
4687                 s->state = done;
4688             return s->count;
4689         default:
4690             break;
4691     }
4692     return 0;
4693 }
4694
4695 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
4696 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
4697 {
4698     int i;
4699     
4700     /* there are 0x10 items with 0x20 bytes per item */
4701     for (i = 0x10; i--; s += 0x20) {
4702         if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
4703         if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
4704     }
4705     return 0;
4706 }
4707
4708 struct omap3_fat_drv_s {
4709     BlockDriverState *bs;
4710     uint8_t ptype; /* 12, 16, 32 */
4711     uint64_t c0;   /* physical byte offset for data cluster 0 */
4712     uint64_t fat;  /* physical byte offset for used FAT sector 0 */
4713     uint32_t spc;  /* sectors per cluster */
4714 };
4715
4716 /* returns cluster data in the buffer and next cluster chain number
4717    or 0 if unsuccessful */
4718 static uint32_t omap3_read_fat_cluster(uint8_t *data,
4719                                        struct omap3_fat_drv_s *drv,
4720                                        uint32_t cl)
4721 {
4722     uint8_t buf[ 4 ];
4723     uint32_t len = drv->spc * 0x200; /* number of bytes to read */
4724     
4725     switch (drv->ptype) { /* check for EOF */
4726         case 12: if (cl > 0xff0) return 0; break;
4727         case 16: if (cl > 0xfff0) return 0; break;
4728         case 32: if (cl > 0x0ffffff0) return 0; break;
4729         default: return 0;
4730     }
4731     
4732     if (bdrv_pread(drv->bs, 
4733                    drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
4734                    data, len) != len)
4735         return 0;
4736     
4737     switch (drv->ptype) { /* determine next cluster # */
4738         case 12:
4739             fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
4740                     __FUNCTION__);
4741             break;
4742         case 16:
4743             return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
4744             ? 0 : omap3_get_le16(buf);
4745         case 32:
4746             return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
4747             ? 0 : omap3_get_le32(buf) & 0x0fffffff;
4748         default:
4749             break;
4750     }
4751     return 0;
4752 }
4753
4754 static int omap3_mmc_fat_boot(BlockDriverState *bs,
4755                               uint8_t *sector,
4756                               uint32_t pstart,
4757                               struct omap_mpu_state_s *mpu)
4758 {
4759     struct omap3_fat_drv_s drv;
4760     struct omap3_boot_s *boot;
4761     uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
4762     const uint8_t *p, *q;
4763     uint8_t *cluster;
4764     int result = 0;
4765     
4766     /* determine FAT type */
4767     
4768     drv.bs = bs;
4769     fatsize = omap3_get_le16(sector + 0x16);
4770     if (!fatsize) 
4771         fatsize = omap3_get_le32(sector + 0x24);
4772     bootsize = omap3_get_le16(sector + 0x0e);
4773     cluster0 = bootsize + fatsize * sector[0x10];
4774     rootsize = omap3_get_le16(sector + 0x11);
4775     if (rootsize & 0x0f)
4776         rootsize += 0x10;
4777     rootsize >>= 4;
4778     drv.spc = sector[0x0d];
4779     i = omap3_get_le16(sector + 0x13);
4780     if (!i)
4781         i = omap3_get_le32(sector + 0x20);
4782     i = (i - (cluster0 + rootsize)) / drv.spc;
4783     drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
4784     
4785     /* search for boot loader file */
4786     
4787     drv.fat = (bootsize + pstart) * 0x200;
4788     drv.c0 = (cluster0 + pstart) * 0x200;
4789     if (drv.ptype == 32) {
4790         i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
4791         j = omap3_get_le16(sector + 0x28);
4792         if (j & 0x80)
4793             drv.fat += (j & 0x0f) * fatsize * 0x200;
4794         cluster = qemu_mallocz(drv.spc * 0x200);
4795         for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
4796             for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
4797                 p = omap3_scan_fat_dir_sector(q);
4798             if (p) 
4799                 memcpy(sector, q - 0x200, 0x200); /* save the sector */
4800         }
4801         free(cluster);
4802     } else { /* FAT12/16 */
4803         for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
4804             if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
4805                 break;
4806             p = omap3_scan_fat_dir_sector(sector);
4807         }
4808     }
4809     
4810     if (p && *p) { /* did we indeed find the file? */
4811         i = omap3_get_le16(p + 0x14);
4812         i <<= 16;
4813         i |= omap3_get_le16(p + 0x1a);
4814         j = drv.spc * 0x200;
4815         uint8 *data = qemu_mallocz(j);
4816         if ((i = omap3_read_fat_cluster(data, &drv, i))) {
4817             boot = omap3_boot_init(data, j, mpu);
4818             boot->state = imagehdr; /* override CH detection */
4819             while (omap3_boot_block(data, j, boot))
4820                 i = omap3_read_fat_cluster(data, &drv, i);
4821             result = (boot->state == done);
4822             free(boot);
4823         } else
4824             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
4825                     __FUNCTION__);
4826         free(data);
4827     } else
4828         fprintf(stderr, "%s: MLO file not found in the root directory\n",
4829                 __FUNCTION__);
4830
4831     return result;
4832 }
4833
4834 static int omap3_mmc_raw_boot(BlockDriverState *bs,
4835                               uint8_t *sector,
4836                               struct omap_mpu_state_s *mpu)
4837 {
4838     struct omap3_boot_s *boot;
4839     uint32_t i = 0;
4840     int result = 0;
4841     
4842     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4843         boot = omap3_boot_init(sector, 0x200, mpu);
4844         if (boot->state == confighdr) { /* CH must be present for raw boot */
4845             while (omap3_boot_block(sector, 0x200, boot)) {
4846                 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
4847                     fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
4848                             __FUNCTION__, i);
4849                     break;
4850                 }
4851             }
4852         }
4853         result = (boot->state == done);
4854         free(boot);
4855     }
4856     return result;
4857 }
4858
4859 /* returns non-zero if successful, zero if unsuccessful */
4860 int omap3_mmc_boot(struct omap_mpu_state_s *s)
4861 {
4862     BlockDriverState *bs;
4863     int sdindex = drive_get_index(IF_SD, 0, 0);
4864     uint8_t *sector, *p;
4865     uint32_t pstart, i;
4866     int result = 0;
4867     
4868     /* very simple implementation for GP device boot,
4869        supports only two modes:
4870        1. MBR partition table with an active FAT partition
4871           and boot loader file (MLO) in its root directory, or
4872        2. CH sector located on first sector, followed by boot loader image */
4873     if (sdindex >= 0) {
4874         bs = drives_table[sdindex].bdrv;
4875         sector = qemu_mallocz(0x200);
4876         if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
4877             for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
4878                 if (p[0] == 0x80) break;
4879             if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
4880                 && i < 4 /* active partition exists */
4881                 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
4882                     || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
4883                 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
4884                               sector, 0x200) == 0x200
4885                 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
4886                 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
4887             else
4888                 result = omap3_mmc_raw_boot(bs, sector, s);
4889         }
4890         free(sector);
4891     }
4892     return result;
4893 }
4894
4895 /* returns non-zero if successful, zero if unsuccessful */
4896 int omap3_nand_boot(struct omap_mpu_state_s *mpu,
4897                     struct nand_flash_s *nand,
4898                     void (*nand_pread_f)(struct nand_flash_s *nand,
4899                                          uint64_t address,
4900                                          uint8_t *data,
4901                                          uint32_t len))
4902 {
4903     struct omap3_boot_s *boot;
4904     uint8_t *data;
4905     uint64_t addr = 0;
4906     int result = 0;
4907     
4908     data = qemu_mallocz(0x1000);
4909     nand_pread_f(nand, 0, data, 0x1000);
4910     boot = omap3_boot_init(data, 0x1000, mpu);
4911     while (omap3_boot_block(data, 0x1000, boot)) {
4912         addr += 0x1000;
4913         nand_pread_f(nand, addr, data, 0x1000);
4914     }
4915     result = (boot->state == done);
4916     free(boot);
4917     free(data);
4918     return result;
4919 }