Exemple #1
0
static int wait_for_command_done(int bank, int timeout) {
    u32 toTest;

    u64 startTime = iphone_microtime();
    if(NoMultibankCmdStatus)
        bank = 0;
    else
        bank &= 0xffff;

    toTest = 1 << (bank + 4);

    while((readl(NAND + FMCSTAT) & toTest) == 0) {
        yield();
        if(iphone_has_elapsed(startTime, timeout * 1000)) {
            return -ETIMEDOUT;
        }
    }

    writel(toTest, NAND + FMCSTAT);

#ifdef FTL_PROFILE
    if(InWrite) Time_wait_for_command_done += iphone_microtime() - startTime;
#endif

    return 0;
}
Exemple #2
0
static int wait_for_nand_bank_ready(int bank)
{
    u32 toTest;
    u64 startTime;

    writel(((WEHighHoldTime & FMCTRL_TWH_MASK) << FMCTRL_TWH_SHIFT) | ((WPPulseTime & FMCTRL_TWP_MASK) << FMCTRL_TWP_SHIFT)
           | (1 << (banksTable[bank] + 1)) | FMCTRL0_ON | FMCTRL0_WPB, NAND + FMCTRL0);

    toTest = 1 << (bank + 4);
    if((readl(NAND + FMCSTAT) & toTest) != 0)
    {
        writel(toTest, NAND + FMCSTAT);
    }

    writel(FMCTRL1_FLUSHFIFOS, NAND + FMCTRL1);
    writel(NAND_CMD_READSTATUS, NAND + NAND_CMD);
    wait_for_ready(500);

    startTime = iphone_microtime();
    while(true)
    {
        u32 data;

        writel(0, NAND + FMDNUM);
        writel(FMCTRL1_DOREADDATA, NAND + FMCTRL1);

        if(wait_for_transfer_done(500) != 0)
        {
            LOG("nand: wait_for_nand_bank_ready: wait for transfer done timed out\n");
            return -ETIMEDOUT;
        }


        data = readl(NAND + FMFIFO);
        writel(FMCTRL1_FLUSHRXFIFO, NAND + FMCTRL1);
        if((data & (1 << 6)) == 0)
        {
            if(iphone_has_elapsed(startTime, 500 * 1000))
            {
                LOG("nand: wait_for_nand_bank_ready: wait for bit 6 of DMA timed out\n");
                return -ETIMEDOUT;
            }
        } else
        {
            break;
        }
    }

    writel(0, NAND + NAND_CMD);
    wait_for_ready(500);

#ifdef FTL_PROFILE
    if(InWrite) Time_wait_for_nand_bank_ready += iphone_microtime() - startTime;
#endif

    return 0;
}
Exemple #3
0
static int transferToFlash(void* buffer, int size) {
    int controller = 0;
    int channel = 0;
    dma_addr_t dma;

#ifdef FTL_PROFILE
    u64 startTime;
#endif

    if((((u32)buffer) & 0x3) != 0) {
        // the buffer needs to be aligned for DMA, last two bits have to be clear
        return -EINVAL;
    }

    writel(readl(NAND + FMCTRL0) | (1 << FMCTRL0_DMASETTINGSHIFT), NAND + FMCTRL0);
    writel(size - 1, NAND + FMDNUM);
    writel(0x7F4, NAND + FMCTRL1);

    dma = dma_map_single(nand_dev, buffer, size, DMA_TO_DEVICE);

    iphone_dma_request(IPHONE_DMA_MEMORY, 4, 4, IPHONE_DMA_NAND, 4, 4, &controller, &channel);
    iphone_dma_perform((u32)dma, IPHONE_DMA_NAND, size, 0, &controller, &channel);

#ifdef FTL_PROFILE
    startTime = iphone_microtime();
#endif

    if(iphone_dma_finish(controller, channel, 500) != 0) {
        LOG("nand: dma timed out\n");
        return -ETIMEDOUT;
    }

#ifdef FTL_PROFILE
    if(InWrite) Time_iphone_dma_finish += iphone_microtime() - startTime;
#endif

    if(wait_for_transfer_done(500) != 0) {
        LOG("nand: waiting for transfer done timed out\n");
        return -ETIMEDOUT;
    }

    writel(FMCTRL1_FLUSHFIFOS, NAND + FMCTRL1);

    dma_unmap_single(nand_dev, dma, size, DMA_TO_DEVICE);

    return 0;
}
Exemple #4
0
static int wait_for_ready(int timeout) {
    u64 startTime;
    if((readl(NAND + FMCSTAT) & FMCSTAT_READY) != 0) {
        return 0;
    }

    startTime = iphone_microtime();
    while((readl(NAND + FMCSTAT) & FMCSTAT_READY) == 0) {
        yield();
        if(iphone_has_elapsed(startTime, timeout * 1000)) {
            return -ETIMEDOUT;
        }
    }

#ifdef FTL_PROFILE
    if(InWrite) Time_wait_for_ready += iphone_microtime() - startTime;
#endif

    return 0;
}
Exemple #5
0
static int wait_for_transfer_done(int timeout) {
    u64 startTime;
    if((readl(NAND + FMCSTAT) & (1 << 3)) != 0) {
        writel(1 << 3, NAND + FMCSTAT);
        return 0;
    }

    startTime = iphone_microtime();
    while((readl(NAND + FMCSTAT) & (1 << 3)) == 0) {
        yield();
        if(iphone_has_elapsed(startTime, timeout * 1000)) {
            return -ETIMEDOUT;
        }
    }

    writel(1 << 3, NAND + FMCSTAT);

#ifdef FTL_PROFILE
    if(InWrite) Time_wait_for_transfer_done += iphone_microtime() - startTime;
#endif

    return 0;
}
Exemple #6
0
static int wait_for_ecc_interrupt(int timeout)
{
    u64 startTime = iphone_microtime();
    u32 mask = (1 << (NANDECC_INT - VIC_InterruptSeparator));
    while((readl(VIC1 + VICRAWINTR) & mask) == 0) {
        yield();
        if(iphone_has_elapsed(startTime, timeout * 1000)) {
            return -ETIMEDOUT;
        }
    }

    writel(1, NANDECC + NANDECC_CLEARINT);

#ifdef FTL_PROFILE
    if(InWrite) Time_wait_for_ecc_interrupt += iphone_microtime() - startTime;
#endif

    if((readl(VIC1 + VICRAWINTR) & mask) == 0) {
        return 0;
    } else {
        return -ETIMEDOUT;
    }
}
Exemple #7
0
int iphone_has_elapsed(u64 startTime, u64 elapsedTime) {
	if((iphone_microtime() - startTime) >= elapsedTime)
		return 1;
	else
		return 0;
}