Changeset 1951


Ignore:
Timestamp:
05/12/07 18:21:11 (6 years ago)
Author:
andrew
Message:

Implement the S3C2410 watchdog timer. Clean-up the machine reset code and make it work.

Location:
trunk/src/host/qemu-neo1973/hw
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/host/qemu-neo1973/hw/neo1973.c

    r1950 r1951  
    6666struct neo_board_s { 
    6767    struct s3c_state_s *cpu; 
     68    unsigned int ram; 
    6869    i2c_slave *pmu; 
    6970    i2c_slave *wm; 
     
    7172    CharDriverState *modem; 
    7273    qemu_irq *kbd_pic; 
     74    const char *kernel; 
    7375}; 
    7476 
     
    349351{ 
    350352    struct neo_board_s *s = (struct neo_board_s *) opaque; 
    351     s3c2410_reset(s->cpu); 
    352     s->cpu->env->regs[15] = S3C_RAM_BASE; 
     353#if 0 
     354    s->cpu->env->regs[15] = S3C_SRAM_BASE; 
     355#else 
     356    load_image("u-boot.bin", phys_ram_base + 0x03f80000); 
     357    load_image(s->kernel, phys_ram_base + 0x02000000); 
     358    s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; 
     359#endif 
     360 
     361    /* Imitate ONKEY wakeup */ 
     362    pcf_onkey_set(s->pmu, 0); 
     363    pcf_onkey_set(s->pmu, 1); 
     364    /* Connect the charger */ 
     365    pcf_exton_set(s->pmu, 1); 
    353366} 
    354367 
     
    359372                const char *initrd_filename, const char *cpu_model) 
    360373{ 
    361     uint32_t neo_ram = 0x08000000; 
    362374    struct neo_board_s *s = (struct neo_board_s *) 
    363375            qemu_mallocz(sizeof(struct neo_board_s)); 
     376    s->ram = 0x08000000; 
     377    s->kernel = kernel_filename; 
    364378 
    365379    /* Setup CPU & memory */ 
    366     if (ram_size < neo_ram + S3C_SRAM_SIZE) { 
     380    if (ram_size < s->ram + S3C_SRAM_SIZE) { 
    367381        fprintf(stderr, "This platform requires %i bytes of memory\n", 
    368                         neo_ram + S3C_SRAM_SIZE); 
     382                        s->ram + S3C_SRAM_SIZE); 
    369383        exit(1); 
    370384    } 
     
    373387        exit(2); 
    374388    } 
    375     s->cpu = s3c2410_init(neo_ram, ds); 
     389    s->cpu = s3c2410_init(s->ram, ds); 
    376390 
    377391    s3c_nand_register(s->cpu, nand_init(NAND_MFR_SAMSUNG, 0x76)); 
     
    388402    neo_gsm_setup(s); 
    389403 
     404    /* Setup initial (reset) machine state */ 
    390405    qemu_register_reset(neo_reset, s); 
    391  
    392     /* Setup initial (reset) machine state */ 
    393406#if 0 
    394     cpu->env->regs[15] = S3C_SRAM_BASE; 
    395  
    396     arm_load_kernel(neo_ram, kernel_filename, kernel_cmdline, 
     407    arm_load_kernel(s->ram, kernel_filename, kernel_cmdline, 
    397408                    initrd_filename, 0x49e, S3C_RAM_BASE); 
    398 #else 
    399     load_image("u-boot.bin", 
    400                     phys_ram_base + 0x03f80000); 
    401     load_image(kernel_filename, 
    402                     phys_ram_base + 0x02000000); 
    403     s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; 
    404 #endif 
    405  
    406     /* Imitate ONKEY wakeup */ 
    407     pcf_onkey_set(s->pmu, 0); 
    408     pcf_onkey_set(s->pmu, 1); 
    409     /* Connect the charger */ 
    410     pcf_exton_set(s->pmu, 1); 
     409#endif 
     410    neo_reset(s); 
    411411} 
    412412 
  • trunk/src/host/qemu-neo1973/hw/s3c.h

    r1950 r1951  
    133133struct s3c_i2s_state_s *s3c_i2s_init(target_phys_addr_t base, qemu_irq *dma); 
    134134 
     135struct s3c_wdt_state_s; 
     136struct s3c_wdt_state_s *s3c_wdt_init(target_phys_addr_t base, qemu_irq irq); 
     137 
    135138/* s3c24xx_gpio.c */ 
    136139struct s3c_gpio_state_s; 
     
    193196    struct s3c_spi_state_s *spi; 
    194197    struct s3c_udc_state_s *udc; 
     198    struct s3c_wdt_state_s *wdt; 
    195199 
    196200    /* Memory controller */ 
     
    213217 
    214218/* s3c2410.c */ 
    215 void s3c2410_reset(struct s3c_state_s *s); 
    216219struct s3c_state_s *s3c2410_init(unsigned int sdram_size, DisplayState *ds); 
    217220void s3c_nand_register(struct s3c_state_s *s, struct nand_flash_s *chip); 
  • trunk/src/host/qemu-neo1973/hw/s3c2410.c

    r1950 r1951  
    21542154} 
    21552155 
     2156/* Watchdog Timer */ 
     2157struct s3c_wdt_state_s { 
     2158    target_phys_addr_t base; 
     2159    qemu_irq irq; 
     2160    uint16_t control; 
     2161    uint16_t data; 
     2162    uint16_t count; 
     2163    QEMUTimer *tm; 
     2164    int64_t timestamp; 
     2165}; 
     2166 
     2167static void s3c_wdt_start(struct s3c_wdt_state_s *s) 
     2168{ 
     2169    int enable = s->control & (1 << 5); 
     2170    int prescaler = (s->control >> 8) + 1; 
     2171    int divider = prescaler << (((s->control >> 3) & 3) + 4); 
     2172    if (enable) { 
     2173        s->timestamp = qemu_get_clock(vm_clock); 
     2174        qemu_mod_timer(s->tm, s->timestamp + muldiv64(divider * s->count, 
     2175                                ticks_per_sec, S3C_PCLK_FREQ)); 
     2176    } else 
     2177        qemu_del_timer(s->tm); 
     2178} 
     2179 
     2180static void s3c_wdt_stop(struct s3c_wdt_state_s *s) 
     2181{ 
     2182    int prescaler = (s->control >> 8) + 1; 
     2183    int divider = prescaler << (((s->control >> 3) & 3) + 4); 
     2184    int diff; 
     2185 
     2186    diff = muldiv64(qemu_get_clock(vm_clock) - s->timestamp, S3C_PCLK_FREQ, 
     2187                    ticks_per_sec) / divider; 
     2188    s->count -= MIN(s->count, diff); 
     2189    s->timestamp = qemu_get_clock(vm_clock); 
     2190} 
     2191 
     2192static void s3c_wdt_reset(struct s3c_wdt_state_s *s) 
     2193{ 
     2194    s->control = 0x8021; 
     2195    s->data = 0x8000; 
     2196    s->count = 0x8000; 
     2197    s3c_wdt_start(s); 
     2198} 
     2199 
     2200static void s3c_wdt_timeout(void *opaque) 
     2201{ 
     2202    struct s3c_wdt_state_s *s = (struct s3c_wdt_state_s *) opaque; 
     2203    if (s->control & (1 << 0)) { 
     2204        qemu_system_reset_request(); 
     2205        return; 
     2206    } 
     2207    if (s->control & (1 << 2)) 
     2208        qemu_irq_raise(s->irq); 
     2209    s->count = s->data; 
     2210    s3c_wdt_start(s); 
     2211} 
     2212 
     2213#define S3C_WTCON       0x00    /* Watchdog timer control register */ 
     2214#define S3C_WTDAT       0x04    /* Watchdog timer data register */ 
     2215#define S3C_WTCNT       0x08    /* Watchdog timer count register */ 
     2216 
     2217static uint32_t s3c_wdt_read(void *opaque, target_phys_addr_t addr) 
     2218{ 
     2219    struct s3c_wdt_state_s *s = (struct s3c_wdt_state_s *) opaque; 
     2220    addr -= s->base; 
     2221 
     2222    switch (addr) { 
     2223    case S3C_WTCON: 
     2224        return s->control; 
     2225    case S3C_WTDAT: 
     2226        return s->data; 
     2227    case S3C_WTCNT: 
     2228        s3c_wdt_stop(s); 
     2229        return s->count; 
     2230    default: 
     2231        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr); 
     2232        break; 
     2233    } 
     2234    return 0; 
     2235} 
     2236 
     2237static void s3c_wdt_write(void *opaque, target_phys_addr_t addr, 
     2238                uint32_t value) 
     2239{ 
     2240    struct s3c_wdt_state_s *s = (struct s3c_wdt_state_s *) opaque; 
     2241    addr -= s->base; 
     2242 
     2243    switch (addr) { 
     2244    case S3C_WTCON: 
     2245        s3c_wdt_stop(s); 
     2246        s->control = value; 
     2247        s3c_wdt_start(s); 
     2248        break; 
     2249    case S3C_WTDAT: 
     2250        s->data = value; 
     2251        break; 
     2252    case S3C_WTCNT: 
     2253        s->count = value; 
     2254        s3c_wdt_start(s); 
     2255        break; 
     2256    default: 
     2257        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr); 
     2258    } 
     2259} 
     2260 
     2261static CPUReadMemoryFunc *s3c_wdt_readfn[] = { 
     2262    s3c_wdt_read, 
     2263    s3c_wdt_read, 
     2264    s3c_wdt_read, 
     2265}; 
     2266 
     2267static CPUWriteMemoryFunc *s3c_wdt_writefn[] = { 
     2268    s3c_wdt_write, 
     2269    s3c_wdt_write, 
     2270    s3c_wdt_write, 
     2271}; 
     2272 
     2273struct s3c_wdt_state_s *s3c_wdt_init(target_phys_addr_t base, qemu_irq irq) 
     2274{ 
     2275    int iomemtype; 
     2276    struct s3c_wdt_state_s *s = (struct s3c_wdt_state_s *) 
     2277            qemu_mallocz(sizeof(struct s3c_wdt_state_s)); 
     2278 
     2279    s->base = base; 
     2280    s->irq = irq; 
     2281    s->tm = qemu_new_timer(vm_clock, s3c_wdt_timeout, s); 
     2282 
     2283    s3c_wdt_reset(s); 
     2284 
     2285    iomemtype = cpu_register_io_memory(0, s3c_wdt_readfn, 
     2286                    s3c_wdt_writefn, s); 
     2287    cpu_register_physical_memory(s->base, 0xffffff, iomemtype); 
     2288 
     2289    return s; 
     2290} 
     2291 
    21562292/* On-chip UARTs */ 
    21572293static struct { 
     
    21792315 
    21802316/* General CPU reset */ 
    2181 inline void s3c2410_reset(struct s3c_state_s *s) 
    2182 { 
     2317void s3c2410_reset(void *opaque) 
     2318{ 
     2319    struct s3c_state_s *s = (struct s3c_state_s *) opaque; 
    21832320    int i; 
    21842321    s3c_mc_reset(s); 
     
    21952332    s3c_spi_reset(s->spi); 
    21962333    s3c_udc_reset(s->udc); 
     2334    s3c_wdt_reset(s->wdt); 
    21972335    s3c_clkpwr_reset(s); 
    21982336    s3c_nand_reset(s); 
     
    22562394    s->udc = s3c_udc_init(0x52000000, s->irq[S3C_PIC_USBD], s->drq); 
    22572395 
    2258     /* Watchdog at 0x53000000 */ 
     2396    s->wdt = s3c_wdt_init(0x53000000, s->irq[S3C_PIC_WDT]); 
    22592397 
    22602398    s->i2c = s3c_i2c_init(0x54000000, s->irq[S3C_PIC_IIC]); 
     
    22792417    } 
    22802418 
     2419    qemu_register_reset(s3c2410_reset, s); 
     2420 
    22812421    s3c_nand_setwp(s, 1); 
    22822422 
Note: See TracChangeset for help on using the changeset viewer.