コード例 #1
0
static unsigned char *hisfc350_read_ids(struct hisfc_host *host,
                                        int chipselect,
                                        unsigned char *buffer)
{
    int regindex = 0;
    int numread = 8;
    unsigned int *ptr = (unsigned int *)buffer;

    if (numread > HISFC350_REG_BUF_SIZE)
        numread = HISFC350_REG_BUF_SIZE;

    hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_RDID);
    hisfc_write(host, HISFC350_CMD_CONFIG,
                HISFC350_CMD_CONFIG_SEL_CS(chipselect)
                | HISFC350_CMD_CONFIG_RW_READ
                | HISFC350_CMD_CONFIG_DATA_EN
                | HISFC350_CMD_CONFIG_DATA_CNT(numread)
                | HISFC350_CMD_CONFIG_START);

    HISFC350_CMD_WAIT_CPU_FINISH(host);

    while (numread) {
        *ptr = hisfc_read(host,
                          HISFC350_CMD_DATABUF0 + regindex);
        ptr      += 1;
        regindex += 4;
        numread  -= 4;
    }

    return buffer;
}
コード例 #2
0
static int hisfc350_reg_erase_one_block(struct hisfc_host *host,
                                        struct hisfc_spi *spi,
                                        unsigned int offset)
{
    if (spi->driver->wait_ready(spi))
        return 1;
    spi->driver->write_enable(spi);
    host->set_system_clock(host, spi->erase, TRUE);

    hisfc_write(host, HISFC350_CMD_INS, spi->erase->cmd);

    hisfc_write(host, HISFC350_CMD_ADDR,
                (offset & HISFC350_CMD_ADDR_MASK));

    hisfc_write(host, HISFC350_CMD_CONFIG,
                HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
                | HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi->erase->iftype)
                | HISFC350_CMD_CONFIG_DUMMY_CNT(spi->erase->dummy)
                | HISFC350_CMD_CONFIG_ADDR_EN
                | HISFC350_CMD_CONFIG_START);

    HISFC350_CMD_WAIT_CPU_FINISH(host);

    return 0;
}
コード例 #3
0
static void hisfc350_dma_transfer(struct hisfc_host *host,
                                  unsigned int spi_start_addr,
                                  unsigned char *dma_buffer,
                                  unsigned char is_read,
                                  unsigned int size,
                                  unsigned char chipselect)
{
    hisfc_write(host, HISFC350_BUS_DMA_MEM_SADDR, dma_buffer);

    hisfc_write(host, HISFC350_BUS_DMA_FLASH_SADDR,
                spi_start_addr);

    hisfc_write(host, HISFC350_BUS_DMA_LEN,
                HISFC350_BUS_DMA_LEN_DATA_CNT(size));

    hisfc_write(host, HISFC350_BUS_DMA_AHB_CTRL,
                HISFC350_BUS_DMA_AHB_CTRL_INCR4_EN
                | HISFC350_BUS_DMA_AHB_CTRL_INCR8_EN
                | HISFC350_BUS_DMA_AHB_CTRL_INCR16_EN);

    hisfc_write(host, HISFC350_BUS_DMA_CTRL,
                HISFC350_BUS_DMA_CTRL_RW(is_read)
                | HISFC350_BUS_DMA_CTRL_CS(chipselect)
                | HISFC350_BUS_DMA_CTRL_START);

    HISFC350_DMA_WAIT_CPU_FINISH(host);

}
コード例 #4
0
static int spi_s25fl256s_entry_4addr(struct hisfc_spi *spi, int enable)
{
	struct hisfc_host *host = (struct hisfc_host *)spi->host;

	if (spi->addrcycle != 4)
		return 0;

	if (enable) {
		hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR);
		hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EN4B);
	} else {
		hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR);
		hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EX4B);
	}

	hisfc_write(host, HISFC350_CMD_CONFIG,
		HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
		| HISFC350_CMD_CONFIG_DATA_CNT(1)
		| HISFC350_CMD_CONFIG_DATA_EN
		| HISFC350_CMD_CONFIG_START);

	HISFC350_CMD_WAIT_CPU_FINISH(host);

	host->set_host_addr_mode(host, enable);

	return 0;
}
コード例 #5
0
ファイル: hisnfc100.c プロジェクト: hmoster/android_kernel
static void hisnfc100_send_cmd_reset(struct hisnfc_host *host)
{
	hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE);
	hisfc_write(host, HISNFC100_OPCODE, SPI_CMD_RESET);
	hisfc_write(host, HISNFC100_OP_CFG, HISNFC100_OP_CFG_DIR_TRANS_ENABLE);
	hisfc_write(host, HISNFC100_OP,
			HISNFC100_OP_SEL_CS(host->cmd_option.chipselect)
			| HISNFC100_OP_OPCODE_EN(ENABLE)
			| HISNFC100_OP_START);

	HISNFC100_CMD_WAIT_CPU_FINISH(host);
}
コード例 #6
0
/*
   enable QE bit if QUAD read write is supported by SPI
 */
