Exemple #1
0
void
do_caches(int argc, char *argv[])
{
    unsigned long oldints;
    int dcache_on=0, icache_on=0;

    if (argc == 2) {
        if (strcasecmp(argv[1], "on") == 0) {
            HAL_DISABLE_INTERRUPTS(oldints);
            HAL_ICACHE_ENABLE();
            HAL_DCACHE_ENABLE();
            HAL_RESTORE_INTERRUPTS(oldints);
        } else if (strcasecmp(argv[1], "off") == 0) {
            HAL_DISABLE_INTERRUPTS(oldints);
            HAL_DCACHE_SYNC();
            HAL_ICACHE_DISABLE();
            HAL_DCACHE_DISABLE();
            HAL_DCACHE_SYNC();
            HAL_ICACHE_INVALIDATE_ALL();
            HAL_DCACHE_INVALIDATE_ALL();
            HAL_RESTORE_INTERRUPTS(oldints);
        } else {
            diag_printf("Invalid cache mode: %s\n", argv[1]);
        }
    } else {
#ifdef HAL_DCACHE_IS_ENABLED
        HAL_DCACHE_IS_ENABLED(dcache_on);
#endif
#ifdef HAL_ICACHE_IS_ENABLED
        HAL_ICACHE_IS_ENABLED(icache_on);
#endif
        diag_printf("Data cache: %s, Instruction cache: %s\n", 
                    dcache_on?"On":"Off", icache_on?"On":"Off");
    }
}
static void 
do_exec(int argc, char *argv[])
{
    unsigned long oldints;
    bool wait_time_set;
    int  wait_time, res;
    bool cmd_line_set;
    struct option_info opts[4];
    code_fun entry;
    char line[8];
    char *cmd_line;
    int num_options;

    entry = (code_fun)entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
              (void **)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
    num_options = 2;

    if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, 
                   OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("Can't execute Linux - invalid entry address\n");
        return;
    }
    if (cmd_line_set) {
	memcpy((char*)CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS,"cmdline:",8);
        strncpy((char*)CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+8,cmd_line,256);
	*(char*)(CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+8+256) = 0;
    }
    else {
	*(char*)(CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+256) = 0;
    }

    if (wait_time_set) {
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        res = _rb_gets(line, sizeof(line), wait_time*1000);
        if (res == _GETS_CTRLC) {
            return;
        }
    }

#ifdef CYGPKG_IO_ETH_DRIVERS
    eth_drv_stop();
