Revision dc2a9045 hw/pxa2xx.c
b/hw/pxa2xx.c | ||
---|---|---|
324 | 324 |
} |
325 | 325 |
} |
326 | 326 |
|
327 |
/* Performace Monitoring Registers */ |
|
328 |
#define CPPMNC 0 /* Performance Monitor Control register */ |
|
329 |
#define CPCCNT 1 /* Clock Counter register */ |
|
330 |
#define CPINTEN 4 /* Interrupt Enable register */ |
|
331 |
#define CPFLAG 5 /* Overflow Flag register */ |
|
332 |
#define CPEVTSEL 8 /* Event Selection register */ |
|
333 |
|
|
334 |
#define CPPMN0 0 /* Performance Count register 0 */ |
|
335 |
#define CPPMN1 1 /* Performance Count register 1 */ |
|
336 |
#define CPPMN2 2 /* Performance Count register 2 */ |
|
337 |
#define CPPMN3 3 /* Performance Count register 3 */ |
|
338 |
|
|
339 |
static uint32_t pxa2xx_perf_read(void *opaque, int op2, int reg, int crm) |
|
340 |
{ |
|
341 |
PXA2xxState *s = (PXA2xxState *) opaque; |
|
342 |
|
|
343 |
switch (reg) { |
|
344 |
case CPPMNC: |
|
345 |
return s->pmnc; |
|
346 |
case CPCCNT: |
|
347 |
if (s->pmnc & 1) |
|
348 |
return qemu_get_clock_ns(vm_clock); |
|
349 |
else |
|
350 |
return 0; |
|
351 |
case CPINTEN: |
|
352 |
case CPFLAG: |
|
353 |
case CPEVTSEL: |
|
354 |
return 0; |
|
355 |
|
|
356 |
default: |
|
357 |
printf("%s: Bad register 0x%x\n", __FUNCTION__, reg); |
|
358 |
break; |
|
359 |
} |
|
360 |
return 0; |
|
361 |
} |
|
362 |
|
|
363 |
static void pxa2xx_perf_write(void *opaque, int op2, int reg, int crm, |
|
364 |
uint32_t value) |
|
365 |
{ |
|
366 |
PXA2xxState *s = (PXA2xxState *) opaque; |
|
367 |
|
|
368 |
switch (reg) { |
|
369 |
case CPPMNC: |
|
370 |
s->pmnc = value; |
|
371 |
break; |
|
372 |
|
|
373 |
case CPCCNT: |
|
374 |
case CPINTEN: |
|
375 |
case CPFLAG: |
|
376 |
case CPEVTSEL: |
|
377 |
break; |
|
378 |
|
|
379 |
default: |
|
380 |
printf("%s: Bad register 0x%x\n", __FUNCTION__, reg); |
|
381 |
break; |
|
382 |
} |
|
383 |
} |
|
384 |
|
|
385 | 327 |
static uint32_t pxa2xx_cp14_read(void *opaque, int op2, int reg, int crm) |
386 | 328 |
{ |
387 | 329 |
switch (crm) { |
388 | 330 |
case 0: |
389 | 331 |
return pxa2xx_clkpwr_read(opaque, op2, reg, crm); |
390 |
case 1: |
|
391 |
return pxa2xx_perf_read(opaque, op2, reg, crm); |
|
392 |
case 2: |
|
393 |
switch (reg) { |
|
394 |
case CPPMN0: |
|
395 |
case CPPMN1: |
|
396 |
case CPPMN2: |
|
397 |
case CPPMN3: |
|
398 |
return 0; |
|
399 |
} |
|
400 |
/* Fall through */ |
|
401 | 332 |
default: |
402 | 333 |
printf("%s: Bad register 0x%x\n", __FUNCTION__, reg); |
403 | 334 |
break; |
... | ... | |
412 | 343 |
case 0: |
413 | 344 |
pxa2xx_clkpwr_write(opaque, op2, reg, crm, value); |
414 | 345 |
break; |
415 |
case 1: |
|
416 |
pxa2xx_perf_write(opaque, op2, reg, crm, value); |
|
417 |
break; |
|
418 |
case 2: |
|
419 |
switch (reg) { |
|
420 |
case CPPMN0: |
|
421 |
case CPPMN1: |
|
422 |
case CPPMN2: |
|
423 |
case CPPMN3: |
|
424 |
return; |
|
425 |
} |
|
426 |
/* Fall through */ |
|
427 | 346 |
default: |
428 | 347 |
printf("%s: Bad register 0x%x\n", __FUNCTION__, reg); |
429 | 348 |
break; |
430 | 349 |
} |
431 | 350 |
} |
432 | 351 |
|
352 |
static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri, |
|
353 |
uint64_t *value) |
|
354 |
{ |
|
355 |
PXA2xxState *s = (PXA2xxState *)ri->opaque; |
|
356 |
*value = s->pmnc; |
|
357 |
return 0; |
|
358 |
} |
|
359 |
|
|
360 |
static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri, |
|
361 |
uint64_t value) |
|
362 |
{ |
|
363 |
PXA2xxState *s = (PXA2xxState *)ri->opaque; |
|
364 |
s->pmnc = value; |
|
365 |
return 0; |
|
366 |
} |
|
367 |
|
|
368 |
static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri, |
|
369 |
uint64_t *value) |
|
370 |
{ |
|
371 |
PXA2xxState *s = (PXA2xxState *)ri->opaque; |
|
372 |
if (s->pmnc & 1) { |
|
373 |
*value = qemu_get_clock_ns(vm_clock); |
|
374 |
} else { |
|
375 |
*value = 0; |
|
376 |
} |
|
377 |
return 0; |
|
378 |
} |
|
379 |
|
|
380 |
static const ARMCPRegInfo pxa_cp_reginfo[] = { |
|
381 |
/* cp14 crn==1: perf registers */ |
|
382 |
{ .name = "CPPMNC", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, |
|
383 |
.access = PL1_RW, |
|
384 |
.readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write }, |
|
385 |
{ .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0, |
|
386 |
.access = PL1_RW, |
|
387 |
.readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore }, |
|
388 |
{ .name = "CPINTEN", .cp = 14, .crn = 1, .crm = 4, .opc1 = 0, .opc2 = 0, |
|
389 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
390 |
{ .name = "CPFLAG", .cp = 14, .crn = 1, .crm = 5, .opc1 = 0, .opc2 = 0, |
|
391 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
392 |
{ .name = "CPEVTSEL", .cp = 14, .crn = 1, .crm = 8, .opc1 = 0, .opc2 = 0, |
|
393 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
394 |
/* cp14 crn==2: performance count registers */ |
|
395 |
{ .name = "CPPMN0", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, |
|
396 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
397 |
{ .name = "CPPMN1", .cp = 14, .crn = 2, .crm = 1, .opc1 = 0, .opc2 = 0, |
|
398 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
399 |
{ .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0, |
|
400 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
401 |
{ .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0, |
|
402 |
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, |
|
403 |
REGINFO_SENTINEL |
|
404 |
}; |
|
405 |
|
|
406 |
static void pxa2xx_setup_cp14(PXA2xxState *s) |
|
407 |
{ |
|
408 |
define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s); |
|
409 |
} |
|
410 |
|
|
433 | 411 |
#define MDCNFG 0x00 /* SDRAM Configuration register */ |
434 | 412 |
#define MDREFR 0x04 /* SDRAM Refresh Control register */ |
435 | 413 |
#define MSC0 0x08 /* Static Memory Control register 0 */ |
... | ... | |
2134 | 2112 |
vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); |
2135 | 2113 |
|
2136 | 2114 |
cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); |
2115 |
pxa2xx_setup_cp14(s); |
|
2137 | 2116 |
|
2138 | 2117 |
s->mm_base = 0x48000000; |
2139 | 2118 |
s->mm_regs[MDMRS >> 2] = 0x00020002; |
... | ... | |
2265 | 2244 |
vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); |
2266 | 2245 |
|
2267 | 2246 |
cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); |
2247 |
pxa2xx_setup_cp14(s); |
|
2268 | 2248 |
|
2269 | 2249 |
s->mm_base = 0x48000000; |
2270 | 2250 |
s->mm_regs[MDMRS >> 2] = 0x00020002; |
Also available in: Unified diff