void nf_readpage(unsigned int block,unsigned int page,unsigned char *dstaddr) { unsigned int i; unsigned int blockpage=(block<<6)+page; /*计算page绝对地址*/ nand_reset(); enable(); enable_rb(); send_cmd(readp1); send_addr(0x00); send_addr(0x00); send_addr((blockpage)&0xff); send_addr((blockpage>>8)&0xff); send_addr((blockpage>>16)&0x01); send_cmd(readp2); check_busy(); for(i=0;i<2048;i++) { dstaddr[i]=read_byte(); } disable(); }
int my_nand_init(void) { s5pv210_nand_regs = ioremap(0xB0E00000, sizeof(struct s5pv210_nand_regs)); mp12con = ioremap(MP0_1CON, 4); *mp12con = (*mp12con & ~(0xf<<8)) | (0x3<<8); *mp12con = (*mp12con & ~(0xf<<12)) | (0x3<<12); *mp12con = (*mp12con & ~(0xf<<16)) | (0x3<<16); *mp12con = (*mp12con & ~(0xf<<20)) | (0x3<<20); mp06con = ioremap(MP0_6CON, 4); //*mp06con = 0x22222222; //1.分配nand_chip s5pv210_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); //2.设置nand_chip /* * 设置nand的操作方法: * 比如: 选中,发命令,发数据,读数据,判断状态 * */ s5pv210_nand->select_chip = s5pv210_select_chip; s5pv210_nand->cmd_ctrl = s5pv210_cmd_ctrl; s5pv210_nand->IO_ADDR_W = &s5pv210_nand_regs->NFDATA; s5pv210_nand->IO_ADDR_R = &s5pv210_nand_regs->NFDATA; s5pv210_nand->dev_ready = s5pv210_dev_ready; s5pv210_nand->options = 0; //3.硬件相关设置 s5pv210_nand_clk = clk_get(NULL, "nand"); if(s5pv210_nand_clk == NULL) { printk("clk get error()\n"); } clk_enable(s5pv210_nand_clk); //配置时序 s5pv210_nand_regs->NFCONF &= ~((0xf<<4) | (0xf<<8) | (0xf<<12)); s5pv210_nand_regs->NFCONF |= (15<<12) | (15<<8) | (15<<4) | (1<<1); //开启nand控制器 s5pv210_nand_regs->NFCONT |= 1; nand_reset(); //4.添加nand s5pv210_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); s5pv210_mtd->owner = THIS_MODULE; s5pv210_mtd->priv = s5pv210_nand; //int nand_scan(struct mtd_info *mtd, int maxchips) if(nand_scan(s5pv210_mtd, 1)) { printk("not found\n"); } //5.添加分区表 return 0; }
void nand_init(void){ NFCONF=(7<<12)|(7<<8)|(7<<4)|(0<<0); NFCONT=(1<<4)|(0<<1)|(1<<0); nand_reset(); }
void nand_init(void) { NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(3<<2)|(1<<1); /*需要加上|(3<<2)|(1<<1) */ /* 初始化ECC, 禁止片选 */ NFCONT = (1<<4)|(1<<1)|(1<<0); NFSTAT =0x0; /* 复位NAND Flash */ nand_reset(); }
void nand_init() { /* 让xm0csn2用作nand flash cs0 片选引脚 */ MEM_SYS_CFG &= ~(1<<1); /* 设置时间参数 */ #define TACLS 0 #define TWRPH0 2 #define TWRPH1 1 NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4)); NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4)); /* 使能nand flash controller */ NFCONT |= 1; nand_reset(); }
void nand_init(void) { /* 设置时间参数 */ #define TACLS 7 #define TWRPH0 7 #define TWRPH1 7 NFCONF &= ~((7<<12)|(7<<8)|(7<<4)); NFCONF |= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* 使能 nandflash controller*/ NFCONT = 1 | (1<<1); /* 复位 */ nand_reset(); }
static void nand_command(NANDFlashState *s) { unsigned int offset; switch (s->cmd) { case NAND_CMD_READ0: s->iolen = 0; break; case NAND_CMD_READID: s->ioaddr = s->io; s->iolen = 0; nand_pushio_byte(s, s->manf_id); nand_pushio_byte(s, s->chip_id); nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */ if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { /* Page Size, Block Size, Spare Size; bit 6 indicates * 8 vs 16 bit width NAND. */ nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15); } else { nand_pushio_byte(s, 0xc0); /* Multi-plane */ } break; case NAND_CMD_RANDOMREAD2: case NAND_CMD_NOSERIALREAD2: if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)) break; offset = s->addr & ((1 << s->addr_shift) - 1); s->blk_load(s, s->addr, offset); if (s->gnd) s->iolen = (1 << s->page_shift) - offset; else s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset; break; case NAND_CMD_RESET: nand_reset(&s->busdev.qdev); break; case NAND_CMD_PAGEPROGRAM1: s->ioaddr = s->io; s->iolen = 0; break; case NAND_CMD_PAGEPROGRAM2: if (s->wp) { s->blk_write(s); } break; case NAND_CMD_BLOCKERASE1: break; case NAND_CMD_BLOCKERASE2: if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) s->addr <<= 16; else s->addr <<= 8; if (s->wp) { s->blk_erase(s); } break; case NAND_CMD_READSTATUS: s->ioaddr = s->io; s->iolen = 0; nand_pushio_byte(s, s->status); break; default: printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd); } }
static int nandbus_attach(device_t dev) { device_t child, nfc; struct nand_id chip_id; struct nandbus_softc *sc; struct nandbus_ivar *ivar; struct nand_softc *nfc_sc; struct nand_params *chip_params; uint8_t cs, onfi; sc = device_get_softc(dev); sc->dev = dev; nfc = device_get_parent(dev); nfc_sc = device_get_softc(nfc); mtx_init(&sc->nandbus_mtx, "nandbus lock", NULL, MTX_DEF); cv_init(&sc->nandbus_cv, "nandbus cv"); /* Check each possible CS for existing nand devices */ for (cs = 0; cs < NAND_NCS; cs++) { nand_debug(NDBG_BUS,"probe chip select %x", cs); /* Select & reset chip */ if (nandbus_select_cs(dev, cs)) break; if (nand_reset(dev)) continue; /* Read manufacturer and device id */ if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id)) continue; if (chip_id.man_id == 0xff) continue; /* * First try to get info from the table. If that fails, see if * the chip can provide ONFI info. We check the table first to * allow table entries to override info from chips that are * known to provide bad ONFI data. */ onfi = 0; chip_params = nand_get_params(&chip_id); if (chip_params == NULL) { nand_probe_onfi(dev, &onfi); } /* * At this point it appears there is a chip at this chipselect, * so if we can't work with it, whine about it. */ if (chip_params == NULL && onfi == 0) { if (bootverbose || (nand_debug_flag & NDBG_BUS)) printf("Chip params not found, chipsel: %d " "(manuf: 0x%0x, chipid: 0x%0x, onfi: %d)\n", cs, chip_id.man_id, chip_id.dev_id, onfi); continue; } ivar = malloc(sizeof(struct nandbus_ivar), M_NAND, M_WAITOK); if (onfi == 1) { ivar->cs = cs; ivar->cols = 0; ivar->rows = 0; ivar->params = NULL; ivar->man_id = chip_id.man_id; ivar->dev_id = chip_id.dev_id; ivar->is_onfi = onfi; ivar->chip_cdev_name = nfc_sc->chip_cdev_name; child = device_add_child(dev, NULL, -1); device_set_ivars(child, ivar); continue; } ivar->cs = cs; ivar->cols = 1; ivar->rows = 2; ivar->params = chip_params; ivar->man_id = chip_id.man_id; ivar->dev_id = chip_id.dev_id; ivar->is_onfi = onfi; ivar->chip_cdev_name = nfc_sc->chip_cdev_name; /* * Check what type of device we have. * devices bigger than 32MiB have on more row (3) */ if (chip_params->chip_size > 32) ivar->rows++; /* Large page devices have one more col (2) */ if (chip_params->chip_size >= 128 && chip_params->page_size > 512) ivar->cols++; child = device_add_child(dev, NULL, -1); device_set_ivars(child, ivar); } bus_generic_attach(dev); return (0); }