193 lines
5.4 KiB
C
193 lines
5.4 KiB
C
|
/*
|
|||
|
* File : drv_sfc_gd25qxx_mtd.c
|
|||
|
* COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
|
|||
|
*
|
|||
|
* Change Logs:
|
|||
|
* Date Author Notes
|
|||
|
* 2017<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD>19<EFBFBD><EFBFBD> Urey the first version
|
|||
|
*/
|
|||
|
|
|||
|
#include <rthw.h>
|
|||
|
#include <rtthread.h>
|
|||
|
#include <rtdevice.h>
|
|||
|
#include <drivers/mtd_nor.h>
|
|||
|
|
|||
|
#include "board.h"
|
|||
|
#include "drv_clock.h"
|
|||
|
#include "drv_gpio.h"
|
|||
|
#include "drv_sfc.h"
|
|||
|
|
|||
|
/* JEDEC Manufacturer's ID */
|
|||
|
#define MF_ID (0xC8)
|
|||
|
|
|||
|
/* JEDEC Device ID: Memory type and Capacity */
|
|||
|
#define MTC_GD25Q128 (0x4018)
|
|||
|
#define MTC_GD25Q256 (0x4019)
|
|||
|
|
|||
|
|
|||
|
/* RT-Thread MTD device interface */
|
|||
|
static rt_base_t mtd_gd25_read_id(struct rt_mtd_nor_device *device)
|
|||
|
{
|
|||
|
struct sfc_flash *flash = (struct sfc_flash *)device;
|
|||
|
|
|||
|
return (rt_uint32_t)flash->id;
|
|||
|
}
|
|||
|
|
|||
|
static rt_size_t mtd_gd25_read(struct rt_mtd_nor_device *device, rt_off_t position, rt_uint8_t *data, rt_size_t size)
|
|||
|
{
|
|||
|
struct sfc_flash *flash = (struct sfc_flash *)device;
|
|||
|
|
|||
|
return sfc_norflash_read(flash,position,data,size);
|
|||
|
}
|
|||
|
|
|||
|
static rt_size_t mtd_gd25_write(struct rt_mtd_nor_device *device, rt_off_t position, const rt_uint8_t *data, rt_size_t size)
|
|||
|
{
|
|||
|
struct sfc_flash *flash = (struct sfc_flash *)device;
|
|||
|
|
|||
|
return sfc_norflash_write(flash,position,data,size);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static rt_err_t mtd_gd25_erase_block(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint32_t length)
|
|||
|
{
|
|||
|
struct sfc_flash *flash = (struct sfc_flash *)device;
|
|||
|
|
|||
|
sfc_norflash_erase_sector(flash,offset);
|
|||
|
return RT_EOK;
|
|||
|
}
|
|||
|
|
|||
|
const static struct rt_mtd_nor_driver_ops mtd_gd25_ops =
|
|||
|
{
|
|||
|
mtd_gd25_read_id,
|
|||
|
mtd_gd25_read,
|
|||
|
mtd_gd25_write,
|
|||
|
mtd_gd25_erase_block,
|
|||
|
};
|
|||
|
|
|||
|
#ifdef SFC_USE_QUAD
|
|||
|
struct sfc_quad_mode flash_quad_mode[] =
|
|||
|
{
|
|||
|
{
|
|||
|
.RDSR_CMD = CMD_RDSR_1,
|
|||
|
.WRSR_CMD = CMD_WRSR_1,
|
|||
|
.RDSR_DATE = 0x2,//the data is write the spi status register for QE bit
|
|||
|
.RD_DATE_SIZE = 1,
|
|||
|
.WRSR_DATE = 0x2,//this bit should be the flash QUAD mode enable
|
|||
|
.WD_DATE_SIZE = 1,
|
|||
|
.cmd_read = CMD_QUAD_READ,//
|
|||
|
.sfc_mode = TRAN_SPI_QUAD,
|
|||
|
},
|
|||
|
{
|
|||
|
.RDSR_CMD = CMD_RDSR,
|
|||
|
.WRSR_CMD = CMD_WRSR,
|
|||
|
.RDSR_DATE = 0x40,//the data is write the spi status register for QE bit
|
|||
|
.RD_DATE_SIZE = 1,
|
|||
|
.WRSR_DATE = 0x40,//this bit should be the flash QUAD mode enable
|
|||
|
.WD_DATE_SIZE = 1,
|
|||
|
.cmd_read = CMD_QUAD_IO_FAST_READ,
|
|||
|
.sfc_mode = TRAN_SPI_IO_QUAD,
|
|||
|
},
|
|||
|
{
|
|||
|
.RDSR_CMD = CMD_RDSR_1,
|
|||
|
.WRSR_CMD = CMD_WRSR,
|
|||
|
.RDSR_DATE = 0x20,//the data is write the spi status register for QE bit
|
|||
|
.RD_DATE_SIZE = 1,
|
|||
|
.WRSR_DATE = 0x200,//this bit should be the flash QUAD mode enable
|
|||
|
.WD_DATE_SIZE = 2,
|
|||
|
.cmd_read = CMD_QUAD_READ,
|
|||
|
.sfc_mode = TRAN_SPI_QUAD,
|
|||
|
},
|
|||
|
{
|
|||
|
.RDSR_CMD = CMD_RDSR,
|
|||
|
.WRSR_CMD = CMD_WRSR,
|
|||
|
.RDSR_DATE = 0x40,//the data is write the spi status register for QE bit
|
|||
|
.RD_DATE_SIZE = 1,
|
|||
|
.WRSR_DATE = 0x40,//this bit should be the flash QUAD mode enable
|
|||
|
.WD_DATE_SIZE = 1,
|
|||
|
.cmd_read = CMD_QUAD_READ,
|
|||
|
.sfc_mode = TRAN_SPI_QUAD,
|
|||
|
},
|
|||
|
|
|||
|
};
|
|||
|
#endif
|
|||
|
|
|||
|
static struct sfc_flash _gd25_flash_info =
|
|||
|
{
|
|||
|
.name = "GD25Q128C",
|
|||
|
.id = 0xc84018,
|
|||
|
.pagesize = 256,
|
|||
|
.sectorsize = ( 4 * 1024),
|
|||
|
.chipsize = (16 * 1024 * 1024),
|
|||
|
.erasesize = ( 4 * 1024),
|
|||
|
.writesize = 256,
|
|||
|
.addrsize = DEFAULT_ADDRSIZE,
|
|||
|
.quad_mode = &flash_quad_mode[0]
|
|||
|
};
|
|||
|
|
|||
|
static char flashIdStr[128];
|
|||
|
extern int rt_hw_gd25qxx_mtd_part_init(const char *mtd_name);
|
|||
|
int rt_hw_gd25qxx_init(void)
|
|||
|
{
|
|||
|
struct sfc_flash *flash = &_gd25_flash_info;
|
|||
|
int result;
|
|||
|
|
|||
|
result = sfc_norflash_probe(flash);
|
|||
|
if(result != RT_EOK)
|
|||
|
{
|
|||
|
rt_kprintf("GD25 init Failed..\n");
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
if((flash->id >> 16) != MF_ID)
|
|||
|
{
|
|||
|
rt_kprintf("Manufacturers ID error!\r\n");
|
|||
|
rt_kprintf("JEDEC Read-ID Data : %06X\r\n", flash->id);
|
|||
|
return -RT_ENOSYS;
|
|||
|
}
|
|||
|
|
|||
|
switch (flash->id & 0xFFFF)
|
|||
|
{
|
|||
|
case MTC_GD25Q128:
|
|||
|
flash->name = "GD25Q128C";
|
|||
|
flash->chipsize = (16 * 1024 * 1024);
|
|||
|
flash->addrsize = 3;
|
|||
|
flash->quad_mode = &flash_quad_mode[0];
|
|||
|
break;
|
|||
|
case MTC_GD25Q256:
|
|||
|
flash->name = "GD25Q256C";
|
|||
|
flash->chipsize = (32 * 1024 * 1024);
|
|||
|
flash->addrsize = 4;
|
|||
|
flash->quad_mode = &flash_quad_mode[3];
|
|||
|
/* enable 4-byte addressing if the device exceeds 16MiB */
|
|||
|
sfc_norflash_set_addr_width_4byte(flash,1);
|
|||
|
break;
|
|||
|
default:
|
|||
|
rt_kprintf("Memory Capacity error!\r\n");
|
|||
|
return -RT_ENOSYS;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//format FLASH UUID...
|
|||
|
{
|
|||
|
int strSize,i;
|
|||
|
|
|||
|
strSize = rt_snprintf(flashIdStr + 0,sizeof(flashIdStr) - 0,"%06X",flash->id);
|
|||
|
for(i=0;i<8;i++)
|
|||
|
strSize += rt_snprintf(flashIdStr + strSize,sizeof(flashIdStr) - strSize,"%02X",flash->uid[i]);
|
|||
|
flashIdStr[strSize] = '\0';
|
|||
|
}
|
|||
|
|
|||
|
/* Init device interface ... */
|
|||
|
flash->mtd.block_size = flash->erasesize;
|
|||
|
flash->mtd.block_start = 0;
|
|||
|
flash->mtd.block_end = flash->chipsize / flash->erasesize;
|
|||
|
flash->mtd.ops = &mtd_gd25_ops;
|
|||
|
rt_mtd_nor_register_device("gd25mtd",&flash->mtd);
|
|||
|
|
|||
|
rt_hw_gd25qxx_mtd_part_init("gd25mtd");
|
|||
|
|
|||
|
return RT_EOK;
|
|||
|
}
|
|||
|
INIT_DEVICE_EXPORT(rt_hw_gd25qxx_init);
|