#endif

    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    HAL_ICACHE_DISABLE();
    HAL_DCACHE_DISABLE();
    HAL_DCACHE_SYNC();
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();
    (*entry)();
}
Exemple #3
0
void
do_go(int argc, char *argv[])
{
    typedef void code_fun(void);
    unsigned long entry;
    unsigned long oldints;
    code_fun *fun;
    bool wait_time_set;
    int  wait_time, res;
    struct option_info opts[1];
    char line[8];

    entry = entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
    if (!scan_opts(argc, argv, 1, opts, 1, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }
    fun = (code_fun *)entry;
    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    HAL_ICACHE_DISABLE();
    HAL_DCACHE_DISABLE();
    HAL_DCACHE_SYNC();
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();
#ifdef HAL_ARCH_PROGRAM_NEW_STACK
    HAL_ARCH_PROGRAM_NEW_STACK(fun);
#else
    (*fun)();
#endif
}
Exemple #4
0
int
flash_query(unsigned char *data)
{
    volatile unsigned long *lROM;
    volatile unsigned char *cROM;
    int i, cnt;
    int cache_on;

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    lROM = 0x41000000;
    cROM = 0x41000000;

    lROM[0] = FLASH_Read_ID;
    for (cnt = CNT;  cnt > 0;  cnt--) ;
    for (i = 0;  i < 8;  i++) {
        *data++ = cROM[i];
    }
    lROM[0] = FLASH_Reset;

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return 0;
}
Exemple #5
0
static void time0DI(register cyg_uint32 stride)
{
    register cyg_uint32 j,k;
    volatile cyg_tick_count_t count0;
    cyg_tick_count_t count1;
    cyg_ucount32 t;
    register char c;
    register CYG_INTERRUPT_STATE oldints;

    count0 = cyg_current_time();

    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();

    k = 0;
    if ( cyg_test_is_simulator )
        k = 3960;

    for(; k<4000;k++) {
        for(j=0; j<(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE); j++) {
            HAL_DCACHE_INVALIDATE_ALL();
            c=m[stride*j];
        }
    }
    HAL_RESTORE_INTERRUPTS(oldints);    

    count1 = cyg_current_time();
    t = count1 - count0;
    diag_printf("stride=%d, time=%d\n", stride, t);
}
Exemple #6
0
int
flash_lock_block(volatile unsigned char *block)
{
    volatile unsigned char *ROM;
    unsigned short stat;
    int timeout = 5000000;
    int cache_on;

    ROM = FLASH_P2V((unsigned long)block & 0xFF800000);

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

    // Set lock bit
    FLASH_P2V(block)[0] = FLASH_Set_Lock;
    FLASH_P2V(block)[0] = FLASH_Set_Lock_Confirm;  // Confirmation
    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
        if (--timeout == 0) break;
    }

    // Restore ROM to "normal" mode
    ROM[0] = FLASH_Reset;

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
Exemple #7
0
int
flash_hwr_init(void)
{
    struct FLASH_query data, *qp;
    extern char flash_query, flash_query_end;
    typedef int code_fun(unsigned char *);
    code_fun *_flash_query;
    int code_len, stat, num_regions, region_size;

    // Copy 'program' code to RAM for execution
    code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query;
    _flash_query = (code_fun *)flash_info.work_space;
    memcpy(_flash_query, &flash_query, code_len);

    HAL_DCACHE_SYNC();             // Should guarantee this code will run
    HAL_ICACHE_INVALIDATE_ALL();   // is also required to avoid old contents
    stat = (*_flash_query)(&data);

    qp = &data;
    if (/*(qp->manuf_code == FLASH_Intel_code) && */
        (strncmp(qp->id, "QRY", 3) == 0)) {
        num_regions = _si(qp->num_regions)+1;
        region_size = _si(qp->region_size)*256;

        flash_info.block_size = region_size*2;   // Pairs of chips in parallel
        flash_info.blocks = num_regions*2;	 // and pairs of chips in serial
        flash_info.start = (void *)0x9c000000;
        flash_info.end = (void *)0x9e000000;
        return FLASH_ERR_OK;
    } else {
        (*flash_info.pf)("Can't identify FLASH, sorry\n");
        diag_dump_buf(data, sizeof(data));
        return FLASH_ERR_HWR;
    }
}
Exemple #8
0
/* Starting another CPUs */
__externC void cyg_hal_cpu_start(HAL_SMP_CPU_TYPE cpu) {
    if (cyg_hal_smp_cpu_running[cpu] == 1)
        return;

    if (cpu == 0) {
        cyg_hal_smp_cpu_running[cpu] = 1;
        hal_scu_join_smp();
    } else {
        hal_delay_us(100);
        /* Flush cache */
        HAL_DCACHE_INVALIDATE_ALL();
        HAL_ICACHE_INVALIDATE_ALL();

        HAL_DCACHE_SYNC();
        HAL_ICACHE_SYNC();

        zynq_cpu_stop(cpu);
        cyg_uint32 trampoline_size =
            (cyg_uint32)&zynq_secondary_trampoline_jump -
            (cyg_uint32)&zynq_secondary_trampoline;

        memcpy(0x0, &zynq_secondary_trampoline, trampoline_size);
        HAL_WRITE_UINT32(0x0 + trampoline_size,
                         (cyg_uint32)&cyg_hal_smp_start_secondary_cpu);
        zynq_cpu_start(cpu);
    }
}
Exemple #9
0
int flash_erase_block(volatile unsigned char *block)
{
    volatile unsigned char *ROM;
    unsigned short stat;
    int timeout = 50000;
    int cache_on;
    int len;

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }


    // First 4K page of flash at physcial address zero is
    // virtually mapped to address 0xa0000000.
    ROM = FLASH_P2V((unsigned)block & 0xFF800000);

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

    // Erase block
    ROM[0] = FLASH_Block_Erase;
    *FLASH_P2V(block) = FLASH_Confirm;
    timeout = 5000000;
    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
        if (--timeout == 0) break;
    }

    // Restore ROM to "normal" mode
    ROM[0] = FLASH_Reset;

    // If an error was reported, see if the block erased anyway
    if (stat & 0x7E) {
        len = FLASH_BLOCK_SIZE;
        while (len > 0) {
	    if (*FLASH_P2V(block) != 0xFF)
		break;
	    block++;
            len -= sizeof(*block);
        }
        if (len == 0) stat = 0;
    }

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
Exemple #10
0
void
install_async_breakpoint(void *epc)
{
    CYGARC_HAL_SAVE_GP();

    asyncBuffer.targetAddr = epc;
    asyncBuffer.savedInstr = *(t_inst *)epc;
    *(t_inst *)epc = *(t_inst *)_breakinst;

    HAL_DCACHE_SYNC();
    HAL_ICACHE_SYNC();

    CYGARC_HAL_RESTORE_GP();
}
Exemple #11
0
void
hdwr_diag (void)
{
    diag_printf ("Entering Hardware Diagnostics - Disabling Data Cache!\n");

    cyg_pci_init(); 

    HAL_DCACHE_SYNC();
    HAL_DCACHE_DISABLE();
	
    menu (testMenu, NUM_MENU_ITEMS, MENU_TITLE, MENU_OPT_NONE);

    diag_printf ("Exiting Hardware Diagnostics!\n\n");
    HAL_DCACHE_ENABLE();
}
Exemple #12
0
int __computeSignal (unsigned int trap_number)
{
    // Treat everything as a break point

    if (asyncBuffer.targetAddr != NULL)
    {
        // BP installed by serial driver to stop running program

        *asyncBuffer.targetAddr = asyncBuffer.savedInstr;
        HAL_DCACHE_SYNC();
        HAL_ICACHE_SYNC();
        asyncBuffer.targetAddr = NULL;
        return SIGINT;
    }
    return SIGTRAP;
}
Exemple #13
0
int
flash_query(unsigned char *data)
{
    volatile flash_t *ROM;
    int i, cnt;
    int cache_on;

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Get base address and map addresses to virtual addresses
    ROM = FLASH_P2V( CYGNUM_FLASH_BASE );
#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
    // BootBlock flash does not support full Read_Query - we have do a
    // table oriented thing above, after getting just two bytes of results:
    ROM[0] = FLASH_Read_ID;
    i = 2;
#else
    // StrataFlash supports the full Read_Query op:
    ROM[0] = FLASH_Read_Query;
    i = sizeof(struct FLASH_query);
#endif // Not CYGOPT_FLASH_IS_BOOTBLOCK

    for (cnt = CNT;  cnt > 0;  cnt--) ;
    for ( /* i */;  i > 0;  i-- ) {
        // It is very deliberate that data is chars NOT flash_t:
        // The info comes out in bytes regardless of device.
        *data++ = (unsigned char) (*ROM++);
#ifndef CYGOPT_FLASH_IS_BOOTBLOCK
# if  8 == CYGNUM_FLASH_WIDTH
	// strata flash with 'byte-enable' contains the configuration data
	// at even addresses
	++ROM;
# endif
#endif
    }
    ROM[0] = FLASH_Reset;

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return 0;
}
Exemple #14
0
int
flash_hwr_init(void)
{
    unsigned short data[4];
    extern char flash_query, flash_query_end;
    typedef int code_fun(unsigned char *);
    code_fun *_flash_query;
    int code_len, stat, num_regions, region_size;

    // Copy 'program' code to RAM for execution
    code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query;
    _flash_query = (code_fun *)flash_info.work_space;
    memcpy(_flash_query, &flash_query, code_len);
    HAL_DCACHE_SYNC();  // Should guarantee this code will run

    stat = (*_flash_query)(data);
#if 0
    (*flash_info.pf)("stat = %x\n", stat);
    dump_buf(data, sizeof(data));
#endif

    if (data[0] != FLASH_Atmel_code) {
        (*flash_info.pf)("Not Atmel = %x\n", data[0]);
        return FLASH_ERR_HWR;
    }

    if (data[1] == (unsigned short)FLASH_ATMEL_29LV1024) {
        num_regions = 256;
        region_size = 0x100;
    } else {
        (*flash_info.pf)("Unknown device type: %x\n", data[1]);
        return FLASH_ERR_HWR;
    }

    // Hard wired for now
    flash_info.block_size = region_size;
    flash_info.blocks = num_regions;
    flash_info.start = (void *)0x01010000;
    flash_info.end = (void *)(0x01010000+(num_regions*region_size));
    return FLASH_ERR_OK;
}
Exemple #15
0
void __install_breakpoints ()
{
    if (instrBuffer.targetAddr != NULL)
    {
        instrBuffer.savedInstr = *instrBuffer.targetAddr;
        *instrBuffer.targetAddr = __break_opcode ();
    }

    // Ensure that any instructions that are about to be modified aren't in
    // the instruction cache.

    HAL_ICACHE_SYNC();

    // Install the breakpoints in the breakpoint list

    __install_breakpoint_list();

    // Make sure the breakpoints have been written out to memory.

    HAL_DCACHE_SYNC();
}
int
flash_lock_block(volatile flash_t *block)
{
    volatile flash_t *ROM;
    flash_t stat;
    int timeout = 5000000;
    int cache_on;
    volatile int j;

    // Get base address and map addresses to virtual addresses
    ROM = FLASH_P2V(CYGNUM_FLASH_BASE_MASK & (unsigned int)block);
    block = FLASH_P2V(block);

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

    // Set lock bit
    block[0] = FLASH_Set_Lock;
    block[0] = FLASH_Set_Lock_Confirm;  // Confirmation
    for (j = 0; j < FLASH_Delay; ++j);
    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
        if (--timeout == 0) break;
    }

    // Restore ROM to "normal" mode
    ROM[0] = FLASH_Reset;
    for (j = 0; j < FLASH_Delay; ++j);

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
int
flash_program_buf(volatile unsigned long *addr, unsigned long *data, int len)
{
    unsigned long stat = 0;
    int timeout = 5000000;
    int cache_on;
    volatile unsigned long *orig_addr = addr;

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Clear any error conditions
    *addr = FLASH_Clear_Status;

    while (len > 0) {
        *addr = FLASH_Program;
        *addr = *data++;
        timeout = 5000000;
        while (((stat = *addr) & FLASH_Status_Ready) != FLASH_Status_Ready) {
            if (--timeout == 0) {
                goto bad;
            }
        }
        addr++;
        len -= sizeof(unsigned long);
    }

    // Restore ROM to "normal" mode
 bad:
    *orig_addr = FLASH_Reset;            

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
int
flash_hwr_init(void)
{
    struct FLASH_query data, *qp;
    extern char flash_query, flash_query_end;
    typedef int code_fun(unsigned char *);
    code_fun *_flash_query;
    int code_len, stat, num_regions, region_size, icache_isenabled;

    // Copy 'program' code to RAM for execution
    code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query;
    _flash_query = (code_fun *)flash_info.work_space;
    memcpy(_flash_query, &flash_query, code_len);
    HAL_ICACHE_IS_ENABLED(icache_isenabled);
    HAL_DCACHE_SYNC();  // Should guarantee this code will run
    HAL_ICACHE_DISABLE(); // is also required to avoid old contents

    memset(&data,0,sizeof(data));
    stat = (*_flash_query)((void*)&data);
    if (icache_isenabled)
        HAL_ICACHE_ENABLE();

    qp = &data;
    if (/*(qp->manuf_code == FLASH_Intel_code) && */
        (strncmp(qp->id, "QRY", 3) == 0)) {
        num_regions = _si(qp->num_regions)+1;
        region_size = _si(qp->region_size)*256;

        flash_info.block_size = region_size;
        flash_info.blocks = num_regions;
        flash_info.start = (void *)0x00000000;
        flash_info.end = (void *)(0x00000000+(num_regions*region_size));
        return FLASH_ERR_OK;
    } else {
	(*flash_info.pf)("Can't identify FLASH sorry\n");
        diag_dump_buf(data, sizeof(data));
        return FLASH_ERR_HWR;
    }
}
Exemple #19
0
int
flash_hwr_init(void)
{
    unsigned char data[96];
    extern char flash_query, flash_query_end;
    typedef int code_fun(unsigned char *);
    code_fun *_flash_query;
    int code_len, stat, num_regions, region_size, icache_isenabled;

    // Copy 'program' code to RAM for execution
    code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query;
    _flash_query = (code_fun *)flash_info.work_space;
    memcpy(_flash_query, &flash_query, code_len);
    HAL_ICACHE_IS_ENABLED(icache_isenabled);
    HAL_DCACHE_SYNC();  // Should guarantee this code will run
    HAL_ICACHE_DISABLE(); // is also required to avoid old contents

    stat = (*_flash_query)(data);

    if (icache_isenabled)
        HAL_ICACHE_ENABLE();

    if ((data[0] == FLASH_Intel_code) &&
        (data[4] == FLASH_28F016SV_low) &&
        (data[5] == FLASH_28F016SV_hi)) {
        num_regions = 32;
        region_size = 0x20000;
        flash_info.block_size = region_size;
        flash_info.blocks = num_regions;
        flash_info.start = (void *)0x08000000;
        flash_info.end = (void *)(0x08000000+(num_regions*region_size));
        return FLASH_ERR_OK;
    } else {
        (*flash_info.pf)("Can't identify FLASH, sorry\n");
        diag_dump_buf(data, sizeof(data));
        return FLASH_ERR_HWR;
    }
}
Exemple #20
0
int
flash_program_buf(volatile unsigned short *addr, unsigned short *data, int len)
{
    volatile unsigned short *PAGE, *ROM;
    int timeout = 50000;
    int cache_on;
    int i, offset;
    unsigned short hold[FLASH_PAGE_SIZE/2];

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    if (len != FLASH_PAGE_SIZE) {
        return FLASH_LENGTH_ERROR;
    }

    ROM = (volatile unsigned short *)((unsigned long)addr & 0xFFFF0000);
    PAGE = (volatile unsigned short *)((unsigned long)addr & FLASH_PAGE_MASK);

    // Copy current contents (allows for partial updates)
    for (i = 0;  i < FLASH_PAGE_SIZE/2;  i++) {
        hold[i] = PAGE[i];
    }

    // Merge data into holding buffer
    offset = (unsigned long)addr & FLASH_PAGE_OFFSET;
    for (i = 0;  i < (len/2);  i++) {
        hold[offset+i] = data[i];
    }

    // Now write the data

    // Send lead-in sequence
    ROM[FLASH_Key_Addr0] = FLASH_Key0;
    ROM[FLASH_Key_Addr1] = FLASH_Key1;

    // Send 'write' command
    ROM[FLASH_Key_Addr0] = FLASH_Program;

    // Send one page/sector of data
    for (i = 0;  i < FLASH_PAGE_SIZE/2;  i++) {
        PAGE[i] = hold[i];
    }

    // Wait for data to be programmed
    while (timeout-- > 0) {
        if (PAGE[(FLASH_PAGE_SIZE/2)-1] == hold[(FLASH_PAGE_SIZE/2)-1]) {
            break;
        }
    }

    if (timeout <= 0) {
        return FLASH_PROGRAM_ERROR;
    }

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return FLASH_PROGRAM_OK;
}
// Function to initialize the device.  Called at bootstrap time.
static bool 
mpc8xxx_sxx_serial_init(struct cyg_devtab_entry *tab)
{
    serial_channel *chan = (serial_channel *)tab->priv;
    mpc8xxx_sxx_serial_info *smc_chan = (mpc8xxx_sxx_serial_info *)chan->dev_priv;
    int TxBD, RxBD;
    int cache_state;

    HAL_DCACHE_IS_ENABLED(cache_state);
    HAL_DCACHE_SYNC();
    HAL_DCACHE_DISABLE();
#ifdef CYGDBG_IO_INIT
    diag_printf("MPC8XXX_SMC SERIAL init - dev: %x.%d = %s\n", smc_chan->channel, smc_chan->int_num, tab->name);
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SMC1
    if (chan == &mpc8xxx_sxx_serial_channel_smc1) {
        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxNUM);
        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxNUM);
        mpc8xxx_smc_serial_init_info(&mpc8xxx_sxx_serial_info_smc1,
                                     (t_Smc_Pram *)((char *)IMM + DPRAM_SMC1_OFFSET),
                                     &IMM->smc_regs[SMC1],
                                     (unsigned long *)&IMM->brgs_brgc7,
                                     TxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxSIZE,
                                     &mpc8xxx_smc1_txbuf[0],
                                     RxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxSIZE,
                                     &mpc8xxx_smc1_rxbuf[0]
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SMC2
#warning "Serial driver on SMC2 is unverified"
    if (chan == &mpc8xxx_sxx_serial_channel_smc2) {
        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxNUM);
        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxNUM);
        mpc8xxx_smc_serial_init_info(&mpc8xxx_sxx_serial_info_smc2,
                                     &IMM->pram[3].scc.pothers.smc_modem.psmc.u, // PRAM
                                     &IMM->smc_regs[1], // Control registers
                                     &IMM->brgs_brgc7,
                                     TxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxSIZE,
                                     &mpc8xxx_smc2_txbuf[0],
                                     RxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxSIZE,
                                     &mpc8xxx_smc2_rxbuf[0]
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC1
    if (chan == &mpc8xxx_sxx_serial_channel_scc1) {
        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxNUM);
        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxNUM);
        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc1,
                                     &IMM->pram.serials.scc_pram[SCC1],
                                     &IMM->scc_regs[SCC1],
                                     (unsigned long *)&IMM->brgs_brgc1,
                                     TxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxSIZE,
                                     &mpc8xxx_scc1_txbuf[0],
                                     RxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxSIZE,
                                     &mpc8xxx_scc1_rxbuf[0]
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC2
#warning "Serial driver on SCC2 is unverified"
    if (chan == &mpc8xxx_sxx_serial_channel_scc2) {
        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxNUM);
        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxNUM);
        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc2,
                                     &IMM->pram[1].scc.pscc.u, // PRAM
                                     &IMM->scc_regs[1],        // Control registers
                                     &IMM->brgs_brgc2,
                                     TxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxSIZE,
                                     &mpc8xxx_scc2_txbuf[0],
                                     RxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxSIZE,
                                     &mpc8xxx_scc2_rxbuf[0]
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC3
#warning "Serial driver on SCC3 is unverified"
    if (chan == &mpc8xxx_sxx_serial_channel_scc3) {
        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_TxNUM);
        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_RxNUM);
        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc3,
                                     &IMM->pram[2].scc.pscc.u, // PRAM
                                     &IMM->scc_regs[2],        // Control registersn
                                     &IMM->brgs_brgc3,
                                     TxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_TxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_TxSIZE,
                                     &mpc8xxx_scc3_txbuf[0],
                                     RxBD, 
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_RxNUM,
                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_RxSIZE,
                                     &mpc8xxx_scc3_rxbuf[0]
            );
    }
