Revision e2f8a44d

b/hw/pxa2xx.c
224 224
    }
225 225
};
226 226

  
227
static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
227
static int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
228
                              uint64_t *value)
228 229
{
229
    PXA2xxState *s = (PXA2xxState *) opaque;
230

  
231
    switch (reg) {
232
    case 6:	/* Clock Configuration register */
233
        return s->clkcfg;
234

  
235
    case 7:	/* Power Mode register */
236
        return 0;
230
    PXA2xxState *s = (PXA2xxState *)ri->opaque;
231
    *value = s->clkcfg;
232
    return 0;
233
}
237 234

  
238
    default:
239
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
240
        break;
235
static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
236
                               uint64_t value)
237
{
238
    PXA2xxState *s = (PXA2xxState *)ri->opaque;
239
    s->clkcfg = value & 0xf;
240
    if (value & 2) {
241
        printf("%s: CPU frequency change attempt\n", __func__);
241 242
    }
242 243
    return 0;
243 244
}
244 245

  
245
static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
246
                uint32_t value)
246
static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
247
                                uint64_t value)
247 248
{
248
    PXA2xxState *s = (PXA2xxState *) opaque;
249
    PXA2xxState *s = (PXA2xxState *)ri->opaque;
249 250
    static const char *pwrmode[8] = {
250 251
        "Normal", "Idle", "Deep-idle", "Standby",
251 252
        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
252 253
    };
253 254

  
254
    switch (reg) {
255
    case 6:	/* Clock Configuration register */
256
        s->clkcfg = value & 0xf;
257
        if (value & 2)
258
            printf("%s: CPU frequency change attempt\n", __FUNCTION__);
255
    if (value & 8) {
256
        printf("%s: CPU voltage change attempt\n", __func__);
257
    }
258
    switch (value & 7) {
259
    case 0:
260
        /* Do nothing */
259 261
        break;
260 262

  
261
    case 7:	/* Power Mode register */
262
        if (value & 8)
263
            printf("%s: CPU voltage change attempt\n", __FUNCTION__);
264
        switch (value & 7) {
265
        case 0:
266
            /* Do nothing */
267
            break;
268

  
269
        case 1:
270
            /* Idle */
271
            if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) {	/* CPDIS */
272
                cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
273
                break;
274
            }
275
            /* Fall through.  */
276

  
277
        case 2:
278
            /* Deep-Idle */
263
    case 1:
264
        /* Idle */
265
        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
279 266
            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
280
            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
281
            goto message;
282

  
283
        case 3:
284
            s->cpu->env.uncached_cpsr =
285
                    ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
286
            s->cpu->env.cp15.c1_sys = 0;
287
            s->cpu->env.cp15.c1_coproc = 0;
288
            s->cpu->env.cp15.c2_base0 = 0;
289
            s->cpu->env.cp15.c3 = 0;
290
            s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
291
            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
292

  
293
            /*
294
             * The scratch-pad register is almost universally used
295
             * for storing the return address on suspend.  For the
296
             * lack of a resuming bootloader, perform a jump
297
             * directly to that address.
298
             */
299
            memset(s->cpu->env.regs, 0, 4 * 15);
300
            s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
267
            break;
268
        }
269
        /* Fall through.  */
270

  
271
    case 2:
272
        /* Deep-Idle */
273
        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
274
        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
275
        goto message;
276

  
277
    case 3:
278
        s->cpu->env.uncached_cpsr =
279
            ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
280
        s->cpu->env.cp15.c1_sys = 0;
281
        s->cpu->env.cp15.c1_coproc = 0;
282
        s->cpu->env.cp15.c2_base0 = 0;
283
        s->cpu->env.cp15.c3 = 0;
284
        s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
285
        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
286

  
287
        /*
288
         * The scratch-pad register is almost universally used
289
         * for storing the return address on suspend.  For the
290
         * lack of a resuming bootloader, perform a jump
291
         * directly to that address.
292
         */
293
        memset(s->cpu->env.regs, 0, 4 * 15);
294
        s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
301 295

  
302 296
#if 0
303
            buffer = 0xe59ff000;	/* ldr     pc, [pc, #0] */
304
            cpu_physical_memory_write(0, &buffer, 4);
305
            buffer = s->pm_regs[PSPR >> 2];
306
            cpu_physical_memory_write(8, &buffer, 4);
297
        buffer = 0xe59ff000; /* ldr     pc, [pc, #0] */
298
        cpu_physical_memory_write(0, &buffer, 4);
299
        buffer = s->pm_regs[PSPR >> 2];
300
        cpu_physical_memory_write(8, &buffer, 4);
307 301
#endif
308 302

  
309
            /* Suspend */
310
            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
311

  
312
            goto message;
303
        /* Suspend */
304
        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
313 305

  
314
        default:
315
        message:
316
            printf("%s: machine entered %s mode\n", __FUNCTION__,
317
                            pwrmode[value & 7]);
318
        }
319
        break;
306
        goto message;
320 307

  
321 308
    default:
322
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
323
        break;
309
    message:
310
        printf("%s: machine entered %s mode\n", __func__,
311
               pwrmode[value & 7]);
324 312
    }
325
}
326 313

  
327
static uint32_t pxa2xx_cp14_read(void *opaque, int op2, int reg, int crm)
328
{
329
    switch (crm) {
330
    case 0:
331
        return pxa2xx_clkpwr_read(opaque, op2, reg, crm);
332
    default:
333
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
334
        break;
335
    }
336 314
    return 0;
337 315
}
338 316

  
339
static void pxa2xx_cp14_write(void *opaque, int op2, int reg, int crm,
340
                uint32_t value)
341
{
342
    switch (crm) {
343
    case 0:
344
        pxa2xx_clkpwr_write(opaque, op2, reg, crm, value);
345
        break;
346
    default:
347
        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
348
        break;
349
    }
350
}
351

  
352 317
static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
353 318
                              uint64_t *value)
354 319
{
......
400 365
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
401 366
    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
402 367
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
368
    /* cp14 crn==6: CLKCFG */
369
    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
370
      .access = PL1_RW,
371
      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
372
    /* cp14 crn==7: PWRMODE */
373
    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
374
      .access = PL1_RW,
375
      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
403 376
    REGINFO_SENTINEL
404 377
};
405 378

  
......
2111 2084
    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
2112 2085
    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
2113 2086

  
2114
    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
2115 2087
    pxa2xx_setup_cp14(s);
2116 2088

  
2117 2089
    s->mm_base = 0x48000000;
......
2243 2215
    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
2244 2216
    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
2245 2217

  
2246
    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
2247 2218
    pxa2xx_setup_cp14(s);
2248 2219

  
2249 2220
    s->mm_base = 0x48000000;

Also available in: Unified diff