514 lines
16 KiB
C
514 lines
16 KiB
C
/******************************************************************************
|
|
*
|
|
* (C)Copyright 2005 - 2008 Marvell. All Rights Reserved.
|
|
*
|
|
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
|
|
* The copyright notice above does not evidence any actual or intended
|
|
* publication of such source code.
|
|
* This Module contains Proprietary Information of Marvell and should be
|
|
* treated as Confidential.
|
|
* The information in this file is provided for the exclusive use of the
|
|
* licensees of Marvell.
|
|
* Such users have the right to use, modify, and incorporate this code into
|
|
* products for purposes authorized by the license agreement provided they
|
|
* include this notice and the associated copyright notice with any such
|
|
* product.
|
|
* The information in this file is provided "AS IS" without warranty.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***********************************************************
|
|
* SPIFlash.h
|
|
* This is the header file for the SPIFlash driver.
|
|
*
|
|
* Revision History:
|
|
* 5/2/07 - initial draft
|
|
************************************************************/
|
|
#ifndef __SPI_NAND_H__
|
|
#define __SPI_NAND_H__
|
|
|
|
#include "common.h"
|
|
#include "qspi_dma.h"
|
|
#include "xllp_dmac.h"
|
|
#include "SPI.h"
|
|
|
|
|
|
#define DMA_DEFAULT_TIMEOUT 3000U
|
|
#define DEFAULT_WAIT_TIME 1000U
|
|
#define MANU_RESERVE_BLOCK 4U
|
|
|
|
#define WRITE_SIZE (256)
|
|
#define SIZE_4KB (0x1000)
|
|
|
|
/*
|
|
* SPI Command Set
|
|
*/
|
|
#define SPINAND_WRITE_ENABLE 0x06
|
|
#define SPINAND_WRITE_DISABLE 0x04
|
|
#define SPINAND_GET_FEATURES 0x0F
|
|
#define SPINAND_SET_FEATURES 0x1F
|
|
#define SPINAND_CACHE_LOAD 0x13
|
|
#define SPINAND_CACHE_READ 0x03
|
|
#define SPINAND_READ_ID 0x9F
|
|
#define SPINAND_PROGRAM_LOAD 0x02
|
|
#define SPINAND_PROGRAM_EXECUTE 0x10
|
|
#define SPINAND_BLOCK_ERASE 0xD8
|
|
#define SPINAND_RESET 0xFF
|
|
|
|
|
|
/*
|
|
* SPI NAND Feature Types
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
SPINAND_PROTECTION = 0xA0,
|
|
SPINAND_FEATURE = 0xB0,
|
|
SPINAND_STATUS = 0xC0
|
|
} SPINAND_Feature_E;
|
|
|
|
//
|
|
// GigaDevice GD5F1GQ4RAYIG: protection register 0xa0
|
|
//
|
|
// 7 6 5 4 3 2 1 0
|
|
// +------+------+------+------+------+------+------+------+
|
|
// | BRWD | Rerd | BP2 | BP1 | BP0 | INV | CMP |Rerd |
|
|
// +------+------+------+------+------+------+------+------+
|
|
|
|
#define GIGA_SPINAND_PROTECTION_Rerd1 BIT_0 // Rserved
|
|
#define GIGA_SPINAND_PROTECTION_CMP BIT_1 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_INV BIT_2 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_BP0 BIT_3 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_BP1 BIT_4 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_BP2 BIT_5 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_BP3 BIT_6 // level of protected blcok
|
|
#define GIGA_SPINAND_PROTECTION_BRWD BIT_7 // block protection lock
|
|
|
|
//
|
|
// GigaDevice GD5F1GQ4RAYIG: feature register 0xb0
|
|
//
|
|
// 7 6 5 4 3 2 1 0
|
|
// +-------+------+------+------+------+------+------+------+
|
|
// |OTP_PRT|OTP_EN| Rerd |ECC_EN| Rerd | Rerd | Rerd | QE |
|
|
// +-------+------+------+------+------+------+------+------+
|
|
|
|
#define GIGA_SPINAND_FEATURE_QE BIT_0 // quad enable
|
|
#define GIGA_SPINAND_FEATURE_Rerd3 BIT_1 // reserved
|
|
#define GIGA_SPINAND_FEATURE_Rerd2 BIT_2 // reserved
|
|
#define GIGA_SPINAND_FEATURE_Rerd1 BIT_3 // reserved
|
|
#define GIGA_SPINAND_FEATURE_ECC_EN BIT_4 // ecc enable
|
|
#define GIGA_SPINAND_FEATURE_Rerd BIT_5 // reserved
|
|
#define GIGA_SPINAND_FEATURE_OTP_EN BIT_6 // one-time program
|
|
#define GIGA_SPINAND_FEATURE_OTP_PRT BIT_7 // one-time program
|
|
|
|
//
|
|
// GigaDevice GD5F1GQ4RAYIG: status register 0xc0
|
|
//
|
|
// 7 6 5 4 3 2 1 0
|
|
// +-----+------+------+------+------+------+------+------+
|
|
// | Rerd| Rerd |ECCS1 |ECCS0 |P_FAIL|E_FAIL| WEL | OIP |
|
|
// +-----+------+------+------+------+------+------+------+
|
|
|
|
#define GIGA_SPINAND_STATUS_OIP BIT_0 // operation in progress
|
|
#define GIGA_SPINAND_STATUS_WEL BIT_1 // write enable latch
|
|
#define GIGA_SPINAND_STATUS_E_FAIL BIT_2 // erase fail
|
|
#define GIGA_SPINAND_STATUS_P_FAIL BIT_3 // program fail
|
|
#define GIGA_SPINAND_STATUS_ECCS0 BIT_4 // ecc status
|
|
#define GIGA_SPINAND_STATUS_ECCS1 BIT_5 // ecc status
|
|
#define GIGA_SPINAND_STATUS_Rerd BIT_6 // reserved
|
|
#define GIGA_SPINAND_STATUS_Rerd1 BIT_7 // reserved
|
|
|
|
/*
|
|
* SPI NAND Timeouts (all in MICRO seconds!!)
|
|
* NOTE: I roughly doubled all the values listed in the specification, as the
|
|
* core will be running slowly in BootROM and I wanted to avoid any situation
|
|
* where the operation finished at the edge of the timeout value, but the
|
|
* slow running core captures the timer value just after timeout
|
|
*/
|
|
|
|
#define SN_READ_TIMEOUT 0x100 //maximum time to load a page into the cache field
|
|
#define SN_ERASE_TIMEOUT 0x800 //maximum time for the erase operation
|
|
#define SN_PROGRAM_TIMEOUT 0x5000 //maximum time for the program operation
|
|
|
|
#define SSP_READ_TIME_OUT 0x80000 //timeout for reading data from cache to internal memory
|
|
//this is dependent on CPU and DMA clock speeds, NOT the SPI device!
|
|
|
|
// /*
|
|
// * SPI NAND: other values
|
|
// */
|
|
// typedef enum
|
|
// {
|
|
// SSP_CLOCK_13M = 0x0,
|
|
// SSP_CLOCK_26M = 0x1,
|
|
// SSP_CLOCK_52M = 0x2,
|
|
// } SSP_Clock;
|
|
|
|
|
|
#define SPINAND_PAGE_SIZE 0x800
|
|
#define SPINAND_BLOCK_SIZE 0x20000
|
|
|
|
#define SPINAND_PAGE_WORDS_SIZE 0x200
|
|
#define SPINAND_PAGE_WITH_SPARE_WORDS_SIZE 0x210
|
|
#define SPINAND_PAGE_WITH_SPARE_BYTES_SIZE (SPINAND_PAGE_WITH_SPARE_WORDS_SIZE<<2)
|
|
|
|
|
|
#define SPI_NAND_MAX_TEST_SIZE (65536+4)
|
|
|
|
/*
|
|
* Nezha: SSP Register locations.
|
|
*/
|
|
#define SSPORT_BASE_FOR_SPI get_ssp_base()
|
|
|
|
/* SSP Control Register 0: (Offset: 0x00) */
|
|
#define SSPORT_CR0 ((volatile unsigned int *) (SSPORT_BASE_FOR_SPI+SSP_SSCR0))
|
|
|
|
/* SSP Control Register 1: (Offset: 0x04) */
|
|
#define SSPORT_CR1 ((volatile unsigned int *) (SSPORT_BASE_FOR_SPI+SSP_SSCR1))
|
|
|
|
/* SSP Status Register: (Offset: 0x08) */
|
|
#define SSPORT_SR ((volatile unsigned int *) (SSPORT_BASE_FOR_SPI+SSP_SSSR))
|
|
|
|
/* SSP Data Write/Read Register: (Offset: 0x10) */
|
|
#define SSPORT_DR ((volatile unsigned int *) (SSPORT_BASE_FOR_SPI+SSP_SSDR))
|
|
|
|
/* SSP SSP Programmable Serial Protocol Register: (Offset: 0x2C) */
|
|
#define SSPORT_SP ((volatile unsigned int *) (SSPORT_BASE_FOR_SPI+SSP_SSPSP))
|
|
|
|
/* SSP Top Control Register: (Offset: 0x00)*/
|
|
#define SSPORT_TCR ((volatile int *) (SSPORT_BASE_FOR_SPI+SSP_TOP_CTRL))
|
|
|
|
/* SSP FIFO Control Register: (Offset: 0x04)*/
|
|
#define SSPORT_FCR ((volatile int *) (SSPORT_BASE_FOR_SPI+SSP_FIFO_CTRL))
|
|
|
|
/* SSP Interrupt Enable Register: (Offset: 0x08)*/
|
|
#define SSPORT_IER ((volatile int *) (SSPORT_BASE_FOR_SPI+SSP_INT_EN))
|
|
|
|
/* SSP Time Out Register: (Offset: 0x0C)*/
|
|
#define SSPORT_TOR ((volatile int *) (SSPORT_BASE_FOR_SPI+SSP_TIMEOUT))
|
|
|
|
/* SSP Status Register: (Offset: 0x14)*/
|
|
#define SSPORT_STS ((volatile int *) (SSPORT_BASE_FOR_SPI+SSP_STATUS))
|
|
|
|
#define SPINAND_MAX_ID_LEN 4
|
|
|
|
|
|
struct spinand_device;
|
|
|
|
/**
|
|
* struct nand_ecc_req - NAND ECC reqirement.
|
|
* @strength: ECC strength
|
|
* @step_size: ECC step/block size.
|
|
*/
|
|
struct nand_ecc_req {
|
|
unsigned int strength;
|
|
unsigned int step_size;
|
|
unsigned int hw_ecc;
|
|
};
|
|
|
|
#define NAND_ECCREQ(str, stp, ecc) \
|
|
{ \
|
|
.strength=(str), \
|
|
.step_size=(stp), \
|
|
.hw_ecc=(ecc), \
|
|
}
|
|
|
|
/**
|
|
* struct nand_memory_organization structures.
|
|
* @bit_per_celi: number of bits per NAND celi.
|
|
* @pagesize: page size
|
|
* @oobsize: OOB area size
|
|
* @pages_per_eraseblock: number of pages per eraseblock.
|
|
* @eraseblocks_per_lun: number of eraseblocks per LUN(Logical Unit Number).
|
|
* @max_bad_eraseblocks_per_lun: maxium number of eraseblocks per LUN.
|
|
* @plans_per_lun:numbers of plans per LUN.
|
|
* @luns_per_target: number of LUN
|
|
* @ntarget: total number of target exposed bu the NAND device.
|
|
*/
|
|
struct nand_memory_organization {
|
|
unsigned int bit_per_celi;
|
|
unsigned int pagesize;
|
|
unsigned int oobsize;
|
|
unsigned int pages_per_eraseblock;
|
|
unsigned int eraseblocks_per_lun;
|
|
unsigned int max_bad_eraseblocks_per_lun;
|
|
unsigned int planes_per_lun;
|
|
unsigned int luns_per_target;
|
|
unsigned int ntargets;
|
|
};
|
|
|
|
#define NAND_MEMORG(bpc, ps, os, ppe, epl, mbb, ppl, lpt, nt) \
|
|
{ \
|
|
.bit_per_celi = (bpc), \
|
|
.pagesize = (ps), \
|
|
.oobsize = (os), \
|
|
.pages_per_eraseblock = (ppe), \
|
|
.eraseblocks_per_lun = (epl), \
|
|
.max_bad_eraseblocks_per_lun = (mbb),\
|
|
.planes_per_lun = (ppl), \
|
|
.luns_per_target = (lpt), \
|
|
.ntargets = (nt), \
|
|
}
|
|
|
|
/**
|
|
* struct nand_device - NAND device.
|
|
* @mtd: MTD instance attached to the NAND device.
|
|
* @memorg: memory layout.
|
|
* @eccreq: ECC Reqirement.
|
|
*/
|
|
struct nand_device {
|
|
struct nand_memory_organization memorg;
|
|
struct nand_ecc_req eccreq;
|
|
};
|
|
|
|
/**
|
|
* struct spinand_id - SPI NAND id structurs.
|
|
* @data: buffer containing the id bytes. Currently 4 bytes large.
|
|
* @len: ID Length.
|
|
*/
|
|
struct spinand_id {
|
|
unsigned char data[SPINAND_MAX_ID_LEN];
|
|
unsigned int len;
|
|
};
|
|
|
|
enum spinand_readid_method {
|
|
SPINAND_READID_METHOD_OPCODE,
|
|
SPINAND_READID_METHOD_OPCODE_ADDR,
|
|
SPINAND_READID_METHOD_OPCODE_DUMMY,
|
|
};
|
|
|
|
/** * struct spinand_devid - SPI NAND device id structure
|
|
* @id: device id of current chip
|
|
* @len: number of bytes in device id
|
|
* @method: method to read chip id
|
|
* There are 3 possible variants:
|
|
* SPINAND_READID_METHOD_OPCODE: chip id is returned immediately
|
|
* after read_id opcode.
|
|
* SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after
|
|
* read_id opcode + 1-byte address.
|
|
* SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after
|
|
* read_id opcode + 1 dummy byte.
|
|
*/
|
|
struct spinand_devid{
|
|
const unsigned char *id;
|
|
const unsigned char len;
|
|
const enum spinand_readid_method method;
|
|
};
|
|
|
|
|
|
#define SPINAND_ID(__method, ...) \
|
|
{ \
|
|
.id = (const unsigned char[]){ __VA_ARGS__ }, \
|
|
.len = sizeof((unsigned char[]){ __VA_ARGS__ }), \
|
|
.method = __method, \
|
|
}
|
|
|
|
|
|
/**
|
|
* struct spinand_info - structture used to describe SPI NAND chips.
|
|
* @model: model name
|
|
* @devid: device id
|
|
* @eccreq: ECC Reqirement.
|
|
* @selcet_target: function used to select a target/die, Required only for
|
|
multi_dies.
|
|
* Each SPI NAND manufaturer driver should have a spinand_info table
|
|
* decribing all the chips supported by the driver.
|
|
*/
|
|
struct spinand_info {
|
|
const char *model;
|
|
struct spinand_devid devid;
|
|
struct nand_memory_organization memorg;
|
|
struct nand_ecc_req eccreq;
|
|
int (*select_target)(struct spinand_device *spinand, unsigned int target);
|
|
};
|
|
|
|
|
|
|
|
#define SPINAND_SELECT_TARGET(__func) \
|
|
.select_target = __func,
|
|
|
|
#define SPINAND_INFO(__model, __id, __memorg, __eccreq, ...) \
|
|
{ \
|
|
.model = __model, \
|
|
.devid = __id, \
|
|
.memorg = __memorg, \
|
|
.eccreq = __eccreq, \
|
|
__VA_ARGS__ \
|
|
}
|
|
|
|
/**
|
|
* struct spinand_device - SPI NAND device instance
|
|
* @base: NAND device instance.
|
|
* @lock: lock used to serialize accessed to the NAND.
|
|
* @id: NAND ID as returned by READ_ID.
|
|
* @select_target:select a specific target/die. Usually called before sending
|
|
a command addressing a page or an eraseblock embedded in this die.
|
|
* @menufacturer: SPI NAND manufacturer informaition.
|
|
*/
|
|
struct spinand_device {
|
|
struct nand_device base;
|
|
struct spinand_id id;
|
|
int (*select_target) (struct spinand_device *spinand, unsigned int cur_target);
|
|
unsigned int cur_target;
|
|
const struct spinand_manufacturer *manufacturer;
|
|
};
|
|
|
|
/**
|
|
* struct manufacotuerer_ops - OPS NAND manufacturer specific operations
|
|
* @init: initlization a SPI NAND device
|
|
* @cleanup: cleanup a SPI NAND devices
|
|
* Each SPI NAND manufactuer driver should implement the interface so that
|
|
* NAND chips coming form this vendor can be initilization properly.
|
|
*/
|
|
struct spinand_manufacturer_ops {
|
|
int (*init)(struct spinand_device *spinand);
|
|
int (*cleanup) (struct spinand_device *spinand);
|
|
int (*check_ecc) (unsigned char val);
|
|
};
|
|
|
|
|
|
/**
|
|
* struct spinand_manufacturer - SPI NAND manfacturer instance.
|
|
* @id: manufacturer ID.
|
|
* @name: manufacturer name.
|
|
* @spinand_info: spinand info.
|
|
* @nchips:
|
|
* manufacturer_ops:
|
|
*/
|
|
struct spinand_manufacturer {
|
|
unsigned char id;
|
|
unsigned char *name;
|
|
const struct spinand_info *chips;
|
|
const unsigned int nchips;
|
|
const struct spinand_manufacturer_ops *ops;
|
|
};
|
|
|
|
/**
|
|
* spinand_to_nand() - Get the SPI NAND device embedded in a SPI NAND object.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the NAND device.
|
|
*/
|
|
static inline struct nand_device * spinand_to_nand(struct spinand_device *spinand)
|
|
{
|
|
return &spinand->base;
|
|
}
|
|
|
|
/**
|
|
* nanddev_page_size() - Get NAND Page Size.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the page size.
|
|
*/
|
|
static inline unsigned int nanddev_page_size(const struct nand_device *nand)
|
|
{
|
|
return nand->memorg.pagesize;
|
|
}
|
|
|
|
/**
|
|
* nanddev_oobsize() - Get NAND Page Size.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the page size.
|
|
*/
|
|
static inline unsigned int nanddev_per_page_oobsize(const struct nand_device *nand)
|
|
{
|
|
return nand->memorg.oobsize;
|
|
}
|
|
|
|
/**
|
|
* nanddev_eraseblock_size() - Get NAND erase block Size.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the erase block size.
|
|
*/
|
|
static inline unsigned int nanddev_eraseblock_size(const struct nand_device *nand)
|
|
{
|
|
return nand->memorg.pages_per_eraseblock * nand->memorg.pagesize ;
|
|
}
|
|
|
|
|
|
/**
|
|
* nanddev_eraseblock_size() - Get NAND erase block Size.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the number of target/die used by us.
|
|
*/
|
|
static inline unsigned int nanddev_eraseblocks_per_target(const struct nand_device *nand)
|
|
{
|
|
return (nand->memorg.luns_per_target *nand->memorg.eraseblocks_per_lun);
|
|
}
|
|
|
|
|
|
/**
|
|
* nanddev_page_size() - Get total size provided by a single target/die.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the total size per target/die.
|
|
*/
|
|
static inline unsigned long long nanddev_target_size(const struct nand_device *nand)
|
|
{
|
|
return (unsigned long long )nand->memorg.luns_per_target *
|
|
nand->memorg.eraseblocks_per_lun *
|
|
nand->memorg.pages_per_eraseblock *
|
|
nand->memorg.pagesize;
|
|
}
|
|
|
|
/**
|
|
* nanddev_size() - Get the total targets.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the total number.
|
|
*/
|
|
static inline unsigned int nanddev_ntargets(const struct nand_device *nand)
|
|
{
|
|
return nand->memorg.ntargets;
|
|
}
|
|
|
|
|
|
/**
|
|
* nanddev_size() - Get NAND Size.
|
|
* @spinand: SPI NAND device.
|
|
* Returns: the page size.
|
|
*/
|
|
static inline unsigned int nanddev_size(const struct nand_device *nand)
|
|
{
|
|
return nanddev_target_size(nand) * nanddev_ntargets(nand);
|
|
}
|
|
|
|
struct SPINAND_ADDRESS_FIELDS
|
|
{
|
|
unsigned int CA :11;
|
|
unsigned int RA :16;
|
|
unsigned int reserved :5;
|
|
};
|
|
|
|
typedef union
|
|
{
|
|
unsigned int value;
|
|
struct SPINAND_ADDRESS_FIELDS fields;
|
|
} SPINAND_ADDRESS_FIELD_T;
|
|
|
|
enum{
|
|
QUEC_SPI_NAND_DEV0 = 0,
|
|
QUEC_SPI_NAND_DEV2 = 2
|
|
};
|
|
enum{
|
|
QUEC_SPI_NAND_PIN_16_19 ,
|
|
QUEC_SPI_NAND_PIN_33_36 ,
|
|
QUEC_SPI_NAND_PIN_12_15 ,
|
|
};
|
|
enum{
|
|
QUEC_SPI_NAND_CLOCK_13M = 0x0,
|
|
QUEC_SPI_NAND_CLOCK_26M = 0x1,
|
|
QUEC_SPI_NAND_CLOCK_52M = 0x2,
|
|
};
|
|
|
|
unsigned int SPINANDDevice_Init(unsigned char flashnu, FlashBootType_T flashbootType, unsigned char *P_DefaultPartitonNum);
|
|
unsigned int SPINAND_Read(unsigned int FlashOffset, unsigned int Buffer,
|
|
unsigned int Size, FlashBootType_T fbt);
|
|
unsigned int SPINAND_Write(unsigned int FlashOffset, unsigned int Buffer,
|
|
unsigned int Size, FlashBootType_T fbt);
|
|
unsigned int SPINAND_Erase(unsigned int FlashOffset, unsigned int Size,
|
|
FlashBootType_T fbt);
|
|
unsigned int SPINAND_Read_Page_SpareData(unsigned int FlashOffset,
|
|
unsigned int Buffer, unsigned int size);
|
|
unsigned int SPINAND_Write_Page_SpareData(unsigned int FlashOffset,
|
|
unsigned int Buffer, unsigned int size);
|
|
int quec_nand_spi_init(int spi_port,int spi_pin,int spi_clk);
|
|
|
|
|
|
#endif
|