#endif
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
    if (chan->out_cbuf.len != 0) {
        cyg_drv_interrupt_create(smc_chan->int_num,
                                 0,                      // Priority - unused (but asserted)
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
                                 mpc8xxx_sxx_serial_ISR,
                                 mpc8xxx_sxx_serial_DSR,
                                 &smc_chan->serial_interrupt_handle,
                                 &smc_chan->serial_interrupt);
        cyg_drv_interrupt_attach(smc_chan->serial_interrupt_handle);
        cyg_drv_interrupt_unmask(smc_chan->int_num);
    }
    if (smc_chan->type == _SMC_CHAN) {
        mpc8xxx_smc_serial_config_port(chan, &chan->config, true);
    } else {
        mpc8xxx_scc_serial_config_port(chan, &chan->config, true);
    }
    if (cache_state)
        HAL_DCACHE_ENABLE();
    return true;
}
Exemple #22
0
void
do_go(int argc, char *argv[])
{
    int i, cur, num_options;
    unsigned long entry;
    unsigned long oldints;
    bool wait_time_set;
    int  wait_time, res;
    bool cache_enabled = false;
#ifdef CYGPKG_IO_ETH_DRIVERS
    bool stop_net = false;
#endif
    struct option_info opts[3];
    char line[8];
    hal_virtual_comm_table_t *__chan;

    __mem_fault_handler = 0; // Let GDB handle any faults directly
    entry = entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 
              (void *)&cache_enabled, (bool *)0, "go with caches enabled");
    num_options = 2;
#ifdef CYGPKG_IO_ETH_DRIVERS
    init_opts(&opts[2], 'n', false, OPTION_ARG_TYPE_FLG, 
              (void *)&stop_net, (bool *)0, "go with network driver stopped");
    num_options++;
#endif

    CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");

    if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("No entry point known - aborted\n");
        return;
    }
    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }

    // Mask interrupts on all channels
    cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
    for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
	CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
	__chan = CYGACC_CALL_IF_CONSOLE_PROCS();
	CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
    }
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);

    __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH);

#ifdef CYGPKG_IO_ETH_DRIVERS
    if (stop_net)
	eth_drv_stop();
#endif
	
    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    if (!cache_enabled) {
	HAL_ICACHE_DISABLE();
	HAL_DCACHE_DISABLE();
	HAL_DCACHE_SYNC();
    }
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();
    // set up a temporary context that will take us to the trampoline
    HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, trampoline, 0);

    // switch context to trampoline
    HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);

    // we get back here by way of return_to_redboot()

    // undo the changes we made before switching context
    if (!cache_enabled) {
	HAL_ICACHE_ENABLE();
	HAL_DCACHE_ENABLE();
    }

    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH);

    HAL_RESTORE_INTERRUPTS(oldints);

    diag_printf("\nProgram completed with status %d\n", return_status);
}
Exemple #23
0
void
do_go(int argc, char *argv[])
{
    unsigned long entry;
    unsigned long oldints;
    bool wait_time_set;
    int  wait_time, res;
    bool cache_enabled = false;
    struct option_info opts[2];
    char line[8];
    hal_virtual_comm_table_t *__chan = CYGACC_CALL_IF_CONSOLE_PROCS();

    entry = entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
              (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
              (void **)&cache_enabled, (bool *)0, "go with caches enabled");
    if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }
    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH);

    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    if (!cache_enabled) {
        HAL_ICACHE_DISABLE();
        HAL_DCACHE_DISABLE();
        HAL_DCACHE_SYNC();
    }
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();

    // set up a temporary context that will take us to the trampoline
    HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, go_trampoline, 0);

    // switch context to trampoline
    HAL_THREAD_SWITCH_CONTEXT(&go_saved_context, &workspace_end);

    // we get back here by way of return_to_redboot()

    // undo the changes we made before switching context
    if (!cache_enabled) {
        HAL_ICACHE_ENABLE();
        HAL_DCACHE_ENABLE();
    }

    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH);

    HAL_RESTORE_INTERRUPTS(oldints);

    diag_printf("\nProgram completed with status %d\n", go_return_status);
}
int flash_erase_block(volatile flash_t *block, unsigned int block_size)
{
    volatile flash_t *ROM;
    flash_t stat = 0;
    int timeout = 50000;
    int cache_on;
    int len, block_len, erase_block_size;
    volatile flash_t *eb;

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Get base address and map addresses to virtual addresses
    ROM = FLASH_P2V(CYGNUM_FLASH_BASE_MASK & (unsigned int)block);
    eb = block = FLASH_P2V(block);
    block_len = block_size;

#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
#define BLOCKSIZE (0x10000*CYGNUM_FLASH_DEVICES)
#define ERASE_BLOCKSIZE (0x2000*CYGNUM_FLASH_DEVICES)
    if ((eb - ROM) < BLOCKSIZE) {
// FIXME - Handle 'boot' blocks
        erase_block_size = ERASE_BLOCKSIZE;
    } else {
        erase_block_size = block_size;
    }
#else
    erase_block_size = block_size;
#endif

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

    // Erase block
    while (block_len > 0) {
        ROM[0] = FLASH_Block_Erase;
        *eb = FLASH_Confirm;
        timeout = 5000000;
        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
            if (--timeout == 0) break;
        }
        block_len -= erase_block_size;
        eb = FLASH_P2V((unsigned int)eb + erase_block_size);
    }

    // Restore ROM to "normal" mode
    ROM[0] = FLASH_Reset;

    // If an error was reported, see if the block erased anyway
    if (stat & FLASH_ErrorMask ) {
        len = block_size;
        while (len > 0) {
            if (*block++ != FLASH_BlankValue ) break;
            len -= sizeof(*block);
        }
        if (len == 0) stat = 0;
    }

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
int
flash_unlock_block(volatile flash_t *block, int block_size, int blocks)
{
    volatile flash_t *ROM;
    flash_t stat;
    int timeout = 5000000;
    int cache_on;
#ifndef CYGOPT_FLASH_IS_SYNCHRONOUS
    int i;
    volatile flash_t *bp, *bpv;
    unsigned char is_locked[MAX_FLASH_BLOCKS];
#endif

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Get base address and map addresses to virtual addresses
    ROM = FLASH_P2V( CYGNUM_FLASH_BASE_MASK & (unsigned int)block );
    block = FLASH_P2V(block);

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

#ifdef CYGOPT_FLASH_IS_SYNCHRONOUS
    // Clear lock bit
    block[0] = FLASH_Clear_Locks;
    block[0] = FLASH_Clear_Locks_Confirm;  // Confirmation
    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
        if (--timeout == 0) break;
    }
#else
    // Get current block lock state.  This needs to access each block on
    // the device so currently locked blocks can be re-locked.
    bp = ROM;
    for (i = 0;  i < blocks;  i++) {
        bpv = FLASH_P2V( bp );
        *bpv = FLASH_Read_Query;
        if (bpv == block) {
            is_locked[i] = 0;
        } else {
#if 8 == CYGNUM_FLASH_WIDTH
            is_locked[i] = bpv[4];
#else
            is_locked[i] = bpv[2];
# endif
        }
        bp += block_size / sizeof(*bp);
    }

    // Clears all lock bits
    ROM[0] = FLASH_Clear_Locks;
    ROM[0] = FLASH_Clear_Locks_Confirm;  // Confirmation
    timeout = 5000000;
    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
        if (--timeout == 0) break;
    }

    // Restore the lock state
    bp = ROM;
    for (i = 0;  i < blocks;  i++) {
        bpv = FLASH_P2V( bp );
        if (is_locked[i]) {
            *bpv = FLASH_Set_Lock;
            *bpv = FLASH_Set_Lock_Confirm;  // Confirmation
            timeout = 5000000;
            while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
                if (--timeout == 0) break;
            }
        }
        bp += block_size / sizeof(*bp);
    }
#endif  // CYGOPT_FLASH_IS_SYNCHRONOUS

    // Restore ROM to "normal" mode
    ROM[0] = FLASH_Reset;

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
void
cyg_ldr_flush_cache(void)
{
    HAL_DCACHE_SYNC();
    HAL_ICACHE_SYNC();
}
// Function to initialize the device.  Called at bootstrap time.
static bool 
quicc_sxx_serial_init(struct cyg_devtab_entry *tab)
{
    serial_channel *chan = (serial_channel *)tab->priv;
    quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv;
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
    int TxBD, RxBD;
    int cache_state;

    HAL_DCACHE_IS_ENABLED(cache_state);
    HAL_DCACHE_SYNC();
    HAL_DCACHE_DISABLE();
#ifdef CYGDBG_IO_INIT
    diag_printf("QUICC_SMC SERIAL init - dev: %x.%d = %s\n", smc_chan->channel, smc_chan->int_num, tab->name);
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1
    if (chan == &quicc_sxx_serial_channel_smc1) {
        TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM);
        RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM);
        quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc1,
                                   &eppc->pram[2].scc.pothers.smc_modem.psmc.u, // PRAM
                                   &eppc->smc_regs[0], // Control registers
                                   TxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxSIZE,
                                   &quicc_smc1_txbuf[0],
                                   RxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxSIZE,
                                   &quicc_smc1_rxbuf[0],
                                   0xC0, // PortB mask
                                   QUICC_CPM_SMC1
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2
    if (chan == &quicc_sxx_serial_channel_smc2) {
        TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM);
        RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM);
        quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc2,
                                   &eppc->pram[3].scc.pothers.smc_modem.psmc.u, // PRAM
                                   &eppc->smc_regs[1], // Control registers
                                   TxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxSIZE,
                                   &quicc_smc2_txbuf[0],
                                   RxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxSIZE,
                                   &quicc_smc2_rxbuf[0],
                                   0xC00, // PortB mask
                                   QUICC_CPM_SMC2
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1
    if (chan == &quicc_sxx_serial_channel_scc1) {
        TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM);
        RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM);
        quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc1,
                                   &eppc->pram[0].scc.pscc.u, // PRAM
                                   &eppc->scc_regs[0],        // Control registersn
                                   TxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxSIZE,
                                   &quicc_scc1_txbuf[0],
                                   RxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxSIZE,
                                   &quicc_scc1_rxbuf[0],
                                   0x0003, // PortA mask
                                   0x1000, // PortB mask
                                   0x0800, // PortC mask
                                   QUICC_CPM_SCC1
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2
    if (chan == &quicc_sxx_serial_channel_scc2) {
        TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM);
        RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM);
        quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc2,
                                   &eppc->pram[1].scc.pscc.u, // PRAM
                                   &eppc->scc_regs[1],        // Control registersn
                                   TxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxSIZE,
                                   &quicc_scc2_txbuf[0],
                                   RxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxSIZE,
                                   &quicc_scc2_rxbuf[0],
                                   0x000C, // PortA mask
                                   0x2000, // PortB mask
                                   0x0C00, // PortC mask
                                   QUICC_CPM_SCC2
            );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3
    if (chan == &quicc_sxx_serial_channel_scc3) {
        TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM);
        RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM);
        quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc3,
                                   &eppc->pram[2].scc.pscc.u, // PRAM
                                   &eppc->scc_regs[2],        // Control registersn
                                   TxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE,
                                   &quicc_scc3_txbuf[0],
                                   RxBD, 
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM,
                                   CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE,
                                   &quicc_scc3_rxbuf[0],
