📄 uboot_driver_flash.c
字号:
/*
* (C) Copyright 2001 - Analog Devices, Inc. All rights reserved.
* BF533EzFlash.c
* Analog Devices, Inc. - 2001
*
*
* Change Log
* 1.00.1
* - made changes so that the driver will work with
* the revised GUI
* 1.00.0
* - initial release
*
* VisualDSP++ "Flash Programmer" flash driver for use with the
* ADSP-BF533 EZ-KIT Lite containing the STMicroelectronics PSD4256G
* flash device. \hhbf
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/moduleparam.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <linux/delay.h>
#include "uboot_common.h"
unsigned long uboot_flash_get_size(vu_long *addr, uboot_flash_info_t * info)
{
short i;
FLASH_WORD_SIZE manu_id, dev_id;
ulong base = (ulong) addr;
volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
/* Write Auto Select Command and read Manufacturer's ID and Dev ID */
addr2[ADDR0] = (FLASH_WORD_SIZE) 0xAAAAAAAA; asm("ssync;");
addr2[ADDR1] = (FLASH_WORD_SIZE) 0x55555555; asm("ssync;");
addr2[ADDR0] = (FLASH_WORD_SIZE) 0x90909090; asm("ssync;");
printk(""); //for delay ??? by beyond.cheng
manu_id = addr2[0];
switch (manu_id)
{
case (FLASH_WORD_SIZE) AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
case (FLASH_WORD_SIZE) MX_MANUFACT:
info->flash_id = FLASH_MAN_MX;
break;
default:
info->flash_id = FLASH_UNKNOWN;
info->sector_count = 0;
info->size = 0;
break;
}
/* Read Device Id */
dev_id = addr2[1];
switch (dev_id)
{
case (FLASH_WORD_SIZE) AMD_ID_LV320B:
info->flash_id += FLASH_AM320B;
info->sector_count = 71; /* 8 - boot sec + 63 normal */
info->size = 0x400000; /* 4MByte */
break;
case (FLASH_WORD_SIZE) AMD_ID_LV160B:
info->flash_id += FLASH_AM160B;
info->sector_count = 35; /* 8 - boot sec + 27 normal */
info->size = 0x200000; /* 2MByte */
break;
case (FLASH_WORD_SIZE) MX_ID_LV320B:
info->flash_id += FLASH_MXLV320B;
info->sector_count = 71; /* 8 - boot sec + 63 normal */
info->size = 0x400000; /* 4MByte */
break;
default:
info->flash_id = FLASH_UNKNOWN;
break;
}
/* Set up sector start Addresses */
if (info->flash_id & FLASH_BTYPE)
{
if(info->size==0x400000)
{
/* set sector offsets for bottom boot block
** Eight 8 Kb Boot sectors
** Sixty Three 64Kb sectors
*/
for (i = 0; i < 8; i++)
{
info->start[i] = base + (i * 0x00002000);
info->protect[i] = 0;
}
for (i = 8; i < info->sector_count; i++)
{
info->start[i] = base + (i * 0x00010000) - 0x00070000;
info->protect[i] = 0;
}
}
else if(info->size==0x200000)
{
/* set sector offsets for bottom boot block
** one 16 Kb Boot sectors
** two 8kb Boot Sectors
** one 32kb Boot Sectors
** twenty_nine 64Kb sectors
*/
info->start[0]=base;
info->protect[0] = 0;
for (i = 1; i < 3; i++)
{
info->start[i] = base +0x4000+ ((i-1) * 0x00002000);
info->protect[i] = 0;
}
info->start[3]=base+0x8000;
info->protect[3] = 0;
for (i = 4; i < info->sector_count; i++)
{
info->start[i] = base +0x10000+ ((i-4) * 0x00010000);
info->protect[i] = 0;
}
}
}
/* Reset To read mode */
if (info->flash_id != FLASH_UNKNOWN)
{
addr = (ulong *) info->start[0];
*addr = 0xF0F0F0F0;
}
return (info->size);
}
unsigned long uboot_flash_init(void)
{
unsigned long size_b0 = -1;
int i;
/* Set Flash to unknown */
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
{
uboot_flash_info[i].flash_id = FLASH_UNKNOWN;
}
/* Get the Flash Bank Size */
size_b0 = uboot_flash_get_size ((vu_long *) (CFG_FLASH_BASE), &uboot_flash_info[0]);
if (uboot_flash_info[0].flash_id == FLASH_UNKNOWN)
{
printk ("## UNKNOWN Flash on Bank 0 - Size = 0x%08lx = %ldMB\n",
size_b0, size_b0 >> 20);
}
return size_b0;
}
int uboot_flash_erase(uboot_flash_info_t * info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
volatile FLASH_WORD_SIZE *addr2;
int prot, sect;
int i;
if ((s_first < 0) || (s_first > s_last))
{
if (info->flash_id == FLASH_UNKNOWN)
{
printk ("- missing\n");
}
else
{
printk ("- no sectors to erase\n");
}
return 1;
}
//printk("first sector=0x%x, last sector = 0x%x\n", s_first, s_last);
if (info->flash_id == FLASH_UNKNOWN)
{
printk ("Can't erase unknown flash type - aborted\n");
return 1;
}
prot = 0;
for (sect = s_first; sect <= s_last; ++sect)
{
if (info->protect[sect])
{
//printk("protected sect = %x \n",sect);
prot++;
}
}
if (prot)
{
printk ("Warning: %d protected sectors will not be erased!\n",
prot);
}
else
{
//printk ("\n");
}
/* Disable interrupts which might cause a timeout here */
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++)
{
if (info->protect[sect] == 0)
{ /* not protected */
addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
//printf("info->flash_id = %x \n",info->flash_id);
addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080; asm("ssync;");
addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
addr2[0] = (FLASH_WORD_SIZE) 0x00300030; asm("ssync;"); /* sector erase */
while ((addr2[0] & (FLASH_WORD_SIZE) 0x00800080) != (FLASH_WORD_SIZE) 0x00800080)
{
//int delay;
//for(delay=0; delay<0xff;delay++);
udelay(1);
}
}
}
//for(i=0;i<0xffff;i++); //wait for reset
udelay(100);
//for(i=0;i<0xffffff;i++); //wait for reset
// i= i;
/* wait at least 80us - let's wait 1 ms */
addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; asm("ssync;");/* reset bank */
//for(i=0;i<0xffffff;i++); //wait for reset
//for(i=0;i<0xffffff;i++); //wait for reset
udelay(100);
// i=i;
// block erase should be complete
//printk (" done\n");
return 0;
}
static int uboot_write_word (uboot_flash_info_t * info, ulong dest, ulong data)
{
volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]);
volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
ulong start;
int i;
/* Check if Flash is (sufficiently) erased */
if ((*((volatile FLASH_WORD_SIZE *) dest) &
(FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data)
{
printk("Flash Erasing Error\n");
return (2);
}
for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++)
{
int flag;
addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; asm("ssync;");
addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; asm("ssync;");
addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0; asm("ssync;");
dest2[i] = data2[i]; asm("ssync;");
/* data polling for D7 */
while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
(data2[i] & (FLASH_WORD_SIZE) 0x00800080))
{
//int delay;
//for(delay=0; delay<0xff;delay++);
udelay(1);
}
}
return (0);
}
int uboot_write_buff(uboot_flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;
/* get lower word aligned address */
wp = (addr & ~3);
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0)
{
//printk("write test\n");
data = 0;
for (i = 0, cp = wp; i < l; ++i, ++cp)
{
data |= (*(uchar *) cp)<<(8*i);
}
for (; i < 4 && cnt > 0; ++i)
{
data |= (*src++)<<(8*i);
--cnt;
++cp;
}
for (; cnt == 0 && i < 4; ++i, ++cp)
{
data |= (*(uchar *) cp)<<(8*i);
}
if ((rc = uboot_write_word (info, wp, data)) != 0)
{
return (rc);
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4)
{
data = 0;
for (i = 0; i < 4; ++i)
{
data |= (*src++)<<(8*i);
}
if ((rc = uboot_write_word (info, wp, data)) != 0)
{
printk("Error\n");
return (rc);
}
wp += 4;
cnt -= 4;
}
if (cnt == 0)
{
return (0);
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp)
{
data |= (*src++)<<(8*i);
--cnt;
}
for (; i < 4; ++i, ++cp)
{
data |= (*(uchar *) cp)<<(8*i);
}
return (uboot_write_word (info, wp, data));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -