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