#if defined(CYGHWR_HAL_POWERPC_MPC8XX_850)
                                   0x0000, // PortA mask
                                   0x00C0, // PortB mask
                                   0x0000, // PortC mask
#elif defined(CYGHWR_HAL_POWERPC_MPC8XX_852T)
                                   0x0030, // PortA mask
                                   0x0000, // PortB mask
                                   0x0000, // PortC mask
#elif defined(CYGHWR_HAL_POWERPC_MPC8XX_823)
                                   0x0000, // PortA mask
                                   0x00C0, // PortB mask
                                   0x0000, // PortC mask
#else
#error "Cannot route SCC3"
#endif
                                   QUICC_CPM_SCC3
            );
    }
#endif
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
    if (chan->out_cbuf.len != 0) {
        cyg_drv_interrupt_create(smc_chan->int_num,
                                 CYGARC_SIU_PRIORITY_HIGH, // Priority - unused (but asserted)
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
                                 quicc_sxx_serial_ISR,
                                 quicc_sxx_serial_DSR,
                                 &smc_chan->serial_interrupt_handle,
                                 &smc_chan->serial_interrupt);
        cyg_drv_interrupt_attach(smc_chan->serial_interrupt_handle);
        cyg_drv_interrupt_unmask(smc_chan->int_num);
    }
    if (smc_chan->type == _SMC_CHAN) {
        quicc_smc_serial_config_port(chan, &chan->config, true);
    } else {
        quicc_scc_serial_config_port(chan, &chan->config, true);
    }
    if (cache_state)
        HAL_DCACHE_ENABLE();
    return true;
}
Exemple #28
0
int
flash_program_buf(volatile flash_t *addr, flash_t *data, int len,
                  unsigned long block_mask, int buffer_size)
{
    volatile flash_t *ROM;
    volatile flash_t *BA;
    flash_t stat = 0;
    int timeout = 50000;
    int cache_on;
#ifdef FLASH_Write_Buffer
    int i, wc;
#endif

    HAL_DCACHE_IS_ENABLED(cache_on);
    if (cache_on) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }

    // Get base address and map addresses to virtual addresses
    ROM = FLASH_P2V( CYGNUM_FLASH_BASE_MASK & (unsigned int)addr );
    BA = FLASH_P2V( block_mask & (unsigned int)addr );
    addr = FLASH_P2V(addr);

    // Clear any error conditions
    ROM[0] = FLASH_Clear_Status;

#ifdef FLASH_Write_Buffer
    // Write any big chunks first
    while (len >= buffer_size) {
        wc = buffer_size;
        if (wc > len) wc = len;
        len -= wc;
	// convert 'wc' in bytes to 'wc' in 'flash_t' 
        wc = wc / sizeof(flash_t);  // Word count
        *BA = FLASH_Write_Buffer;
        timeout = 5000000;
        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
            if (--timeout == 0) {
                goto bad;
            }
            *BA = FLASH_Write_Buffer;
        }
        *BA = FLASHWORD(wc-1);  // Count is 0..N-1
        for (i = 0;  i < wc;  i++) {
#ifdef CYGHWR_FLASH_WRITE_ELEM
            CYGHWR_FLASH_WRITE_ELEM(addr+i, data+i);
#else
            *(addr+i) = *(data+i);
#endif
        }
        *BA = FLASH_Confirm;
    
        ROM[0] = FLASH_Read_Status;
        timeout = 5000000;
        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
            if (--timeout == 0) {
                goto bad;
            }
        }
        // Jump out if there was an error
        if (stat & FLASH_ErrorMask) {
            goto bad;
        }
        // And verify the data - also increments the pointers.
        *BA = FLASH_Reset;            
        for (i = 0;  i < wc;  i++) {
            if ( *addr++ != *data++ ) {
                stat = FLASH_ErrorNotVerified;
                goto bad;
            }
        }
    }
