📄 k9k8g08u0a.c
字号:
/* * drivers/mtd/nand/nw_nand_nd.c * * Copyright (C) 2004 Embedded Edge, LLC * * $Id: nw_nand_nd.c,v 1.1.2.1 2007/08/27 22:25:16 quy Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/slab.h>#include <linux/init.h>#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <asm/io.h>//#include <asm/au1000.h>#define NW_NAND_PHYS_ADDR 0x20000000#define NW_MEM_STNAND_CMD 0x10000000#define NW_MEM_STNAND_ADDR 0x00000020//MA20 0x00100000->MA05 0x00000020#define NW_MEM_STNAND_DATA 0x00000000/* * MTD structure for NAND controller */static struct mtd_info *nw_nand_mtd = NULL;static volatile u32 p_nand,p_nand1;static int nand_width = 1; /* default, only x8 supported for now *//* * Define partitions for flash device */const static struct mtd_partition nw_partition_info[] ={ #define NW_NUM_PARTITIONS 1 { .name = "nw NAND FS 0", .offset = 0, .size = 8*1024*1024 }};static inline void write_cmd_reg(u8 cmd){ #if 0 if (nand_width) *((volatile u8 *)(p_nand + NW_MEM_STNAND_CMD)) = cmd; else *((volatile u16 *)(p_nand + NW_MEM_STNAND_CMD)) = cmd; #else if (nand_width) *((volatile u8 *)(p_nand1)) = cmd; else *((volatile u16 *)(p_nand1)) = cmd; #endif //au_sync();}static inline void write_addr_reg(u8 addr){ if (nand_width) *((volatile u8 *)(p_nand + NW_MEM_STNAND_ADDR)) = addr; else *((volatile u16 *)(p_nand + NW_MEM_STNAND_ADDR)) = addr; //au_sync();}static inline void write_data_reg(u8 data){ if (nand_width) *((volatile u8 *)(p_nand + NW_MEM_STNAND_DATA)) = data; else *((volatile u16 *)(p_nand + NW_MEM_STNAND_DATA)) = data; //au_sync();}static inline u32 read_data_reg(void){ u32 data; if (nand_width) { data = *((volatile u8 *)(p_nand + NW_MEM_STNAND_DATA)); //au_sync(); } else { data = *((volatile u16 *)(p_nand + NW_MEM_STNAND_DATA)); //au_sync(); } return data;}void nw_nand_hwcontrol(struct mtd_info *mtd, int cmd){ switch(cmd) { case NAND_CTL_SETWP: GPSR1 = 0x00080000; break; case NAND_CTL_CLRWP: GPCR1 = 0x00080000; break; }}int nw_nand_device_ready(struct mtd_info *mtd){ int ready; ready = (GPLR2 >> 18)&0x1; return ready;}static u_char nw_nand_read_byte(struct mtd_info *mtd){ u_char ret; ret = read_data_reg(); return ret;}static void nw_nand_write_byte(struct mtd_info *mtd, u_char byte){ write_data_reg((u8)byte);}static void nw_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len){ int i; for (i=0; i<len; i++) write_data_reg(buf[i]);}static void nw_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len){ int i; for (i=0; i<len; i++) buf[i] = (u_char)read_data_reg();}static int nw_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len){ int i; for (i=0; i<len; i++) if (buf[i] != (u_char)read_data_reg()) return -EFAULT; return 0;}static void nw_nand_select_chip(struct mtd_info *mtd, int chip){ return;}static void nw_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr){ register struct nand_chip *this = mtd->priv; printk("quy command=0x%x column=0x%x page_addr=0x%x\n",command,column,page_addr); /**Write out the command to the device**/ if(command==NAND_CMD_READ0) { write_cmd_reg(command); /* Serially input address 0x00*/ if (column != -1) { write_addr_reg((unsigned char) (column & 0xff)); write_addr_reg((unsigned char) ((column>>8) & 0xff)); } if (page_addr != -1) { write_addr_reg((unsigned char) (page_addr & 0xff)); write_addr_reg(((page_addr >> 8) & 0xff)); write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07)); } write_cmd_reg(NAND_CMD_READSTART); } else if(command==NAND_CMD_SEQIN) { write_cmd_reg(command); /* Serially input address 0x80*/ if (column != -1) { write_addr_reg((unsigned char) (column & 0xff)); write_addr_reg((unsigned char) ((column>>8) & 0xff)); } if (page_addr != -1) { write_addr_reg((unsigned char) (page_addr & 0xff)); write_addr_reg(((page_addr >> 8) & 0xff)); write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07)); } } else if(command==NAND_CMD_PAGEPROG) { /*0x10*/ write_cmd_reg(command); } else if((command==NAND_CMD_STATUS)||(command==NAND_CMD_STATUS_MULTI)) { /*0x70 0x71*/ command = NAND_CMD_STATUS; write_cmd_reg(command); } else if(command==NAND_CMD_ERASE1) { /*0x60*/ write_cmd_reg(command); if (page_addr != -1) { write_addr_reg((unsigned char) (page_addr & 0xff)); write_addr_reg(((page_addr >> 8) & 0xff)); write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07)); } } else if(command==NAND_CMD_ERASE2) { /*0x60*/ write_cmd_reg(command); } else if(command==NAND_CMD_READID) { /* Serially input address 0x90*/ write_cmd_reg(command); if (column != -1) { write_addr_reg((unsigned char) (column & 0xff)); } if (page_addr != -1) { write_addr_reg((unsigned char) (page_addr & 0xff)); write_addr_reg(((page_addr >> 8) & 0xff)); /* One more address cycle for higher density devices */ if (mtd->size & 0x0c000000) write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07)); } } else if(command==NAND_CMD_RESET) { /*0xff*/ write_cmd_reg(command); udelay(100); } else if(command==NAND_CMD_READOOB) { printk("err cmd =0x%x\n",command); } while (!this->dev_ready(mtd));}void nw_nand_getid(void){ int * preg; printk("nw_nand_getid 0 2007-9-22 15:04\n"); write_cmd_reg((u8)0x90); write_addr_reg((u8)0x00); printk("nand id=0x%x\n",read_data_reg()); printk("nand id=0x%x\n",read_data_reg()); printk("nand id=0x%x\n",read_data_reg()); printk("nand id=0x%x\n",read_data_reg()); printk("nand id=0x%x\n",read_data_reg());}/* * Main initialization routine */int __init nw_nand_init (void){ struct nand_chip *this; u16 boot_swapboot = 0; /* default value */ u32 mem_time; u8 * preg; /* Allocate memory for MTD device structure and private data */ nw_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); if (!nw_nand_mtd) { printk ("Unable to allocate NAND MTD dev structure.\n"); return -ENOMEM; } /* Get pointer to private data */ this = (struct nand_chip *) (&nw_nand_mtd[1]); /* Initialize structures */ memset((char *) nw_nand_mtd, 0, sizeof(struct mtd_info)); memset((char *) this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ nw_nand_mtd->priv = this; p_nand = (volatile u8 *)ioremap(NW_NAND_PHYS_ADDR, 0x1000); p_nand1 = (volatile u8 *)ioremap(NW_NAND_PHYS_ADDR+0x10000000, 0x1000); /* Init GPIOs with alternate functions */ GPSR0 = 0x00008000; GPSR2 = 0x00008000; GPSR1 = 0x00040000; GPSR1 = 0x00080000; GPSR1 = 0x02000000; GPSR1 = 0x01000000; GPSR2 = 0x00040000; GPSR2 = 0x00080000; GPDR1 &= ~0x01000000; GAFR1_U = (GAFR1_U & 0xfffcffff) | 0x00010000;//nPAWIT GPIO56->nPAWIT //GPDR1 |= 0x00800000; //GAFR1_U = (GAFR1_U & 0xffff3fff) | 0x00008000;//nPREG GPIO55 GPDR0 |= 0x00008000; GAFR0_L = (GAFR0_L & 0x3fffffff) | 0x40000000;//nPCE<1> GPIO15->CE1\ GPDR2 |= 0x00008000; GAFR2_L = (GAFR2_L & 0x3fffffff) | 0x40000000;//PSKTSEL GPIO79->CLE GPDR1 |= 0x00040000; GAFR1_U = (GAFR1_U & 0xffffffcf) | 0x00000020;//PIOR GPIO50->RE\ GPDR1 |= 0x00080000; GAFR1_U = (GAFR1_U & 0xffffff3f) | 0x00000080;//PIOW GPIO51->WE\ GPDR1 &= 0xfdffffff; GAFR1_U = (GAFR1_U & 0xfff3ffff) | 0x00400000;//nIOIS16 GPIO57 GPDR2 &= 0xfffbffff;//R/B\ GPIO82 in GPDR2 |= 0x00080000;//WP\ GPIO83 out GPSR2 |= 0x00080000;//WP\ high MECR = 0x00000003;//PC Card inserted PCFR &= 0xfffd;//indicate signals should not be floated in sleep mode //?Software should program the PGSRx bits correctly so that during sleep mode //nPCE1 signal is held high during sleep mode PGSR0 |= 0x00008000; MCIO0 = 0x00001004;//for timing MCIO1 = 0x00001004;//for timing /* Set address of hardware control function */ this->hwcontrol = nw_nand_hwcontrol; this->dev_ready = nw_nand_device_ready; /* 30 us command delay time */ this->chip_delay = 30; this->cmdfunc = nw_nand_command; this->select_chip = nw_nand_select_chip; this->write_byte = nw_nand_write_byte; this->read_byte = nw_nand_read_byte; this->write_buf = nw_nand_write_buf; this->read_buf = nw_nand_read_buf; this->verify_buf = nw_nand_verify_buf; this->eccmode = NAND_ECC_SOFT;//NAND_ECC_SOFT NAND_ECC_HW3_512 //nw_nand_getid(); /* Scan to find existence of the device */ if (nand_scan (nw_nand_mtd, 1)) { kfree (nw_nand_mtd); return -ENXIO; } /* Register the partitions */ add_mtd_partitions(nw_nand_mtd, nw_partition_info, NW_NUM_PARTITIONS); return 0;}module_init(nw_nand_init);/* * Clean up routine */static void __exit nw_nand_cleanup (void){ struct nand_chip *this = (struct nand_chip *) &nw_nand_mtd[1]; iounmap ((void *)p_nand); /* Unregister partitions */ del_mtd_partitions(nw_nand_mtd); /* Unregister the device */ del_mtd_device (nw_nand_mtd); /* Free the MTD device structure */ kfree (nw_nand_mtd);}module_exit(nw_nand_cleanup);MODULE_LICENSE("GPL");MODULE_AUTHOR("Embedded Edge, LLC");MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -