static void __init mv_init(void) { /* init the Board environment */ mvBoardEnvInit(); /* init the controller environment */ if (mvCtrlEnvInit() ) { printk( "Controller env initialization failed.\n" ); return; } /* Init the CPU windows setting and the access protection windows. */ if (mvCpuIfInit(mv_sys_map())) { printk( "Cpu Interface initialization failed.\n" ); return; } #if defined (CONFIG_MV78XX0_Z0) mvCpuIfBridgeReorderWAInit(); #endif /* Init Tclk & SysClk */ mvTclk = mvBoardTclkGet(); mvSysclk = mvBoardSysClkGet(); support_wait_for_interrupt = 1; #ifdef CONFIG_JTAG_DEBUG support_wait_for_interrupt = 0; /* for Lauterbach */ #endif mv_vfp_init(); elf_hwcap &= ~HWCAP_JAVA; serial_initialize(); /* At this point, the CPU windows are configured according to default definitions in mvSysHwConfig.h */ /* and cpuAddrWinMap table in mvCpuIf.c. Now it's time to change defaults for each platform. */ mvCpuIfAddrDecShow(whoAmI()); print_board_info(); }
/***************************************************************************** * UART ****************************************************************************/ static struct resource mv_uart_resources[] = { { .start = PORT0_BASE, .end = PORT0_BASE + 0xff, .flags = IORESOURCE_MEM, }, { .start = IRQ_UART0, .end = IRQ_UART0, .flags = IORESOURCE_IRQ, }, { .start = PORT1_BASE, .end = PORT1_BASE + 0xff, .flags = IORESOURCE_MEM, }, { .start = IRQ_UART1, .end = IRQ_UART1, .flags = IORESOURCE_IRQ, }, }; static struct plat_serial8250_port mv_uart_data[] = { { .mapbase = PORT0_BASE, .membase = (char *)PORT0_BASE, .irq = IRQ_UART0, .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, }, { .mapbase = PORT1_BASE, .membase = (char *)PORT1_BASE, .irq = IRQ_UART1, .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, }, { }, }; static struct platform_device mv_uart = { .name = "serial8250", .id = PLAT8250_DEV_PLATFORM, .dev = { .platform_data = mv_uart_data, }, .num_resources = ARRAY_SIZE(mv_uart_resources), .resource = mv_uart_resources, }; static void serial_initialize(void) { mv_uart_data[0].uartclk = mv_uart_data[1].uartclk = mvTclk; platform_device_register(&mv_uart); } static void __init mv_vfp_init(void) { #if defined CONFIG_VFP_FASTVFP printk("VFP initialized to Run Fast Mode.\n"); #endif } #if defined(MV_88F6183) #ifdef CONFIG_MV_INCLUDE_AUDIO typedef struct { unsigned int base; unsigned int size; } _audio_mem_info; typedef struct { u32 spdif_rec; u32 spdif_play; u32 i2s_rec; u32 i2s_play; _audio_mem_info mem_array[MV_DRAM_MAX_CS + 1]; } _audio_info; _audio_info audio_info = {1, 1, 1, 1}; static struct resource mv_snd_resources[] = { [0] = { .start = INTER_REGS_BASE + AUDIO_REG_BASE, .end = INTER_REGS_BASE + AUDIO_REG_BASE + SZ_16K -1, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_AUDIO_INT, .end = IRQ_AUDIO_INT, .flags = IORESOURCE_IRQ, }, [2] = { .start = NR_IRQS, /* should obtained from board information*/ .end = NR_IRQS, /* should obtained from board information */ .flags = IORESOURCE_IRQ, } }; static u64 mv_snd_dmamask = 0xFFFFFFFFUL; static struct platform_device mv_snd_device = { .name = "mv88fx_snd", .id = -1, .dev = { .dma_mask = &mv_snd_dmamask, .coherent_dma_mask = 0xFFFFFFFF, .platform_data = &audio_info, }, .num_resources = ARRAY_SIZE(mv_snd_resources), .resource = mv_snd_resources, }; #endif /* #ifdef CONFIG_MV_INCLUDE_AUDIO */ #ifdef CONFIG_MV_INCLUDE_SDIO static struct resource mvsdmmc_resources[] = { [0] = { .start = INTER_REGS_BASE + 0x80000, .end = INTER_REGS_BASE + 0x80000 + SZ_1K -1, .flags = IORESOURCE_MEM, }, [1] = { .start = SDIO_IRQ_NUM, .end = SDIO_IRQ_NUM, .flags = IORESOURCE_IRQ, }, [2] = { .start = NR_IRQS, /* should obtained from board information*/ .end = NR_IRQS, /* should obtained from board information */ .flags = IORESOURCE_IRQ, } }; static u64 mvsdmmc_dmamask = 0xffffffffUL; static struct platform_device mvsdmmc_device = { .name = "mvsdmmc", .id = -1, .dev = { .dma_mask = &mvsdmmc_dmamask, .coherent_dma_mask = 0xffffffff, }, .num_resources = ARRAY_SIZE(mvsdmmc_resources), .resource = mvsdmmc_resources, }; #endif /* CONFIG_MV_INCLUDE_SDIO */ static struct platform_device *devices[] __initdata = { #ifdef CONFIG_MV_INCLUDE_AUDIO &mv_snd_device, #endif #ifdef CONFIG_MV_INCLUDE_SDIO &mvsdmmc_device, #endif NULL }; #endif /* #if defined(MV_88F6183) */ static void __init mv_init(void) { unsigned int temp; /* init the Board environment */ if (mvBoardIdGet() != RD_88F6082_MICRO_DAS_NAS) /* excluded for HDD power problem - to be fixed */ mvBoardEnvInit(); /* init the controller environment */ if( mvCtrlEnvInit() ) { printk( "Controller env initialization failed.\n" ); return; } if(mvBoardIdGet() == RD_88F5181_POS_NAS) { temp = MV_REG_READ(GPP_DATA_OUT_REG(0)); temp &= ~(1 << 0x5); /* for host mode should be set to 0 */ if(!mvIsUsbHost) { temp |= (1 << 0x5); } MV_REG_WRITE(GPP_DATA_OUT_REG(0), temp); } /* Init the CPU windows setting and the access protection windows. */ if( mvCpuIfInit(mv_sys_map()) ) { printk( "Cpu Interface initialization failed.\n" ); return; } /* Init Tclk & SysClk */ mvTclk = mvBoardTclkGet(); mvSysclk = mvBoardSysClkGet(); printk("Sys Clk = %d, Tclk = %d\n",mvSysclk ,mvTclk ); if ((mvCtrlModelGet() == MV_5281_DEV_ID) || (mvCtrlModelGet() == MV_1281_DEV_ID) || (mvCtrlModelGet() == MV_6183_DEV_ID)) mv_orion_ver = MV_ORION2; /* Orion II */ else mv_orion_ver = MV_ORION1; /* Orion I */ /* Implement workaround for FEr# CPU-C16: Wait for interrupt command */ /* is not processed properly, the workaround is not to use this command */ /* the erratum is relevant for 5281 devices with revision less than C0 */ if((mvCtrlModelGet() == MV_5281_DEV_ID) && (mvCtrlRevGet() < MV_5281_C0_REV)) { support_wait_for_interrupt = 0; } #ifdef CONFIG_JTAG_DEBUG support_wait_for_interrupt = 0; /* for Lauterbach */ #endif mv_vfp_init(); elf_hwcap &= ~HWCAP_JAVA; serial_initialize(); /* At this point, the CPU windows are configured according to default definitions in mvSysHwConfig.h */ /* and cpuAddrWinMap table in mvCpuIf.c. Now it's time to change defaults for each platform. */ mvCpuIfAddDecShow(); #if defined(CONFIG_MTD_PHYSMAP) mv_mtd_initialize(); #endif print_board_info(); #ifdef CONFIG_MV_INCLUDE_IDMA mvDmaInit(); #endif #if defined(MV_88F6183) #ifdef CONFIG_MV_INCLUDE_SDIO mvsdmmc_resources[2].end = mvBoardSDIOGpioPinGet() + IRQ_GPP_START; mvsdmmc_resources[2].start = mvBoardSDIOGpioPinGet() + IRQ_GPP_START; irq_int_type[mvBoardSDIOGpioPinGet()] = GPP_IRQ_TYPE_CHANGE_LEVEL; #endif /* CONFIG_MV_INCLUDE_SDIO */ #ifdef CONFIG_MV_INCLUDE_AUDIO for (temp=0 ; temp< MV_DRAM_MAX_CS; temp++) { MV_DRAM_DEC_WIN win; audio_info.mem_array[temp].base = 0; audio_info.mem_array[temp].size = 0; mvDramIfWinGet(SDRAM_CS0 + temp, &win); if (win.enable) { audio_info.mem_array[temp].base = win.addrWin.baseLow; audio_info.mem_array[temp].size = win.addrWin.size; } } #endif /* CONFIG_MV_INCLUDE_AUDIO */ if ((temp = ARRAY_SIZE(devices) - 1)) platform_add_devices(devices, temp); #endif /* MV_88F6183 */ return; }
/******************************************************************************* * mvDramIfDetect - Prepare DRAM interface configuration values. * * DESCRIPTION: * This function implements the full DRAM detection and timing * configuration for best system performance. * Since this routine runs from a ROM device (Boot Flash), its stack * resides on RAM, that might be the system DRAM. Changing DRAM * configuration values while keeping vital data in DRAM is risky. That * is why the function does not preform the configuration setting but * prepare those in predefined 32bit registers (in this case IDMA * registers are used) for other routine to perform the settings. * The function will call for board DRAM SPD information for each DRAM * chip select. The function will then analyze those SPD parameters of * all DRAM banks in order to decide on DRAM configuration compatible * for all DRAM banks. * The function will set the CPU DRAM address decode registers. * Note: This routine prepares values that will overide configuration of * mvDramBasicAsmInit(). * * INPUT: * forcedCl - Forced CAL Latency. If equal to zero, do not force. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_STATUS mvDramIfDetect(MV_U32 forcedCl) { MV_U32 retVal = MV_OK; /* return value */ MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS]; MV_U32 busClk, size, base = 0, i, temp, deviceW, dimmW; MV_U8 minCas; MV_DRAM_DEC_WIN dramDecWin; dramDecWin.addrWin.baseHigh = 0; busClk = mvBoardSysClkGet(); if (0 == busClk) { mvOsPrintf("Dram: ERR. Can't detect system clock! \n"); return MV_ERROR; } /* Close DRAM banks except bank 0 (in case code is excecuting from it...) */ for(i= SDRAM_CS1; i <= SDRAM_CS3; i++) mvCpuIfTargetWinEnable(i, MV_FALSE); /* we will use bank 0 as the representative of the all the DRAM banks, */ /* since bank 0 must exist. */ for(i = 0; i < MV_DRAM_MAX_CS; i++) { /* if Bank exist */ if(MV_OK == mvDramBankInfoGet(i, &bankInfo[i])) { /* check it isn't SDRAM */ if(bankInfo[i].memoryType == MEM_TYPE_SDRAM) { mvOsPrintf("Dram: ERR. SDRAM type not supported !!!\n"); return MV_ERROR; } /* All banks must support registry in order to activate it */ if(bankInfo[i].registeredAddrAndControlInputs != bankInfo[0].registeredAddrAndControlInputs) { mvOsPrintf("Dram: ERR. different Registered settings !!!\n"); return MV_ERROR; } /* Init the CPU window decode */ /* Note that the size in Bank info is in MB units */ /* Note that the Dimm width might be different then the device DRAM width */ temp = MV_REG_READ(SDRAM_CONFIG_REG); deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_16BIT )? 16 : 32; dimmW = bankInfo[0].dataWidth - (bankInfo[0].dataWidth % 16); size = ((bankInfo[i].size << 20) / (dimmW/deviceW)); /* We can not change DRAM window settings while excecuting */ /* code from it. That is why we skip the DRAM CS[0], saving */ /* it to the ROM configuration routine */ if(i == SDRAM_CS0) { MV_U32 sizeToReg; /* Translate the given window size to register format */ sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n" ,i); return MV_BAD_PARAM; } /* Size is located at upper 16 bits */ sizeToReg <<= SCSR_SIZE_OFFS; /* enable it */ sizeToReg |= SCSR_WIN_EN; MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg); } else { dramDecWin.addrWin.baseLow = base; dramDecWin.addrWin.size = size; dramDecWin.enable = MV_TRUE; if (MV_OK != mvDramIfWinSet(SDRAM_CS0 + i, &dramDecWin)) { mvOsPrintf("Dram: ERR. Fail to set bank %d!!!\n", SDRAM_CS0 + i); return MV_ERROR; } } base += size; /* update the suportedCasLatencies mask */ bankInfo[0].suportedCasLatencies &= bankInfo[i].suportedCasLatencies; } else { if( i == 0 ) /* bank 0 doesn't exist */ { mvOsPrintf("Dram: ERR. Fail to detect bank 0 !!!\n"); return MV_ERROR; } else { DB(mvOsPrintf("Dram: Could not find bank %d\n", i)); bankInfo[i].size = 0; /* Mark this bank as non exist */ } } } /* calculate minimum CAS */ minCas = minCasCalc(&bankInfo[0], busClk, forcedCl); if (0 == minCas) { mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n", (busClk / 1000000)); if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { minCas = DDR2_CL_4; /* Continue with this CAS */ mvOsPrintf("Set default CAS latency 4\n"); } else { minCas = DDR1_CL_3; /* Continue with this CAS */ mvOsPrintf("Set default CAS latency 3\n"); } } /* calc SDRAM_CONFIG_REG and save it to temp register */ temp = sdramConfigRegCalc(&bankInfo[0], busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramConfigRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG1, temp); /* calc SDRAM_MODE_REG and save it to temp register */ temp = sdramModeRegCalc(minCas); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG2, temp); /* calc SDRAM_EXTENDED_MODE_REG and save it to temp register */ temp = sdramExtModeRegCalc(&bankInfo[0]); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG10, temp); /* calc D_UNIT_CONTROL_LOW and save it to temp register */ temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas); if(-1 == temp) { mvOsPrintf("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG3, temp); /* calc SDRAM_ADDR_CTRL_REG and save it to temp register */ temp = sdramAddrCtrlRegCalc(&bankInfo[0]); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG4, temp); /* calc SDRAM_TIMING_CTRL_LOW_REG and save it to temp register */ temp = sdramTimeCtrlLowRegCalc(&bankInfo[0], minCas, busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG5, temp); /* calc SDRAM_TIMING_CTRL_HIGH_REG and save it to temp register */ temp = sdramTimeCtrlHighRegCalc(&bankInfo[0], busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG6, temp); /* Config DDR2 On Die Termination (ODT) registers */ if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { sdramDDr2OdtConfig(bankInfo); } /* Note that DDR SDRAM Address/Control and Data pad calibration */ /* settings is done in mvSdramIfConfig.s */ return retVal; }