#endif

    while (len > 0) {
        ROM[0] = FLASH_Program;
#ifdef CYGHWR_FLASH_WRITE_ELEM
        CYGHWR_FLASH_WRITE_ELEM(addr, data);
#else
        *addr = *data;
#endif
        timeout = 5000000;
        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
            if (--timeout == 0) {
                goto bad;
            }
        }
        if (stat & FLASH_ErrorMask) {
            break;
        }
        ROM[0] = FLASH_Reset;            
        if (*addr++ != *data++) {
            stat = FLASH_ErrorNotVerified;
            break;
        }
        len -= sizeof( flash_t );
    }

    // Restore ROM to "normal" mode
 bad:
    ROM[0] = FLASH_Reset;            

    if (cache_on) {
        HAL_DCACHE_ENABLE();
    }

    return stat;
}
Exemple #29
0
//
// Initialize the interface - performed at system startup
// This function must set up the interface, including arranging to
// handle interrupts, etc, so that it may be "started" cheaply later.
//
static bool
quicc_eth_init(struct cyg_netdevtab_entry *tab)
{
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
    struct cp_bufdesc *rxbd, *txbd;
    unsigned char *RxBUF, *TxBUF, *ep, *ap;
    volatile struct ethernet_pram *enet_pram;
    volatile struct scc_regs *scc;
    int TxBD, RxBD;
    int cache_state;
    int i;
    bool esa_ok;

    // Fetch the board address from the VPD
#define VPD_ETHERNET_ADDRESS 0x08
    if (_mbx_fetch_VPD(VPD_ETHERNET_ADDRESS, enaddr, sizeof(enaddr)) == 0) {
#if defined(CYGPKG_REDBOOT) && \
    defined(CYGSEM_REDBOOT_FLASH_CONFIG)
        esa_ok = flash_get_config("quicc_esa", enaddr, CONFIG_ESA);
#else
        esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
                                             "quicc_esa", enaddr, CONFIG_ESA);
#endif
        if (!esa_ok) {
            // Can't figure out ESA
            diag_printf("QUICC_ETH - Warning! ESA unknown\n");
            memcpy(&enaddr, &_default_enaddr, sizeof(enaddr));
        }
    }

    // Ensure consistent state between cache and what the QUICC sees
    HAL_DCACHE_IS_ENABLED(cache_state);
    HAL_DCACHE_SYNC();
    HAL_DCACHE_DISABLE();

#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
    // Set up to handle interrupts
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_CPM_SCC1,
                             CYGARC_SIU_PRIORITY_HIGH,
                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler
                             (cyg_ISR_t *)quicc_eth_isr,
                             (cyg_DSR_t *)eth_drv_dsr,
                             &quicc_eth_interrupt_handle,
                             &quicc_eth_interrupt);
    cyg_drv_interrupt_attach(quicc_eth_interrupt_handle);
    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
