📄 omap-nor-flash.c
字号:
/******************************************************************************* omap-nor-flash.c Self-Contained MTD driver for OMAP NOR Flash - Supports Intel 28F256L18T and Intel 28F128L18T - Automatically detects which one of the supported flashes is used - Automatically detects the location of the supported flashes (CS3 or CS2B) Author: MontaVista Software, Inc. <source@mvista.com> Copyright (c) 2003 MontaVista Software, Inc. The code for this driver is based on board/omap1610inn/flash.c from U-Boot 0.4.3: * (C) Copyright 2001 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * * (C) Copyright 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2003 * Texas Instruments, <www.ti.com> * Kshitij Gupta <Kshitij@ti.com> The code for this driver is also based on syncflash.c: * MTD driver for Micron SyncFlash flash memory. * * Author: Jon McClintock <jonm@bluemug.com> * * Based loosely upon the LART flash driver, authored by * Abraham vd Merwe * <abraham@2d3d.co.za>. * * Copyright 2003, Blue Mug, Inc. for Motorola, Inc. * Copyright 2003, MontaVista Software, Inc * * References: * * * [1] MTD internal API documentation * - http://www.linux-mtd.infradead.org/tech/ * Modifications: Feb 2004, Texas Instruments, <www.ti.com> - Ported to 2.6 Kernel (Feb 2004) - Added address probing (Sept 2004) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*******************************************************************************/#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/mtd/mtd.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/mtd/partitions.h>#include <asm/arch/hardware.h>#ifdef CONFIG_MTD_PARTITIONS_MODULE#define CONFIG_MTD_PARTITIONS 1#endif#define NB_OF(x) (sizeof (x) / sizeof (x[0]))/* * General flash configuration parameters. */#define OMAP_BOOTLOADER_LEN 0x20000#define OMAP_PARAMS_LEN 0x20000#define OMAP_KERNEL_LEN 0x200000#define BUSWIDTH 2 /*warning: this is used only in some functions, the code is specific to 16-bit data bus */#define INTEL_MANUFACT 0x0089#define INTEL_ID_28F256L18T 0x880D /* 256M = 128K x 255 + 32k x 4 */#define INTEL_ID_28F128L18T 0x880C /* 128M = 128K x 127 + 32k x 4 */void __exit omap_flash_exit(void);int __init omap_flash_init(void);static int omap_flash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);static int omap_flash_write_word(__u32 offset, __u16 x);static int omap_flash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);static int omap_flash_erase(struct mtd_info *mtd, struct erase_info *instr);static inline int omap_flash_sector_erase(__u32 offset);static int omap_flash_probe(void);static struct mtd_info mtd;#ifdef CONFIG_MACH_OMAP_H4#define E_REGIONS 4#else#define E_REGIONS 2#endifstatic struct mtd_erase_region_info erase_regions[E_REGIONS];static unsigned long omap_nor_flash_base;DECLARE_MUTEX(omap_flash_lock);#ifdef CONFIG_MTD_PARTITIONSstatic struct mtd_partition omap_partitions[] = { /* bootloader */ { name:"bootloader", offset:0, size:OMAP_BOOTLOADER_LEN, mask_flags:MTD_WRITEABLE, /* force read-only */ }, /* bootloader params */ { name:"params", offset:MTDPART_OFS_APPEND, size:OMAP_PARAMS_LEN, mask_flags:0, }, /* kernel */ { name:"kernel", offset:MTDPART_OFS_APPEND, size:OMAP_KERNEL_LEN, mask_flags:0 }, /* file system */ { name:"file system", offset:MTDPART_OFS_APPEND, size:MTDPART_SIZ_FULL, mask_flags:0 }};#endifstatic char module_name[] = "OMAP NOR FLASH";#define omap_flash_inw(o) readw((omap_nor_flash_base+(__u32)o))#define omap_flash_outw(o,d) writew((__u16)(d),(omap_nor_flash_base+(__u32)o))/* Probe for NOR Flash on OMAP board at address omap_nor_flash_base */static intomap_flash_probe(void){ __u16 mfgid, devid; __u32 offset; int i, j; memset(&mtd, 0, sizeof (mtd)); down(&omap_flash_lock); /* Write auto select command: read Manufacturer ID */ omap_flash_outw(0, 0x0090); mfgid = omap_flash_inw(0); /*manufacturer ID */ switch (mfgid) { case INTEL_MANUFACT: break; default: omap_flash_outw(0, 0x00FF); /* restore read mode */ up(&omap_flash_lock); printk(KERN_ERR "%s ERROR: no supported Flash device found\n", module_name); return -ENXIO; /* no or unknown flash */ } devid = omap_flash_inw(2); /* device ID */ switch (devid) { case INTEL_ID_28F256L18T: erase_regions[0].offset = 0; erase_regions[0].erasesize = 128 * 1024; erase_regions[0].numblocks = 255; erase_regions[1].offset = erase_regions[0].erasesize * erase_regions[0].numblocks; erase_regions[1].erasesize = 32 * 1024; erase_regions[1].numblocks = 4;#ifdef CONFIG_MACH_OMAP_H4 erase_regions[2].offset = erase_regions[1].offset + erase_regions[1].erasesize * erase_regions[1].numblocks; erase_regions[2].erasesize = 128 * 1024; erase_regions[2].numblocks = 255; erase_regions[3].offset = erase_regions[2].offset + erase_regions[2].erasesize * erase_regions[2].numblocks; erase_regions[3].erasesize = 32 * 1024; erase_regions[3].numblocks = 4;#endif printk(KERN_INFO "%s: Intel 28F256L18T found at 0x%lx\n", module_name, omap_nor_flash_base); break; case INTEL_ID_28F128L18T: erase_regions[0].offset = 0; erase_regions[0].erasesize = 128 * 1024; erase_regions[0].numblocks = 127; erase_regions[1].offset = erase_regions[0].erasesize * erase_regions[0].numblocks; erase_regions[1].erasesize = 32 * 1024; erase_regions[1].numblocks = 4;#ifdef CONFIG_MACH_OMAP_H4 erase_regions[2].offset = erase_regions[1].offset + erase_regions[1].erasesize * erase_regions[1].numblocks; erase_regions[2].erasesize = 128 * 1024; erase_regions[2].numblocks = 127; erase_regions[3].offset = erase_regions[2].offset + erase_regions[2].erasesize * erase_regions[2].numblocks; erase_regions[3].erasesize = 32 * 1024; erase_regions[3].numblocks = 4;#endif printk(KERN_INFO "%s: Intel 28F128L18T found at 0x%lx\n", module_name, omap_nor_flash_base); break; default: omap_flash_outw(0, 0x00FF); /* restore read mode */ up(&omap_flash_lock); printk(KERN_ERR "%s ERROR: no supported Flash device found\n", module_name); return -ENXIO; /* no or unknown flash */ } omap_flash_outw(0, 0x00FF); /* restore read mode */ mtd.name = module_name; mtd.type = MTD_NORFLASH; mtd.flags = MTD_CAP_NORFLASH; mtd.erasesize = 128 * 1024; mtd.numeraseregions = NB_OF(erase_regions); mtd.eraseregions = erase_regions; for (i = 0; i < NB_OF(erase_regions); i++) { mtd.size += erase_regions[i].erasesize * erase_regions[i].numblocks; offset = erase_regions[i].offset; for (j = 0; j < erase_regions[i].numblocks; j++) { /* this sends the clear lock bit command */ omap_flash_outw(offset, 0x0060); omap_flash_outw(offset, 0x00D0); omap_flash_outw(offset, 0x00FF);/* reset to read mode */ offset += erase_regions[i].erasesize; } } up(&omap_flash_lock); mtd.owner = THIS_MODULE; mtd.erase = omap_flash_erase; mtd.read = omap_flash_read; mtd.write = omap_flash_write; return 0;}/* Erase a flash sector */static inline intomap_flash_sector_erase(__u32 offset){ __u16 status; down(&omap_flash_lock); /*erase sector */ omap_flash_outw(offset, 0x0050); /* clear status register */ omap_flash_outw(offset, 0x0020); /* erase setup */ omap_flash_outw(offset, 0x00D0); /* erase confirm */ /* wait for erase complete while polling the status register */ while (((status = omap_flash_inw(offset)) & 0x0080) != 0x0080) schedule_timeout(1); omap_flash_outw(offset, 0x0050); /* clear status register */ omap_flash_outw(offset, 0x00FF); /* reset to read mode */ up(&omap_flash_lock); /* process status register */ if (status & (1 << 3)) { printk(KERN_ERR "%s ERROR: erasing at address 0x%.8x: Vpp range error \n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -