80 }
81
82 static int tiny_nand_init(void)
83 {
84 struct clk *nand_clk;
85 /*1.分配一个nand_chip结构体,主要定义了一些操作函数*/
86 tiny_nand_chip = kzalloc(sizeof(struct nand_chip),GFP_KERNEL); //分配nand_chip结构体内存
87 nand_regs = ioremap(0xB0E00000,sizeof(struct nand_regs)); //映射nand_chip结构体地址
88
89 /*2.设置*/
90 /*
91 * 初始化nand_chip结构体中的函数指针,设置nand_chip 是给nand_scan函数使用的,
92 * 如果不知道咋么设置先看nand_scan怎么使用
93 * 提供选中芯片,发命令,发地址,读数据,写数据,等待等操作
94 */
95 tiny_nand_chip->select_chip = tiny_nand_select_chip; //nand片选控制函数
96 tiny_nand_chip->cmd_ctrl = tiny_nand_cmd_ctrl; //命令控制函数,包括数据和地址命令的发送
97 tiny_nand_chip->IO_ADDR_R = &nand_regs->nfdata; //nandflash的读寄存器
98 tiny_nand_chip->IO_ADDR_W = &nand_regs->nfdata; //nandflash的写寄存器
99 tiny_nand_chip->dev_ready = tiny_nand_dev_ready; //nand准备完毕,可以开始读写, GPIO_RDY 8
100 tiny_nand_chip->ecc.mode = NAND_ECC_SOFT; ////ecc的校验模式(软件,硬件)
101 /*3.硬件相关*/
102 /*使能时钟*/
103 nand_clk = clk_get(NULL, 'nand'); //从内核中找到nand的时钟信息,通过名字匹配
104 clk_enable(nand_clk); //时能nandflash的时钟
105
106 /*
107 * AddrCycle[1]:1 = 发送地址需要5个周期
108 */
109 nand_regs->nfconf |= 1<<1; //取消片选
110 //HCLK = 100MHz
111 //TACLS : 发出CLE/ALE之后多长时间才发出nWE信号,
112 // 从NAND手册克制CLE/ALE与nWE可以同时faculty,所以TACLS = 0
113 //TWRPH0:nWE的脉冲宽度,HCLK x(TWRPH0 + 1),
114 // 从NAND手册克制它要>=12ns, 所以TWRPH0 >= 1
115 //TWRPH1: nWE变为高电平后多长时间CLE/ALE才能变为低电平,
116 // 从NAND手册值要>=5ns, 所以TWRPH1 >= 0
117 #define TWRPH1 0 //1
118 #define TWRPH0 1
119 #define TACLS 0 //1
120 nand_regs->nfconf |= (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4); //设置脉冲信号
121 /*
122 * MODE[0]:1 = 使能Nand Flash控制器
123 * Reg_nCE0[1]:1 = 取消片选
124 */
125 nand_regs->nfcont |= (1<<1)|(1<<0); //时能nandflash控制器,取消片选
126 /*4.使用*/
127 tiny_nand_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); //申请mtd_info结构体内存
128 tiny_nand_mtd->owner = THIS_MODULE;
129 tiny_nand_mtd->priv = tiny_nand_chip; //设置设备私有数据指针,绑定前面的nand_chip结构体
130
131 nand_scan(tiny_nand_mtd, 1); //扫描识别nand flash ,构造mtd_info结构体
132
133 }
134
135 static void tiny_nand_exit(void)
136 {
137 kfree(tiny_nand_mtd); //释放mtd结构体的内存
138 iounmap(nand_regs); //取消地址映射
139 kfree(tiny_nand_chip); //释放nand-chip结构体的内存
140 }
141
142 module_init(tiny_nand_init);
143 module_exit(tiny_nand_exit);
144
145 MODULE_LICENSE('GPL');
附驱动源程序2:
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 #include 15 #include 16 #include 17 #include 18 19 #include 20 21 #include 22 #include 23 24 static unsigned long *clk_gate_ip1; 25 static unsigned long *clk_gate_block; 26 static unsigned long *mp0_3con; 27 28 static struct mtd_partition tiny_nand_part[] = { 29 [0] = { 30 .name = 'bootloader', 31 .size = SZ_4M, 32 .offset = 0, 33 }, 34 [1] = { 35 .name = 'kernel', 36 .size = SZ_8M, 37 .offset = MTDPART_OFS_APPEND, 38 }, 39 [2] = { 40 .name = 'root', 41 .size = MTDPART_SIZ_FULL, 42 .offset = MTDPART_OFS_APPEND, 43 }, 44 }; 45 46 struct nand_regs { 47 unsigned long nfconf; 48 unsigned long nfcont; 49 unsigned long nfcmmd; 50 unsigned long nfaddr; 51 unsigned long nfdata; 52 unsigned long nfmeccd0; 53 unsigned long nfmeccd1; 54 unsigned long nfseccd; 55 unsigned long nfsblk; 56 unsigned long nfeblk; 57 unsigned long nfstat; 58 unsigned long nfeccerr0; 59 unsigned long nfeccerr1; 60 }; 61 62 static struct nand_regs *nand_regs; 63 static struct nand_chip *tiny_nand_chip; 64 static struct mtd_info *tiny_nand_mtd; 65 66 static void tiny_nand_select_chip(struct mtd_info *mtd, int chipnr) 67 { 68 if(chipnr == -1) 69 { 70 /*取消选择*/ 71 nand_regs->nfcont |= (1<<1); 72 } 73 else 74 { 75 /*选中芯片*/ 76 nand_regs->nfcont &= ~(1<<1); 77 } 78 } 79 80 static void tiny_nand_cmd_ctrl(struct mtd_info *mtd, int dat, 81 unsigned int ctrl) 82 { 83 84 if (ctrl & NAND_CLE) 85 { 86 /*发命令*/ 87 nand_regs->nfcmmd = dat; 88 } 89 else 90 { 91 /*发地址*/ 92 nand_regs->nfaddr = dat; 93 } 94 } 95 96 static int tiny_nand_dev_ready(struct mtd_info *mtd) 97 { 98 /*等待命令的操作完成*/ 99 return (nand_regs->nfstat & (1<<0)); 100 } 101 102 static int tiny_nand_init(void) 103 { 104 /*1.分配一个nand_chip结构体*/ 105 tiny_nand_chip = kzalloc(sizeof(struct nand_chip),GFP_KERNEL); 106 nand_regs = ioremap(0xB0E00000,sizeof(struct nand_regs)); 107 mp0_3con = ioremap(0xE0200320,4); 108 clk_gate_ip1 = ioremap(0xE0100464,4); 109 clk_gate_block = ioremap(0xE0100480,4); 110 111 /*2.设置*/ 112 /* 113 * 初始化nand_chip结构体中的函数指针 114 * 提供选中芯片,发命令,发地址,读数据,写数据,等待等操作 115 */ 116 tiny_nand_chip->select_chip = tiny_nand_select_chip; 117 tiny_nand_chip->cmd_ctrl = tiny_nand_cmd_ctrl; 118 tiny_nand_chip->IO_ADDR_R = &nand_regs->nfdata; 119 tiny_nand_chip->IO_ADDR_W = &nand_regs->nfdata; 120 tiny_nand_chip->dev_ready = tiny_nand_dev_ready; 121 tiny_nand_chip->ecc.mode = NAND_ECC_SOFT; 122 //tiny_nand_chip->ecc.mode = NAND_ECC_NONE; 123 124 /*3.硬件相关*/ 125 /*使能时钟*/ 126 *clk_gate_ip1 = 0xffffffff; 127 *clk_gate_block = 0xffffffff; 128 129 /* 设置相应GPIO管脚用于Nand */ 130 *mp0_3con = 0x22222222; 131 132 /* 设置时序 */ 133 #define TWRPH1 1 134 #define TWRPH0 1 135 #define TACLS 1 136 nand_regs->nfconf |= (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
上一篇:NorFlash驱动
下一篇:块设备驱动程序
推荐阅读最新更新时间:2024-11-13 17:20
设计资源 培训 开发板 精华推荐
- MIC94345-FYCS 1.5V 输出电压、500mA LDO 采用纹波阻断技术的典型应用
- AM1D-2412D-RZ ±12V 1 瓦 DC-DC 转换器的典型应用
- LT3990HMSE-5 12V 降压转换器的典型应用
- z2m&& zigbee2mqtt网关
- 使用 Asahi Kasei Microdevices Corporation 的 AK4103AVF 的参考设计
- LT3970EDDB-3.42 5V 降压转换器的典型应用
- 具有电源正常输出的 LTC1728ES5-2.5、3.3V 和 5V 三路电源监视器的典型应用
- 基于C8051F410 8051 MCU的录音机电路
- STM32Demo_Pro
- 使用 LTC2377HMS-16、16 位、500ksps SAR ADC 的典型应用