示例#1
0
/* sends a pipeline command operation to the controller. See the Denali NAND
 * controller's user guide for more information (section 4.2.3.6).
 */
static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
							bool ecc_en,
							bool transfer_spare,
							int access_type,
							int op)
{
	int status = PASS;
	uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0,
		 irq_mask = 0;

	if (op == DENALI_READ)
		irq_mask = INTR_STATUS__LOAD_COMP;
	else if (op == DENALI_WRITE)
		irq_mask = 0;
	else
		BUG();

	setup_ecc_for_xfer(denali, ecc_en, transfer_spare);

	/* clear interrupts */
	clear_interrupts(denali);

	addr = BANK(denali->flash_bank) | denali->page;

	if (op == DENALI_WRITE && access_type != SPARE_ACCESS) {
		cmd = MODE_01 | addr;
		iowrite32(cmd, denali->flash_mem);
	} else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) {
		/* read spare area */
		cmd = MODE_10 | addr;
		index_addr(denali, (uint32_t)cmd, access_type);

		cmd = MODE_01 | addr;
		iowrite32(cmd, denali->flash_mem);
	} else if (op == DENALI_READ) {
		/* setup page read request for access type */
		cmd = MODE_10 | addr;
		index_addr(denali, (uint32_t)cmd, access_type);

		/* page 33 of the NAND controller spec indicates we should not
		   use the pipeline commands in Spare area only mode. So we
		   don't.
		 */
		if (access_type == SPARE_ACCESS) {
			cmd = MODE_01 | addr;
			iowrite32(cmd, denali->flash_mem);
		} else {
			index_addr(denali, (uint32_t)cmd,
					0x2000 | op | page_count);

			/* wait for command to be accepted
			 * can always use status0 bit as the
			 * mask is identical for each
			 * bank. */
			irq_status = wait_for_irq(denali, irq_mask);

			if (irq_status == 0) {
				dev_err(denali->dev,
						"cmd, page, addr on timeout "
						"(0x%x, 0x%x, 0x%x)\n",
						cmd, denali->page, addr);
				status = FAIL;
			} else {
				cmd = MODE_01 | addr;
				iowrite32(cmd, denali->flash_mem);
			}
		}
	}
	return status;
}
示例#2
0
static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
			   int page)
{
	struct denali_nand_info *denali = mtd_to_denali(mtd);
	uint32_t addr, id;
	uint32_t pages_per_block;
	uint32_t block;
	int i;

	switch (cmd) {
	case NAND_CMD_PAGEPROG:
		break;
	case NAND_CMD_STATUS:
		read_status(denali);
		break;
	case NAND_CMD_READID:
		reset_buf(denali);
		/*
		 * sometimes ManufactureId read from register is not right
		 * e.g. some of Micron MT29F32G08QAA MLC NAND chips
		 * So here we send READID cmd to NAND insteand
		 */
		addr = MODE_11 | BANK(denali->flash_bank);
		index_addr(denali, addr | 0, 0x90);
		index_addr(denali, addr | 1, col);
		for (i = 0; i < 8; i++) {
			index_addr_read_data(denali, addr | 2, &id);
			write_byte_to_buf(denali, id);
		}
		break;
	case NAND_CMD_PARAM:
		reset_buf(denali);

		/* turn on R/B interrupt */
		denali_set_intr_modes(denali, false);
		denali_irq_mask = DENALI_IRQ_ALL | INTR_STATUS__INT_ACT;
		clear_interrupts(denali);
		denali_irq_enable(denali, denali_irq_mask);
		denali_set_intr_modes(denali, true);

		addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
		index_addr(denali, (uint32_t)addr | 0, cmd);
		index_addr(denali, (uint32_t)addr | 1, col & 0xFF);
		/* Wait tR time... */
		udelay(25);
		/* And then wait for R/B interrupt */
		wait_for_irq(denali, INTR_STATUS__INT_ACT);

		/* turn off R/B interrupt now */
		denali_irq_mask = DENALI_IRQ_ALL;
		denali_set_intr_modes(denali, false);
		denali_irq_enable(denali, denali_irq_mask);
		denali_set_intr_modes(denali, true);

		for (i = 0; i < 256; i++) {
			index_addr_read_data(denali,
						(uint32_t)addr | 2,
						&id);
			write_byte_to_buf(denali, id);
		}
		break;
	case NAND_CMD_READ0:
	case NAND_CMD_SEQIN:
		denali->page = page;
		break;
	case NAND_CMD_RESET:
		reset_bank(denali);
		break;
	case NAND_CMD_READOOB:
		/* TODO: Read OOB data */
		break;
	case NAND_CMD_UNLOCK1:
		pages_per_block = mtd->erasesize / mtd->writesize;
		block = page / pages_per_block;
		addr = (uint32_t)MODE_10 | (block * pages_per_block);
		index_addr(denali, addr, 0x10);
		break;
	case NAND_CMD_UNLOCK2:
		pages_per_block = mtd->erasesize / mtd->writesize;
		block = (page+pages_per_block-1) / pages_per_block;
		addr = (uint32_t)MODE_10 | (block * pages_per_block);
		index_addr(denali, addr, 0x11);
		break;
	case NAND_CMD_ERASE1:
	case NAND_CMD_ERASE2:
		addr = MODE_10 | BANK(denali->flash_bank) | page;
		index_addr(denali, addr, 0x1);
		break;
	default:
		pr_err(": unsupported command received 0x%x\n", cmd);
		break;
	}
}
示例#3
0
文件: main.c 项目: elkhadiy/cours-tlm
int __start() {

    printf("-- boot complete -- \r\n");

    refresh = 0;
    old_img_addr = SRAM_BASEADDR;
    new_img_addr = SRAM_BASEADDR + 0x80000;

    clr_screen(old_img_addr);
    clr_screen(new_img_addr);

    draw_gun(0, 30);

    /* blinker */
    set_pixel(old_img_addr, 20, 10, 1);
    set_pixel(old_img_addr, 20, 11, 1);
    set_pixel(old_img_addr, 20, 12, 1);

    /* another blinker */
    set_pixel(old_img_addr, 30, 10, 1);
    set_pixel(old_img_addr, 31, 10, 1);
    set_pixel(old_img_addr, 32, 10, 1);

    /* pixel alone, will die after the first iteration */
    set_pixel(old_img_addr, 32, 30, 1);

    /* start vga */
    write_mem(VGA_BASEADDR + VGA_CFG_OFFSET, old_img_addr);

    /* program timer: 0x01000000 / (50MHz) = 0.33554432 seconds */
    write_mem(TIMER_BASEADDR + TIMER_0_TLR_OFFSET, 0x04000000);
    write_mem(TIMER_BASEADDR + TIMER_0_CSR_OFFSET, TIMER_RELOAD);
    write_mem(TIMER_BASEADDR + TIMER_0_CSR_OFFSET, TIMER_START);

    /* program gpio to input */
    write_mem(GPIO_BASEADDR + GPIO_TRI_OFFSET, GPIO_INPUT);

    while (1) {
        /* glider */
        set_pixel(old_img_addr, 11, 10, 1);
        set_pixel(old_img_addr, 12, 11, 1);
        set_pixel(old_img_addr, 10, 12, 1);
        set_pixel(old_img_addr, 11, 12, 1);
        set_pixel(old_img_addr, 12, 12, 1);

        /* another glider */
        set_pixel(old_img_addr, 51, 10, 1);
        set_pixel(old_img_addr, 50, 11, 1);
        set_pixel(old_img_addr, 52, 12, 1);
        set_pixel(old_img_addr, 51, 12, 1);
        set_pixel(old_img_addr, 50, 12, 1);

        while (1) {
            uint32_t d = read_mem(GPIO_BASEADDR + GPIO_DATA_OFFSET);
            if (TEST_BIT(d, GPIO_BTN0)) {
                break;
            }

            // put cpu in a lower consumption state while waiting for an int
            wait_for_irq();
            //cpu_relax();
        }
    }

    return 0;
}
示例#4
0
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
			    uint8_t *buf, int oob_required, int page)
{
	unsigned int max_bitflips = 0;
	struct denali_nand_info *denali = mtd_to_denali(mtd);

	dma_addr_t addr = (unsigned long)denali->buf.buf;
	size_t size = denali->mtd.writesize + denali->mtd.oobsize;

	uint32_t irq_status;
	uint32_t irq_mask = denali->have_hw_ecc_fixup ?
		(INTR_STATUS__DMA_CMD_COMP) :
		(INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR);
	bool check_erased_page = false;

	if (page != denali->page) {
		dev_err(denali->dev,
			"IN %s: page %d is not equal to denali->page %d",
			__func__, page, denali->page);
		BUG();
	}

	setup_ecc_for_xfer(denali, true, false);

	denali_enable_dma(denali, true);
	dma_sync_single_for_device(addr, size, DMA_FROM_DEVICE);

	clear_interrupts(denali);
	denali_setup_dma(denali, DENALI_READ);

	/* wait for operation to complete */
	irq_status = wait_for_irq(denali, irq_mask);

	dma_sync_single_for_cpu(addr, size, DMA_FROM_DEVICE);

	memcpy(buf, denali->buf.buf, mtd->writesize);

	check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips);
	denali_enable_dma(denali, false);

	if (check_erased_page) {
		if (denali->have_hw_ecc_fixup) {
			/* When we have hw ecc fixup, don't check oob.
			 * That code below looks jacked up anyway.  I mean,
			 * look at it, wtf? */
			if (!is_erased(buf, denali->mtd.writesize))
				denali->mtd.ecc_stats.failed++;
		} else {
			read_oob_data(&denali->mtd, chip->oob_poi,
				denali->page);

			/* check ECC failures that may have occurred on
			 * erased pages */
			if (check_erased_page) {
				if (!is_erased(buf, denali->mtd.writesize))
					denali->mtd.ecc_stats.failed++;
				if (!is_erased(buf, denali->mtd.oobsize))
					denali->mtd.ecc_stats.failed++;
			}
		}
	}
	return max_bitflips;
}