static int spi_mx25l25635e_qe_enable(struct hisfc_spi *spi)
{
	struct hisfc_host *host = (struct hisfc_host *)spi->host;
	unsigned int regval = 0;
	unsigned int qe_op = 0;
	if (hisfc350_is_quad(spi))
		qe_op = MX_SPI_CMD_SR_QE;
	else
		qe_op = SPI_CMD_SR_XQE;

	spi->driver->write_enable(spi);

	hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WRSR);
	hisfc_write(host, HISFC350_CMD_DATABUF0, qe_op);

	hisfc_write(host, HISFC350_CMD_CONFIG,
			HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi->
				write->iftype)
			| HISFC350_CMD_CONFIG_DATA_CNT(1)
			| HISFC350_CMD_CONFIG_DATA_EN
			| HISFC350_CMD_CONFIG_DUMMY_CNT(spi->
				write->dummy)
			| HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
			| HISFC350_CMD_CONFIG_START);

	HISFC350_CMD_WAIT_CPU_FINISH(host);

	spi->driver->wait_ready(spi);

	if (DEBUG_SPI) {
		hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_RDSR);

		hisfc_write(host, HISFC350_CMD_CONFIG,
				HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
				| HISFC350_CMD_CONFIG_DATA_CNT(1)
				| HISFC350_CMD_CONFIG_DATA_EN
				| HISFC350_CMD_CONFIG_RW_READ
				| HISFC350_CMD_CONFIG_START);
		HISFC350_CMD_WAIT_CPU_FINISH(host);
		regval = hisfc_read(host, HISFC350_CMD_DATABUF0);
		printf("QEbit = 0x40? : 0x%x\n", regval);
		if ((regval & MX_SPI_CMD_SR_QE))
			printf("QE bit enable success\n");
		else
			printf("QE bit enable failed\n");
	}
	return 0;
}
コード例 #7
0
static int hisfc350_controller_spi_init(struct hisfc_spi *spi, int offset)
{
    int regval;
    struct hisfc_host *host = (struct hisfc_host *)spi->host;

    regval = hisfc_read(host, HISFC350_BUS_FLASH_SIZE);
    regval &= ~(HISFC350_BUS_FLASH_SIZE_CS0_MASK
                << (spi->chipselect << 3));
    regval |= (hisfc350_map_chipsize(spi->chipsize)
               << (spi->chipselect << 3));
    hisfc_write(host, HISFC350_BUS_FLASH_SIZE, regval);

    hisfc_write(host,
                (HISFC350_BUS_BASE_ADDR_CS0 + (spi->chipselect << 2)),
                (CONFIG_HISFC350_BUFFER_BASE_ADDRESS + offset));

    return 0;
}
コード例 #8
0
static void hisfc350_set_host_addr_mode(struct hisfc_host *host, int enable)
{
    unsigned int regval;

    regval = hisfc_read(host, HISFC350_GLOBAL_CONFIG);
    if (enable)
        regval |= HISFC350_GLOBAL_CONFIG_ADDR_MODE_4B;
    else
        regval &= ~HISFC350_GLOBAL_CONFIG_ADDR_MODE_4B;

    hisfc_write(host, HISFC350_GLOBAL_CONFIG, regval);
}
コード例 #9
0
static int spi_s25fl256s_entry_4addr(struct hisfc_spi *spi, int enable)
{
	struct hisfc_host *host = (struct hisfc_host *)spi->host;
	unsigned int regval = 0;

	if (spi->addrcycle != SPI_4BYTE_ADDR_LEN)
		return 0;

	if (enable) {
		hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR);
		hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EN4B);
	} else {
		hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR);
		hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EX4B);
	}

	hisfc_write(host, HISFC350_CMD_CONFIG,
		HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
		| HISFC350_CMD_CONFIG_DATA_CNT(1)
		| HISFC350_CMD_CONFIG_DATA_EN
		| HISFC350_CMD_CONFIG_START);

	HISFC350_CMD_WAIT_CPU_FINISH(host);
	if (DEBUG_SPI) {
		regval = hisfc_read(host, HISFC350_CMD_DATABUF0);
		if (!(regval & SPI_EN4B)) {
			printk(KERN_INFO "now is 3-byte address mode\n");
			printk(KERN_INFO "regval_read_SPI : 0x%x\n", regval);
		} else
			printk(KERN_INFO "now is 4-byte address mode\n");

	}
	host->set_host_addr_mode(host, enable);

	return 0;
}
コード例 #10
0
int hisfc350_probe(struct hisfc_host *host)
{
    host->set_system_clock = hisfc350_set_system_clock;
    host->set_host_addr_mode = hisfc350_set_host_addr_mode;

    hisfc350_set_system_clock(host, NULL, TRUE);
    hisfc_write(host, HISFC350_TIMING,
                HISFC350_TIMING_TCSS(0x6)
                | HISFC350_TIMING_TCSH(0x6)
                | HISFC350_TIMING_TSHSL(0xf));

    if (!hisfc350_spi_probe(host))
        return -1;

    hisfc350_probe_spi_size(host);

    return 0;
}
コード例 #11
0
static int spi_w25q256fv_entry_4addr(struct hisfc_spi *spi, int enable)
{
    struct hisfc_host *host = (struct hisfc_host *)spi->host;

    if (spi->addrcycle != SPI_4BYTE_ADDR_LEN)
        return 0;
    /* This chip should not enable write here,
     * we have confirmed with the WINBOND */
    /* spi->driver->write_enable(spi); */
    if (enable) {
        hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EN4B);
        if (DEBUG_SPI)
            printk(KERN_INFO "now w25q256fv is 4-byte address mode\n");

        hisfc_write(host, HISFC350_CMD_CONFIG,
                    HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
                    | HISFC350_CMD_CONFIG_START);

        HISFC350_CMD_WAIT_CPU_FINISH(host);
    } else {
        hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_FIRST_RESET_4ADDR);
        hisfc_write(host, HISFC350_CMD_CONFIG,
                    HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
                    | HISFC350_CMD_CONFIG_START);


        HISFC350_CMD_WAIT_CPU_FINISH(host);


        hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_SECOND_RESET_4ADDR);
        hisfc_write(host, HISFC350_CMD_CONFIG,
                    HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
                    | HISFC350_CMD_CONFIG_START);

        HISFC350_CMD_WAIT_CPU_FINISH(host);
        if (DEBUG_SPI)
            printk(KERN_INFO "now W25Q256FV 6699 cmd\n");
    }
    /*
    	hisfc_write(host, HISFC350_CMD_CONFIG,
    		HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect)
    		| HISFC350_CMD_CONFIG_DATA_CNT(1)
    		| HISFC350_CMD_CONFIG_DATA_EN
    		| HISFC350_CMD_CONFIG_START);

    	HISFC350_CMD_WAIT_CPU_FINISH(host);
    */
    host->set_host_addr_mode(host, enable);

    return 0;
}
コード例 #12
0
ファイル: hisnfc100.c プロジェクト: hmoster/android_kernel
static void hisnfc100_send_cmd_readid(struct hisnfc_host *host)
{
	hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE);
	hisfc_write(host, HISNFC100_OPCODE, SPI_CMD_RDID);
	hisfc_write(host, HISNFC100_OP_ADDR, READ_ID_ADDR);
	hisfc_write(host, HISNFC100_DATA_NUM,
			HISNFC100_DATA_NUM_CNT(MAX_ID_LEN));
	hisfc_write(host, HISNFC100_OP_CFG, HISNFC100_OP_CFG_DIR_TRANS_ENABLE);

	hisfc_write(host, HISNFC100_OP,
			HISNFC100_OP_SEL_CS(host->cmd_option.chipselect)
			| HISNFC100_OP_ADDR_NUM(READ_ID_ADDR_NUM)
			| HISNFC100_OP_OPCODE_EN(ENABLE)
			| HISNFC100_OP_ADDR_EN(ENABLE)
			| HISNFC100_OP_DATE_READ_EN(ENABLE)
			| HISNFC100_OP_START);

	HISNFC100_CMD_WAIT_CPU_FINISH(host);
}
コード例 #13
0
ファイル: hisnfc100.c プロジェクト: hmoster/android_kernel
static void hisnfc100_send_cmd_erase(struct hisnfc_host *host)
{
	unsigned val;
	struct hisnfc_op *spi = host->spi;

	if (DEBUG_ERASE)
		pr_info("* Enter send cmd erase!\n");

	val = spi->driver->wait_ready(spi);
	if (val) {
		pr_info("hisnfc: erase wait ready fail! status[%#x]\n", val);
		return;
	}

	if (spi->driver->write_enable(spi)) {
		pr_info("%s erase write enable failed!\n", __func__);
		return;
	}

	if (DEBUG_ERASE) {
		spi_feature_op(host, GET_OP, STATUS_ADDR, &val);
		pr_info("  Get feature addr[0xC0], val[%#x]\n", val);
	}

	val = HISNFC100_INT_CLR_ALL;
	hisfc_write(host, HISNFC100_INT_CLR, val);
	if (DEBUG_ERASE)
		pr_info("  Set REG INT_CLR[0x14]%#x\n", val);

	val = spi->erase->cmd;
	hisfc_write(host, HISNFC100_OPCODE, val);
	if (DEBUG_ERASE)
		pr_info("  Set REG OPCODE[0x18]%#x\n", val);

	val = HISNFC100_OP_ADDRH_BLOCK_MASK(host->addr_value[1])
		| HISNFC100_OP_ADDRL_BLOCK_MASK(host->addr_value[0]);
	hisfc_write(host, HISNFC100_OP_ADDR, val);
	if (DEBUG_ERASE)
		pr_info("  Set REG OP_ADDR[0x18]%#x\n", val);

	val = HISNFC100_OP_CFG_DIR_TRANS_ENABLE;
	hisfc_write(host, HISNFC100_OP_CFG, val);
	if (DEBUG_ERASE)
		pr_info("  Set REG OP_CFG[0x28]%#x\n", val);

	val = HISNFC100_OP_SEL_CS(host->cmd_option.chipselect)
		| HISNFC100_OP_ADDR_NUM(STD_OP_ADDR_NUM)
		| HISNFC100_OP_OPCODE_EN(ENABLE)
		| HISNFC100_OP_ADDR_EN(ENABLE)
		| HISNFC100_OP_START;
	hisfc_write(host, HISNFC100_OP, val);
	if (DEBUG_ERASE)
		pr_info("  Set REG OP[0x20]%#x\n", val);

	HISNFC100_CMD_WAIT_CPU_FINISH(host);

	if (DEBUG_ERASE) {
		val = spi->driver->wait_ready(spi);
		if (val & STATUS_E_FAIL_MASK)
			pr_info("hisnfc100: erase failed! status[%#x]\n", val);
	}

	if (DEBUG_ERASE)
		pr_info("* End send cmd erase!\n");
}
コード例 #14
0
ファイル: hisnfc100.c プロジェクト: hmoster/android_kernel
static void hisnfc100_send_cmd_pageprog(struct hisnfc_host *host)
{
	unsigned char pages_per_block_shift;
	unsigned val, block_num, block_num_h, page_num;
	struct hisnfc_op *spi = host->spi;
	struct nand_chip *chip = host->chip;
#ifdef HISNFC100_SUPPORT_REG_WRITE
	const char *op_type = "reg";
#else
	const char *op_type = "dma";
#endif

	if (DEBUG_WRITE)
		pr_info("* Enter %s page program!\n", op_type);

	val = spi->driver->wait_ready(spi);
	if (val) {
		pr_info("%s: %s page program wait ready fail! status[%#x]\n",
			__func__, op_type, val);
		return;
	}

	if (spi->driver->write_enable(spi)) {
		pr_info("%s %s page program write enable failed!\n", __func__,
			op_type);
		return;
	}

	val = HISNFC100_INT_CLR_ALL;
	hisfc_write(host, HISNFC100_INT_CLR, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG INT_CLR[0x14]%#x\n", val);

	val = HISNFC100_OP_CFG_MEM_IF_TYPE(spi->write->iftype);
	hisfc_write(host, HISNFC100_OP_CFG, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG OP_CFG[0x28]%#x\n", val);

	pages_per_block_shift = chip->phys_erase_shift - chip->page_shift;
	block_num = host->addr_value[1] >> pages_per_block_shift;
	block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT;
	val = HISNFC100_ADDRH_SET(block_num_h);
	hisfc_write(host, HISNFC100_ADDRH, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG ADDRH[0x2c]%#x\n", val);

	page_num = host->addr_value[1] - (block_num << pages_per_block_shift);
	val = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT)
	     | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT);
	hisfc_write(host, HISNFC100_ADDRL, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG ADDRL[0x30]%#x\n", val);

#ifndef HISNFC100_SUPPORT_REG_WRITE
	val = HISNFC100_DMA_CTRL_ALL_ENABLE;
	hisfc_write(host, HISNFC100_DMA_CTRL, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG DMA_CTRL[0x3c]%#x\n", val);

	val = host->dma_buffer;
	hisfc_write(host, HISNFC100_DMA_SADDR_D, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG DMA_SADDR_D[0x40]%#x\n", val);

	val = host->dma_oob;
	hisfc_write(host, HISNFC100_DMA_SADDR_OOB, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG DMA_SADDR_OOB[%#x]%#x\n",
			HISNFC100_DMA_SADDR_OOB, val);
#endif

	val = HISNFC100_OP_CTRL_WR_OPCODE(spi->write->cmd)
		| HISNFC100_OP_CTRL_CS_OP(host->cmd_option.chipselect)
#ifdef HISNFC100_SUPPORT_REG_WRITE
		| HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_REG)
#else
		| HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_DMA)
#endif
		| HISNFC100_OP_CTRL_RW_OP(RW_OP_WRITE)
		| HISNFC100_OP_CTRL_OP_READY;
	hisfc_write(host, HISNFC100_OP_CTRL, val);
	if (DEBUG_WRITE)
		pr_info("  Set REG OP_CTRL[0x34]%#x\n", val);

	HISNFC100_DMA_WAIT_INT_FINISH(host);

	if (DEBUG_WRITE) {
		val = spi->driver->wait_ready(spi);
		if (val & STATUS_P_FAIL_MASK)
			pr_info("hisnfc100: %s page program failed!",
					op_type);
			pr_info(" status[%#x]\n", val);
	}

	if (DEBUG_WRITE)
		pr_info("* End %s page program!\n", op_type);
}
コード例 #15
0
ファイル: hisnfc100.c プロジェクト: hmoster/android_kernel
static void hisnfc100_send_cmd_readstart(struct hisnfc_host *host)
{
	unsigned char pages_per_block_shift, only_oob = 0;
	unsigned short wrap = 0;
	unsigned val, block_num, block_num_h, page_num, addr_of = 0;
	struct hisnfc_op *spi = host->spi;
	struct nand_chip *chip = host->chip;
#ifdef HISNFC100_SUPPORT_REG_READ
	char *op_type = "reg";
#else
	char *op_type = "dma";
#endif

	if (DEBUG_READ)
		pr_info("* Enter %s page read start!\n", op_type);

	if ((host->addr_value[0] == host->cache_addr_value[0])
		&& (host->addr_value[1] == host->cache_addr_value[1])) {
		if (DEBUG_READ)
			pr_info("* %s page read cache hit! addr1[%#x], ",
					op_type,  host->addr_value[1]);
			pr_info("addr0[%#x]\n",	host->addr_value[0]);
		return;
	}

	val = spi->driver->wait_ready(spi);
	if (val) {
		pr_info("%s: %s read wait ready fail! status[%#x]\n", __func__,
			op_type, val);
		return;
	}

	val = HISNFC100_INT_CLR_ALL;
	hisfc_write(host, HISNFC100_INT_CLR, val);
	if (DEBUG_READ)
		pr_info("  Set REG INT_CLR[0x14]%#x\n", val);

	if (host->cmd_option.last_cmd == NAND_CMD_READOOB) {
		only_oob = 1;
		host->cmd_option.op_config =
				HISNFC100_OP_CFG_RD_OP_SEL(RD_OP_READ_OOB);
	} else
		host->cmd_option.op_config =
				HISNFC100_OP_CFG_RD_OP_SEL(RD_OP_READ_PAGE);

	val = host->cmd_option.op_config
		| HISNFC100_OP_CFG_MEM_IF_TYPE(spi->read->iftype)
		| HISNFC100_OP_CFG_DUMMY_ADDR_NUM(spi->read->dummy);
	hisfc_write(host, HISNFC100_OP_CFG, val);
	if (DEBUG_READ)
		pr_info("  Set REG OP_CFG[0x28]%#x\n", val);

	pages_per_block_shift = chip->phys_erase_shift - chip->page_shift;
	block_num = host->addr_value[1] >> pages_per_block_shift;
	block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT;

	val = HISNFC100_ADDRH_SET(block_num_h);
	hisfc_write(host, HISNFC100_ADDRH, val);
	if (DEBUG_READ)
		pr_info("  Set REG ADDRH[0x2c]%#x\n", val);

	page_num = host->addr_value[1] - (block_num << pages_per_block_shift);
	if (only_oob)
		switch (host->ecctype) {
		case NAND_ECC_8BIT:
			addr_of = REG_CNT_ECC_8BIT_OFFSET;
			break;
		case NAND_ECC_16BIT:
			addr_of = REG_CNT_ECC_16BIT_OFFSET;
			break;
		case NAND_ECC_24BIT:
			addr_of = REG_CNT_ECC_24BIT_OFFSET;
			break;
		case NAND_ECC_0BIT:
		default:
			break;
		}

	val = (((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT)
		| ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT)
		| ((wrap & REG_CNT_WRAP_MASK) << REG_CNT_WRAP_SHIFT)
		| (addr_of & REG_CNT_ECC_OFFSET_MASK));
	hisfc_write(host, HISNFC100_ADDRL, val);
	if (DEBUG_READ)
		pr_info("  Set REG ADDRL[0x30]%#x\n", val);

#ifndef HISNFC100_SUPPORT_REG_READ
	val = HISNFC100_DMA_CTRL_ALL_ENABLE;
	hisfc_write(host, HISNFC100_DMA_CTRL, val);
	if (DEBUG_READ)
		pr_info("  Set REG DMA_CTRL[0x3c]%#x\n", val);

	val = host->dma_buffer;
	hisfc_write(host, HISNFC100_DMA_SADDR_D, val);
	if (DEBUG_READ)
		pr_info("  Set REG DMA_SADDR_D[0x40]%#x\n", val);

	val = host->dma_oob;
	hisfc_write(host, HISNFC100_DMA_SADDR_OOB, val);
	if (DEBUG_READ)
		pr_info("  Set REG DMA_SADDR_OOB[%#x]%#x\n",
			HISNFC100_DMA_SADDR_OOB, val);
#endif

	val = HISNFC100_OP_CTRL_RD_OPCODE(spi->read->cmd)
		| HISNFC100_OP_CTRL_CS_OP(host->cmd_option.chipselect)
#ifdef HISNFC100_SUPPORT_REG_READ
		| HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_REG)
#else
		| HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_DMA)
#endif
		| HISNFC100_OP_CTRL_RW_OP(RW_OP_READ)
		| HISNFC100_OP_CTRL_OP_READY;
	hisfc_write(host, HISNFC100_OP_CTRL, val);
	if (DEBUG_READ)
		pr_info("  Set REG OP_CTRL[0x34]%#x\n", val);

	HISNFC100_DMA_WAIT_INT_FINISH(host);

	host->cache_addr_value[0] = host->addr_value[0];
	host->cache_addr_value[1] = host->addr_value[1];

	if (DEBUG_READ)
		pr_info("* End %s page read start!\n", op_type);
}