qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog


From: Kuo-Jung Su
Subject: Re: [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer support
Date: Thu, 7 Mar 2013 13:53:39 +0800

2013/3/7 Kuo-Jung Su <address@hidden>:
> 2013/3/6 Paolo Bonzini <address@hidden>:
>>> > > It doesn't work while running under ROM mode. ( no -kernel )
>>> > > Because Faraday SoC Platform usually designed to boot from ROM and
>>> > > followed by an AHB remapping process (i.e. remap ROM/RAM address).
>>> >
>>> > What doesn't work exactly?  Why aren't these called?  Or are
>>> > you forcing a particular reset order?
>>> >
>>> > Paolo
>>>
>>> While booting from ROM, the faraday soc usually remap the ROM / RAM
>>> before jumping into linux.
>>>
>>> In other words,  the system mapping is:
>>>
>>> 1. Power-On:
>>>
>>>     ROM: 0x00000000
>>>     RAM: N/A
>>>     SRAM: 0xA0000000
>>>
>>> 2. AHB Remap (u-boot/linux)
>>>
>>>     ROM: 0x20000000
>>>     RAM: 0x00000000
>>>
>>> So I have to register my own reset handler to
>>>
>>> 1. Undo the ROM/RAM remap (i.e. device_reset(s->ahbc))
>>> 2. Reset CPU
>>
>> ----- Messaggio originale -----
>>> Da: "Kuo-Jung Su" <address@hidden>
>>> A: "Paolo Bonzini" <address@hidden>
>>> Inviato: Mercoledì, 6 marzo 2013 11:00:49
>>> Oggetto: Re: [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer 
>>> support
>>>
>>> 2013/3/6 Paolo Bonzini <address@hidden>:
>>> >
>>> >> 2013/3/6 Paolo Bonzini <address@hidden>:
>>> >> > Il 06/03/2013 08:27, Kuo-Jung Su ha scritto:
>>> >> >> The FTWDT010 is used to prevent system from infinite loop
>>> >> >> while software gets trapped in the deadlock.
>>> >> >>
>>> >> >> Under the normal operation, users should restart FTWDT010
>>> >> >> at the regular intervals before counter counts down to 0.
>>> >> >>
>>> >> >> If the counter does reach 0, FTWDT010 will try to reset
>>> >> >> the system by generating one or a combination of signals,
>>> >> >> system reset, system interrupt, and external interrupt.
>>> >> >>
>>> >> >> Signed-off-by: Kuo-Jung Su <address@hidden>
>>> >> >> ---
>>> >> >>  hw/arm/Makefile.objs      |    1 +
>>> >> >>  hw/arm/faraday_a369_soc.c |   23 +++++
>>> >> >>  hw/arm/ftwdt010.c         |  212
>>> >> >>  +++++++++++++++++++++++++++++++++++++++++++++
>>> >> >>  hw/arm/ftwdt010.h         |   35 ++++++++
>>> >> >>  4 files changed, 271 insertions(+)
>>> >> >>  create mode 100644 hw/arm/ftwdt010.c
>>> >> >>  create mode 100644 hw/arm/ftwdt010.h
>>> >> >>
>>> >> >> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>>> >> >> index 2190edd..bc8e2de 100644
>>> >> >> --- a/hw/arm/Makefile.objs
>>> >> >> +++ b/hw/arm/Makefile.objs
>>> >> >> @@ -41,3 +41,4 @@ obj-y += ftintc020.o
>>> >> >>  obj-y += ftahbc020.o
>>> >> >>  obj-y += ftddrii030.o
>>> >> >>  obj-y += ftpwmtmr010.o
>>> >> >> +obj-y += ftwdt010.o
>>> >> >> diff --git a/hw/arm/faraday_a369_soc.c
>>> >> >> b/hw/arm/faraday_a369_soc.c
>>> >> >> index 66d9891..1bf64d4 100644
>>> >> >> --- a/hw/arm/faraday_a369_soc.c
>>> >> >> +++ b/hw/arm/faraday_a369_soc.c
>>> >> >> @@ -68,6 +68,25 @@ static void a369soc_reset(DeviceState *ds)
>>> >> >>  }
>>> >> >>
>>> >> >>  static void
>>> >> >> +a369soc_system_reset(void *opaque)
>>> >> >> +{
>>> >> >> +    FaradaySoCState *s = FARADAY_SOC(opaque);
>>> >> >> +
>>> >> >> +    if (s->scu) {
>>> >> >> +        device_reset(s->scu);
>>> >> >> +    }
>>> >> >> +    if (s->ddrc) {
>>> >> >> +        device_reset(s->ddrc);
>>> >> >> +    }
>>> >> >> +    if (s->ahbc) {
>>> >> >> +        device_reset(s->ahbc);
>>> >> >> +    }
>>> >> >> +    if (s->cpu) {
>>> >> >> +        cpu_reset(CPU(s->cpu));
>>> >> >> +    }
>>> >> >> +}
>>> >> >
>>> >> > Why is this needed?  Aren't they called already by
>>> >> >
>>> >> >     qemu_register_reset(qbus_reset_all_fn,
>>> >> >     sysbus_get_default());
>>> >> >
>>> >> > ?
>>> >> >
>>> >>
>>> >> It doesn't work while running under ROM mode. ( no -kernel )
>>> >> Because Faraday SoC Platform usually designed to boot from ROM and
>>> >> followed by an AHB remapping process (i.e. remap ROM/RAM address).
>>> >
>>> > What doesn't work exactly?  Why aren't these called?  Or are
>>> > you forcing a particular reset order?
>>> >
>>> > Paolo
>>>
>>> While booting from ROM, the faraday soc usually remap the ROM / RAM
>>> before jumping into linux.
>>>
>>> In other words,  the system mapping is:
>>>
>>> 1. Power-On:
>>>
>>>     ROM: 0x00000000
>>>     RAM: N/A
>>>     SRAM: 0xA0000000
>>>
>>> 2. AHB Remap (u-boot/linux)
>>>
>>>     ROM: 0x20000000
>>>     RAM: 0x00000000
>>>
>>> So I have to register my own reset handler to
>>>
>>> 1. Undo the ROM/RAM remap (i.e. device_reset(s->ahbc))
>>> 2. Reset CPU
>>
>> I understand that.  What I'm missing is, why these reset handlers aren't
>> called anyway when QEMU does qemu_devices_reset(), for example from
>> qemu_system_reset().
>>
>
> 1. arm_cpu_reset() is never be invoked from the default reset handler.
>
> 2. Undo ROM/RAM remap would make bus become unstable there is no
>     guaranty when the bus would be stabilized.
>     (It looks to me that it's true for both QEMU and real hardware)
>
> 3. In QEMU, my guess is without arm_cpu_reset(), when the AHB remap process
>     activated upon watchdog counts down to zero.
>     The PC (r15) could be anywhere, and so does the stack & bss.
>     Which means the CPU would likely suffers from UNKNOWN INSTRUCTION,
>     DATA ABORT... etc.
>
>> Also, I do not understand who performs this again:
>>
>
> It's performed at my ROM code:
>
> https://github.com/dantesu1218/virgil/blob/master/arch/mach-a369/board.c
>
> line 200 ~ 220
>
> #ifndef CONFIG_SKIP_SYSINIT
> /* Skip AHB remap if the jump address is not inside SDRAM address space */
> "ldr r4, =0x10000000\n"
> "cmp %2, r4\n"
> "movhs pc, %2\n" /* jump without AHB remapped */
> /* AHB remap
> * REG32(CONFIG_IOBASE_DDR + 0x10) &= 0x00FFFFFF
> * REG32(CONFIG_IOBASE_AHB + 0x88)  = 0x00100F01
> */
> "ldr r4, [%0, #0x10]\n"
> "bic r4, #0xff000000\n"
> "ldr r5, =0x00100f01\n"
> ".ALIGN 5\n" /* Make sure all the following codes to be fetched in a
> single 32-bytes cache line */
> "str r4, [%0, #0x10]\n" /* REG32(CONFIG_IOBASE_DDR + 0x10) &= 0x00FFFFFF */
> "str r5, [%1, #0x88]\n" /* REG32(CONFIG_IOBASE_AHB + 0x88)  = 0x00100F01 */
> "5:\n"
> "ldr r4, [%2, #0]\n" /* while(magic != REG32(addr)) */
> "teq r4, %3\n"
> "bne 5b\n"
> #endif
> "mov pc, %2\n" /* jump */
>
>

Sorry, if I get you wrong, and what you're actually asking is:
Where or which module is responsible for SDRAM init and AHB remap?

The answer is:

1. ftahbc020: It's responsible for AHB remap, please check this:

   static void ftahbc020_mem_write()
   {
        ......
        if (!soc->ahb_remapped && (s->cr & CR_REMAP)) {
            /* Remap AHB slave 4 (ROM) & slave 6 (RAM) */
            /* 1. Remap RAM to base of ROM */
            soc->ram_base = soc->ahb_slave[4] & 0xfff00000;
            /* 2. Remap ROM to base of ROM + size of RAM */
            soc->rom_base = soc->ram_base
                          + ((1 << extract32(soc->ahb_slave[6], 16, 4)) << 20);
            /* 3. Update ROM memory map */
            sysbus_mmio_map(SYS_BUS_DEVICE(soc->rom), 0, soc->rom_base);
            /* 4. Update RAM memory map if it has been initialized. */
            if (soc->ddr_inited) {
                memory_region_del_subregion(soc->as, soc->ram);
                memory_region_add_subregion(soc->as, soc->ram_base, soc->ram);
            }
            soc->ahb_remapped = true;
        }
        ......
   }

2. ftddrii030: It's responsible for SDRAM init, please check this:

static void ftddrii030_mem_write()
{
    ......
        if (!soc->ddr_inited && (val & MSR_CMD_MRS)) {
            val &= ~MSR_CMD_MRS;
            val |= MSR_INIT_OK;
            memory_region_add_subregion(soc->as, soc->ram_base, soc->ram);
            soc->ddr_inited = true;
        }
    ......
}

>> +        /* Remap AHB slave 4 (ROM) & slave 6 (RAM) */
>> +        /* 1. Remap RAM to base of ROM */
>> +        s->ram_base = s->ahb_slave[4] & 0xfff00000;
>> +        s->ahb_slave[6] = s->ram_base | (s->ahb_slave[6] & 0x000f0000);
>> +        /* 2. Remap ROM to base of ROM + size of RAM */
>> +        s->rom_base = s->ram_base
>> +                    + ((1 << extract32(s->ahb_slave[6], 16, 4)) << 20);
>> +        s->ahb_slave[4] = s->rom_base | (s->ahb_slave[4] & 0x000f0000);
>>
>> when you do a system_reset and the board was started in kernel mode.
>>
>
> The problem is not about the kernel mode. In my words, I call them:
>
> 1. RAM Mode Emulation (Launching QEMU with -kernel) :
>     The emulator would assume that the SDRAM has been remapped to
>     0x00000000.
>
> 2. ROM Mode Emulation (Without -kernel):
>     The emulator would map the 6KB ROM (pflash) to 0x00000000, 32KB SRAM
>     to 0xA0000000, but no SDRAM
>
> P.S:
>
> In A369, the the boot sequence of ROM mode is:
>
> 1. Power-on
> 2. ROM code execution on ROM @ 0x00000000
> 3. 2nd bootstrap on SRAM @ 0xA0000000
> 4. General software (Linux/U-boot) execution on SDRAM @ 0x00000000
>
> In newer design, (from 2010, after my referenced ROM code is reay)
> the the boot sequence of ROM mode becomes:
>
> 1. Power-on
> 2. ROM code execution on ROM @ 0x00000000
> 3. General software (Linux/U-boot) execution on SDRAM @ 0x00000000
>
> Currently I have a kw9505 QEMU model ready for this,  and since it's a
> customer ASIC,
> it shall never be merged into open source.
> But if you want, I could provide the kw9505.c with lots of coding style issues
> for function test.
>
>> Paolo
>
>
>
> --
> Best wishes,
> Kuo-Jung Su



--
Best wishes,
Kuo-Jung Su



reply via email to

[Prev in Thread] Current Thread [Next in Thread]