1.fix the new line issue(dos2unix)
[qemu/qemu-JZ.git] / hw / mips_jz.c
blobadf7ff1becdab1cacf07037fc23ac1a7d1043626
1 /*
2 * QEMU JZ Soc emulation
4 * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
27 * The emulation target is pavo demo board.
28 * http://www.ingenic.cn/eng/productServ/kfyd/Hardware/pffaqQuestionContent.aspx?Category=2&Question=3
32 #include "hw.h"
33 #include "arm-misc.h"
34 #include "mips_jz.h"
35 #include "sysemu.h"
36 #include "qemu-timer.h"
37 #include "qemu-char.h"
38 #include "flash.h"
39 #include "soc_dma.h"
40 #include "audio/audio.h"
42 #define DEBUG_CPM (1<<0x1)
44 #define DEBUG_FLAG (DEBUG_CPM)
46 #ifdef DEBUG
48 FILE *fp;
49 static void debug_init()
51 fp = fopen("jz4740.txt", "w+");
52 if (fp == NULL)
54 fprintf(stderr, "can not open jz4740.txt \n");
55 exit(-1);
58 static void debug_out(uint32_t flag, const char *format, ...)
60 va_list ap;
61 if (fp)
63 if (flag & DEBUG_FLAG)
65 va_start(ap, format);
66 vfprintf(fp, format, ap);
67 fflush(fp);
68 va_end(ap);
72 #else
73 static void debug_init()
76 static void debug_out(uint32_t flag, const char *format, ...)
79 #endif
81 uint32_t jz4740_badwidth_read8(void *opaque, target_phys_addr_t addr)
83 uint8_t ret;
85 JZ4740_8B_REG(addr);
86 cpu_physical_memory_read(addr, (void *) &ret, 1);
87 return ret;
90 void jz4740_badwidth_write8(void *opaque, target_phys_addr_t addr,
91 uint32_t value)
93 uint8_t val8 = value;
95 JZ4740_8B_REG(addr);
96 cpu_physical_memory_write(addr, (void *) &val8, 1);
99 uint32_t jz4740_badwidth_read16(void *opaque, target_phys_addr_t addr)
101 uint16_t ret;
102 JZ4740_16B_REG(addr);
103 cpu_physical_memory_read(addr, (void *) &ret, 2);
104 return ret;
107 void jz4740_badwidth_write16(void *opaque, target_phys_addr_t addr,
108 uint32_t value)
110 uint16_t val16 = value;
112 JZ4740_16B_REG(addr);
113 cpu_physical_memory_write(addr, (void *) &val16, 2);
116 uint32_t jz4740_badwidth_read32(void *opaque, target_phys_addr_t addr)
118 uint32_t ret;
120 JZ4740_32B_REG(addr);
121 cpu_physical_memory_read(addr, (void *) &ret, 4);
122 return ret;
125 void jz4740_badwidth_write32(void *opaque, target_phys_addr_t addr,
126 uint32_t value)
128 JZ4740_32B_REG(addr);
129 cpu_physical_memory_write(addr, (void *) &value, 4);
133 /*clock reset and power control*/
134 struct jz4740_cpm_s
136 target_phys_addr_t base;
137 struct jz_state_s *soc;
139 uint32_t cpccr;
140 uint32_t cppcr;
141 uint32_t i2scdr;
142 uint32_t lpcdr;
143 uint32_t msccdr;
144 uint32_t uhccdr;
145 uint32_t uhctst;
146 uint32_t ssicdr;
149 static inline void jz4740_dump_clocks(struct clk *parent)
151 struct clk *i = parent;
153 debug_out(DEBUG_CPM, "clock %x rate 0x%x \n", i->name, i->rate);
154 for (i = clk->child1; i; i = i->sibling)
155 jz4740_dump_clocks(i);
158 static inline void jz4740_cpccr_update(struct jz4740_cpm_s *s,
159 uint32_t new_value)
161 uint32_t ldiv, mdiv, pdiv, hdiv, cdiv, udiv;
162 uint32_t div_table[10] = { 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 };
164 if (unlikely(new_value == s->cpccr))
165 return;
167 if (new_value & CPM_CPCCR_PCS)
168 jz_clk_setrate(jz_findclk(s->cpu, "pll_divider"), 1, 1);
169 else
170 jz_clk_setrate(jz_findclk(s->cpu, "pll_divider"), 2, 1);
173 ldiv = (new_value & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT;
174 ldiv++;
176 mdiv = div_table[(new_value & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT];
177 pdiv = div_table[(new_value & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT];
178 hdiv = div_table[(new_value & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT];
179 cdiv = div_table[(new_value & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT];
180 udiv = div_table[(new_value & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT];
182 jz_clk_setrate(jz_findclk(s->cpu, "ldclk"), ldiv, 1);
183 jz_clk_setrate(jz_findclk(s->cpu, "mclk"), mdiv, 1);
184 jz_clk_setrate(jz_findclk(s->cpu, "pclk"), pdiv, 1);
185 jz_clk_setrate(jz_findclk(s->cpu, "hclk"), hdiv, 1);
186 jz_clk_setrate(jz_findclk(s->cpu, "cclk"), cdiv, 1);
187 jz_clk_setrate(jz_findclk(s->cpu, "usbclk"), udiv, 1);
189 if (new_value & CPM_CPCCR_UCS)
190 jz_clk_reparent(jz_findclk(s->cpu, "usbclk"),
191 jz_findclk(s->cpu, "pll_divider"));
192 else
193 jz_clk_reparent(jz_findclk(s->cpu, "usbclk"),
194 jz_findclk(s->cpu, "osc_extal"));
196 if (new_value & CPM_CPCCR_I2CS)
197 jz_clk_reparent(jz_findclk(s->cpu, "i2sclk"),
198 jz_findclk(s->cpu, "pll_divider"));
199 else
200 jz_clk_reparent(jz_findclk(s->cpu, "i2sclk"),
201 jz_findclk(s->cpu, "osc_extal"));
203 s->cpccr = new_value;
205 debug_out(DEBUG_CPM, "write to cpccr 0x%x\n", new_value);
206 jz4740_dump_clocks(jz_findclk(s->cpu, "osc_extal"));
210 static inline void jz4740_cppcr_update(struct jz4740_cpm_s *s,
211 uint32_t new_value)
213 uint32_t pllm, plln, pllod, pllbp, pllen, pllst, pllen, pllbp;
214 uint32_t pll0[4] = { 1, 2, 2, 4 };
217 pllen = new_value & CPM_CPPCR_PLLEN;
218 pllbp = new_value & CPM_CPPCR_PLLBP;
219 if ((!pllen) || (pllen && pllbp))
221 jz_clk_setrate(jz_findclk(s->cpu, "pll_output"), 1, 1);
222 debug_out(DEBUG_CPM, "pll is bypassed \n");
223 s->cppcr = new_value | CPM_CPPCR_PLLS;
224 return;
228 pllm = (new_value & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT;
229 plln = (new_value & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT;
230 pllod = (new_value & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT;
231 jz_clk_setrate(jz_findclk(s->cpu, "pll_output"), (plln + 2) * pll0[pllod],
232 pllm + 2);
234 s->cppcr = new_value;
236 debug_out(DEBUG_CPM, "write to cppcr 0x%x\n", new_value);
237 jz4740_dump_clocks(jz_findclk(s->cpu, "osc_extal"));
241 static inline void jz4740_i2scdr_update(struct jz4740_cpm_s *s,
242 uint32_t new_value)
244 uint32_t i2scdr;
246 i2scdr = new_value & CPM_I2SCDR_I2SDIV_MASK;
247 if (unlikely(i2scdr == s->i2scdr))
248 return;
251 jz_clk_setrate(jz_findclk(s->cpu, "i2sclk"), i2scdr + 1, 1);
253 s->i2scdr = i2scdr;
255 debug_out(DEBUG_CPM, "write to i2scdr 0x%x\n", new_value);
256 jz4740_dump_clocks(jz_findclk(s->cpu, "osc_extal"));
260 static inline void jz4740_lpcdr_update(struct jz4740_cpm_s *s,
261 uint32_t new_value)
263 uint32_t ipcdr;
265 ipcdr = new_value & CPM_LPCDR_PIXDIV_MASK;
266 /*TODO: */
267 s->lpcdr = ipcdr;
270 static inline void jz4740_msccdr_update(struct jz4740_cpm_s *s,
271 uint32_t new_value)
273 uint32_t msccdr;
275 msccdr = new_value & CPM_MSCCDR_MSCDIV_MASK;
277 if (unlikely(msccdr == s->msccdr))
278 return;
281 jz_clk_setrate(jz_findclk(s->cpu, "mscclk"), msccdr + 1, 1);
283 s->msccdr = msccdr;
285 debug_out(DEBUG_CPM, "write to msccdr 0x%x\n", new_value);
286 jz4740_dump_clocks(jz_findclk(s->cpu, "osc_extal"));
290 static inline void jz4740_uhccdr_update(struct jz4740_cpm_s *s,
291 uint32_t new_value)
293 uint32_t uhccdr;
295 uhccdr = new_value & 0xf;
296 /*TODO: */
297 s->uhccdr = uhccdr;
300 static void jz4740_cpm_write(void *opaque, target_phys_addr_t addr,
301 uint32_t value)
303 struct jz4740_cpm_s *s = (struct jz4740_cpm_s *) opaque;
304 int offset = addr - s->base;
306 switch (offset)
308 case 0x0:
309 jz4740_cpccr_update(s, value);
310 break;
311 case 0x10:
312 jz4740_cppcr_update(s, value);
313 break;
314 case 0x60:
315 jz4740_i2scdr_update(s, value);
316 break;
317 case 0x64:
318 jz4740_lpcdr_update(s, value);
319 break;
320 case 0x68:
321 jz4740_msccdr_update(s, value);
322 break;
323 case 0x6c:
324 jz4740_uhccdr_update(s, value);
325 break;
326 case 0x70:
327 s->uhctst = value & 0x3f;
328 break;
329 case 0x74:
330 s->ssicdr = value & 0xf;
331 break;
332 default:
333 cpu_abort(s->cpu->env,
334 "jz4740_cpm_write undefined addr " JZ_FMT_plx " value %x \n",
335 addr, value);
341 static uint32_t jz474_cpm_read(void *opaque, target_phys_addr_t addr)
343 struct jz4740_cpm_s *s = (struct jz4740_cpm_s *) opaque;
344 int offset = addr - s->base;
346 switch (offset)
348 case 0x0:
349 return s->cpccr;
350 case 0x10:
351 return s->cppcr;
352 case 0x60:
353 return s->i2scdr;
354 case 0x64:
355 return s->lpcdr;
356 case 0x68:
357 return s->msccdr;
358 case 0x6c:
359 return s->uhccdr;
360 case 0x70:
361 return s->uhctst;
362 case 0x74:
363 return s->ssicdr;
364 default:
365 cpu_abort(s->cpu->env,
366 "jz474_cpm_read undefined addr " JZ_FMT_plx " \n", addr);
373 static CPUReadMemoryFunc *jz4740_cpm_readfn[] = {
374 jz4740_badwidth_read32,
375 jz4740_badwidth_read32,
376 jz474_cpm_read,
379 static CPUWriteMemoryFunc *jz4740_cpm_writefn[] = {
380 jz4740_badwidth_write32,
381 jz4740_badwidth_write32,
382 jz4740_cpm_write,
385 static void jz4740_cpm_reset(struct jz4740_cpm_s *s)
387 s->cpccr = 0x42040000;
388 s->cppcr = 0x28080011;
389 s->i2scdr = 0x00000004;
390 s->lpcdr = 0x00000004;
391 s->msccdr = 0x00000004;
392 s->uhccdr = 0x00000004;
393 s->uhctst = 0x0;
394 s->ssicdr = 0x00000004;
397 static struct jz4740_cpm_s *jz4740_cpm_init(struct jz_state_s *soc)
399 int iomemtype;
400 struct jz4740_cpm_s *s = (struct jz4740_cpm_s *) qemu_mallocz(sizeof(*s));
401 s->base = JZ4740_PHYS_BASE(JZ4740_CPM_BASE);
402 s->soc = soc;
404 jz4740_cpm_reset(s);
406 iomemtype =
407 cpu_register_io_memory(0, jz4740_cpm_readfn, jz4740_cpm_writefn, s);
408 cpu_register_physical_memory(s->base, 0x00001000, iomemtype);
412 /* JZ4740 interrupt controller
413 * It issues INT2 to MIPS
415 struct jz4740_intc_s
417 qemu_irq parent_irq;
419 target_phys_addr_t base;
420 struct jz_state_s *soc;
422 uint32_t icsr;
423 uint32_t icmr;
424 uint32_t icmsr;
425 uint32_t icmcr;
426 uint32_t icpr;
429 static uint32_t jz4740_intc_read(void *opaque, target_phys_addr_t addr)
431 struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
432 int offset = addr - s->base;
433 switch (offset)
435 case 0x8:
436 case 0xc:
437 JZ4740_WO_REG(addr);
438 break;
439 case 0x0:
440 return s->icsr;
441 case 0x4:
442 return s->icmr;
443 case 0x10:
444 return s->icpr;
445 default:
446 cpu_abort(s->cpu->env,
447 "jz4740_intc_read undefined addr " JZ_FMT_plx " \n", addr);
452 static void jz4740_intc_write(void *opaque, target_phys_addr_t addr,
453 uint32_t value)
455 struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
456 int offset = addr - s->base;
458 switch (offset)
460 case 0x0:
461 case 0x10:
462 JZ4740_RO_REG(addr);
463 break;
464 case 0x4:
465 s->icmr = value ;
466 break;
467 case 0x8:
468 s->icmr |= value;
469 break;
470 case 0xc:
471 s->icmr &= ~value;
472 break;
473 default:
474 cpu_abort(s->cpu->env,
475 "jz4740_intc_write undefined addr value %x" JZ_FMT_plx " \n",
476 addr, value);
481 static CPUReadMemoryFunc *jz4740_intc_readfn[] = {
482 jz4740_badwidth_read32,
483 jz4740_badwidth_read32,
484 jz4740_intc_read,
487 static CPUWriteMemoryFunc *jz4740_intc_writefn[] = {
488 jz4740_badwidth_write32,
489 jz4740_badwidth_write32,
490 jz4740_intc_write,
493 static void jz4740_intc_reset(struct jz4740_intc_s *s)
495 s->icsr = 0x0;
496 s->icmr = 0xffffffff;
497 s->icpr = 0x0;
500 static void jz4740_set_irq(void *opaque, int irq, int level)
502 struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
503 uint32_t irq_mask = 1<<irq;
505 s->icsr |= irq_mask;
506 s->icpr |= irq_mask;
507 s->icpr &= ~s->icmr;
509 if ((~s->icmr)&irq_mask)
510 qemu_set_irq(s->parent_irq,1);
511 else
512 qemu_set_irq(s->parent_irq,0);
515 static qemu_irq *jz4740_intc_init(struct jz_state_s *soc,qemu_irq parent_irq)
517 int iomemtype;
518 struct jz4740_intc_s *s = (struct jz4740_intc_s *) qemu_mallocz(sizeof(*s));
519 s->base = JZ4740_PHYS_BASE(JZ4740_INTC_BASE);
520 s->parent_irq = parent_irq;
521 s->soc = soc;
523 jz4740_intc_reset(s);
525 iomemtype =
526 cpu_register_io_memory(0, jz4740_intc_readfn, jz4740_intc_writefn, s);
527 cpu_register_physical_memory(s->base, 0x00001000, iomemtype);
528 return qemu_allocate_irqs(jz4740_set_irq, s, 32);
531 /*external memory controller*/
532 struct jz4740_emc_s
534 qemu_irq irq;
535 target_phys_addr_t base;
536 struct jz_state_s *soc;
538 uint32_t smcr1; /*0x13010014*/
539 uint32_t smcr2; /*0x13010018*/
540 uint32_t smcr3; /*0x1301001c*/
541 uint32_t smcr4; /*0x13010020*/
542 uint32_t sacr1; /*0x13010034*/
543 uint32_t sacr2; /*0x13010038*/
544 uint32_t sacr3; /*0x1301003c*/
545 uint32_t sacr4; /*0x13010040*/
547 uint32_t nfcsr; /*0x13010050*/
548 uint32_t nfeccr; /*0x13010100*/
549 uint32_t nfecc; /*0x13010104*/
550 uint32_t nfpar0; /*0x13010108*/
551 uint32_t nfpar1; /*0x1301010c*/
552 uint32_t nfpar2; /*0x13010110*/
553 uint32_t nfints; /*0x13010114*/
554 uint32_t nfinte; /*0x13010118*/
555 uint32_t nferr0; /*0x1301011c*/
556 uint32_t nferr1; /*0x13010120*/
557 uint32_t nferr2; /*0x13010124*/
558 uint32_t nferr3; /*0x13010128*/
560 uint32_t dmcr; /*0x13010080*/
561 uint32_t rtcsr; /*0x13010084*/
562 uint32_t rtcnt; /*0x13010088*/
563 uint32_t rtcor; /*0x1301008c*/
564 uint32_t dmar; /*0x13010090*/
565 uint32_t sdmr; /*0x1301a000*/
569 static void jz4740_emc_init(struct jz_state_s *soc,qemu_irq irq)
574 struct jz_state_s *jz4740_init(unsigned long sdram_size,
575 uint32_t osc_extal_freq)
577 struct jz_state_s *s = (struct jz_state_s *)
578 qemu_mallocz(sizeof(struct jz_state_s));
579 ram_addr_t sram_base, sdram_base;
580 qemu_irq * intc;
582 s->mpu_model = jz4740;
583 s->env = cpu_init("jz4740");
585 if (!s->env)
587 fprintf(stderr, "Unable to find CPU definition\n");
588 exit(1);
590 qemu_register_reset(main_cpu_reset, env);
592 s->sdram_size = sdram_size;
593 s->sram_size = JZ4740_SRAM_SIZE;
595 /*map sram to 0x80000000 and sdram to 0x80004000 */
596 sram_base = qemu_ram_alloc(s->sram_size);
597 cpu_register_physical_memory(JZ4740_SRAM_BASE, s->sram_size,
598 (sram_base | IO_MEM_RAM));
599 sdram_base = qemu_ram_alloc(s->sdram_size);
600 cpu_register_physical_memory(JZ4740_SDRAM_BASE, s->sdram_size,
601 (sdram_base | IO_MEM_RAM));
603 /* Init internal devices */
604 cpu_mips_irq_init_cpu(env);
605 cpu_mips_clock_init(env);
608 /* Clocks */
609 jz_clk_init(s, osc_extal_freq);
611 intc = jz4740_intc_init(s,s->env->irq[2]);
612 jz4740_cpm_init(s);