Exemple #1
0
uint8_t *
nand_read_id(nand_port *nandp)
{
	nand_enable(nandp);

	NAND_COMMAND(nandp, 0x90);

	/* follow by address - 0 */
	*(nandp->cont_port) |= NAND_CONT_ALE;
	NAND_IO_SET(nandp, 0x00);
	*(nandp->cont_port) &= ~NAND_CONT_ALE;

	NAND_IO_INPUT(nandp);
	NAND_IO_READ(nandp, device_id[0]);
	NAND_IO_READ(nandp, device_id[1]);

	/* hynix */
	if (device_id[0] == 0xAD && device_id[1] == 0x73) {
		/* hynix flash device */
		PAGE_SZ = 512;
		NBLOCKS = 1024;
		PAGES_PER_BLOCK = 32;
		PAGE_PLUS_RAS_SZ = PAGE_SZ+16; 
		BLOCK_SZ = PAGES_PER_BLOCK * PAGE_SZ;
		return device_id;	
	}

	/* samsung */
	if (device_id[0] == 0xEC) {
		NAND_IO_READ(nandp, device_id[2]);
		NAND_IO_READ(nandp, device_id[3]);
		
		NBLOCKS = 1024;
		PAGE_SZ = (device_id[3] & 0x1) ? 2048 : 1024; /* !! 2048 */
		switch ( ((device_id[3] >> 4) & 0x3) ) {
		case 0:
			BLOCK_SZ = (uint32_t)64 * (uint32_t)1024;
			break;
		case 1:
			BLOCK_SZ = (uint32_t)128 * (uint32_t)1024; /* should be 128 !! */
			break;
		case 2:
			BLOCK_SZ = (uint32_t)256 * (uint32_t)1024;
			break;
		}
		
	//	PAGE_PLUS_RAS_SZ 	 = PAGE_SZ + ((device_id[3] & 4) ? (16 * (PAGE_SZ/512)) : (8 * (PAGE_SZ/512)));
		PAGE_PLUS_RAS_SZ = 2112;

		PAGES_PER_BLOCK = BLOCK_SZ / PAGE_SZ; /* !! 64 */
		return device_id;
	}
//mtd子系统有对nand的请求时候调用
void nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
	struct nand_info *nand = container_of(mtd, struct nand_info, mtd);	

	if(ctrl & NAND_CTRL_CHANGE){
		if(ctrl & NAND_NCE)
			nand_enable(nand);
		else
			nand_disable(nand);
	}

	if(dat != NAND_CMD_NONE){
		if(ctrl & NAND_CLE)
			writeb(dat, nand->virt + NFCMMD);
		else if(ctrl & NAND_ALE)
			writeb(dat, nand->virt + NFADDR);
	}
}
void nand_init(struct nand_info *nand)
{
	u32 tmp;
	
    //配置nand时序
	tmp = TACLS | TWRPH0 | TWRPH1 | MUST1;
	writel(tmp, nand->virt + NFCONF);
    //打开nand控制器,并把nand芯片的片选无效
	tmp = CSN2_DIS | CTROLLER_EN;
	writel(tmp, nand->virt + NFCONT);

    //打开nand片选
	nand_enable(nand);

    //发送重启命令
	writel(RESET_CMD, nand->virt + NFCMMD);
	while(!(nand_dev_ready(&nand->mtd)));

    //关掉nand芯片的片选
	nand_disable(nand);
}
/**
 * jz_nemc_ctrl_select -
 * @nand_nce:	
 */
int jz_nemc_ctrl_select(NAND_BASE *host,void *pnand_io,int nand_nce)
{
	JZ_IO *p_io = (JZ_IO *)pnand_io;
	unsigned int i=0,ret=0;	
	if ((nand_nce >= g_maxchips) || (nand_nce == -1))
	{
		nemc_writel(host->nemc_iomem,NEMC_NFCSR,0);
		return -1; /*bigger than support, or unselect all chips*/
	}
	while(ret <= nand_nce && ret < NEMC_CS_COUNT)
	{
		if(g_chips_mark[i])
			ret++;
		i++;
	}
	switch(i){
	case 1:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 5 * 0x01000000);
		nand_enable(host,1);
		ret =1;
		break;
	case 2:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 4 * 0x01000000);
		nand_enable(host,2);
		ret =2;
		break;
	case 3:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 3 * 0x01000000);
		nand_enable(host,3);
		ret =3;
		break;
	case 4:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 2 * 0x01000000);
		nand_enable(host,4);
		ret =4;
		break;
	case 5:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 1 * 0x01000000);
		nand_enable(host,5);
		ret =5;
		break;
	case 6:
		p_io->dataport = (void *)(host->nemc_cs6_iomem + 0 * 0x01000000);
		nand_enable(host,6);
		ret =6;
		break;
	default:
	  eprintf("error: no nand_nce 0x%x\n",nand_nce);
	  ret = -1;
		break;
	}
#ifdef CONFIG_TOGGLE_NAND
	switch(i){
	case 1:
		tnand_enable(host,1);
		break;
	case 2:
		tnand_enable(host,2);
		break;
	case 3:
		tnand_enable(host,3);
		break;
	case 4:
		tnand_enable(host,4);
		break;
	case 5:
		tnand_enable(host,5);
		break;
	case 6:
		tnand_enable(host,6);
		break;
	default:
	  eprintf(1,"error: no nand_nce 0x%x\n",nand_nce);
		break;
	}
#endif
	p_io->cmdport = p_io->dataport + NAND_CMD_OFFSET;
	p_io->addrport = p_io->dataport + NAND_ADDR_OFFSET;
//	dprintf("DEBUG nand: jz_nemc_ctrl_select i = %d , p_io->dataport = 0x%x\n",i,(unsigned int)p_io->dataport);
	return ret;
}