#endif

    qi->pram = enet_pram = &eppc->pram[0].enet_scc;
    qi->ctl = scc = &eppc->scc_regs[0];  // Use SCC1

    // Shut down ethernet, in case it is already running
    scc->scc_gsmr_l &= ~(QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT);

    memset((void *)enet_pram, 0, sizeof(*enet_pram));

    TxBD = 0x2C00;  // FIXME
    RxBD = TxBD + CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM * sizeof(struct cp_bufdesc);

    txbd = (struct cp_bufdesc *)((char *)eppc + TxBD);
    rxbd = (struct cp_bufdesc *)((char *)eppc + RxBD);
    qi->tbase = txbd;
    qi->txbd = txbd;
    qi->tnext = txbd;
    qi->rbase = rxbd;
    qi->rxbd = rxbd;
    qi->rnext = rxbd;

    RxBUF = &quicc_eth_rxbufs[0][0];
    TxBUF = &quicc_eth_txbufs[0][0];

    // setup buffer descriptors
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM;  i++) {
        rxbd->length = 0;
        rxbd->buffer = RxBUF;
        rxbd->ctrl   = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
        RxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
        rxbd++;
    }
    rxbd--;
    rxbd->ctrl |= QUICC_BD_CTL_Wrap;  // Last buffer
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM;  i++) {
        txbd->length = 0;
        txbd->buffer = TxBUF;
        txbd->ctrl   = 0;
        TxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
        txbd++;
    }
    txbd--;
    txbd->ctrl |= QUICC_BD_CTL_Wrap;  // Last buffer

    // Set up parallel ports for connection to MC68160 ethernet tranceiver
    eppc->pio_papar |= (QUICC_MBX_PA_RXD | QUICC_MBX_PA_TXD);
    eppc->pio_padir &= ~(QUICC_MBX_PA_RXD | QUICC_MBX_PA_TXD);
    eppc->pio_paodr &= ~QUICC_MBX_PA_TXD;

    eppc->pio_pcpar &= ~(QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);
    eppc->pio_pcdir &= ~(QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);
    eppc->pio_pcso  |= (QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);

    eppc->pio_papar |= (QUICC_MBX_PA_Tx_CLOCK | QUICC_MBX_PA_Rx_CLOCK);
    eppc->pio_padir &= ~(QUICC_MBX_PA_Tx_CLOCK | QUICC_MBX_PA_Rx_CLOCK);

    // Set up clock routing
    eppc->si_sicr &= ~QUICC_MBX_SICR_MASK;
    eppc->si_sicr |= QUICC_MBX_SICR_ENET;
    eppc->si_sicr &= ~QUICC_MBX_SICR_SCC1_ENABLE;

    // Set up DMA mode
    eppc->dma_sdcr = 0x0001;

    // Initialize shared PRAM
    enet_pram->rbase = RxBD;
    enet_pram->tbase = TxBD;

    // Set Big Endian mode
    enet_pram->rfcr = QUICC_SCC_FCR_BE;
    enet_pram->tfcr = QUICC_SCC_FCR_BE;

    // Size of receive buffers
    enet_pram->mrblr = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;

    // Initialize CRC calculations
    enet_pram->c_pres = 0xFFFFFFFF;
    enet_pram->c_mask = 0xDEBB20E3;  // Actual CRC formula
    enet_pram->crcec = 0;
    enet_pram->alec = 0;
    enet_pram->disfc = 0;

    // Frame padding
    enet_pram->pads = 0x8888;
    enet_pram->pads = 0x0000;

    // Retries
    enet_pram->ret_lim = 15;
    enet_pram->ret_cnt = 0;

    // Frame sizes
    enet_pram->mflr = IEEE_8023_MAX_FRAME;
    enet_pram->minflr = IEEE_8023_MIN_FRAME;
    enet_pram->maxd1 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
    enet_pram->maxd2 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;

    // Group address hash
    enet_pram->gaddr1 = 0;
    enet_pram->gaddr2 = 0;
    enet_pram->gaddr3 = 0;
    enet_pram->gaddr4 = 0;

    // Device physical address
    ep = &enaddr[sizeof(enaddr)];
    ap = (unsigned char *)&enet_pram->paddr_h;
    for (i = 0;  i < sizeof(enaddr);  i++) {
        *ap++ = *--ep;
    }

    // Persistence counter
    enet_pram->p_per = 0;

    // Individual address filter
    enet_pram->iaddr1 = 0;
    enet_pram->iaddr2 = 0;
    enet_pram->iaddr3 = 0;
    enet_pram->iaddr4 = 0;

    // Temp address
    enet_pram->taddr_h = 0;
    enet_pram->taddr_m = 0;
    enet_pram->taddr_l = 0;

    // Initialize the CPM (set up buffer pointers, etc).
    eppc->cp_cr = QUICC_CPM_SCC1 | QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_CR_BUSY;
    while (eppc->cp_cr & QUICC_CPM_CR_BUSY) ;

    // Clear any pending interrupt/exceptions
    scc->scc_scce = 0xFFFF;

    // Enable interrupts
    scc->scc_sccm = QUICC_SCCE_INTS;

    // Set up SCC1 to run in ethernet mode
    scc->scc_gsmr_h = 0;
    scc->scc_gsmr_l = QUICC_SCC_GSML_TCI | QUICC_SCC_GSML_TPL_48 |
                      QUICC_SCC_GSML_TPP_01 | QUICC_SCC_GSML_MODE_ENET;

    // Sync delimiters
    scc->scc_dsr = 0xD555;

    // Protocol specifics (as if GSML wasn't enough)
    scc->scc_psmr = QUICC_PMSR_ENET_CRC | QUICC_PMSR_SEARCH_AFTER_22 |
                    QUICC_PMSR_RCV_SHORT_FRAMES;

    // Configure board interface
    *MBX_CTL1 = MBX_CTL1_ETEN | MBX_CTL1_TPEN;  // Enable ethernet, TP mode

    // Enable ethernet interface
    eppc->pio_pcpar |= QUICC_MBX_PC_Tx_ENABLE;
    eppc->pio_pcdir &= ~QUICC_MBX_PC_Tx_ENABLE;

    if (cache_state)
        HAL_DCACHE_ENABLE();

    // Initialize upper level driver
    (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);

    return true;
}
//
// Execute a Linux kernel - this is a RedBoot CLI command
//
static void 
do_exec(int argc, char *argv[])
{
    unsigned long entry;
    bool wait_time_set, cmd_line_set;
    int  wait_time;
    char *cmd_line;
    char *cline;
    struct option_info opts[2];
    hal_virtual_comm_table_t *__chan;
    int baud_rate;

    bd_t *board_info;
    CYG_INTERRUPT_STATE oldints;
    unsigned long sp = CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE;
    
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
              (void *)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
    entry = entry_address;  // Default from last 'load' operation
    if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, 
                   "[physical] starting address")) {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("Can't execute Linux - invalid entry address\n");
        return;
    }

    // Determine baud rate on current console
    __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
    baud_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
    if (baud_rate <= 0) {
        baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
    }

    // Make a little space at the top of the stack, and align to
    // 64-bit boundary.
    sp = (sp-128) & ~7;  // The Linux boot code uses this space for FIFOs
    
    // Copy the commandline onto the stack, and set the SP to just below it.
    if (cmd_line_set) {
	int len,i;

	// get length of string
	for( len = 0; cmd_line[len] != '\0'; len++ );

	// decrement sp by length of string and align to
	// word boundary.
	sp = (sp-(len+1)) & ~3;

	// assign this SP value to command line start
	cline = (char *)sp;

	// copy command line over.
	for( i = 0; i < len; i++ )
	    cline[i] = cmd_line[i];
	cline[len] = '\0';

    } else {
        cline = (char *)NULL;
    }
    
    // Set up parameter struct at top of stack
    sp = sp-sizeof(bd_t);
    board_info = (bd_t *)sp;
    memset(board_info, sizeof(*board_info), 0);
    
    board_info->bi_tag		= 0x42444944;
    board_info->bi_size		= sizeof(*board_info);
    board_info->bi_revision	= 1;
    board_info->bi_bdate	= 0x06012002;
    board_info->bi_memstart	= CYGMEM_REGION_ram;
    board_info->bi_memsize	= CYGMEM_REGION_ram_SIZE;
    board_info->bi_baudrate     = baud_rate;
    board_info->bi_cmdline      = cline;
#ifdef CYGPKG_REDBOOT_NETWORKING
    memcpy(board_info->bi_enetaddr, __local_enet_addr, sizeof(enet_addr_t));
#endif
    // Call platform specific code to fill in the platform/architecture specific details
    plf_redboot_linux_exec(board_info);

    // adjust SP to 64 byte boundary, and leave a little space
    // between it and the commandline for PowerPC calling
    // conventions.
	
    sp = (sp-64)&~63;

    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            int res;
            char line[80];
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }

#ifdef CYGPKG_IO_ETH_DRIVERS
    eth_drv_stop();
#endif

    // Disable interrupts
    HAL_DISABLE_INTERRUPTS(oldints);

    // Put the caches to sleep.
    HAL_DCACHE_SYNC();
    HAL_ICACHE_DISABLE();
    HAL_DCACHE_DISABLE();
    HAL_DCACHE_SYNC();
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();

//    diag_printf("entry %08x, sp %08x, info %08x, cmd line %08x, baud %d\n",
//		entry, sp, board_info, cline, baud_rate);
//    breakpoint();
    
    // Call into Linux
    __asm__ volatile (        
	               // Start by disabling MMU - the mappings are
	               // 1-1 so this should not cause any problems
	               "mfmsr	3\n"
		       "li      4,0xFFFFFFCF\n"
		       "and	3,3,4\n"
		       "sync\n"
		       "mtmsr	3\n"
		       "sync\n"

		       // Now set up parameters to jump into linux

		       "mtlr	%0\n"		// set entry address in LR
		       "mr	1,%1\n"		// set stack pointer
		       "mr	3,%2\n"		// set board info in R3
		       "mr	4,%3\n"		// set command line in R4
		       "blr          \n"	// jump into linux
		       :
		       : "r"(entry),"r"(sp),"r"(board_info),"r"(cline)
		       : "r3", "r4"
	             
	             );
}